mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-22 08:56:17 +00:00
Starring support
This commit is contained in:
parent
d9caa025fd
commit
197e43a142
@ -1,13 +1,13 @@
|
||||
# coding: utf-8
|
||||
|
||||
from flask import request
|
||||
from sqlalchemy import desc, func, Interval
|
||||
from sqlalchemy import desc, func
|
||||
from sqlalchemy.orm import aliased
|
||||
import random
|
||||
import uuid
|
||||
|
||||
from web import app
|
||||
from db import Track, Folder, Album, Artist, User, now
|
||||
from db import *
|
||||
|
||||
@app.route('/rest/getRandomSongs.view', methods = [ 'GET', 'POST' ])
|
||||
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
|
||||
import os.path
|
||||
from PIL import Image
|
||||
from time import time as now
|
||||
|
||||
import config
|
||||
from web import app
|
||||
from db import Track, Folder, User, now, session
|
||||
from api import get_entity
|
||||
from lastfm import LastFm
|
||||
|
||||
@app.route('/rest/stream.view', methods = [ 'GET', 'POST' ])
|
||||
def stream_media():
|
||||
@ -49,6 +47,14 @@ def stream_media():
|
||||
|
||||
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' ])
|
||||
def cover_art():
|
||||
status, res = get_entity(request, Folder)
|
||||
@ -82,32 +88,3 @@ def cover_art():
|
||||
im.save(path, 'JPEG')
|
||||
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),
|
||||
'isDir': True,
|
||||
'title': self.name,
|
||||
'album': self.name,
|
||||
'created': self.created.isoformat()
|
||||
}
|
||||
if not self.root:
|
||||
@ -209,6 +210,46 @@ class Track(Base):
|
||||
def sort_key(self):
|
||||
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():
|
||||
Base.metadata.create_all(bind = engine)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user