diff --git a/api/funkwhale_api/subsonic/serializers.py b/api/funkwhale_api/subsonic/serializers.py index a340a1aad835a81ff12515870a41edfcd439a80a..5308146e14f6ffa1cc416242285e5fcf9261f14d 100644 --- a/api/funkwhale_api/subsonic/serializers.py +++ b/api/funkwhale_api/subsonic/serializers.py @@ -130,6 +130,14 @@ class GetAlbumSerializer(serializers.Serializer): return payload +class GetSongSerializer(serializers.Serializer): + def to_representation(self, track): + tf = track.files.all() + if not len(tf): + return {} + return get_track_data(track.album, track, tf[0]) + + def get_starred_tracks_data(favorites): by_track_id = {f.track_id: f for f in favorites} tracks = ( diff --git a/api/funkwhale_api/subsonic/views.py b/api/funkwhale_api/subsonic/views.py index de7284cd62cd502edf5d0aacb7abf785a23e7479..b2469a8cade7aad9c27d3aa6e5aed649704477ee 100644 --- a/api/funkwhale_api/subsonic/views.py +++ b/api/funkwhale_api/subsonic/views.py @@ -147,6 +147,15 @@ class SubsonicViewSet(viewsets.GenericViewSet): return response.Response(payload, status=200) + @list_route(methods=["get", "post"], url_name="get_song", url_path="getSong") + @find_object(music_models.Track.objects.all()) + def get_song(self, request, *args, **kwargs): + track = kwargs.pop("obj") + data = serializers.GetSongSerializer(track).data + payload = {"song": data} + + return response.Response(payload, status=200) + @list_route( methods=["get", "post"], url_name="get_artist_info2", url_path="getArtistInfo2" ) diff --git a/api/tests/subsonic/test_views.py b/api/tests/subsonic/test_views.py index d9b50d3eb25ac574364eeaaa37e57e8c22685691..1c7c528ccb8f00afbbe15719b1c06dc9bfde22ac 100644 --- a/api/tests/subsonic/test_views.py +++ b/api/tests/subsonic/test_views.py @@ -140,6 +140,20 @@ def test_get_album(f, db, logged_in_api_client, factories): assert response.data == expected +@pytest.mark.parametrize("f", ["xml", "json"]) +def test_get_song(f, db, logged_in_api_client, factories): + url = reverse("api:subsonic-get-song") + assert url.endswith("getSong") is True + artist = factories["music.Artist"]() + album = factories["music.Album"](artist=artist) + track = factories["music.Track"](album=album) + tf = factories["music.TrackFile"](track=track) + response = logged_in_api_client.get(url, {"f": f, "id": track.pk}) + + assert response.status_code == 200 + assert response.data == {"song": serializers.get_track_data(track.album, track, tf)} + + @pytest.mark.parametrize("f", ["xml", "json"]) def test_stream(f, db, logged_in_api_client, factories, mocker): url = reverse("api:subsonic-stream")