fix:support positions

This commit is contained in:
Petitminion 2025-06-11 15:45:03 +02:00
parent 154e2f635d
commit cc1767c9ad
1 changed files with 31 additions and 10 deletions

View File

@ -5,6 +5,8 @@ from rest_framework import serializers
from funkwhale_api import musicbrainz from funkwhale_api import musicbrainz
from funkwhale_api.tags import models as tags_models from funkwhale_api.tags import models as tags_models
from . import client
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -48,7 +50,7 @@ class ArtistCreditSerializer(serializers.Serializer):
return artist_credit return artist_credit
class ReleaseForTrackSerializer(serializers.Serializer): class ReleaseForRecordingSerializer(serializers.Serializer):
""" """
Serializer for Musicbrainz release data when returned in a recording object. Serializer for Musicbrainz release data when returned in a recording object.
""" """
@ -74,10 +76,6 @@ class ReleaseForTrackSerializer(serializers.Serializer):
album.artist_credit.set(artist_credit) album.artist_credit.set(artist_credit)
album.save() album.save()
tags_models.add_tags(album, *validated_data.get("tags", [])) tags_models.add_tags(album, *validated_data.get("tags", []))
if validated_data["media"]:
# an album can have various media/physical representation, we take the first one
validated_data["media"][0]
return album return album
def update(self, instance, validated_data): def update(self, instance, validated_data):
@ -97,8 +95,9 @@ class RecordingSerializer(serializers.Serializer):
id = serializers.CharField() id = serializers.CharField()
title = serializers.CharField() title = serializers.CharField()
artist_credit = ArtistCreditSerializer(many=True) artist_credit = ArtistCreditSerializer(many=True)
releases = ReleaseForTrackSerializer(many=True, required=False) releases = ReleaseForRecordingSerializer(many=True, required=False)
tags = serializers.ListField(child=serializers.CharField(), allow_empty=True) tags = serializers.ListField(child=serializers.CharField(), allow_empty=True)
position = serializers.IntegerField(required=False, allow_null=True)
def create(self, validated_data): def create(self, validated_data):
from funkwhale_api.music.models import Track from funkwhale_api.music.models import Track
@ -109,13 +108,26 @@ class RecordingSerializer(serializers.Serializer):
"mbid": validated_data["id"], "mbid": validated_data["id"],
# In mb a recording can have various releases, we take the fist one # In mb a recording can have various releases, we take the fist one
"album": ( "album": (
ReleaseForTrackSerializer(many=True).create(validated_data["releases"])[ ReleaseForRecordingSerializer(many=True).create(
0 validated_data["releases"]
] )[0]
if validated_data.get("releases") if validated_data.get("releases")
else None else None
), ),
# this will be none if the recording is not fetched from the release endpoint
"position": validated_data.get("position", None),
} }
if defaults["album"] is not None and defaults["position"] is None:
result = client.api.releases.get(
id=validated_data["releases"][0]["id"],
includes=["tags", "artists", "recordings"],
)
tracks = result["media"][0]["tracks"]
defaults["position"] = next(
(o for o in tracks if o["recording"]["id"] == data["mbid"]), {}
).get("position", None)
track, created = Track.objects.get_or_create(**data, defaults=defaults) track, created = Track.objects.get_or_create(**data, defaults=defaults)
artist_credit = ArtistCreditSerializer(many=True).create( artist_credit = ArtistCreditSerializer(many=True).create(
validated_data["artist_credit"] validated_data["artist_credit"]
@ -138,6 +150,8 @@ class RecordingSerializer(serializers.Serializer):
class RecordingForReleaseSerializer(serializers.Serializer): class RecordingForReleaseSerializer(serializers.Serializer):
id = serializers.CharField() id = serializers.CharField()
title = serializers.CharField() title = serializers.CharField()
# not in Musicbrainz recording object, but used to store the position of the track in the album
position = serializers.IntegerField(required=False, allow_null=True)
def create(self, validated_data): def create(self, validated_data):
def replace_hyphens_in_keys(obj): def replace_hyphens_in_keys(obj):
@ -155,6 +169,7 @@ class RecordingForReleaseSerializer(serializers.Serializer):
id=validated_data["id"], includes=["tags", "artists"] id=validated_data["id"], includes=["tags", "artists"]
) )
recordings_data = replace_hyphens_in_keys(recordings_data) recordings_data = replace_hyphens_in_keys(recordings_data)
recordings_data["position"] = validated_data.get("position", None)
serializer = RecordingSerializer(data=recordings_data) serializer = RecordingSerializer(data=recordings_data)
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
track = serializer.save() track = serializer.save()
@ -172,6 +187,7 @@ class RecordingForReleaseSerializer(serializers.Serializer):
class TrackSerializer(serializers.Serializer): class TrackSerializer(serializers.Serializer):
recording = RecordingForReleaseSerializer() recording = RecordingForReleaseSerializer()
position = serializers.IntegerField()
class MediaSerializer(serializers.Serializer): class MediaSerializer(serializers.Serializer):
@ -207,7 +223,12 @@ class ReleaseSerializer(serializers.Serializer):
tags_models.add_tags(album, *validated_data.get("tags", [])) tags_models.add_tags(album, *validated_data.get("tags", []))
# an album can have various media/physical representation, we take the first one # an album can have various media/physical representation, we take the first one
recordings = [t["recording"] for t in validated_data["media"][0]["tracks"]] tracks = [t for t in validated_data["media"][0]["tracks"]]
recordings = []
for t in tracks:
t["recording"]["position"] = t["position"]
recordings.append(t["recording"])
for r in recordings: for r in recordings:
r["album"] = album r["album"] = album
RecordingForReleaseSerializer().create(r) RecordingForReleaseSerializer().create(r)