diff --git a/api/funkwhale_api/favorites/activities.py b/api/funkwhale_api/favorites/activities.py new file mode 100644 index 0000000000000000000000000000000000000000..a9deef552586c0cc210dcf0745d224f90c42e6a8 --- /dev/null +++ b/api/funkwhale_api/favorites/activities.py @@ -0,0 +1,17 @@ +from funkwhale_api.common import channels +from funkwhale_api.activity import record + +from . import serializers + +record.registry.register_serializer( + serializers.TrackFavoriteActivitySerializer) + + +@record.registry.register_consumer('favorites.TrackFavorite') +def broadcast_track_favorite_to_instance_timeline(data, obj): + if obj.user.privacy_level not in ['instance', 'everyone']: + return + channels.group_send('instance_timeline', { + 'type': 'event', + 'data': data + }) diff --git a/api/funkwhale_api/favorites/consumers.py b/api/funkwhale_api/favorites/consumers.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/api/funkwhale_api/favorites/views.py b/api/funkwhale_api/favorites/views.py index 08ae00b684c30bcf5df91d5438dae1c03c790259..d874c9e1e626b9b30101088217336735d544a0e1 100644 --- a/api/funkwhale_api/favorites/views.py +++ b/api/funkwhale_api/favorites/views.py @@ -4,6 +4,7 @@ from rest_framework.response import Response from rest_framework import pagination from rest_framework.decorators import list_route +from funkwhale_api.activity import record from funkwhale_api.music.models import Track from funkwhale_api.common.permissions import ConditionalAuthentication @@ -33,6 +34,7 @@ class TrackFavoriteViewSet(mixins.CreateModelMixin, instance = self.perform_create(serializer) serializer = self.get_serializer(instance=instance) headers = self.get_success_headers(serializer.data) + record.send(instance) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) def get_queryset(self): diff --git a/api/tests/favorites/test_activity.py b/api/tests/favorites/test_activity.py index b4d76658a8688fd4dc81144e288653186b18e1c2..84778fd0fc8779ca1bf32ddfa8e69621ad6fa492 100644 --- a/api/tests/favorites/test_activity.py +++ b/api/tests/favorites/test_activity.py @@ -1,5 +1,6 @@ from funkwhale_api.users.serializers import UserActivitySerializer from funkwhale_api.favorites import serializers +from funkwhale_api.favorites import activities def test_get_favorite_activity_url(settings, factories): @@ -26,3 +27,45 @@ def test_activity_favorite_serializer(factories): data = serializers.TrackFavoriteActivitySerializer(favorite).data assert data == expected + + +def test_track_favorite_serializer_is_connected(activity_registry): + conf = activity_registry['favorites.TrackFavorite'] + assert conf['serializer'] == serializers.TrackFavoriteActivitySerializer + + +def test_track_favorite_serializer_instance_activity_consumer( + activity_registry): + conf = activity_registry['favorites.TrackFavorite'] + consumer = activities.broadcast_track_favorite_to_instance_timeline + assert consumer in conf['consumers'] + + +def test_broadcast_track_favorite_to_instance_timeline( + factories, mocker): + p = mocker.patch('funkwhale_api.common.channels.group_send') + favorite = factories['favorites.TrackFavorite']() + data = serializers.TrackFavoriteActivitySerializer(favorite).data + consumer = activities.broadcast_track_favorite_to_instance_timeline + message = { + "type": 'event', + "data": data + } + consumer(data=data, obj=favorite) + p.assert_called_once_with('instance_timeline', message) + + +def test_broadcast_track_favorite_to_instance_timeline_private( + factories, mocker): + p = mocker.patch('funkwhale_api.common.channels.group_send') + favorite = factories['favorites.TrackFavorite']( + user__privacy_level='me' + ) + data = serializers.TrackFavoriteActivitySerializer(favorite).data + consumer = activities.broadcast_track_favorite_to_instance_timeline + message = { + "type": 'event', + "data": data + } + consumer(data=data, obj=favorite) + p.assert_not_called() diff --git a/api/tests/favorites/test_favorites.py b/api/tests/favorites/test_favorites.py index 8165722eacc969a9ea651dd70815d3fa1d9c75ea..f4a045af825e9431f308903569ac16b07d609692 100644 --- a/api/tests/favorites/test_favorites.py +++ b/api/tests/favorites/test_favorites.py @@ -33,7 +33,8 @@ def test_user_can_get_his_favorites(factories, logged_in_client, client): assert expected == parsed_json['results'] -def test_user_can_add_favorite_via_api(factories, logged_in_client, client): +def test_user_can_add_favorite_via_api( + factories, logged_in_client, activity_muted): track = factories['music.Track']() url = reverse('api:v1:favorites:tracks-list') response = logged_in_client.post(url, {'track': track.pk}) @@ -51,6 +52,27 @@ def test_user_can_add_favorite_via_api(factories, logged_in_client, client): assert favorite.user == logged_in_client.user +def test_adding_favorites_calls_activity_record( + factories, logged_in_client, activity_muted): + track = factories['music.Track']() + url = reverse('api:v1:favorites:tracks-list') + response = logged_in_client.post(url, {'track': track.pk}) + + favorite = TrackFavorite.objects.latest('id') + expected = { + 'track': track.pk, + 'id': favorite.id, + 'creation_date': favorite.creation_date.isoformat().replace('+00:00', 'Z'), + } + parsed_json = json.loads(response.content.decode('utf-8')) + + assert expected == parsed_json + assert favorite.track == track + assert favorite.user == logged_in_client.user + + activity_muted.assert_called_once_with(favorite) + + def test_user_can_remove_favorite_via_api(logged_in_client, factories, client): favorite = factories['favorites.TrackFavorite'](user=logged_in_client.user) url = reverse('api:v1:favorites:tracks-detail', kwargs={'pk': favorite.pk})