mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-23 01:16:18 +00:00
Starring support
This commit is contained in:
parent
d9caa025fd
commit
197e43a142
@ -1,13 +1,13 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
from flask import request
|
from flask import request
|
||||||
from sqlalchemy import desc, func, Interval
|
from sqlalchemy import desc, func
|
||||||
from sqlalchemy.orm import aliased
|
from sqlalchemy.orm import aliased
|
||||||
import random
|
import random
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from web import app
|
from web import app
|
||||||
from db import Track, Folder, Album, Artist, User, now
|
from db import *
|
||||||
|
|
||||||
@app.route('/rest/getRandomSongs.view', methods = [ 'GET', 'POST' ])
|
@app.route('/rest/getRandomSongs.view', methods = [ 'GET', 'POST' ])
|
||||||
def rand_songs():
|
def rand_songs():
|
||||||
@ -134,3 +134,31 @@ def now_playing():
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@app.route('/rest/getStarred.view', methods = [ 'GET', 'POST' ])
|
||||||
|
def get_starred():
|
||||||
|
username = request.args.get('u')
|
||||||
|
if not username:
|
||||||
|
username = request.authorization.username
|
||||||
|
|
||||||
|
return request.formatter({
|
||||||
|
'starred': {
|
||||||
|
'artist': [ { 'id': sf.starred.name, 'name': sf.starred_id } for sf in StarredFolder.query.join(User).join(Folder).filter(User.name == username).filter(~ Folder.tracks.any()) ],
|
||||||
|
'album': [ sf.starred.as_subsonic_child() for sf in StarredFolder.query.join(User).join(Folder).filter(User.name == username).filter(Folder.tracks.any()) ],
|
||||||
|
'song': [ st.starred.as_subsonic_child() for st in StarredTrack.query.join(User).filter(User.name == username) ]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
@app.route('/rest/getStarred2.view', methods = [ 'GET', 'POST' ])
|
||||||
|
def get_starred_id3():
|
||||||
|
username = request.args.get('u')
|
||||||
|
if not username:
|
||||||
|
username = request.authorization.username
|
||||||
|
|
||||||
|
return request.formatter({
|
||||||
|
'starred2': {
|
||||||
|
'artist': [ sa.starred.as_subsonic_artist() for sa in StarredArtist.query.join(User).filter(User.name == username) ],
|
||||||
|
'album': [ sa.starred.as_subsonic_album() for sa in StarredAlbum.query.join(User).filter(User.name == username) ],
|
||||||
|
'song': [ st.starred.as_subsonic_child() for st in StarredTrack.query.join(User).filter(User.name == username) ]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
125
api/annotation.py
Executable file
125
api/annotation.py
Executable file
@ -0,0 +1,125 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
|
||||||
|
from time import time
|
||||||
|
import uuid
|
||||||
|
from flask import request
|
||||||
|
from web import app
|
||||||
|
from api import get_entity
|
||||||
|
from lastfm import LastFm
|
||||||
|
from db import *
|
||||||
|
|
||||||
|
@app.route('/rest/star.view', methods = [ 'GET', 'POST' ])
|
||||||
|
def star():
|
||||||
|
id, albumId, artistId = map(request.args.getlist, [ 'id', 'albumId', 'artistId' ])
|
||||||
|
|
||||||
|
username = request.args.get('u')
|
||||||
|
if not username:
|
||||||
|
username = request.authorization.username
|
||||||
|
user = User.query.filter(User.name == username).one()
|
||||||
|
|
||||||
|
def try_star(ent, starred_ent, eid):
|
||||||
|
try:
|
||||||
|
uid = uuid.UUID(eid)
|
||||||
|
except:
|
||||||
|
return 2, request.error_formatter(0, 'Invalid %s id' % ent.__name__)
|
||||||
|
|
||||||
|
if starred_ent.query.filter(starred_ent.user_id == user.id).filter(starred_ent.starred_id == uid).first():
|
||||||
|
return 2, request.error_formatter(0, '%s already starred' % ent.__name__)
|
||||||
|
e = ent.query.get(uid)
|
||||||
|
if e:
|
||||||
|
session.add(starred_ent(user = user, starred = e))
|
||||||
|
else:
|
||||||
|
return 1, request.error_formatter(70, 'Unknown %s id' % ent.__name__)
|
||||||
|
|
||||||
|
return 0, None
|
||||||
|
|
||||||
|
for eid in id:
|
||||||
|
err, ferror = try_star(Track, StarredTrack, eid)
|
||||||
|
if err == 1:
|
||||||
|
err, ferror = try_star(Folder, StarredFolder, eid)
|
||||||
|
if err:
|
||||||
|
return ferror
|
||||||
|
elif err == 2:
|
||||||
|
return ferror
|
||||||
|
|
||||||
|
for alId in albumId:
|
||||||
|
err, ferror = try_star(Album, StarredAlbum, alId)
|
||||||
|
if err:
|
||||||
|
return ferror
|
||||||
|
|
||||||
|
for arId in artistId:
|
||||||
|
err, ferror = try_star(Artist, StarredArtist, arId)
|
||||||
|
if err:
|
||||||
|
return ferror
|
||||||
|
|
||||||
|
session.commit()
|
||||||
|
return request.formatter({})
|
||||||
|
|
||||||
|
@app.route('/rest/unstar.view', methods = [ 'GET', 'POST' ])
|
||||||
|
def unstar():
|
||||||
|
id, albumId, artistId = map(request.args.getlist, [ 'id', 'albumId', 'artistId' ])
|
||||||
|
|
||||||
|
username = request.args.get('u')
|
||||||
|
if not username:
|
||||||
|
username = request.authorization.username
|
||||||
|
user = User.query.filter(User.name == username).one()
|
||||||
|
|
||||||
|
def try_unstar(ent, eid):
|
||||||
|
try:
|
||||||
|
uid = uuid.UUID(eid)
|
||||||
|
except:
|
||||||
|
return request.error_formatter(0, 'Invalid id')
|
||||||
|
|
||||||
|
ent.query.filter(ent.user_id == user.id).filter(ent.starred_id == uid).delete()
|
||||||
|
return None
|
||||||
|
|
||||||
|
for eid in id:
|
||||||
|
err = try_unstar(StarredTrack, eid)
|
||||||
|
if err:
|
||||||
|
return err
|
||||||
|
err = try_unstar(StarredFolder, eid)
|
||||||
|
if err:
|
||||||
|
return err
|
||||||
|
|
||||||
|
for alId in albumId:
|
||||||
|
err = try_unstar(StarredAlbum, alId)
|
||||||
|
if err:
|
||||||
|
return err
|
||||||
|
|
||||||
|
for arId in artistId:
|
||||||
|
err = try_unstar(StarredArtist, arId)
|
||||||
|
if err:
|
||||||
|
return err
|
||||||
|
|
||||||
|
session.commit()
|
||||||
|
return request.formatter({})
|
||||||
|
|
||||||
|
@app.route('/rest/scrobble.view', methods = [ 'GET', 'POST' ])
|
||||||
|
def scrobble():
|
||||||
|
status, res = get_entity(request, Track)
|
||||||
|
if not status:
|
||||||
|
return res
|
||||||
|
|
||||||
|
t, submission, u = map(request.args.get, [ 'time', 'submission', 'u' ])
|
||||||
|
|
||||||
|
if t:
|
||||||
|
try:
|
||||||
|
t = int(t) / 1000
|
||||||
|
except:
|
||||||
|
return request.error_formatter(0, 'Invalid time value')
|
||||||
|
else:
|
||||||
|
t = int(time())
|
||||||
|
|
||||||
|
if u:
|
||||||
|
user = User.query.filter(User.name == u).one()
|
||||||
|
else:
|
||||||
|
user = User.query.filter(User.name == request.authorization.username).one()
|
||||||
|
lfm = LastFm(user, app.logger)
|
||||||
|
|
||||||
|
if submission in (None, '', True, 'true', 'True', 1, '1'):
|
||||||
|
lfm.scrobble(res, t)
|
||||||
|
else:
|
||||||
|
lfm.now_playing(res)
|
||||||
|
|
||||||
|
return request.formatter({})
|
||||||
|
|
39
api/media.py
39
api/media.py
@ -3,13 +3,11 @@
|
|||||||
from flask import request, send_file
|
from flask import request, send_file
|
||||||
import os.path
|
import os.path
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from time import time as now
|
|
||||||
|
|
||||||
import config
|
import config
|
||||||
from web import app
|
from web import app
|
||||||
from db import Track, Folder, User, now, session
|
from db import Track, Folder, User, now, session
|
||||||
from api import get_entity
|
from api import get_entity
|
||||||
from lastfm import LastFm
|
|
||||||
|
|
||||||
@app.route('/rest/stream.view', methods = [ 'GET', 'POST' ])
|
@app.route('/rest/stream.view', methods = [ 'GET', 'POST' ])
|
||||||
def stream_media():
|
def stream_media():
|
||||||
@ -49,6 +47,14 @@ def stream_media():
|
|||||||
|
|
||||||
return send_file(res.path)
|
return send_file(res.path)
|
||||||
|
|
||||||
|
@app.route('/rest/download.view', methods = [ 'GET', 'POST' ])
|
||||||
|
def download_media():
|
||||||
|
status, res = get_entity(request, Track)
|
||||||
|
if not status:
|
||||||
|
return res
|
||||||
|
|
||||||
|
return send_file(res.path)
|
||||||
|
|
||||||
@app.route('/rest/getCoverArt.view', methods = [ 'GET', 'POST' ])
|
@app.route('/rest/getCoverArt.view', methods = [ 'GET', 'POST' ])
|
||||||
def cover_art():
|
def cover_art():
|
||||||
status, res = get_entity(request, Folder)
|
status, res = get_entity(request, Folder)
|
||||||
@ -82,32 +88,3 @@ def cover_art():
|
|||||||
im.save(path, 'JPEG')
|
im.save(path, 'JPEG')
|
||||||
return send_file(path)
|
return send_file(path)
|
||||||
|
|
||||||
@app.route('/rest/scrobble.view', methods = [ 'GET', 'POST' ])
|
|
||||||
def scrobble():
|
|
||||||
status, res = get_entity(request, Track)
|
|
||||||
if not status:
|
|
||||||
return res
|
|
||||||
|
|
||||||
time, submission, u = map(request.args.get, [ 'time', 'submission', 'u' ])
|
|
||||||
|
|
||||||
if time:
|
|
||||||
try:
|
|
||||||
time = int(time) / 1000
|
|
||||||
except:
|
|
||||||
return request.error_formatter(0, 'Invalid time value')
|
|
||||||
else:
|
|
||||||
time = int(now())
|
|
||||||
|
|
||||||
if u:
|
|
||||||
user = User.query.filter(User.name == u).one()
|
|
||||||
else:
|
|
||||||
user = User.query.filter(User.name == request.authorization.username).one()
|
|
||||||
lfm = LastFm(user, app.logger)
|
|
||||||
|
|
||||||
if submission in (None, '', True, 'true', 'True', 1, '1'):
|
|
||||||
lfm.scrobble(res, time)
|
|
||||||
else:
|
|
||||||
lfm.now_playing(res)
|
|
||||||
|
|
||||||
return request.formatter({})
|
|
||||||
|
|
||||||
|
41
db.py
41
db.py
@ -83,6 +83,7 @@ class Folder(Base):
|
|||||||
'id': str(self.id),
|
'id': str(self.id),
|
||||||
'isDir': True,
|
'isDir': True,
|
||||||
'title': self.name,
|
'title': self.name,
|
||||||
|
'album': self.name,
|
||||||
'created': self.created.isoformat()
|
'created': self.created.isoformat()
|
||||||
}
|
}
|
||||||
if not self.root:
|
if not self.root:
|
||||||
@ -209,6 +210,46 @@ class Track(Base):
|
|||||||
def sort_key(self):
|
def sort_key(self):
|
||||||
return (self.album.artist.name + self.album.name + ("%02i" % self.disc) + ("%02i" % self.number) + self.title).lower()
|
return (self.album.artist.name + self.album.name + ("%02i" % self.disc) + ("%02i" % self.number) + self.title).lower()
|
||||||
|
|
||||||
|
class StarredFolder(Base):
|
||||||
|
__tablename__ = 'starred_folder'
|
||||||
|
|
||||||
|
user_id = Column(UUID, ForeignKey('user.id'), primary_key = True)
|
||||||
|
starred_id = Column(UUID, ForeignKey('folder.id'), primary_key = True)
|
||||||
|
date = Column(DateTime, default = now)
|
||||||
|
|
||||||
|
user = relationship('User')
|
||||||
|
starred = relationship('Folder')
|
||||||
|
|
||||||
|
class StarredArtist(Base):
|
||||||
|
__tablename__ = 'starred_artist'
|
||||||
|
|
||||||
|
user_id = Column(UUID, ForeignKey('user.id'), primary_key = True)
|
||||||
|
starred_id = Column(UUID, ForeignKey('artist.id'), primary_key = True)
|
||||||
|
date = Column(DateTime, default = now)
|
||||||
|
|
||||||
|
user = relationship('User')
|
||||||
|
starred = relationship('Artist')
|
||||||
|
|
||||||
|
class StarredAlbum(Base):
|
||||||
|
__tablename__ = 'starred_album'
|
||||||
|
|
||||||
|
user_id = Column(UUID, ForeignKey('user.id'), primary_key = True)
|
||||||
|
starred_id = Column(UUID, ForeignKey('album.id'), primary_key = True)
|
||||||
|
date = Column(DateTime, default = now)
|
||||||
|
|
||||||
|
user = relationship('User')
|
||||||
|
starred = relationship('Album')
|
||||||
|
|
||||||
|
class StarredTrack(Base):
|
||||||
|
__tablename__ = 'starred_track'
|
||||||
|
|
||||||
|
user_id = Column(UUID, ForeignKey('user.id'), primary_key = True)
|
||||||
|
starred_id = Column(UUID, ForeignKey('track.id'), primary_key = True)
|
||||||
|
date = Column(DateTime, default = now)
|
||||||
|
|
||||||
|
user = relationship('User')
|
||||||
|
starred = relationship('Track')
|
||||||
|
|
||||||
def init_db():
|
def init_db():
|
||||||
Base.metadata.create_all(bind = engine)
|
Base.metadata.create_all(bind = engine)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user