initial work to add 'Move' activity

This commit is contained in:
Hugh Rundle 2023-08-29 21:07:41 +10:00
parent e5f8e4babc
commit e7ba6a3141
No known key found for this signature in database
GPG key ID: A7E35779918253F9
6 changed files with 121 additions and 1 deletions

View file

@ -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

View file

@ -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)

50
bookwyrm/models/move.py Normal file
View file

@ -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?

View file

@ -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,
)

View file

@ -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 %}

View file

@ -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 %}
<span class="icon icon-local"></span>
{% endblock %}
{% block description %}
<!--
TODO: a user has a 'name' but not everything does, notably a book.
On the other hand, maybe we don't need to notify anyone if a book
is moved, just update the remote_id?
-->
{% blocktrans trimmed with object_name=notification.related_object.name object_path=notification.related_object.local_path %}
<a href="{{ related_user_link }}">{{ related_user }}</a>
moved {{ object_name }}
"<a href="{{ object_path }}">{{ object_name }}</a>"
{% endblocktrans %}
<!-- TODO maybe put a brief context message here for migrated user accounts? -->
{% endblock %}