From 691665e3cf209da431299ef04646ca65b6d89127 Mon Sep 17 00:00:00 2001 From: Eliot Berriot <contact@eliotberriot.com> Date: Sun, 25 Feb 2018 14:44:00 +0100 Subject: [PATCH] Activity stream representations for user and favorites --- api/funkwhale_api/activity/__init__.py | 0 api/funkwhale_api/activity/serializers.py | 9 ++++++ api/funkwhale_api/favorites/models.py | 6 ++++ api/funkwhale_api/favorites/serializers.py | 33 +++++++++++++++++++++ api/funkwhale_api/music/consumers.py | 17 +++++++++++ api/funkwhale_api/music/models.py | 6 ++++ api/funkwhale_api/users/models.py | 4 +++ api/funkwhale_api/users/serializers.py | 18 +++++++++++ api/tests/favorites/test_activity.py | 28 +++++++++++++++++ api/tests/{ => favorites}/test_favorites.py | 0 api/tests/music/test_activity.py | 17 +++++++++++ api/tests/users/test_activity.py | 21 +++++++++++++ 12 files changed, 159 insertions(+) create mode 100644 api/funkwhale_api/activity/__init__.py create mode 100644 api/funkwhale_api/activity/serializers.py create mode 100644 api/funkwhale_api/music/consumers.py create mode 100644 api/tests/favorites/test_activity.py rename api/tests/{ => favorites}/test_favorites.py (100%) create mode 100644 api/tests/music/test_activity.py create mode 100644 api/tests/users/test_activity.py diff --git a/api/funkwhale_api/activity/__init__.py b/api/funkwhale_api/activity/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/api/funkwhale_api/activity/serializers.py b/api/funkwhale_api/activity/serializers.py new file mode 100644 index 00000000..4b40bb0d --- /dev/null +++ b/api/funkwhale_api/activity/serializers.py @@ -0,0 +1,9 @@ +from rest_framework import serializers + + +class ModelSerializer(serializers.ModelSerializer): + id = serializers.CharField(source='get_activity_url') + # url = serializers.SerializerMethodField() + + def get_url(self, obj): + return self.get_id(obj) diff --git a/api/funkwhale_api/favorites/models.py b/api/funkwhale_api/favorites/models.py index 899ed9cf..0c6a6b11 100644 --- a/api/funkwhale_api/favorites/models.py +++ b/api/funkwhale_api/favorites/models.py @@ -1,8 +1,10 @@ +from django.conf import settings from django.db import models from django.utils import timezone from funkwhale_api.music.models import Track + class TrackFavorite(models.Model): creation_date = models.DateTimeField(default=timezone.now) user = models.ForeignKey( @@ -18,3 +20,7 @@ class TrackFavorite(models.Model): def add(cls, track, user): favorite, created = cls.objects.get_or_create(user=user, track=track) return favorite + + def get_activity_url(self): + return '{}/favorites/tracks/{}'.format( + self.user.get_activity_url(), self.pk) diff --git a/api/funkwhale_api/favorites/serializers.py b/api/funkwhale_api/favorites/serializers.py index 57af4570..01ad2e47 100644 --- a/api/funkwhale_api/favorites/serializers.py +++ b/api/funkwhale_api/favorites/serializers.py @@ -1,10 +1,43 @@ +from django.conf import settings + from rest_framework import serializers +from funkwhale_api.activity import serializers as activity_serializers from funkwhale_api.music.serializers import TrackSerializerNested +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') + actor = UserActivitySerializer(source='user') + published = serializers.DateTimeField(source='creation_date') + + class Meta: + model = models.TrackFavorite + fields = [ + 'id', + 'object', + 'type', + 'actor', + 'published' + ] + + def get_actor(self, obj): + return UserActivitySerializer(obj.user).data + + 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) class Meta: diff --git a/api/funkwhale_api/music/consumers.py b/api/funkwhale_api/music/consumers.py new file mode 100644 index 00000000..452346d1 --- /dev/null +++ b/api/funkwhale_api/music/consumers.py @@ -0,0 +1,17 @@ +from funkwhale_api.common.consumers import JsonAuthConsumer + + +class MyConsumer(JsonAuthConsumer): + groups = ["broadcast"] + + def receive_json(self, payload): + print(payload, self.scope["user"]) + # Called with either text_data or bytes_data for each frame + # You can call: + self.send_json({'test': 'me'}) + # Or, to send a binary frame: + # self.send(bytes_data="{Hello} world!") + # Want to force-close the connection? Call: + # self.close() + # # Or add a custom WebSocket error code! + # self.close(code=4123) diff --git a/api/funkwhale_api/music/models.py b/api/funkwhale_api/music/models.py index 97992fc8..7138dcdd 100644 --- a/api/funkwhale_api/music/models.py +++ b/api/funkwhale_api/music/models.py @@ -360,6 +360,12 @@ class Track(APIModelMixin): self.title, ) + def get_activity_url(self): + if self.mbid: + return 'https://musicbrainz.org/recording/{}'.format( + self.mbid) + return settings.FUNKWHALE_URL + '/tracks/{}'.format(self.pk) + class TrackFile(models.Model): track = models.ForeignKey( diff --git a/api/funkwhale_api/users/models.py b/api/funkwhale_api/users/models.py index 3a0baf11..2b0dfa88 100644 --- a/api/funkwhale_api/users/models.py +++ b/api/funkwhale_api/users/models.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals, absolute_import import uuid +from django.conf import settings from django.contrib.auth.models import AbstractUser from django.urls import reverse from django.db import models @@ -43,3 +44,6 @@ class User(AbstractUser): def set_password(self, raw_password): super().set_password(raw_password) self.update_secret_key() + + def get_activity_url(self): + return settings.FUNKWHALE_URL + '/@{}'.format(self.username) diff --git a/api/funkwhale_api/users/serializers.py b/api/funkwhale_api/users/serializers.py index 8c218b1c..2e873d94 100644 --- a/api/funkwhale_api/users/serializers.py +++ b/api/funkwhale_api/users/serializers.py @@ -1,8 +1,26 @@ from rest_framework import serializers +from funkwhale_api.activity import serializers as activity_serializers + from . import models +class UserActivitySerializer(activity_serializers.ModelSerializer): + type = serializers.SerializerMethodField() + name = serializers.CharField(source='username') + + class Meta: + model = models.User + fields = [ + 'id', + 'name', + 'type' + ] + + def get_type(self, obj): + return 'Person' + + class UserBasicSerializer(serializers.ModelSerializer): class Meta: model = models.User diff --git a/api/tests/favorites/test_activity.py b/api/tests/favorites/test_activity.py new file mode 100644 index 00000000..b4d76658 --- /dev/null +++ b/api/tests/favorites/test_activity.py @@ -0,0 +1,28 @@ +from funkwhale_api.users.serializers import UserActivitySerializer +from funkwhale_api.favorites import serializers + + +def test_get_favorite_activity_url(settings, factories): + favorite = factories['favorites.TrackFavorite']() + user_url = favorite.user.get_activity_url() + expected = '{}/favorites/tracks/{}'.format( + user_url, favorite.pk) + assert favorite.get_activity_url() == expected + + +def test_activity_favorite_serializer(factories): + favorite = factories['favorites.TrackFavorite']() + + actor = UserActivitySerializer(favorite.user).data + field = serializers.serializers.DateTimeField() + expected = { + "type": "Like", + "id": favorite.get_activity_url(), + "actor": actor, + "object": favorite.track.get_activity_url(), + "published": field.to_representation(favorite.creation_date), + } + + data = serializers.TrackFavoriteActivitySerializer(favorite).data + + assert data == expected diff --git a/api/tests/test_favorites.py b/api/tests/favorites/test_favorites.py similarity index 100% rename from api/tests/test_favorites.py rename to api/tests/favorites/test_favorites.py diff --git a/api/tests/music/test_activity.py b/api/tests/music/test_activity.py new file mode 100644 index 00000000..f604874c --- /dev/null +++ b/api/tests/music/test_activity.py @@ -0,0 +1,17 @@ +from funkwhale_api.users.serializers import UserActivitySerializer +from funkwhale_api.favorites import serializers + + + +def test_get_track_activity_url_mbid(factories): + track = factories['music.Track']() + expected = 'https://musicbrainz.org/recording/{}'.format( + track.mbid) + assert track.get_activity_url() == expected + + +def test_get_track_activity_url_no_mbid(settings, factories): + track = factories['music.Track'](mbid=None) + expected = settings.FUNKWHALE_URL + '/tracks/{}'.format( + track.pk) + assert track.get_activity_url() == expected diff --git a/api/tests/users/test_activity.py b/api/tests/users/test_activity.py new file mode 100644 index 00000000..3cee4fb4 --- /dev/null +++ b/api/tests/users/test_activity.py @@ -0,0 +1,21 @@ +from funkwhale_api.users import serializers + + +def test_get_user_activity_url(settings, factories): + user = factories['users.User']() + assert user.get_activity_url() == '{}/@{}'.format( + settings.FUNKWHALE_URL, user.username) + + +def test_activity_user_serializer(factories): + user = factories['users.User']() + + expected = { + "type": "Person", + "id": user.get_activity_url(), + "name": user.username, + } + + data = serializers.UserActivitySerializer(user).data + + assert data == expected -- GitLab