From b1e8d4cabdc1c604f37aa4e6bc8e2004d2126a8e Mon Sep 17 00:00:00 2001 From: Eliot Berriot <contact@eliotberriot.com> Date: Tue, 15 Oct 2019 11:38:21 +0200 Subject: [PATCH] Fix #936: Support byYear filtering in Subsonic API (#936) --- api/funkwhale_api/subsonic/views.py | 30 +++++++++++++++++++++++++++++ api/tests/subsonic/test_views.py | 29 ++++++++++++++++++++++++++++ changes/changelog.d/936.enhancement | 1 + 3 files changed, 60 insertions(+) create mode 100644 changes/changelog.d/936.enhancement diff --git a/api/funkwhale_api/subsonic/views.py b/api/funkwhale_api/subsonic/views.py index 6633224df..60209a92d 100644 --- a/api/funkwhale_api/subsonic/views.py +++ b/api/funkwhale_api/subsonic/views.py @@ -1,3 +1,6 @@ +""" +Documentation of Subsonic API can be found at http://www.subsonic.org/pages/api.jsp +""" import datetime import functools @@ -427,7 +430,34 @@ class SubsonicViewSet(viewsets.GenericViewSet): Q(tagged_items__tag__name=genre) | Q(artist__tagged_items__tag__name=genre) ) + elif type == "byYear": + try: + boundaries = [ + int(data.get("fromYear", 0)), + int(data.get("toYear", 99999999)), + ] + except (TypeError, ValueError): + return response.Response( + { + "error": { + "code": 10, + "message": "Invalid fromYear or toYear parameter", + } + } + ) + # because, yeah, the specification explicitly state that fromYear can be greater + # than toYear, to indicate reverse ordering… + # http://www.subsonic.org/pages/api.jsp#getAlbumList2 + from_year = min(boundaries) + to_year = max(boundaries) + queryset = queryset.filter( + release_date__year__gte=from_year, release_date__year__lte=to_year + ) + if boundaries[0] <= boundaries[1]: + queryset = queryset.order_by("release_date") + else: + queryset = queryset.order_by("-release_date") try: offset = int(data["offset"]) except (TypeError, KeyError, ValueError): diff --git a/api/tests/subsonic/test_views.py b/api/tests/subsonic/test_views.py index 298ad34f7..d58cc3932 100644 --- a/api/tests/subsonic/test_views.py +++ b/api/tests/subsonic/test_views.py @@ -469,6 +469,35 @@ def test_get_album_list2_by_genre(f, db, logged_in_api_client, factories): } +@pytest.mark.parametrize( + "params, expected", + [ + ({"type": "byYear", "fromYear": 1902, "toYear": 1903}, [2, 3]), + # Because why not, it's supported in Subsonic API… + # http://www.subsonic.org/pages/api.jsp#getAlbumList2 + ({"type": "byYear", "fromYear": 1903, "toYear": 1902}, [3, 2]), + ], +) +def test_get_album_list2_by_year(params, expected, db, logged_in_api_client, factories): + albums = [ + factories["music.Album"]( + playable=True, release_date=datetime.date(1900 + i, 1, 1) + ) + for i in range(5) + ] + url = reverse("api:subsonic-get_album_list2") + base_params = {"f": "json"} + base_params.update(params) + response = logged_in_api_client.get(url, base_params) + + assert response.status_code == 200 + assert response.data == { + "albumList2": { + "album": serializers.get_album_list2_data([albums[i] for i in expected]) + } + } + + @pytest.mark.parametrize("f", ["json"]) @pytest.mark.parametrize( "tags_field", diff --git a/changes/changelog.d/936.enhancement b/changes/changelog.d/936.enhancement new file mode 100644 index 000000000..2c16ffe54 --- /dev/null +++ b/changes/changelog.d/936.enhancement @@ -0,0 +1 @@ +Support byYear filtering in Subsonic API (#936) -- GitLab