diff --git a/api/funkwhale_api/subsonic/views.py b/api/funkwhale_api/subsonic/views.py index 8c4f26ddea938e47e91bc778bfd4bdc1a1208e81..37a06f0c7ddd689b7b524fc8624670ca680ec56c 100644 --- a/api/funkwhale_api/subsonic/views.py +++ b/api/funkwhale_api/subsonic/views.py @@ -219,6 +219,27 @@ class SubsonicViewSet(viewsets.GenericViewSet): data = {"starred2": {"song": serializers.get_starred_tracks_data(favorites)}} return response.Response(data) + @list_route( + methods=["get", "post"], url_name="get_random_songs", url_path="getRandomSongs" + ) + def get_random_songs(self, request, *args, **kwargs): + data = request.GET or request.POST + actor = utils.get_actor_from_request(request) + queryset = music_models.Track.objects.all() + queryset = queryset.playable_by(actor) + try: + size = int(data["size"]) + except (TypeError, KeyError, ValueError): + size = 50 + + queryset = queryset.playable_by(actor).prefetch_related('uploads').order_by("?")[:size] + data = { + "randomSongs": { + "song": serializers.GetSongSerializer(queryset, many=True).data + } + } + return response.Response(data) + @list_route(methods=["get", "post"], url_name="get_starred", url_path="getStarred") def get_starred(self, request, *args, **kwargs): favorites = request.user.track_favorites.all() diff --git a/api/tests/subsonic/test_views.py b/api/tests/subsonic/test_views.py index 9161888e2e397e6f02c608bfeb4c1f56578afcdb..9e71fca94f8f7984dd29e8126a47568ab4670bef 100644 --- a/api/tests/subsonic/test_views.py +++ b/api/tests/subsonic/test_views.py @@ -245,6 +245,27 @@ def test_get_starred2(f, db, logged_in_api_client, factories): } +@pytest.mark.parametrize("f", ["json"]) +def test_get_random_songs(f, db, logged_in_api_client, factories, mocker): + url = reverse("api:subsonic-get-random-songs") + assert url.endswith("getRandomSongs") is True + track1 = factories["music.Track"]() + track2 = factories["music.Track"]() + factories["music.Track"]() + + order_by = mocker.patch.object( + music_models.TrackQuerySet, 'order_by', return_value=[track1, track2] + ) + response = logged_in_api_client.get(url, {"f": f, "size": 2}) + + assert response.status_code == 200 + assert response.data == { + "randomSongs": {"song": serializers.GetSongSerializer([track1, track2], many=True).data} + } + + order_by.assert_called_once_with("?") + + @pytest.mark.parametrize("f", ["xml", "json"]) def test_get_starred(f, db, logged_in_api_client, factories): url = reverse("api:subsonic-get-starred")