Easy and resusable Audio and AudioCollection serializer
This commit is contained in:
parent
679adfe156
commit
80206761a3
|
@ -22,6 +22,7 @@ from versatileimagefield.fields import VersatileImageField
|
||||||
|
|
||||||
from funkwhale_api import downloader
|
from funkwhale_api import downloader
|
||||||
from funkwhale_api import musicbrainz
|
from funkwhale_api import musicbrainz
|
||||||
|
from funkwhale_api.federation import utils as federation_utils
|
||||||
from . import importers
|
from . import importers
|
||||||
from . import utils
|
from . import utils
|
||||||
|
|
||||||
|
@ -69,6 +70,12 @@ class APIModelMixin(models.Model):
|
||||||
pass
|
pass
|
||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
|
@property
|
||||||
|
def musicbrainz_url(self):
|
||||||
|
if self.mbid:
|
||||||
|
return 'https://musicbrainz.org/{}/{}'.format(
|
||||||
|
self.musicbrainz_model, self.mbid)
|
||||||
|
|
||||||
|
|
||||||
class Artist(APIModelMixin):
|
class Artist(APIModelMixin):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
|
@ -426,6 +433,11 @@ class TrackFile(models.Model):
|
||||||
shutil.rmtree(tmp_dir)
|
shutil.rmtree(tmp_dir)
|
||||||
return self.audio_file
|
return self.audio_file
|
||||||
|
|
||||||
|
def get_federation_url(self):
|
||||||
|
return federation_utils.full_url(
|
||||||
|
'/federation/music/file/{}'.format(self.uuid)
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self):
|
def path(self):
|
||||||
if settings.PROTECT_AUDIO_FILES:
|
if settings.PROTECT_AUDIO_FILES:
|
||||||
|
|
|
@ -3,6 +3,8 @@ from rest_framework import serializers
|
||||||
from taggit.models import Tag
|
from taggit.models import Tag
|
||||||
|
|
||||||
from funkwhale_api.activity import serializers as activity_serializers
|
from funkwhale_api.activity import serializers as activity_serializers
|
||||||
|
from funkwhale_api.federation.serializers import AP_CONTEXT
|
||||||
|
from funkwhale_api.federation import utils as federation_utils
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
|
|
||||||
|
@ -212,6 +214,29 @@ class AudioSerializer(serializers.Serializer):
|
||||||
metadata=metadata,
|
metadata=metadata,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def to_representation(self, instance):
|
||||||
|
d = {
|
||||||
|
'type': 'Audio',
|
||||||
|
'id': instance.get_federation_url(),
|
||||||
|
'name': instance.track.full_name,
|
||||||
|
'metadata': {
|
||||||
|
'artist': instance.track.artist.musicbrainz_url,
|
||||||
|
'release': instance.track.album.musicbrainz_url,
|
||||||
|
'track': instance.track.musicbrainz_url,
|
||||||
|
},
|
||||||
|
'url': {
|
||||||
|
'href': federation_utils.full_url(instance.path),
|
||||||
|
'type': 'Link',
|
||||||
|
'mediaType': instance.mimetype
|
||||||
|
},
|
||||||
|
'attributedTo': [
|
||||||
|
self.context['actor'].url
|
||||||
|
]
|
||||||
|
}
|
||||||
|
if self.context.get('include_ap_context', True):
|
||||||
|
d['@context'] = AP_CONTEXT
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
class AudioCollectionImportSerializer(serializers.Serializer):
|
class AudioCollectionImportSerializer(serializers.Serializer):
|
||||||
id = serializers.URLField()
|
id = serializers.URLField()
|
||||||
|
@ -231,3 +256,24 @@ class AudioCollectionImportSerializer(serializers.Serializer):
|
||||||
s = AudioSerializer(data=i)
|
s = AudioSerializer(data=i)
|
||||||
job = s.create(i, batch)
|
job = s.create(i, batch)
|
||||||
return batch
|
return batch
|
||||||
|
|
||||||
|
def to_representation(self, instance):
|
||||||
|
d = {
|
||||||
|
'id': instance['id'],
|
||||||
|
'actor': instance['actor'].url,
|
||||||
|
'totalItems': len(instance['items']),
|
||||||
|
'type': 'Collection',
|
||||||
|
'items': [
|
||||||
|
AudioSerializer(
|
||||||
|
i,
|
||||||
|
context={
|
||||||
|
'actor': instance['actor'],
|
||||||
|
'include_ap_context': False
|
||||||
|
}
|
||||||
|
).data
|
||||||
|
for i in instance['items']
|
||||||
|
]
|
||||||
|
}
|
||||||
|
if self.context.get('include_ap_context', True):
|
||||||
|
d['@context'] = AP_CONTEXT
|
||||||
|
return d
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
|
from funkwhale_api.federation import actors
|
||||||
|
from funkwhale_api.federation import utils as federation_utils
|
||||||
|
from funkwhale_api.federation.serializers import AP_CONTEXT
|
||||||
from funkwhale_api.music import serializers
|
from funkwhale_api.music import serializers
|
||||||
|
|
||||||
|
|
||||||
def test_activity_pub_audio_collection_serializer(factories):
|
def test_activity_pub_audio_collection_serializer_to_import(factories):
|
||||||
sender = factories['federation.Actor']()
|
sender = factories['federation.Actor']()
|
||||||
|
|
||||||
collection = {
|
collection = {
|
||||||
|
@ -30,3 +33,62 @@ def test_activity_pub_audio_collection_serializer(factories):
|
||||||
assert job.source == a['url']['href']
|
assert job.source == a['url']['href']
|
||||||
a['metadata']['mediaType'] = a['url']['mediaType']
|
a['metadata']['mediaType'] = a['url']['mediaType']
|
||||||
assert job.metadata == a['metadata']
|
assert job.metadata == a['metadata']
|
||||||
|
|
||||||
|
|
||||||
|
def test_activity_pub_audio_serializer_to_ap(factories):
|
||||||
|
tf = factories['music.TrackFile'](mimetype='audio/mp3')
|
||||||
|
library = actors.SYSTEM_ACTORS['library'].get_actor_instance()
|
||||||
|
expected = {
|
||||||
|
'@context': AP_CONTEXT,
|
||||||
|
'type': 'Audio',
|
||||||
|
'id': tf.get_federation_url(),
|
||||||
|
'name': tf.track.full_name,
|
||||||
|
'metadata': {
|
||||||
|
'artist': tf.track.artist.musicbrainz_url,
|
||||||
|
'release': tf.track.album.musicbrainz_url,
|
||||||
|
'track': tf.track.musicbrainz_url,
|
||||||
|
},
|
||||||
|
'url': {
|
||||||
|
'href': federation_utils.full_url(tf.path),
|
||||||
|
'type': 'Link',
|
||||||
|
'mediaType': 'audio/mp3'
|
||||||
|
},
|
||||||
|
'attributedTo': [
|
||||||
|
library.url
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
serializer = serializers.AudioSerializer(tf, context={'actor': library})
|
||||||
|
|
||||||
|
assert serializer.data == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_activity_pub_audio_collection_serializer_to_ap(factories):
|
||||||
|
tf1 = factories['music.TrackFile'](mimetype='audio/mp3')
|
||||||
|
tf2 = factories['music.TrackFile'](mimetype='audio/ogg')
|
||||||
|
library = actors.SYSTEM_ACTORS['library'].get_actor_instance()
|
||||||
|
expected = {
|
||||||
|
'@context': AP_CONTEXT,
|
||||||
|
'id': 'https://test.id',
|
||||||
|
'actor': library.url,
|
||||||
|
'totalItems': 2,
|
||||||
|
'type': 'Collection',
|
||||||
|
'items': [
|
||||||
|
serializers.AudioSerializer(
|
||||||
|
tf1, context={'actor': library, 'include_ap_context': False}
|
||||||
|
).data,
|
||||||
|
serializers.AudioSerializer(
|
||||||
|
tf2, context={'actor': library, 'include_ap_context': False}
|
||||||
|
).data,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
collection = {
|
||||||
|
'id': expected['id'],
|
||||||
|
'actor': library,
|
||||||
|
'items': [tf1, tf2],
|
||||||
|
}
|
||||||
|
serializer = serializers.AudioCollectionImportSerializer(
|
||||||
|
collection, context={'actor': library, 'id': 'https://test.id'})
|
||||||
|
|
||||||
|
assert serializer.data == expected
|
||||||
|
|
Loading…
Reference in New Issue