enhancement(backend):support mb release has fetch object
This commit is contained in:
parent
98a80c4a87
commit
07f37b458c
|
@ -414,6 +414,7 @@ class Fetch(models.Model):
|
|||
contexts.AS.Application: [serializers.ActorSerializer],
|
||||
# for mb the key must be the api namespace
|
||||
"recordings": [musicbrainz_serializers.RecordingSerializer],
|
||||
"releases": [musicbrainz_serializers.ReleaseSerializer],
|
||||
}
|
||||
|
||||
@property
|
||||
|
|
|
@ -484,10 +484,13 @@ def musicbrainz_metadata_handler(type_, id):
|
|||
else:
|
||||
return obj
|
||||
|
||||
if type_ == "recordings":
|
||||
includes = ["tags", "artists", "releases"]
|
||||
elif type_ == "releases":
|
||||
includes = ["tags", "artists", "recordings"]
|
||||
|
||||
result = replace_hyphens_in_keys(
|
||||
getattr(musicbrainz.api, type_).get(
|
||||
id=id, includes=["tags", "artists", "releases"]
|
||||
)
|
||||
getattr(musicbrainz.api, type_).get(id=id, includes=includes)
|
||||
)
|
||||
|
||||
existing = (
|
||||
|
@ -537,7 +540,7 @@ def third_party_fetch(fetch_obj):
|
|||
type_, id = type_and_id_from_third_party[service](fetch_obj)
|
||||
logger.debug("Parsed URL %s into type %s and id %s", url, type_, id)
|
||||
except ValueError as e:
|
||||
return error("url_parse_error", message=e.message)
|
||||
return error("url_parse_error", message=str(e))
|
||||
|
||||
try:
|
||||
result, existing = metadata_from_third_party_[service](type_, id)
|
||||
|
@ -587,6 +590,7 @@ def third_party_fetch(fetch_obj):
|
|||
fetch_obj.object = obj
|
||||
fetch_obj.status = "finished"
|
||||
fetch_obj.fetch_date = timezone.now()
|
||||
# to do : trigger third party download ?
|
||||
return fetch_obj.save(
|
||||
update_fields=["fetch_date", "status", "object_id", "object_content_type"]
|
||||
)
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
import logging
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from funkwhale_api import musicbrainz
|
||||
from funkwhale_api.tags import models as tags_models
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ArtistSerializer(serializers.Serializer):
|
||||
"""
|
||||
|
@ -18,7 +23,7 @@ class ArtistSerializer(serializers.Serializer):
|
|||
"name": validated_data["name"],
|
||||
"mbid": validated_data["id"],
|
||||
}
|
||||
artist = Artist.objects.create(**data)
|
||||
artist, created = Artist.objects.get_or_create(**data)
|
||||
return artist
|
||||
|
||||
|
||||
|
@ -39,13 +44,13 @@ class ArtistCreditSerializer(serializers.Serializer):
|
|||
"joinphrase": validated_data.get("joinphrase", ""),
|
||||
"artist": ArtistSerializer().create(validated_data["artist"]),
|
||||
}
|
||||
artist_credit = ArtistCredit.objects.create(**data)
|
||||
artist_credit, created = ArtistCredit.objects.get_or_create(**data)
|
||||
return artist_credit
|
||||
|
||||
|
||||
class ReleaseSerializer(serializers.Serializer):
|
||||
class ReleaseForTrackSerializer(serializers.Serializer):
|
||||
"""
|
||||
Serializer for Musicbrainz release data.
|
||||
Serializer for Musicbrainz release data when returned in a recording object.
|
||||
"""
|
||||
|
||||
id = serializers.CharField()
|
||||
|
@ -60,9 +65,9 @@ class ReleaseSerializer(serializers.Serializer):
|
|||
data = {
|
||||
"title": validated_data["title"],
|
||||
"mbid": validated_data["id"],
|
||||
"release_date": validated_data.get("date"),
|
||||
"release_date": validated_data.get("date", None),
|
||||
}
|
||||
album = Album.objects.create(**data)
|
||||
album, created = Album.objects.get_or_create(**data)
|
||||
artist_credit = ArtistCreditSerializer(many=True).create(
|
||||
validated_data["artist_credit"]
|
||||
)
|
||||
|
@ -70,6 +75,9 @@ class ReleaseSerializer(serializers.Serializer):
|
|||
album.save()
|
||||
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
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
|
@ -86,25 +94,29 @@ class RecordingSerializer(serializers.Serializer):
|
|||
Serializer for Musicbrainz track data.
|
||||
"""
|
||||
|
||||
# class Meta:
|
||||
# model = Track
|
||||
|
||||
id = serializers.CharField()
|
||||
title = serializers.CharField()
|
||||
artist_credit = ArtistCreditSerializer(many=True)
|
||||
releases = ReleaseSerializer(many=True)
|
||||
releases = ReleaseForTrackSerializer(many=True, required=False)
|
||||
tags = serializers.ListField(child=serializers.CharField(), allow_empty=True)
|
||||
|
||||
def create(self, validated_data):
|
||||
from funkwhale_api.music.models import Track
|
||||
|
||||
data = {
|
||||
data = {"mbid": validated_data["id"]}
|
||||
defaults = {
|
||||
"title": validated_data["title"],
|
||||
"mbid": validated_data["id"],
|
||||
# In mb a recording can have various releases, we take the fist one
|
||||
"album": ReleaseSerializer(many=True).create(validated_data["releases"])[0],
|
||||
"album": (
|
||||
ReleaseForTrackSerializer(many=True).create(validated_data["releases"])[
|
||||
0
|
||||
]
|
||||
if validated_data.get("releases")
|
||||
else None
|
||||
),
|
||||
}
|
||||
track = Track.objects.create(**data)
|
||||
track, created = Track.objects.get_or_create(**data, defaults=defaults)
|
||||
artist_credit = ArtistCreditSerializer(many=True).create(
|
||||
validated_data["artist_credit"]
|
||||
)
|
||||
|
@ -121,3 +133,98 @@ class RecordingSerializer(serializers.Serializer):
|
|||
tags_models.add_tags(instance, *validated_data.get("tags", []))
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
class RecordingForReleaseSerializer(serializers.Serializer):
|
||||
id = serializers.CharField()
|
||||
title = serializers.CharField()
|
||||
|
||||
def create(self, validated_data):
|
||||
def replace_hyphens_in_keys(obj):
|
||||
if isinstance(obj, dict):
|
||||
return {
|
||||
k.replace("-", "_"): replace_hyphens_in_keys(v)
|
||||
for k, v in obj.items()
|
||||
}
|
||||
elif isinstance(obj, list):
|
||||
return [replace_hyphens_in_keys(item) for item in obj]
|
||||
else:
|
||||
return obj
|
||||
|
||||
recordings_data = musicbrainz.api.recordings.get(
|
||||
id=validated_data["id"], includes=["tags", "artists"]
|
||||
)
|
||||
recordings_data = replace_hyphens_in_keys(recordings_data)
|
||||
serializer = RecordingSerializer(data=recordings_data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
track = serializer.save()
|
||||
track.album = validated_data["album"]
|
||||
track.save()
|
||||
return track
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
instance.title = validated_data["title"]
|
||||
tags_models.add_tags(instance, *validated_data.get("tags", []))
|
||||
instance.album = validated_data["album"]
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
|
||||
class TrackSerializer(serializers.Serializer):
|
||||
recording = RecordingForReleaseSerializer()
|
||||
|
||||
|
||||
class MediaSerializer(serializers.Serializer):
|
||||
tracks = TrackSerializer(many=True)
|
||||
|
||||
|
||||
class ReleaseSerializer(serializers.Serializer):
|
||||
"""
|
||||
Serializer for Musicbrainz release data.
|
||||
"""
|
||||
|
||||
id = serializers.CharField()
|
||||
title = serializers.CharField()
|
||||
artist_credit = ArtistCreditSerializer(many=True)
|
||||
tags = serializers.ListField(child=serializers.CharField(), allow_empty=True)
|
||||
date = serializers.DateField(input_formats=["%Y", "%Y/%m/%d", "%Y-%m-%d"])
|
||||
media = serializers.ListField(child=MediaSerializer())
|
||||
|
||||
def create(self, validated_data):
|
||||
from funkwhale_api.music.models import Album
|
||||
|
||||
data = {
|
||||
"title": validated_data["title"],
|
||||
"mbid": validated_data["id"],
|
||||
"release_date": validated_data.get("date"),
|
||||
}
|
||||
album, created = Album.objects.get_or_create(**data)
|
||||
artist_credit = ArtistCreditSerializer(many=True).create(
|
||||
validated_data["artist_credit"]
|
||||
)
|
||||
album.artist_credit.set(artist_credit)
|
||||
album.save()
|
||||
tags_models.add_tags(album, *validated_data.get("tags", []))
|
||||
|
||||
# an album can have various media/physical representation, we take the first one
|
||||
recordings = [t["recording"] for t in validated_data["media"][0]["tracks"]]
|
||||
for r in recordings:
|
||||
r["album"] = album
|
||||
RecordingForReleaseSerializer().create(r)
|
||||
|
||||
return album
|
||||
|
||||
# this will never be used while FetchViewSet and third_party_fetch filter out finished fetch
|
||||
# Would be nice to have a way to manually update releases from Musicbrainz
|
||||
def update(self, instance, validated_data):
|
||||
logger.info(f"Updating release {instance} with data: {validated_data}")
|
||||
instance.title = validated_data["title"]
|
||||
instance.release_date = validated_data.get("date")
|
||||
instance.save()
|
||||
tags_models.add_tags(instance, *validated_data.get("tags", []))
|
||||
|
||||
recordings = [t["recording"] for t in validated_data["media"][0]["tracks"]]
|
||||
for r in recordings:
|
||||
r["album"] = instance
|
||||
RecordingForReleaseSerializer().update(r)
|
||||
return instance
|
||||
|
|
Loading…
Reference in New Issue