1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-10-18 08:52:17 +00:00

Adding ratings and stars as disablable features

This commit is contained in:
spl0k 2014-03-09 21:15:03 +01:00
parent 72f8e6b52c
commit c6b197689a
5 changed files with 205 additions and 133 deletions

View File

@ -23,6 +23,7 @@ from xml.etree import ElementTree
import simplejson import simplejson
import uuid import uuid
import config
from web import app from web import app
from managers.user import UserManager from managers.user import UserManager
@ -190,12 +191,27 @@ def get_entity(req, ent, param = 'id'):
return True, entity return True, entity
def disabled_api_feature():
return request.error_formatter(0, 'Feature disabled')
from .system import * from .system import *
from .browse import * from .browse import *
from .user import * from .user import *
from .albums_songs import * from .albums_songs import *
from .media import * from .media import *
from .annotation import * from .scrobble import *
if config.getbool('features', 'star', True):
from .star import *
else:
app.add_url_rule('/rest/star.view', view_func = disabled_api_feature, methods = [ 'GET', 'POST' ])
app.add_url_rule('/rest/unstar.view', view_func = disabled_api_feature, methods = [ 'GET', 'POST' ])
if config.getbool('features', 'rating', True):
from .rating import *
else:
app.add_url_rule('/rest/setRating.view', view_func = disabled_api_feature, methods = [ 'GET', 'POST' ])
from .chat import * from .chat import *
from .search import * from .search import *
from .playlists import * from .playlists import *

61
api/rating.py Normal file
View File

@ -0,0 +1,61 @@
# coding: utf-8
# This file is part of Supysonic.
#
# Supysonic is a Python implementation of the Subsonic server API.
# Copyright (C) 2013 Alban 'spl0k' Féron
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import uuid
from flask import request
from web import app
from db import RatingTrack, RatingFolder, Track, Folder, session
@app.route('/rest/setRating.view', methods = [ 'GET', 'POST' ])
def rate():
id, rating = map(request.args.get, [ 'id', 'rating' ])
if not id or not rating:
return request.error_formatter(10, 'Missing parameter')
try:
uid = uuid.UUID(id)
rating = int(rating)
except:
return request.error_formatter(0, 'Invalid parameter')
if not rating in xrange(6):
return request.error_formatter(0, 'rating must be between 0 and 5 (inclusive)')
if rating == 0:
RatingTrack.query.filter(RatingTrack.user_id == request.user.id).filter(RatingTrack.rated_id == uid).delete()
RatingFolder.query.filter(RatingFolder.user_id == request.user.id).filter(RatingFolder.rated_id == uid).delete()
else:
rated = Track.query.get(uid)
rating_ent = RatingTrack
if not rated:
rated = Folder.query.get(uid)
rating_ent = RatingFolder
if not rated:
return request.error_formatter(70, 'Unknown id')
rating_info = rating_ent.query.get((request.user.id, uid))
if rating_info:
rating_info.rating = rating
else:
session.add(rating_ent(user = request.user, rated = rated, rating = rating))
session.commit()
return request.formatter({})

52
api/scrobble.py Normal file
View File

@ -0,0 +1,52 @@
# coding: utf-8
# This file is part of Supysonic.
#
# Supysonic is a Python implementation of the Subsonic server API.
# Copyright (C) 2013 Alban 'spl0k' Féron
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import time
from flask import request
from web import app
from . import get_entity
from lastfm import LastFm
from db import Track
@app.route('/rest/scrobble.view', methods = [ 'GET', 'POST' ])
def scrobble():
status, res = get_entity(request, Track)
if not status:
return res
t, submission = map(request.args.get, [ 'time', 'submission' ])
if t:
try:
t = int(t) / 1000
except:
return request.error_formatter(0, 'Invalid time value')
else:
t = int(time.time())
lfm = LastFm(request.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

@ -18,13 +18,9 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import time
import uuid
from flask import request from flask import request
from web import app from web import app
from . import get_entity from db import Track, StarredTrack, Album, StarredAlbum, Artist, StarredArtist, Folder, StarredFolder, session
from lastfm import LastFm
from db import *
@app.route('/rest/star.view', methods = [ 'GET', 'POST' ]) @app.route('/rest/star.view', methods = [ 'GET', 'POST' ])
def star(): def star():
@ -102,64 +98,3 @@ def unstar():
session.commit() session.commit()
return request.formatter({}) return request.formatter({})
@app.route('/rest/setRating.view', methods = [ 'GET', 'POST' ])
def rate():
id, rating = map(request.args.get, [ 'id', 'rating' ])
if not id or not rating:
return request.error_formatter(10, 'Missing parameter')
try:
uid = uuid.UUID(id)
rating = int(rating)
except:
return request.error_formatter(0, 'Invalid parameter')
if not rating in xrange(6):
return request.error_formatter(0, 'rating must be between 0 and 5 (inclusive)')
if rating == 0:
RatingTrack.query.filter(RatingTrack.user_id == request.user.id).filter(RatingTrack.rated_id == uid).delete()
RatingFolder.query.filter(RatingFolder.user_id == request.user.id).filter(RatingFolder.rated_id == uid).delete()
else:
rated = Track.query.get(uid)
rating_ent = RatingTrack
if not rated:
rated = Folder.query.get(uid)
rating_ent = RatingFolder
if not rated:
return request.error_formatter(70, 'Unknown id')
rating_info = rating_ent.query.get((request.user.id, uid))
if rating_info:
rating_info.rating = rating
else:
session.add(rating_ent(user = request.user, rated = rated, rating = rating))
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 = map(request.args.get, [ 'time', 'submission' ])
if t:
try:
t = int(t) / 1000
except:
return request.error_formatter(0, 'Invalid time value')
else:
t = int(time.time())
lfm = LastFm(request.user, app.logger)
if submission in (None, '', True, 'true', 'True', 1, '1'):
lfm.scrobble(res, t)
else:
lfm.now_playing(res)
return request.formatter({})

20
db.py
View File

@ -151,10 +151,12 @@ class Folder(Base):
if self.has_cover_art: if self.has_cover_art:
info['coverArt'] = str(self.id) info['coverArt'] = str(self.id)
if config.getbool('features', 'star', True):
starred = StarredFolder.query.get((user.id, self.id)) starred = StarredFolder.query.get((user.id, self.id))
if starred: if starred:
info['starred'] = starred.date.isoformat() info['starred'] = starred.date.isoformat()
if config.getbool('features', 'rating', True):
rating = RatingFolder.query.get((user.id, self.id)) rating = RatingFolder.query.get((user.id, self.id))
if rating: if rating:
info['userRating'] = rating.rating info['userRating'] = rating.rating
@ -179,6 +181,7 @@ class Artist(Base):
'albumCount': len(self.albums) 'albumCount': len(self.albums)
} }
if config.getbool('features', 'star', True):
starred = StarredArtist.query.get((user.id, self.id)) starred = StarredArtist.query.get((user.id, self.id))
if starred: if starred:
info['starred'] = starred.date.isoformat() info['starred'] = starred.date.isoformat()
@ -206,6 +209,7 @@ class Album(Base):
if self.tracks[0].folder.has_cover_art: if self.tracks[0].folder.has_cover_art:
info['coverArt'] = str(self.tracks[0].folder_id) info['coverArt'] = str(self.tracks[0].folder_id)
if config.getbool('features', 'star', True):
starred = StarredAlbum.query.get((user.id, self.id)) starred = StarredAlbum.query.get((user.id, self.id))
if starred: if starred:
info['starred'] = starred.date.isoformat() info['starred'] = starred.date.isoformat()
@ -272,10 +276,12 @@ class Track(Base):
if self.folder.has_cover_art: if self.folder.has_cover_art:
info['coverArt'] = str(self.folder_id) info['coverArt'] = str(self.folder_id)
if config.getbool('features', 'star', True):
starred = StarredTrack.query.get((user.id, self.id)) starred = StarredTrack.query.get((user.id, self.id))
if starred: if starred:
info['starred'] = starred.date.isoformat() info['starred'] = starred.date.isoformat()
if config.getbool('features', 'rating', True):
rating = RatingTrack.query.get((user.id, self.id)) rating = RatingTrack.query.get((user.id, self.id))
if rating: if rating:
info['userRating'] = rating.rating info['userRating'] = rating.rating
@ -300,7 +306,8 @@ 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): if config.getbool('features', 'star', True):
class StarredFolder(Base):
__tablename__ = 'starred_folder' __tablename__ = 'starred_folder'
user_id = Column(UUID, ForeignKey('user.id'), primary_key = True) user_id = Column(UUID, ForeignKey('user.id'), primary_key = True)
@ -310,7 +317,7 @@ class StarredFolder(Base):
user = relationship('User') user = relationship('User')
starred = relationship('Folder') starred = relationship('Folder')
class StarredArtist(Base): class StarredArtist(Base):
__tablename__ = 'starred_artist' __tablename__ = 'starred_artist'
user_id = Column(UUID, ForeignKey('user.id'), primary_key = True) user_id = Column(UUID, ForeignKey('user.id'), primary_key = True)
@ -320,7 +327,7 @@ class StarredArtist(Base):
user = relationship('User') user = relationship('User')
starred = relationship('Artist') starred = relationship('Artist')
class StarredAlbum(Base): class StarredAlbum(Base):
__tablename__ = 'starred_album' __tablename__ = 'starred_album'
user_id = Column(UUID, ForeignKey('user.id'), primary_key = True) user_id = Column(UUID, ForeignKey('user.id'), primary_key = True)
@ -330,7 +337,7 @@ class StarredAlbum(Base):
user = relationship('User') user = relationship('User')
starred = relationship('Album') starred = relationship('Album')
class StarredTrack(Base): class StarredTrack(Base):
__tablename__ = 'starred_track' __tablename__ = 'starred_track'
user_id = Column(UUID, ForeignKey('user.id'), primary_key = True) user_id = Column(UUID, ForeignKey('user.id'), primary_key = True)
@ -340,7 +347,8 @@ class StarredTrack(Base):
user = relationship('User') user = relationship('User')
starred = relationship('Track') starred = relationship('Track')
class RatingFolder(Base): if config.getbool('features', 'rating', True):
class RatingFolder(Base):
__tablename__ = 'rating_folder' __tablename__ = 'rating_folder'
user_id = Column(UUID, ForeignKey('user.id'), primary_key = True) user_id = Column(UUID, ForeignKey('user.id'), primary_key = True)
@ -350,7 +358,7 @@ class RatingFolder(Base):
user = relationship('User') user = relationship('User')
rated = relationship('Folder') rated = relationship('Folder')
class RatingTrack(Base): class RatingTrack(Base):
__tablename__ = 'rating_track' __tablename__ = 'rating_track'
user_id = Column(UUID, ForeignKey('user.id'), primary_key = True) user_id = Column(UUID, ForeignKey('user.id'), primary_key = True)