1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-12-22 17:06:17 +00:00

Starring support

This commit is contained in:
spl0k 2013-06-12 21:29:42 +02:00
parent d9caa025fd
commit 197e43a142
5 changed files with 205 additions and 33 deletions

View File

@ -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
View 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({})

View File

@ -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
View File

@ -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)

1
web.py
View File

@ -59,4 +59,5 @@ import api.browse
import api.user
import api.albums_songs
import api.media
import api.annotation