Add OpenSubsonic support
Fixes #2270 Part-of: <https://dev.funkwhale.audio/funkwhale/funkwhale/-/merge_requests/2695>
This commit is contained in:
parent
c1d91ce4d6
commit
81401075aa
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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"],
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
],
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Extend Subsonic API with OpenSubsonic support (#2270)
|
Loading…
Reference in New Issue