mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-22 17:06:17 +00:00
Reworked star/unstar error handling
Don't stop at the first error anymore, instead treat all provided ids Potential errors are aggregated, if there's only one it is returned as-is, if there are more they are all nested in a top-level error whose code is 0 if there are different error codes, or their value if all error codes are the same. This error-nesting doesn't validate against the XSD, but the Subsonic API gives absolutely no information on how errors should be handled. And reverse-engineering is not in my line of work
This commit is contained in:
parent
5084c745dc
commit
da857b9ceb
@ -28,84 +28,108 @@ from supysonic.db import Track, Album, Artist, Folder
|
|||||||
from supysonic.db import StarredTrack, StarredAlbum, StarredArtist, StarredFolder
|
from supysonic.db import StarredTrack, StarredAlbum, StarredArtist, StarredFolder
|
||||||
from supysonic.db import RatingTrack, RatingFolder
|
from supysonic.db import RatingTrack, RatingFolder
|
||||||
|
|
||||||
|
def try_star(ent, starred_ent, eid):
|
||||||
|
""" Stars an entity
|
||||||
|
|
||||||
|
:param ent: entity class, Folder, Artist, Album or Track
|
||||||
|
:param starred_ent: class used for the db representation of the starring of ent
|
||||||
|
:param eid: id of the entity to star
|
||||||
|
:return error dict, if any. None otherwise
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
uid = uuid.UUID(eid)
|
||||||
|
except:
|
||||||
|
return { 'code': 0, 'message': 'Invalid {} id {}'.format(ent.__name__, eid) }
|
||||||
|
|
||||||
|
if store.get(starred_ent, (request.user.id, uid)):
|
||||||
|
return { 'code': 0, 'message': '{} {} already starred'.format(ent.__name__, eid) }
|
||||||
|
|
||||||
|
e = store.get(ent, uid)
|
||||||
|
if not e:
|
||||||
|
return { 'code': 70, 'message': 'Unknown {} id {}'.format(ent.__name__, eid) }
|
||||||
|
|
||||||
|
starred = starred_ent()
|
||||||
|
starred.user_id = request.user.id
|
||||||
|
starred.starred_id = uid
|
||||||
|
store.add(starred)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def try_unstar(starred_ent, eid):
|
||||||
|
""" Unstars an entity
|
||||||
|
|
||||||
|
:param starred_ent: class used for the db representation of the starring of the entity
|
||||||
|
:param eid: id of the entity to unstar
|
||||||
|
:return error dict, if any. None otherwise
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
uid = uuid.UUID(eid)
|
||||||
|
except:
|
||||||
|
return { 'code': 0, 'message': 'Invalid id {}'.format(eid) }
|
||||||
|
|
||||||
|
store.find(starred_ent, starred_ent.user_id == request.user.id, starred_ent.starred_id == uid).remove()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def merge_errors(errors):
|
||||||
|
error = None
|
||||||
|
errors = filter(None, errors)
|
||||||
|
if len(errors) == 1:
|
||||||
|
error = errors[0]
|
||||||
|
elif len(errors) > 1:
|
||||||
|
codes = set(map(lambda e: e['code'], errors))
|
||||||
|
error = { 'code': list(codes)[0] if len(codes) == 1 else 0, 'error': errors }
|
||||||
|
|
||||||
|
return error
|
||||||
|
|
||||||
@app.route('/rest/star.view', methods = [ 'GET', 'POST' ])
|
@app.route('/rest/star.view', methods = [ 'GET', 'POST' ])
|
||||||
def star():
|
def star():
|
||||||
id, albumId, artistId = map(request.values.getlist, [ 'id', 'albumId', 'artistId' ])
|
id, albumId, artistId = map(request.values.getlist, [ 'id', 'albumId', 'artistId' ])
|
||||||
|
|
||||||
def try_star(ent, starred_ent, eid):
|
if not id and not albumId and not artistId:
|
||||||
try:
|
return request.error_formatter(10, 'Missing parameter')
|
||||||
uid = uuid.UUID(eid)
|
|
||||||
except:
|
|
||||||
return 2, request.error_formatter(0, 'Invalid %s id' % ent.__name__)
|
|
||||||
|
|
||||||
if store.get(starred_ent, (request.user.id, uid)):
|
|
||||||
return 2, request.error_formatter(0, '%s already starred' % ent.__name__)
|
|
||||||
e = store.get(ent, uid)
|
|
||||||
if e:
|
|
||||||
starred = starred_ent()
|
|
||||||
starred.user_id = request.user.id
|
|
||||||
starred.starred_id = uid
|
|
||||||
store.add(starred)
|
|
||||||
else:
|
|
||||||
return 1, request.error_formatter(70, 'Unknown %s id' % ent.__name__)
|
|
||||||
|
|
||||||
return 0, None
|
|
||||||
|
|
||||||
|
errors = []
|
||||||
for eid in id:
|
for eid in id:
|
||||||
err, ferror = try_star(Track, StarredTrack, eid)
|
terr = try_star(Track, StarredTrack, eid)
|
||||||
if err == 1:
|
ferr = try_star(Folder, StarredFolder, eid)
|
||||||
err, ferror = try_star(Folder, StarredFolder, eid)
|
if terr and ferr:
|
||||||
if err:
|
errors += [ terr, ferr ]
|
||||||
return ferror
|
|
||||||
elif err == 2:
|
|
||||||
return ferror
|
|
||||||
|
|
||||||
for alId in albumId:
|
for alId in albumId:
|
||||||
err, ferror = try_star(Album, StarredAlbum, alId)
|
errors.append(try_star(Album, StarredAlbum, alId))
|
||||||
if err:
|
|
||||||
return ferror
|
|
||||||
|
|
||||||
for arId in artistId:
|
for arId in artistId:
|
||||||
err, ferror = try_star(Artist, StarredArtist, arId)
|
errors.append(try_star(Artist, StarredArtist, arId))
|
||||||
if err:
|
|
||||||
return ferror
|
|
||||||
|
|
||||||
store.commit()
|
store.commit()
|
||||||
return request.formatter({})
|
error = merge_errors(errors)
|
||||||
|
return request.formatter({ 'error': error }, error = True) if error else request.formatter({})
|
||||||
|
|
||||||
@app.route('/rest/unstar.view', methods = [ 'GET', 'POST' ])
|
@app.route('/rest/unstar.view', methods = [ 'GET', 'POST' ])
|
||||||
def unstar():
|
def unstar():
|
||||||
id, albumId, artistId = map(request.values.getlist, [ 'id', 'albumId', 'artistId' ])
|
id, albumId, artistId = map(request.values.getlist, [ 'id', 'albumId', 'artistId' ])
|
||||||
|
|
||||||
def try_unstar(ent, eid):
|
if not id and not albumId and not artistId:
|
||||||
try:
|
return request.error_formatter(10, 'Missing parameter')
|
||||||
uid = uuid.UUID(eid)
|
|
||||||
except:
|
|
||||||
return request.error_formatter(0, 'Invalid id')
|
|
||||||
|
|
||||||
store.find(ent, ent.user_id == request.user.id, ent.starred_id == uid).remove()
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
errors = []
|
||||||
for eid in id:
|
for eid in id:
|
||||||
err = try_unstar(StarredTrack, eid)
|
terr = try_unstar(StarredTrack, eid)
|
||||||
if err:
|
ferr = try_unstar(StarredFolder, eid)
|
||||||
return err
|
if terr and ferr:
|
||||||
err = try_unstar(StarredFolder, eid)
|
errors += [ terr, ferr ]
|
||||||
if err:
|
|
||||||
return err
|
|
||||||
|
|
||||||
for alId in albumId:
|
for alId in albumId:
|
||||||
err = try_unstar(StarredAlbum, alId)
|
errors.append(try_unstar(StarredAlbum, alId))
|
||||||
if err:
|
|
||||||
return err
|
|
||||||
|
|
||||||
for arId in artistId:
|
for arId in artistId:
|
||||||
err = try_unstar(StarredArtist, arId)
|
errors.append(try_unstar(StarredArtist, arId))
|
||||||
if err:
|
|
||||||
return err
|
|
||||||
|
|
||||||
store.commit()
|
store.commit()
|
||||||
return request.formatter({})
|
error = merge_errors(errors)
|
||||||
|
return request.formatter({ 'error': error }, error = True) if error else request.formatter({})
|
||||||
|
|
||||||
@app.route('/rest/setRating.view', methods = [ 'GET', 'POST' ])
|
@app.route('/rest/setRating.view', methods = [ 'GET', 'POST' ])
|
||||||
def rate():
|
def rate():
|
||||||
|
Loading…
Reference in New Issue
Block a user