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

Porting supysonic.api.playlists

This commit is contained in:
Alban Féron 2022-12-23 18:57:14 +01:00
parent 50b98e641a
commit 6179daf4ce
No known key found for this signature in database
GPG Key ID: 8CE0313646D16165
2 changed files with 72 additions and 69 deletions

View File

@ -9,30 +9,29 @@ import uuid
from flask import request from flask import request
from ..db import Playlist, User, Track from ..db import Playlist, User, Track, db
from . import get_entity, api_routing from . import get_entity, api_routing
from .exceptions import Forbidden, MissingParameter, NotFound from .exceptions import Forbidden, MissingParameter
@api_routing("/getPlaylists") @api_routing("/getPlaylists")
def list_playlists(): def list_playlists():
query = Playlist.select( query = (
lambda p: p.user.id == request.user.id or p.public Playlist.select()
).order_by(Playlist.name) .orwhere(Playlist.user == request.user, Playlist.public)
.order_by(Playlist.name)
)
username = request.values.get("username") username = request.values.get("username")
if username: if username:
if not request.user.admin: if not request.user.admin:
raise Forbidden() raise Forbidden()
# get rather than join in the following query to raise an exception if the
# requested user doesn't exist
user = User.get(name=username) user = User.get(name=username)
if user is None: query = Playlist.select().where(Playlist.user == user).order_by(Playlist.name)
raise NotFound("User")
query = Playlist.select(lambda p: p.user.name == username).order_by(
Playlist.name
)
return request.formatter( return request.formatter(
"playlists", "playlists",
@ -43,7 +42,7 @@ def list_playlists():
@api_routing("/getPlaylist") @api_routing("/getPlaylist")
def show_playlist(): def show_playlist():
res = get_entity(Playlist) res = get_entity(Playlist)
if res.user.id != request.user.id and not res.public and not request.user.admin: if res.user != request.user and not res.public and not request.user.admin:
raise Forbidden() raise Forbidden()
info = res.as_subsonic_playlist(request.user) info = res.as_subsonic_playlist(request.user)
@ -54,6 +53,7 @@ def show_playlist():
@api_routing("/createPlaylist") @api_routing("/createPlaylist")
@db.atomic()
def create_playlist(): def create_playlist():
playlist_id, name = map(request.values.get, ("playlistId", "name")) playlist_id, name = map(request.values.get, ("playlistId", "name"))
# songId actually doesn't seem to be required # songId actually doesn't seem to be required
@ -63,14 +63,14 @@ def create_playlist():
if playlist_id: if playlist_id:
playlist = Playlist[playlist_id] playlist = Playlist[playlist_id]
if playlist.user.id != request.user.id and not request.user.admin: if playlist.user != request.user and not request.user.admin:
raise Forbidden() raise Forbidden()
playlist.clear() playlist.clear()
if name: if name:
playlist.name = name playlist.name = name
elif name: elif name:
playlist = Playlist(user=request.user, name=name) playlist = Playlist.create(user=request.user, name=name)
else: else:
raise MissingParameter("playlistId or name") raise MissingParameter("playlistId or name")
@ -78,6 +78,7 @@ def create_playlist():
sid = uuid.UUID(sid) sid = uuid.UUID(sid)
track = Track[sid] track = Track[sid]
playlist.add(track) playlist.add(track)
playlist.save()
return request.formatter.empty return request.formatter.empty
@ -85,17 +86,17 @@ def create_playlist():
@api_routing("/deletePlaylist") @api_routing("/deletePlaylist")
def delete_playlist(): def delete_playlist():
res = get_entity(Playlist) res = get_entity(Playlist)
if res.user.id != request.user.id and not request.user.admin: if res.user != request.user and not request.user.admin:
raise Forbidden() raise Forbidden()
res.delete() res.delete_instance()
return request.formatter.empty return request.formatter.empty
@api_routing("/updatePlaylist") @api_routing("/updatePlaylist")
def update_playlist(): def update_playlist():
res = get_entity(Playlist, "playlistId") res = get_entity(Playlist, "playlistId")
if res.user.id != request.user.id and not request.user.admin: if res.user != request.user and not request.user.admin:
raise Forbidden() raise Forbidden()
playlist = res playlist = res
@ -119,5 +120,6 @@ def update_playlist():
playlist.add(track) playlist.add(track)
playlist.remove_at_indexes(to_remove) playlist.remove_at_indexes(to_remove)
playlist.save()
return request.formatter.empty return request.formatter.empty

View File

@ -1,15 +1,13 @@
# This file is part of Supysonic. # This file is part of Supysonic.
# Supysonic is a Python implementation of the Subsonic server API. # Supysonic is a Python implementation of the Subsonic server API.
# #
# Copyright (C) 2017-2018 Alban 'spl0k' Féron # Copyright (C) 2017-2022 Alban 'spl0k' Féron
# #
# Distributed under terms of the GNU AGPLv3 license. # Distributed under terms of the GNU AGPLv3 license.
import unittest import unittest
import uuid import uuid
from pony.orm import db_session
from supysonic.db import Folder, Artist, Album, Track, Playlist, User from supysonic.db import Folder, Artist, Album, Track, Playlist, User
from .apitestbase import ApiTestBase from .apitestbase import ApiTestBase
@ -19,41 +17,45 @@ class PlaylistTestCase(ApiTestBase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
with db_session: root = Folder.create(root=True, name="Root folder", path="tests/assets")
root = Folder(root=True, name="Root folder", path="tests/assets") artist = Artist.create(name="Artist")
artist = Artist(name="Artist") album = Album.create(name="Album", artist=artist)
album = Album(name="Album", artist=artist)
songs = {} songs = {}
for num, song in enumerate(["One", "Two", "Three", "Four"]): for num, song in enumerate(["One", "Two", "Three", "Four"]):
track = Track( track = Track.create(
disc=1, disc=1,
number=num, number=num,
title=song, title=song,
duration=2, duration=2,
album=album, album=album,
artist=artist, artist=artist,
bitrate=320, bitrate=320,
path="tests/assets/" + song, path="tests/assets/" + song,
last_modification=0, last_modification=0,
root_folder=root, root_folder=root,
folder=root, folder=root,
) )
songs[song] = track songs[song] = track
users = {u.name: u for u in User.select()} users = {u.name: u for u in User.select()}
playlist = Playlist(user=users["alice"], name="Alice's") playlist = Playlist.create(user=users["alice"], name="Alice's")
playlist.add(songs["One"]) playlist.add(songs["One"])
playlist.add(songs["Three"]) playlist.add(songs["Three"])
playlist.save()
playlist = Playlist(user=users["alice"], public=True, name="Alice's public") playlist = Playlist.create(
playlist.add(songs["One"]) user=users["alice"], public=True, name="Alice's public"
playlist.add(songs["Two"]) )
playlist.add(songs["One"])
playlist.add(songs["Two"])
playlist.save()
playlist = Playlist(user=users["bob"], name="Bob's") playlist = Playlist.create(user=users["bob"], name="Bob's")
playlist.add(songs["Two"]) playlist.add(songs["Two"])
playlist.add(songs["Four"]) playlist.add(songs["Four"])
playlist.save()
def test_get_playlists(self): def test_get_playlists(self):
# get own playlists # get own playlists
@ -99,8 +101,12 @@ class PlaylistTestCase(ApiTestBase):
self._make_request("getPlaylist", {"id": str(uuid.uuid4())}, error=70) self._make_request("getPlaylist", {"id": str(uuid.uuid4())}, error=70)
# other's private from non admin # other's private from non admin
with db_session: playlist = (
playlist = Playlist.get(lambda p: not p.public and p.user.name == "alice") Playlist.select()
.join(User)
.where(~Playlist.public, User.name == "alice")
.get()
)
self._make_request( self._make_request(
"getPlaylist", {"u": "bob", "p": "B0b", "id": str(playlist.id)}, error=50 "getPlaylist", {"u": "bob", "p": "B0b", "id": str(playlist.id)}, error=50
) )
@ -166,8 +172,7 @@ class PlaylistTestCase(ApiTestBase):
) )
# create more useful playlist # create more useful playlist
with db_session: songs = {s.title: str(s.id) for s in Track.select()}
songs = {s.title: str(s.id) for s in Track.select()}
self._make_request( self._make_request(
"createPlaylist", "createPlaylist",
{ {
@ -176,8 +181,7 @@ class PlaylistTestCase(ApiTestBase):
}, },
skip_post=True, skip_post=True,
) )
with db_session: playlist = Playlist.get(name="songs")
playlist = Playlist.get(name="songs")
self.assertIsNotNone(playlist) self.assertIsNotNone(playlist)
rv, child = self._make_request( rv, child = self._make_request(
"getPlaylist", {"id": str(playlist.id)}, tag="playlist" "getPlaylist", {"id": str(playlist.id)}, tag="playlist"
@ -201,7 +205,6 @@ class PlaylistTestCase(ApiTestBase):
self.assertEqual(self._xpath(child, "count(./entry)"), 1) self.assertEqual(self._xpath(child, "count(./entry)"), 1)
self.assertEqual(child[0].get("title"), "Two") self.assertEqual(child[0].get("title"), "Two")
@db_session
def assertPlaylistCountEqual(self, count): def assertPlaylistCountEqual(self, count):
self.assertEqual(Playlist.select().count(), count) self.assertEqual(Playlist.select().count(), count)
@ -212,8 +215,7 @@ class PlaylistTestCase(ApiTestBase):
self._make_request("deletePlaylist", {"id": str(uuid.uuid4())}, error=70) self._make_request("deletePlaylist", {"id": str(uuid.uuid4())}, error=70)
# delete unowned when not admin # delete unowned when not admin
with db_session: playlist = Playlist.select().join(User).where(User.name == "alice").first()
playlist = Playlist.select(lambda p: p.user.name == "alice").first()
self._make_request( self._make_request(
"deletePlaylist", {"u": "bob", "p": "B0b", "id": str(playlist.id)}, error=50 "deletePlaylist", {"u": "bob", "p": "B0b", "id": str(playlist.id)}, error=50
) )
@ -226,8 +228,7 @@ class PlaylistTestCase(ApiTestBase):
self.assertPlaylistCountEqual(2) self.assertPlaylistCountEqual(2)
# delete unowned when admin # delete unowned when admin
with db_session: playlist = Playlist.select().join(User).where(User.name == "bob").get()
playlist = Playlist.get(lambda p: p.user.name == "bob")
self._make_request("deletePlaylist", {"id": str(playlist.id)}, skip_post=True) self._make_request("deletePlaylist", {"id": str(playlist.id)}, skip_post=True)
self.assertPlaylistCountEqual(1) self.assertPlaylistCountEqual(1)
@ -238,12 +239,13 @@ class PlaylistTestCase(ApiTestBase):
"updatePlaylist", {"playlistId": str(uuid.uuid4())}, error=70 "updatePlaylist", {"playlistId": str(uuid.uuid4())}, error=70
) )
with db_session: playlist = (
playlist = ( Playlist.select()
Playlist.select(lambda p: p.user.name == "alice") .join(User)
.order_by(Playlist.created) .where(User.name == "alice")
.first() .order_by(Playlist.created)
) .first()
)
pid = str(playlist.id) pid = str(playlist.id)
self._make_request( self._make_request(
"updatePlaylist", {"playlistId": pid, "songIdToAdd": "string"}, error=0 "updatePlaylist", {"playlistId": pid, "songIdToAdd": "string"}, error=0
@ -288,8 +290,7 @@ class PlaylistTestCase(ApiTestBase):
self.assertEqual(self._xpath(child, "count(./entry)"), 1) self.assertEqual(self._xpath(child, "count(./entry)"), 1)
self.assertEqual(self._find(child, "./entry").get("title"), "Three") self.assertEqual(self._find(child, "./entry").get("title"), "Three")
with db_session: songs = {s.title: str(s.id) for s in Track.select()}
songs = {s.title: str(s.id) for s in Track.select()}
self._make_request( self._make_request(
"updatePlaylist", "updatePlaylist",