Skip to content
Snippets Groups Projects
Verified Commit 80206761 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Easy and resusable Audio and AudioCollection serializer

parent 679adfe1
No related branches found
No related tags found
No related merge requests found
...@@ -22,6 +22,7 @@ from versatileimagefield.fields import VersatileImageField ...@@ -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): ...@@ -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): ...@@ -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 ...@@ -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): ...@@ -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): ...@@ -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
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): ...@@ -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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment