API refinements for activity stream
This commit is contained in:
parent
d509c090d3
commit
a6da10be41
|
@ -3,6 +3,7 @@ from rest_framework import serializers
|
|||
|
||||
class ModelSerializer(serializers.ModelSerializer):
|
||||
id = serializers.CharField(source='get_activity_url')
|
||||
local_id = serializers.IntegerField(source='id')
|
||||
# url = serializers.SerializerMethodField()
|
||||
|
||||
def get_url(self, obj):
|
||||
|
|
|
@ -4,17 +4,15 @@ from rest_framework import serializers
|
|||
|
||||
from funkwhale_api.activity import serializers as activity_serializers
|
||||
from funkwhale_api.music.serializers import TrackSerializerNested
|
||||
from funkwhale_api.music.serializers import TrackActivitySerializer
|
||||
from funkwhale_api.users.serializers import UserActivitySerializer
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class TrackFavoriteActivitySerializer(activity_serializers.ModelSerializer):
|
||||
type = serializers.SerializerMethodField()
|
||||
object = serializers.CharField(source='track.get_activity_url')
|
||||
object = TrackActivitySerializer(source='track')
|
||||
actor = UserActivitySerializer(source='user')
|
||||
published = serializers.DateTimeField(source='creation_date')
|
||||
|
||||
|
@ -22,6 +20,7 @@ class TrackFavoriteActivitySerializer(activity_serializers.ModelSerializer):
|
|||
model = models.TrackFavorite
|
||||
fields = [
|
||||
'id',
|
||||
'local_id',
|
||||
'object',
|
||||
'type',
|
||||
'actor',
|
||||
|
@ -34,9 +33,6 @@ class TrackFavoriteActivitySerializer(activity_serializers.ModelSerializer):
|
|||
def get_type(self, obj):
|
||||
return 'Like'
|
||||
|
||||
def get_object(self, obj):
|
||||
return obj.track.get_activity_url()
|
||||
|
||||
|
||||
class UserTrackFavoriteSerializer(serializers.ModelSerializer):
|
||||
# track = TrackSerializerNested(read_only=True)
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
from funkwhale_api.common import channels
|
||||
from funkwhale_api.activity import record
|
||||
|
||||
from . import serializers
|
||||
|
||||
record.registry.register_serializer(
|
||||
serializers.ListeningActivitySerializer)
|
||||
|
||||
|
||||
@record.registry.register_consumer('history.Listening')
|
||||
def broadcast_listening_to_instance_activity(data, obj):
|
||||
if obj.user.privacy_level not in ['instance', 'everyone']:
|
||||
return
|
||||
|
||||
channels.group_send('instance_activity', {
|
||||
'type': 'event.send',
|
||||
'text': '',
|
||||
'data': data
|
||||
})
|
|
@ -25,3 +25,8 @@ class Listening(models.Model):
|
|||
raise ValidationError('Cannot have both session_key and user empty for listening')
|
||||
|
||||
super().save(**kwargs)
|
||||
|
||||
|
||||
def get_activity_url(self):
|
||||
return '{}/listenings/tracks/{}'.format(
|
||||
self.user.get_activity_url(), self.pk)
|
||||
|
|
|
@ -1,9 +1,37 @@
|
|||
from rest_framework import serializers
|
||||
|
||||
from funkwhale_api.activity import serializers as activity_serializers
|
||||
from funkwhale_api.music.serializers import TrackSerializerNested
|
||||
from funkwhale_api.music.serializers import TrackActivitySerializer
|
||||
from funkwhale_api.users.serializers import UserActivitySerializer
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
class ListeningActivitySerializer(activity_serializers.ModelSerializer):
|
||||
type = serializers.SerializerMethodField()
|
||||
object = TrackActivitySerializer(source='track')
|
||||
actor = UserActivitySerializer(source='user')
|
||||
published = serializers.DateTimeField(source='end_date')
|
||||
|
||||
class Meta:
|
||||
model = models.Listening
|
||||
fields = [
|
||||
'id',
|
||||
'local_id',
|
||||
'object',
|
||||
'type',
|
||||
'actor',
|
||||
'published'
|
||||
]
|
||||
|
||||
def get_actor(self, obj):
|
||||
return UserActivitySerializer(obj.user).data
|
||||
|
||||
def get_type(self, obj):
|
||||
return 'Listen'
|
||||
|
||||
|
||||
class ListeningSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
|
|
|
@ -3,8 +3,9 @@ from rest_framework import status
|
|||
from rest_framework.response import Response
|
||||
from rest_framework.decorators import detail_route
|
||||
|
||||
from funkwhale_api.music.serializers import TrackSerializerNested
|
||||
from funkwhale_api.activity import record
|
||||
from funkwhale_api.common.permissions import ConditionalAuthentication
|
||||
from funkwhale_api.music.serializers import TrackSerializerNested
|
||||
|
||||
from . import models
|
||||
from . import serializers
|
||||
|
@ -17,6 +18,12 @@ class ListeningViewSet(mixins.CreateModelMixin,
|
|||
queryset = models.Listening.objects.all()
|
||||
permission_classes = [ConditionalAuthentication]
|
||||
|
||||
def perform_create(self, serializer):
|
||||
r = super().perform_create(serializer)
|
||||
if self.request.user.is_authenticated:
|
||||
record.send(serializer.instance)
|
||||
return r
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
if self.request.user.is_authenticated:
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
from rest_framework import serializers
|
||||
from taggit.models import Tag
|
||||
|
||||
from funkwhale_api.activity import serializers as activity_serializers
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
|
@ -127,3 +129,24 @@ class ImportBatchSerializer(serializers.ModelSerializer):
|
|||
model = models.ImportBatch
|
||||
fields = ('id', 'jobs', 'status', 'creation_date', 'import_request')
|
||||
read_only_fields = ('creation_date',)
|
||||
|
||||
|
||||
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'
|
||||
|
|
|
@ -8,11 +8,13 @@ from . import models
|
|||
class UserActivitySerializer(activity_serializers.ModelSerializer):
|
||||
type = serializers.SerializerMethodField()
|
||||
name = serializers.CharField(source='username')
|
||||
local_id = serializers.CharField(source='username')
|
||||
|
||||
class Meta:
|
||||
model = models.User
|
||||
fields = [
|
||||
'id',
|
||||
'local_id',
|
||||
'name',
|
||||
'type'
|
||||
]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from funkwhale_api.users.serializers import UserActivitySerializer
|
||||
from funkwhale_api.music.serializers import TrackActivitySerializer
|
||||
from funkwhale_api.favorites import serializers
|
||||
from funkwhale_api.favorites import activities
|
||||
|
||||
|
@ -18,9 +19,10 @@ def test_activity_favorite_serializer(factories):
|
|||
field = serializers.serializers.DateTimeField()
|
||||
expected = {
|
||||
"type": "Like",
|
||||
"local_id": favorite.pk,
|
||||
"id": favorite.get_activity_url(),
|
||||
"actor": actor,
|
||||
"object": favorite.track.get_activity_url(),
|
||||
"object": TrackActivitySerializer(favorite.track).data,
|
||||
"published": field.to_representation(favorite.creation_date),
|
||||
}
|
||||
|
||||
|
@ -48,7 +50,8 @@ def test_broadcast_track_favorite_to_instance_activity(
|
|||
data = serializers.TrackFavoriteActivitySerializer(favorite).data
|
||||
consumer = activities.broadcast_track_favorite_to_instance_activity
|
||||
message = {
|
||||
"type": 'event',
|
||||
"type": 'event.send',
|
||||
"text": '',
|
||||
"data": data
|
||||
}
|
||||
consumer(data=data, obj=favorite)
|
||||
|
@ -64,7 +67,8 @@ def test_broadcast_track_favorite_to_instance_activity_private(
|
|||
data = serializers.TrackFavoriteActivitySerializer(favorite).data
|
||||
consumer = activities.broadcast_track_favorite_to_instance_activity
|
||||
message = {
|
||||
"type": 'event',
|
||||
"type": 'event.send',
|
||||
"text": '',
|
||||
"data": data
|
||||
}
|
||||
consumer(data=data, obj=favorite)
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
from funkwhale_api.users.serializers import UserActivitySerializer
|
||||
from funkwhale_api.music.serializers import TrackActivitySerializer
|
||||
from funkwhale_api.history import serializers
|
||||
from funkwhale_api.history import activities
|
||||
|
||||
|
||||
def test_get_listening_activity_url(settings, factories):
|
||||
listening = factories['history.Listening']()
|
||||
user_url = listening.user.get_activity_url()
|
||||
expected = '{}/listenings/tracks/{}'.format(
|
||||
user_url, listening.pk)
|
||||
assert listening.get_activity_url() == expected
|
||||
|
||||
|
||||
def test_activity_listening_serializer(factories):
|
||||
listening = factories['history.Listening']()
|
||||
|
||||
actor = UserActivitySerializer(listening.user).data
|
||||
field = serializers.serializers.DateTimeField()
|
||||
expected = {
|
||||
"type": "Listen",
|
||||
"local_id": listening.pk,
|
||||
"id": listening.get_activity_url(),
|
||||
"actor": actor,
|
||||
"object": TrackActivitySerializer(listening.track).data,
|
||||
"published": field.to_representation(listening.end_date),
|
||||
}
|
||||
|
||||
data = serializers.ListeningActivitySerializer(listening).data
|
||||
|
||||
assert data == expected
|
||||
|
||||
|
||||
def test_track_listening_serializer_is_connected(activity_registry):
|
||||
conf = activity_registry['history.Listening']
|
||||
assert conf['serializer'] == serializers.ListeningActivitySerializer
|
||||
|
||||
|
||||
def test_track_listening_serializer_instance_activity_consumer(
|
||||
activity_registry):
|
||||
conf = activity_registry['history.Listening']
|
||||
consumer = activities.broadcast_listening_to_instance_activity
|
||||
assert consumer in conf['consumers']
|
||||
|
||||
|
||||
def test_broadcast_listening_to_instance_activity(
|
||||
factories, mocker):
|
||||
p = mocker.patch('funkwhale_api.common.channels.group_send')
|
||||
listening = factories['history.Listening']()
|
||||
data = serializers.ListeningActivitySerializer(listening).data
|
||||
consumer = activities.broadcast_listening_to_instance_activity
|
||||
message = {
|
||||
"type": 'event.send',
|
||||
"text": '',
|
||||
"data": data
|
||||
}
|
||||
consumer(data=data, obj=listening)
|
||||
p.assert_called_once_with('instance_activity', message)
|
||||
|
||||
|
||||
def test_broadcast_listening_to_instance_activity_private(
|
||||
factories, mocker):
|
||||
p = mocker.patch('funkwhale_api.common.channels.group_send')
|
||||
listening = factories['history.Listening'](
|
||||
user__privacy_level='me'
|
||||
)
|
||||
data = serializers.ListeningActivitySerializer(listening).data
|
||||
consumer = activities.broadcast_listening_to_instance_activity
|
||||
message = {
|
||||
"type": 'event.send',
|
||||
"text": '',
|
||||
"data": data
|
||||
}
|
||||
consumer(data=data, obj=listening)
|
||||
p.assert_not_called()
|
|
@ -28,7 +28,8 @@ def test_anonymous_user_can_create_listening_via_api(client, factories, settings
|
|||
assert listening.session_key == client.session.session_key
|
||||
|
||||
|
||||
def test_logged_in_user_can_create_listening_via_api(logged_in_client, factories):
|
||||
def test_logged_in_user_can_create_listening_via_api(
|
||||
logged_in_client, factories, activity_muted):
|
||||
track = factories['music.Track']()
|
||||
|
||||
url = reverse('api:v1:history:listenings-list')
|
||||
|
@ -40,3 +41,17 @@ def test_logged_in_user_can_create_listening_via_api(logged_in_client, factories
|
|||
|
||||
assert listening.track == track
|
||||
assert listening.user == logged_in_client.user
|
||||
|
||||
|
||||
def test_adding_listening_calls_activity_record(
|
||||
factories, logged_in_client, activity_muted):
|
||||
track = factories['music.Track']()
|
||||
|
||||
url = reverse('api:v1:history:listenings-list')
|
||||
response = logged_in_client.post(url, {
|
||||
'track': track.pk,
|
||||
})
|
||||
|
||||
listening = models.Listening.objects.latest('id')
|
||||
|
||||
activity_muted.assert_called_once_with(listening)
|
|
@ -13,6 +13,7 @@ def test_activity_user_serializer(factories):
|
|||
expected = {
|
||||
"type": "Person",
|
||||
"id": user.get_activity_url(),
|
||||
"local_id": user.username,
|
||||
"name": user.username,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue