Add OpenSubsonic support

Fixes #2270

Part-of: <https://dev.funkwhale.audio/funkwhale/funkwhale/-/merge_requests/2695>
environments/review-docs-renov-r6aeyi/deployments/19166
Philipp Wolfer 2023-12-30 17:34:59 +01:00 zatwierdzone przez Marge
rodzic c1d91ce4d6
commit 81401075aa
6 zmienionych plików z 37 dodań i 4 usunięć

Wyświetl plik

@ -32,9 +32,11 @@ ET._serialize_xml = ET._serialize["xml"] = _serialize_xml
def structure_payload(data):
payload = {
"funkwhaleVersion": funkwhale_api.__version__,
"serverVersion": funkwhale_api.__version__,
"status": "ok",
"type": "funkwhale",
"version": "1.16.0",
"openSubsonic": "true",
}
payload.update(data)
if "detail" in payload:

Wyświetl plik

@ -126,6 +126,7 @@ def get_track_data(album, track, upload):
"albumId": album.pk if album else "",
"artistId": album.artist.pk if album else track.artist.pk,
"type": "music",
"musicBrainzId": str(track.mbid or ""),
}
if album and album.attachment_cover_id:
data["coverArt"] = f"al-{album.id}"
@ -149,13 +150,16 @@ def get_album2_data(album):
"created": to_subsonic_date(album.creation_date),
"duration": album.duration,
"playCount": album.tracks.aggregate(l=Count("listenings"))["l"] or 0,
"musicBrainzId": str(album.mbid or ""),
}
if album.attachment_cover_id:
payload["coverArt"] = f"al-{album.id}"
if album.tagged_items:
genres = [{"name": i.tag.name} for i in album.tagged_items.all()]
# exposes only first genre since the specification uses singular noun
first_genre = album.tagged_items.first()
payload["genre"] = first_genre.tag.name if first_genre else ""
payload["genre"] = genres[0]["name"] if len(genres) > 0 else ""
# OpenSubsonic full genre list
payload["genres"] = genres
if album.release_date:
payload["year"] = album.release_date.year
try:

Wyświetl plik

@ -180,6 +180,20 @@ class SubsonicViewSet(viewsets.GenericViewSet):
}
return response.Response(data, status=200)
@action(
detail=False,
methods=["get", "post"],
url_name="get_open_subsonic_extensions",
permission_classes=[],
url_path="getOpenSubsonicExtensions",
)
def get_open_subsonic_extensions(self, request, *args, **kwargs):
data = {
# No specific extensions are currently supported
"openSubsonicExtensions": [""],
}
return response.Response(data, status=200)
@action(
detail=False,
methods=["get", "post"],

Wyświetl plik

@ -17,6 +17,8 @@ from funkwhale_api.subsonic import renderers
"version": "1.16.0",
"type": "funkwhale",
"funkwhaleVersion": funkwhale_api.__version__,
"serverVersion": funkwhale_api.__version__,
"openSubsonic": "true",
"hello": "world",
},
),
@ -30,6 +32,8 @@ from funkwhale_api.subsonic import renderers
"version": "1.16.0",
"type": "funkwhale",
"funkwhaleVersion": funkwhale_api.__version__,
"serverVersion": funkwhale_api.__version__,
"openSubsonic": "true",
"hello": "world",
"error": {"code": 10, "message": "something went wrong"},
},
@ -41,6 +45,8 @@ from funkwhale_api.subsonic import renderers
"version": "1.16.0",
"type": "funkwhale",
"funkwhaleVersion": funkwhale_api.__version__,
"serverVersion": funkwhale_api.__version__,
"openSubsonic": "true",
"hello": "world",
"error": {"code": 0, "message": "something went wrong"},
},
@ -59,6 +65,8 @@ def test_json_renderer():
"version": "1.16.0",
"type": "funkwhale",
"funkwhaleVersion": funkwhale_api.__version__,
"serverVersion": funkwhale_api.__version__,
"openSubsonic": "true",
"hello": "world",
}
}
@ -81,8 +89,9 @@ def test_xml_renderer_dict_to_xml():
def test_xml_renderer():
payload = {"hello": "world"}
expected = '<?xml version="1.0" encoding="UTF-8"?>\n<subsonic-response funkwhaleVersion="{}" hello="world" status="ok" type="funkwhale" version="1.16.0" xmlns="http://subsonic.org/restapi" />' # noqa
expected = expected.format(funkwhale_api.__version__).encode()
expected = '<?xml version="1.0" encoding="UTF-8"?>\n<subsonic-response funkwhaleVersion="{}" hello="world" openSubsonic="true" serverVersion="{}" status="ok" type="funkwhale" version="1.16.0" xmlns="http://subsonic.org/restapi" />' # noqa
version = funkwhale_api.__version__
expected = expected.format(version, version).encode()
renderer = renderers.SubsonicXMLRenderer()
rendered = renderer.render(payload)

Wyświetl plik

@ -184,6 +184,8 @@ def test_get_album_serializer(factories):
"year": album.release_date.year,
"coverArt": f"al-{album.id}",
"genre": tagged_item.tag.name,
"genres": [{"name": tagged_item.tag.name}],
"musicBrainzId": album.mbid,
"duration": 43,
"playCount": album.tracks.aggregate(l=Count("listenings"))["l"] or 0,
"song": [
@ -207,6 +209,7 @@ def test_get_album_serializer(factories):
"albumId": album.pk,
"artistId": artist.pk,
"type": "music",
"musicBrainzId": track.mbid,
}
],
}

Wyświetl plik

@ -0,0 +1 @@
Extend Subsonic API with OpenSubsonic support (#2270)