from django.db.models import Q from rest_framework import serializers from taggit.models import Tag from funkwhale_api.activity import serializers as activity_serializers from funkwhale_api.users.serializers import UserBasicSerializer from . import models, tasks class ArtistAlbumSerializer(serializers.ModelSerializer): tracks_count = serializers.SerializerMethodField() class Meta: model = models.Album fields = ( "id", "mbid", "title", "artist", "release_date", "cover", "creation_date", "tracks_count", ) def get_tracks_count(self, o): return o._tracks_count class ArtistWithAlbumsSerializer(serializers.ModelSerializer): albums = ArtistAlbumSerializer(many=True, read_only=True) class Meta: model = models.Artist fields = ("id", "mbid", "name", "creation_date", "albums") class TrackFileSerializer(serializers.ModelSerializer): path = serializers.SerializerMethodField() class Meta: model = models.TrackFile fields = ( "id", "path", "source", "filename", "mimetype", "track", "duration", "mimetype", "bitrate", "size", ) read_only_fields = ["duration", "mimetype", "bitrate", "size"] def get_path(self, o): url = o.path return url class AlbumTrackSerializer(serializers.ModelSerializer): files = TrackFileSerializer(many=True, read_only=True) class Meta: model = models.Track fields = ( "id", "mbid", "title", "album", "artist", "creation_date", "files", "position", ) class ArtistSimpleSerializer(serializers.ModelSerializer): class Meta: model = models.Artist fields = ("id", "mbid", "name", "creation_date") class AlbumSerializer(serializers.ModelSerializer): tracks = serializers.SerializerMethodField() artist = ArtistSimpleSerializer(read_only=True) class Meta: model = models.Album fields = ( "id", "mbid", "title", "artist", "tracks", "release_date", "cover", "creation_date", ) def get_tracks(self, o): ordered_tracks = sorted( o.tracks.all(), key=lambda v: (v.position, v.title) if v.position else (99999, v.title), ) return AlbumTrackSerializer(ordered_tracks, many=True).data class TrackAlbumSerializer(serializers.ModelSerializer): artist = ArtistSimpleSerializer(read_only=True) class Meta: model = models.Album fields = ( "id", "mbid", "title", "artist", "release_date", "cover", "creation_date", ) class TrackSerializer(serializers.ModelSerializer): files = TrackFileSerializer(many=True, read_only=True) artist = ArtistSimpleSerializer(read_only=True) album = TrackAlbumSerializer(read_only=True) lyrics = serializers.SerializerMethodField() class Meta: model = models.Track fields = ( "id", "mbid", "title", "album", "artist", "creation_date", "files", "position", "lyrics", ) def get_lyrics(self, obj): return obj.get_lyrics_url() class TagSerializer(serializers.ModelSerializer): class Meta: model = Tag fields = ("id", "name", "slug") class SimpleAlbumSerializer(serializers.ModelSerializer): class Meta: model = models.Album fields = ("id", "mbid", "title", "release_date", "cover") class LyricsSerializer(serializers.ModelSerializer): class Meta: model = models.Lyrics fields = ("id", "work", "content", "content_rendered") class ImportJobSerializer(serializers.ModelSerializer): track_file = TrackFileSerializer(read_only=True) class Meta: model = models.ImportJob fields = ("id", "mbid", "batch", "source", "status", "track_file", "audio_file") read_only_fields = ("status", "track_file") class ImportBatchSerializer(serializers.ModelSerializer): submitted_by = UserBasicSerializer(read_only=True) class Meta: model = models.ImportBatch fields = ( "id", "submitted_by", "source", "status", "creation_date", "import_request", ) read_only_fields = ("creation_date", "submitted_by", "source") def to_representation(self, instance): repr = super().to_representation(instance) try: repr["job_count"] = instance.job_count except AttributeError: # Queryset was not annotated pass return repr class TrackActivitySerializer(activity_serializers.ModelSerializer): type = serializers.SerializerMethodField() name = serializers.CharField(source="title") artist = serializers.CharField(source="artist.name") album = serializers.CharField(source="album.title") class Meta: model = models.Track fields = ["id", "local_id", "name", "type", "artist", "album"] def get_type(self, obj): return "Audio" class ImportJobRunSerializer(serializers.Serializer): jobs = serializers.PrimaryKeyRelatedField( many=True, queryset=models.ImportJob.objects.filter(status__in=["pending", "errored"]), ) batches = serializers.PrimaryKeyRelatedField( many=True, queryset=models.ImportBatch.objects.all() ) def validate(self, validated_data): jobs = validated_data["jobs"] batches_ids = [b.pk for b in validated_data["batches"]] query = Q(batch__pk__in=batches_ids) query |= Q(pk__in=[j.id for j in jobs]) queryset = ( models.ImportJob.objects.filter(query) .filter(status__in=["pending", "errored"]) .distinct() ) validated_data["_jobs"] = queryset return validated_data def create(self, validated_data): ids = validated_data["_jobs"].values_list("id", flat=True) validated_data["_jobs"].update(status="pending") for id in ids: tasks.import_job_run.delay(import_job_id=id) return {"jobs": list(ids)}