mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-11-27 20:11:14 +00:00
Created mixin for ordered collection items
This commit is contained in:
parent
12e0e6a1f0
commit
feb8190d8f
4 changed files with 76 additions and 72 deletions
|
@ -16,6 +16,7 @@ from django.db.models import Q
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.utils.http import http_date
|
from django.utils.http import http_date
|
||||||
|
|
||||||
|
|
||||||
from bookwyrm import activitypub
|
from bookwyrm import activitypub
|
||||||
from bookwyrm.settings import PAGE_LENGTH, USER_AGENT
|
from bookwyrm.settings import PAGE_LENGTH, USER_AGENT
|
||||||
from bookwyrm.signatures import make_signature, make_digest
|
from bookwyrm.signatures import make_signature, make_digest
|
||||||
|
@ -55,6 +56,10 @@ class ActivitypubMixin:
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def delete(self, *args, **kwargs):
|
||||||
|
''' broadcast suitable delete activities '''
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def find_existing_by_remote_id(cls, remote_id):
|
def find_existing_by_remote_id(cls, remote_id):
|
||||||
''' look up a remote id in the db '''
|
''' look up a remote id in the db '''
|
||||||
|
@ -293,6 +298,34 @@ class OrderedCollectionMixin(OrderedCollectionPageMixin):
|
||||||
return self.to_ordered_collection(self.collection_queryset, **kwargs)
|
return self.to_ordered_collection(self.collection_queryset, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class CollectionItemMixin(ActivitypubMixin):
|
||||||
|
''' for items that are part of an (Ordered)Collection '''
|
||||||
|
activity_serializer = activitypub.Add
|
||||||
|
object_field = collection_field = None
|
||||||
|
|
||||||
|
def to_add_activity(self):
|
||||||
|
''' AP for shelving a book'''
|
||||||
|
object_field = getattr(self, self.object_field)
|
||||||
|
collection_field = getattr(self, self.collection_field)
|
||||||
|
return activitypub.Add(
|
||||||
|
id='%s#add' % self.remote_id,
|
||||||
|
actor=self.user.remote_id,
|
||||||
|
object=object_field.to_activity(),
|
||||||
|
target=collection_field.remote_id
|
||||||
|
).serialize()
|
||||||
|
|
||||||
|
def to_remove_activity(self):
|
||||||
|
''' AP for un-shelving a book'''
|
||||||
|
object_field = getattr(self, self.object_field)
|
||||||
|
collection_field = getattr(self, self.collection_field)
|
||||||
|
return activitypub.Remove(
|
||||||
|
id='%s#remove' % self.remote_id,
|
||||||
|
actor=self.user.remote_id,
|
||||||
|
object=object_field.to_activity(),
|
||||||
|
target=collection_field.remote_id
|
||||||
|
).serialize()
|
||||||
|
|
||||||
|
|
||||||
def generate_activity(obj):
|
def generate_activity(obj):
|
||||||
''' go through the fields on an object '''
|
''' go through the fields on an object '''
|
||||||
activity = {}
|
activity = {}
|
||||||
|
@ -371,15 +404,35 @@ def sign_and_send(sender, data, destination):
|
||||||
def execute_after_save(sender, instance, created, *args, **kwargs):
|
def execute_after_save(sender, instance, created, *args, **kwargs):
|
||||||
''' broadcast when a model instance is created or updated '''
|
''' broadcast when a model instance is created or updated '''
|
||||||
# user content like statuses, lists, and shelves, have a "user" field
|
# user content like statuses, lists, and shelves, have a "user" field
|
||||||
if created:
|
user = instance.user if hasattr(instance, 'user') else None
|
||||||
if not hasattr(instance, 'user'):
|
if user and not user.local:
|
||||||
# book data and users don't need to broadcast on creation
|
|
||||||
return
|
|
||||||
# we don't want to broadcast when we save remote activities
|
# we don't want to broadcast when we save remote activities
|
||||||
if not instance.user.local:
|
|
||||||
return
|
|
||||||
activity = instance.to_create_activity(instance.user)
|
|
||||||
instance.broadcast(activity, instance.user)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# now, handle updates
|
if created:
|
||||||
|
if not user:
|
||||||
|
# book data and users don't need to broadcast on creation
|
||||||
|
return
|
||||||
|
|
||||||
|
# ordered collection items get "Add"ed
|
||||||
|
if hasattr(instance, 'to_add_activity'):
|
||||||
|
activity = instance.to_add_activity()
|
||||||
|
else:
|
||||||
|
# everything else gets "Create"d
|
||||||
|
activity = instance.to_create_activity(user)
|
||||||
|
else:
|
||||||
|
# now, handle updates
|
||||||
|
if not user:
|
||||||
|
# users don't have associated users, they ARE users
|
||||||
|
if sender.__class__ == 'User':
|
||||||
|
user = instance
|
||||||
|
# book data trakcs last editor
|
||||||
|
elif hasattr(instance, 'last_edited_by'):
|
||||||
|
user = instance.last_edited_by
|
||||||
|
# again, if we don't know the user or they're remote, don't bother
|
||||||
|
if not user or not user.local:
|
||||||
|
return
|
||||||
|
activity = instance.to_update_activity(user)
|
||||||
|
|
||||||
|
if activity and user and user.local:
|
||||||
|
instance.broadcast(activity, user)
|
||||||
|
|
|
@ -3,7 +3,7 @@ from django.db import models
|
||||||
|
|
||||||
from bookwyrm import activitypub
|
from bookwyrm import activitypub
|
||||||
from bookwyrm.settings import DOMAIN
|
from bookwyrm.settings import DOMAIN
|
||||||
from .activitypub_mixin import ActivitypubMixin, OrderedCollectionMixin
|
from .activitypub_mixin import CollectionItemMixin, OrderedCollectionMixin
|
||||||
from .base_model import BookWyrmModel
|
from .base_model import BookWyrmModel
|
||||||
from . import fields
|
from . import fields
|
||||||
|
|
||||||
|
@ -49,13 +49,13 @@ class List(OrderedCollectionMixin, BookWyrmModel):
|
||||||
ordering = ('-updated_date',)
|
ordering = ('-updated_date',)
|
||||||
|
|
||||||
|
|
||||||
class ListItem(ActivitypubMixin, BookWyrmModel):
|
class ListItem(CollectionItemMixin, BookWyrmModel):
|
||||||
''' ok '''
|
''' ok '''
|
||||||
book = fields.ForeignKey(
|
book = fields.ForeignKey(
|
||||||
'Edition', on_delete=models.PROTECT, activitypub_field='object')
|
'Edition', on_delete=models.PROTECT, activitypub_field='object')
|
||||||
book_list = fields.ForeignKey(
|
book_list = fields.ForeignKey(
|
||||||
'List', on_delete=models.CASCADE, activitypub_field='target')
|
'List', on_delete=models.CASCADE, activitypub_field='target')
|
||||||
added_by = fields.ForeignKey(
|
user = fields.ForeignKey(
|
||||||
'User',
|
'User',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
activitypub_field='actor'
|
activitypub_field='actor'
|
||||||
|
@ -66,24 +66,8 @@ class ListItem(ActivitypubMixin, BookWyrmModel):
|
||||||
endorsement = models.ManyToManyField('User', related_name='endorsers')
|
endorsement = models.ManyToManyField('User', related_name='endorsers')
|
||||||
|
|
||||||
activity_serializer = activitypub.AddBook
|
activity_serializer = activitypub.AddBook
|
||||||
|
object_field = 'book'
|
||||||
def to_add_activity(self, user):
|
collection_field = 'book_list'
|
||||||
''' AP for shelving a book'''
|
|
||||||
return activitypub.Add(
|
|
||||||
id='%s#add' % self.remote_id,
|
|
||||||
actor=user.remote_id,
|
|
||||||
object=self.book.to_activity(),
|
|
||||||
target=self.book_list.remote_id,
|
|
||||||
).serialize()
|
|
||||||
|
|
||||||
def to_remove_activity(self, user):
|
|
||||||
''' AP for un-shelving a book'''
|
|
||||||
return activitypub.Remove(
|
|
||||||
id='%s#remove' % self.remote_id,
|
|
||||||
actor=user.remote_id,
|
|
||||||
object=self.book.to_activity(),
|
|
||||||
target=self.book_list.remote_id
|
|
||||||
).serialize()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
''' an opinionated constraint! you can't put a book on a list twice '''
|
''' an opinionated constraint! you can't put a book on a list twice '''
|
||||||
|
|
|
@ -3,7 +3,7 @@ import re
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from bookwyrm import activitypub
|
from bookwyrm import activitypub
|
||||||
from .activitypub_mixin import ActivitypubMixin, OrderedCollectionMixin
|
from .activitypub_mixin import CollectionItemMixin, OrderedCollectionMixin
|
||||||
from .base_model import BookWyrmModel
|
from .base_model import BookWyrmModel
|
||||||
from . import fields
|
from . import fields
|
||||||
|
|
||||||
|
@ -49,13 +49,13 @@ class Shelf(OrderedCollectionMixin, BookWyrmModel):
|
||||||
unique_together = ('user', 'identifier')
|
unique_together = ('user', 'identifier')
|
||||||
|
|
||||||
|
|
||||||
class ShelfBook(ActivitypubMixin, BookWyrmModel):
|
class ShelfBook(CollectionItemMixin, BookWyrmModel):
|
||||||
''' many to many join table for books and shelves '''
|
''' many to many join table for books and shelves '''
|
||||||
book = fields.ForeignKey(
|
book = fields.ForeignKey(
|
||||||
'Edition', on_delete=models.PROTECT, activitypub_field='object')
|
'Edition', on_delete=models.PROTECT, activitypub_field='object')
|
||||||
shelf = fields.ForeignKey(
|
shelf = fields.ForeignKey(
|
||||||
'Shelf', on_delete=models.PROTECT, activitypub_field='target')
|
'Shelf', on_delete=models.PROTECT, activitypub_field='target')
|
||||||
added_by = fields.ForeignKey(
|
user = fields.ForeignKey(
|
||||||
'User',
|
'User',
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
|
@ -64,24 +64,8 @@ class ShelfBook(ActivitypubMixin, BookWyrmModel):
|
||||||
)
|
)
|
||||||
|
|
||||||
activity_serializer = activitypub.AddBook
|
activity_serializer = activitypub.AddBook
|
||||||
|
object_field = 'book'
|
||||||
def to_add_activity(self, user):
|
collection_field = 'shelf'
|
||||||
''' AP for shelving a book'''
|
|
||||||
return activitypub.Add(
|
|
||||||
id='%s#add' % self.remote_id,
|
|
||||||
actor=user.remote_id,
|
|
||||||
object=self.book.to_activity(),
|
|
||||||
target=self.shelf.remote_id,
|
|
||||||
).serialize()
|
|
||||||
|
|
||||||
def to_remove_activity(self, user):
|
|
||||||
''' AP for un-shelving a book'''
|
|
||||||
return activitypub.Remove(
|
|
||||||
id='%s#remove' % self.remote_id,
|
|
||||||
actor=user.remote_id,
|
|
||||||
object=self.book.to_activity(),
|
|
||||||
target=self.shelf.to_activity()
|
|
||||||
).serialize()
|
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -5,7 +5,7 @@ from django.db import models
|
||||||
|
|
||||||
from bookwyrm import activitypub
|
from bookwyrm import activitypub
|
||||||
from bookwyrm.settings import DOMAIN
|
from bookwyrm.settings import DOMAIN
|
||||||
from .activitypub_mixin import OrderedCollectionMixin
|
from .activitypub_mixin import CollectionItemMixin, OrderedCollectionMixin
|
||||||
from .base_model import BookWyrmModel
|
from .base_model import BookWyrmModel
|
||||||
from . import fields
|
from . import fields
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ class Tag(OrderedCollectionMixin, BookWyrmModel):
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class UserTag(BookWyrmModel):
|
class UserTag(CollectionItemMixin, BookWyrmModel):
|
||||||
''' an instance of a tag on a book by a user '''
|
''' an instance of a tag on a book by a user '''
|
||||||
user = fields.ForeignKey(
|
user = fields.ForeignKey(
|
||||||
'User', on_delete=models.PROTECT, activitypub_field='actor')
|
'User', on_delete=models.PROTECT, activitypub_field='actor')
|
||||||
|
@ -51,25 +51,8 @@ class UserTag(BookWyrmModel):
|
||||||
'Tag', on_delete=models.PROTECT, activitypub_field='target')
|
'Tag', on_delete=models.PROTECT, activitypub_field='target')
|
||||||
|
|
||||||
activity_serializer = activitypub.AddBook
|
activity_serializer = activitypub.AddBook
|
||||||
|
object_field = 'book'
|
||||||
def to_add_activity(self, user):
|
collection_field = 'tag'
|
||||||
''' AP for shelving a book'''
|
|
||||||
return activitypub.Add(
|
|
||||||
id='%s#add' % self.remote_id,
|
|
||||||
actor=user.remote_id,
|
|
||||||
object=self.book.to_activity(),
|
|
||||||
target=self.remote_id,
|
|
||||||
).serialize()
|
|
||||||
|
|
||||||
def to_remove_activity(self, user):
|
|
||||||
''' AP for un-shelving a book'''
|
|
||||||
return activitypub.Remove(
|
|
||||||
id='%s#remove' % self.remote_id,
|
|
||||||
actor=user.remote_id,
|
|
||||||
object=self.book.to_activity(),
|
|
||||||
target=self.remote_id,
|
|
||||||
).serialize()
|
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
''' unqiueness constraint '''
|
''' unqiueness constraint '''
|
||||||
|
|
Loading…
Reference in a new issue