1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-12-23 01:16:18 +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 # 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
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 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
View File

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

1
web.py
View File

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