From 7d9220ed49550acbcca171d69eafa027dc4d19a7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@toke.dk>
Date: Thu, 30 Aug 2018 14:04:41 +0200
Subject: [PATCH] subsonic: Implement getSong API endpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The getSong API endpoint is used by, e.g., the subsonic plugin to mopidy.

Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
---
 api/funkwhale_api/subsonic/serializers.py |  8 ++++++++
 api/funkwhale_api/subsonic/views.py       |  9 +++++++++
 api/tests/subsonic/test_views.py          | 14 ++++++++++++++
 3 files changed, 31 insertions(+)

diff --git a/api/funkwhale_api/subsonic/serializers.py b/api/funkwhale_api/subsonic/serializers.py
index a340a1aad8..5308146e14 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 de7284cd62..b2469a8cad 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 d9b50d3eb2..1c7c528ccb 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")
-- 
GitLab