From e7ba6a31418f127e502451836f07d4292a294931 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Tue, 29 Aug 2023 21:07:41 +1000 Subject: [PATCH] initial work to add 'Move' activity --- bookwyrm/activitypub/__init__.py | 1 + bookwyrm/activitypub/verbs.py | 25 ++++++++++ bookwyrm/models/move.py | 50 +++++++++++++++++++ bookwyrm/models/notification.py | 16 +++++- bookwyrm/templates/notifications/item.html | 2 + .../templates/notifications/items/move.html | 28 +++++++++++ 6 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 bookwyrm/models/move.py create mode 100644 bookwyrm/templates/notifications/items/move.html diff --git a/bookwyrm/activitypub/__init__.py b/bookwyrm/activitypub/__init__.py index 05ca44476..e2bd4261d 100644 --- a/bookwyrm/activitypub/__init__.py +++ b/bookwyrm/activitypub/__init__.py @@ -19,6 +19,7 @@ from .verbs import Create, Delete, Undo, Update from .verbs import Follow, Accept, Reject, Block from .verbs import Add, Remove from .verbs import Announce, Like +from .verbs import Move # this creates a list of all the Activity types that we can serialize, # so when an Activity comes in from outside, we can check if it's known diff --git a/bookwyrm/activitypub/verbs.py b/bookwyrm/activitypub/verbs.py index 4b7514b5a..3432da4d5 100644 --- a/bookwyrm/activitypub/verbs.py +++ b/bookwyrm/activitypub/verbs.py @@ -231,3 +231,28 @@ class Announce(Verb): def action(self, allow_external_connections=True): """boost""" self.to_model(allow_external_connections=allow_external_connections) + +@dataclass(init=False) +class Move(Verb): + """a user moving an object""" + + # note the spec example for target and origin is an object but + # Mastodon uses a URI string and TBH this makes more sense + # Is there a way we can account for either format? + + object: str + type: str = "Move" + target: str + origin: str + + def action(self, allow_external_connections=True): + """move""" + + # we need to work out whether the object is a user or something else. + + object_is_user = True # TODO! + + if object_is_user: + self.to_model(object_is_user=True allow_external_connections=allow_external_connections) + else: + self.to_model(object_is_user=False allow_external_connections=allow_external_connections) \ No newline at end of file diff --git a/bookwyrm/models/move.py b/bookwyrm/models/move.py new file mode 100644 index 000000000..cb597e84a --- /dev/null +++ b/bookwyrm/models/move.py @@ -0,0 +1,50 @@ +""" move an object including migrating a user account """ +from django.db import models + +from bookwyrm import activitypub +from .activitypub_mixin import ActivityMixin +from .base_model import BookWyrmModel +from . import fields +from .status import Status + + +class Move(ActivityMixin, BookWyrmModel): + """migrating an activitypub user account""" + + user = fields.ForeignKey( + "User", on_delete=models.PROTECT, activitypub_field="actor" + ) + + # TODO: can we just use the abstract class here? + activitypub_object = fields.ForeignKey( + "BookWyrmModel", on_delete=models.PROTECT, + activitypub_field="object", + blank=True, + null=True + ) + + target = fields.CharField( + max_length=255, blank=True, null=True, deduplication_field=True + ) + + origin = fields.CharField( + max_length=255, blank=True, null=True, deduplication_field=True + ) + + activity_serializer = activitypub.Move + + # pylint: disable=unused-argument + @classmethod + def ignore_activity(cls, activity, allow_external_connections=True): + """don't bother with incoming moves of unknown objects""" + # TODO how do we check this for any conceivable object? + pass + + def save(self, *args, **kwargs): + """update user active time""" + self.user.update_active_date() + super().save(*args, **kwargs) + + # Ok what else? We can trigger a notification for followers of a user who sends a `Move` for themselves + # What about when a book is merged (i.e. moved from one id into another)? We could use that to send out a message + # to other Bookwyrm instances to update their remote_id for the book, but ...how do we trigger any action? \ No newline at end of file diff --git a/bookwyrm/models/notification.py b/bookwyrm/models/notification.py index 522038f9a..48baacfaf 100644 --- a/bookwyrm/models/notification.py +++ b/bookwyrm/models/notification.py @@ -40,11 +40,14 @@ class Notification(BookWyrmModel): GROUP_NAME = "GROUP_NAME" GROUP_DESCRIPTION = "GROUP_DESCRIPTION" + # Migrations + MOVE = "MOVE" + # pylint: disable=line-too-long NotificationType = models.TextChoices( # there has got be a better way to do this "NotificationType", - f"{FAVORITE} {REPLY} {MENTION} {TAG} {FOLLOW} {FOLLOW_REQUEST} {BOOST} {IMPORT} {ADD} {REPORT} {LINK_DOMAIN} {INVITE} {ACCEPT} {JOIN} {LEAVE} {REMOVE} {GROUP_PRIVACY} {GROUP_NAME} {GROUP_DESCRIPTION}", + f"{FAVORITE} {REPLY} {MENTION} {TAG} {FOLLOW} {FOLLOW_REQUEST} {BOOST} {IMPORT} {ADD} {REPORT} {LINK_DOMAIN} {INVITE} {ACCEPT} {JOIN} {LEAVE} {REMOVE} {GROUP_PRIVACY} {GROUP_NAME} {GROUP_DESCRIPTION} {MOVE}", ) user = models.ForeignKey("User", on_delete=models.CASCADE) @@ -326,3 +329,14 @@ def notify_user_on_follow(sender, instance, created, *args, **kwargs): notification_type=Notification.FOLLOW, read=False, ) + +@receiver(models.signals.post_save, sender=Move) +# pylint: disable=unused-argument +def notify_on_move(sender, instance, *args, **kwargs): + """someone moved something""" + Notification.notify( + instance.status.user, + instance.user, + related_object=instance.object, + notification_type=Notification.MOVE, + ) \ No newline at end of file diff --git a/bookwyrm/templates/notifications/item.html b/bookwyrm/templates/notifications/item.html index b53abe3d1..b2020839a 100644 --- a/bookwyrm/templates/notifications/item.html +++ b/bookwyrm/templates/notifications/item.html @@ -35,4 +35,6 @@ {% include 'notifications/items/update.html' %} {% elif notification.notification_type == 'GROUP_DESCRIPTION' %} {% include 'notifications/items/update.html' %} + {% elif notification.notification_type == 'MOVE' %} + {% include 'notifications/items/move.html' %} {% endif %} diff --git a/bookwyrm/templates/notifications/items/move.html b/bookwyrm/templates/notifications/items/move.html new file mode 100644 index 000000000..ffa23829f --- /dev/null +++ b/bookwyrm/templates/notifications/items/move.html @@ -0,0 +1,28 @@ +{% extends 'notifications/items/layout.html' %} + +{% load i18n %} +{% load utilities %} + +{% block primary_link %}{% spaceless %} + {{ notification.related_object.local_path }} +{% endspaceless %}{% endblock %} + +{% block icon %} + +{% endblock %} + +{% block description %} + + {% blocktrans trimmed with object_name=notification.related_object.name object_path=notification.related_object.local_path %} + {{ related_user }} + moved {{ object_name }} + "{{ object_name }}" + {% endblocktrans %} + + + +{% endblock %}