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 RatingTrack, RatingFolder
|
||||
|
||||
@app.route('/rest/star.view', methods = [ 'GET', 'POST' ])
|
||||
def star():
|
||||
id, albumId, artistId = map(request.values.getlist, [ 'id', 'albumId', 'artistId' ])
|
||||
|
||||
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 2, request.error_formatter(0, 'Invalid %s id' % ent.__name__)
|
||||
return { 'code': 0, 'message': 'Invalid {} id {}'.format(ent.__name__, eid) }
|
||||
|
||||
if store.get(starred_ent, (request.user.id, uid)):
|
||||
return 2, request.error_formatter(0, '%s already starred' % ent.__name__)
|
||||
return { 'code': 0, 'message': '{} {} already starred'.format(ent.__name__, eid) }
|
||||
|
||||
e = store.get(ent, uid)
|
||||
if e:
|
||||
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)
|
||||
else:
|
||||
return 1, request.error_formatter(70, 'Unknown %s id' % ent.__name__)
|
||||
|
||||
return 0, None
|
||||
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' ])
|
||||
def star():
|
||||
id, albumId, artistId = map(request.values.getlist, [ 'id', 'albumId', 'artistId' ])
|
||||
|
||||
if not id and not albumId and not artistId:
|
||||
return request.error_formatter(10, 'Missing parameter')
|
||||
|
||||
errors = []
|
||||
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
|
||||
terr = try_star(Track, StarredTrack, eid)
|
||||
ferr = try_star(Folder, StarredFolder, eid)
|
||||
if terr and ferr:
|
||||
errors += [ terr, ferr ]
|
||||
|
||||
for alId in albumId:
|
||||
err, ferror = try_star(Album, StarredAlbum, alId)
|
||||
if err:
|
||||
return ferror
|
||||
errors.append(try_star(Album, StarredAlbum, alId))
|
||||
|
||||
for arId in artistId:
|
||||
err, ferror = try_star(Artist, StarredArtist, arId)
|
||||
if err:
|
||||
return ferror
|
||||
errors.append(try_star(Artist, StarredArtist, arId))
|
||||
|
||||
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' ])
|
||||
def unstar():
|
||||
id, albumId, artistId = map(request.values.getlist, [ 'id', 'albumId', 'artistId' ])
|
||||
|
||||
def try_unstar(ent, eid):
|
||||
try:
|
||||
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
|
||||
if not id and not albumId and not artistId:
|
||||
return request.error_formatter(10, 'Missing parameter')
|
||||
|
||||
errors = []
|
||||
for eid in id:
|
||||
err = try_unstar(StarredTrack, eid)
|
||||
if err:
|
||||
return err
|
||||
err = try_unstar(StarredFolder, eid)
|
||||
if err:
|
||||
return err
|
||||
terr = try_unstar(StarredTrack, eid)
|
||||
ferr = try_unstar(StarredFolder, eid)
|
||||
if terr and ferr:
|
||||
errors += [ terr, ferr ]
|
||||
|
||||
for alId in albumId:
|
||||
err = try_unstar(StarredAlbum, alId)
|
||||
if err:
|
||||
return err
|
||||
errors.append(try_unstar(StarredAlbum, alId))
|
||||
|
||||
for arId in artistId:
|
||||
err = try_unstar(StarredArtist, arId)
|
||||
if err:
|
||||
return err
|
||||
errors.append(try_unstar(StarredArtist, arId))
|
||||
|
||||
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' ])
|
||||
def rate():
|
||||
|
Loading…
Reference in New Issue
Block a user