1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-09-20 03:11:04 +00:00
supysonic/api/playlists.py

147 lines
4.8 KiB
Python
Raw Normal View History

2013-06-25 20:07:49 +00:00
# coding: utf-8
2014-03-02 17:31:32 +00:00
# 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/>.
2013-06-25 20:07:49 +00:00
from flask import request
2014-04-09 18:41:07 +00:00
from storm.expr import Or
2013-06-25 20:07:49 +00:00
import uuid
2014-04-09 18:41:07 +00:00
from web import app, store
from db import Playlist, User, Track
2013-06-25 20:07:49 +00:00
from . import get_entity
@app.route('/rest/getPlaylists.view', methods = [ 'GET', 'POST' ])
def list_playlists():
2014-04-09 18:41:07 +00:00
query = store.find(Playlist, Or(Playlist.user_id == request.user.id, Playlist.public == True)).order_by(Playlist.name)
2013-06-25 20:07:49 +00:00
username = request.args.get('username')
if username:
if not request.user.admin:
return request.error_formatter(50, 'Restricted to admins')
2014-04-09 18:41:07 +00:00
query = store.find(Playlist, Playlist.user_id == User.id, User.name == username).order_by(Playlist.name)
2013-06-25 20:07:49 +00:00
return request.formatter({ 'playlists': { 'playlist': [ p.as_subsonic_playlist(request.user) for p in query ] } })
2013-06-25 20:07:49 +00:00
@app.route('/rest/getPlaylist.view', methods = [ 'GET', 'POST' ])
def show_playlist():
status, res = get_entity(request, Playlist)
if not status:
return res
info = res.as_subsonic_playlist(request.user)
2013-06-25 20:07:49 +00:00
info['entry'] = [ t.as_subsonic_child(request.user) for t in res.tracks ]
return request.formatter({ 'playlist': info })
@app.route('/rest/createPlaylist.view', methods = [ 'GET', 'POST' ])
def create_playlist():
# Only(?) method where the android client uses form data rather than GET params
playlist_id, name = map(lambda x: request.args.get(x) or request.form.get(x), [ 'playlistId', 'name' ])
# songId actually doesn't seem to be required
songs = request.args.getlist('songId') or request.form.getlist('songId')
try:
2013-06-27 10:16:13 +00:00
playlist_id = uuid.UUID(playlist_id) if playlist_id else None
2013-06-25 20:07:49 +00:00
songs = set(map(uuid.UUID, songs))
except:
return request.error_formatter(0, 'Invalid parameter')
if playlist_id:
2014-04-09 18:41:07 +00:00
playlist = store.get(Playlist, playlist_id)
2013-06-25 20:07:49 +00:00
if not playlist:
return request.error_formatter(70, 'Unknwon playlist')
if playlist.user_id != request.user.id and not request.user.admin:
return request.error_formatter(50, "You're not allowed to modify a playlist that isn't yours")
2014-04-09 18:41:07 +00:00
playlist.tracks.clear()
2013-06-25 20:07:49 +00:00
if name:
playlist.name = name
elif name:
2014-04-09 18:41:07 +00:00
playlist = Playlist()
playlist.user_id = request.user.id
playlist.name = name
store.add(playlist)
2013-06-25 20:07:49 +00:00
else:
return request.error_formatter(10, 'Missing playlist id or name')
for sid in songs:
2014-04-09 18:41:07 +00:00
track = store.get(Track, sid)
2013-06-25 20:07:49 +00:00
if not track:
return request.error_formatter(70, 'Unknown song')
2014-04-09 18:41:07 +00:00
playlist.tracks.add(track)
2013-06-25 20:07:49 +00:00
2014-04-09 18:41:07 +00:00
store.commit()
2013-06-25 20:07:49 +00:00
return request.formatter({})
@app.route('/rest/deletePlaylist.view', methods = [ 'GET', 'POST' ])
def delete_playlist():
status, res = get_entity(request, Playlist)
if not status:
return res
if res.user_id != request.user.id and not request.user.admin:
return request.error_formatter(50, "You're not allowed to delete a playlist that isn't yours")
2014-04-09 18:41:07 +00:00
store.remove(res)
store.commit()
2013-06-25 20:07:49 +00:00
return request.formatter({})
@app.route('/rest/updatePlaylist.view', methods = [ 'GET', 'POST' ])
def update_playlist():
status, res = get_entity(request, Playlist, 'playlistId')
if not status:
return res
if res.user_id != request.user.id and not request.user.admin:
return request.error_formatter(50, "You're not allowed to delete a playlist that isn't yours")
playlist = res
name, comment, public = map(request.args.get, [ 'name', 'comment', 'public' ])
to_add, to_remove = map(request.args.getlist, [ 'songIdToAdd', 'songIndexToRemove' ])
try:
to_add = set(map(uuid.UUID, to_add))
to_remove = sorted(set(map(int, to_remove)))
except:
return request.error_formatter(0, 'Invalid parameter')
if name:
playlist.name = name
if comment:
playlist.comment = comment
if public:
playlist.public = public in (True, 'True', 'true', 1, '1')
2014-04-09 18:41:07 +00:00
tracks = list(playlist.tracks)
2013-06-25 20:07:49 +00:00
for sid in to_add:
2014-04-09 18:41:07 +00:00
track = store.get(Track, sid)
2013-06-25 20:07:49 +00:00
if not track:
return request.error_formatter(70, 'Unknown song')
if track not in playlist.tracks:
2014-04-09 18:41:07 +00:00
playlist.tracks.add(track)
2013-06-25 20:07:49 +00:00
for idx in to_remove:
2014-04-09 18:41:07 +00:00
if idx < 0 or idx >= len(tracks):
2013-06-25 20:07:49 +00:00
return request.error_formatter(0, 'Index out of range')
2014-04-09 18:41:07 +00:00
playlist.tracks.remove(tracks[idx])
2013-06-25 20:07:49 +00:00
2014-04-09 18:41:07 +00:00
store.commit()
2013-06-25 20:07:49 +00:00
return request.formatter({})