forked from mirrors/bookwyrm
Serialize lists as custom activitypub object
This commit is contained in:
parent
d37f8f68d8
commit
e61d8b7638
7 changed files with 53 additions and 27 deletions
|
@ -10,6 +10,7 @@ from .note import Note, GeneratedNote, Article, Comment, Review, Quotation
|
||||||
from .note import Tombstone
|
from .note import Tombstone
|
||||||
from .interaction import Boost, Like
|
from .interaction import Boost, Like
|
||||||
from .ordered_collection import OrderedCollection, OrderedCollectionPage
|
from .ordered_collection import OrderedCollection, OrderedCollectionPage
|
||||||
|
from .ordered_collection import BookList
|
||||||
from .person import Person, PublicKey
|
from .person import Person, PublicKey
|
||||||
from .response import ActivitypubResponse
|
from .response import ActivitypubResponse
|
||||||
from .book import Edition, Work, Author
|
from .book import Edition, Work, Author
|
||||||
|
|
|
@ -130,6 +130,7 @@ class ActivityObject:
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
''' convert to dictionary with context attr '''
|
''' convert to dictionary with context attr '''
|
||||||
data = self.__dict__
|
data = self.__dict__
|
||||||
|
data = {k:v for (k, v) in data.items() if v is not None}
|
||||||
data['@context'] = 'https://www.w3.org/ns/activitystreams'
|
data['@context'] = 'https://www.w3.org/ns/activitystreams'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
|
@ -12,13 +12,20 @@ class OrderedCollection(ActivityObject):
|
||||||
first: str
|
first: str
|
||||||
last: str = None
|
last: str = None
|
||||||
name: str = None
|
name: str = None
|
||||||
summary: str = None
|
|
||||||
owner: str = None
|
owner: str = None
|
||||||
to: List[str] = field(default_factory=lambda: [])
|
to: List[str] = field(default_factory=lambda: [])
|
||||||
cc: List[str] = field(default_factory=lambda: [])
|
cc: List[str] = field(default_factory=lambda: [])
|
||||||
type: str = 'OrderedCollection'
|
type: str = 'OrderedCollection'
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(init=False)
|
||||||
|
class BookList(OrderedCollection):
|
||||||
|
''' structure of an ordered collection activity '''
|
||||||
|
summary: str = None
|
||||||
|
curation: str = 'closed'
|
||||||
|
type: str = 'List'
|
||||||
|
|
||||||
|
|
||||||
@dataclass(init=False)
|
@dataclass(init=False)
|
||||||
class OrderedCollectionPage(ActivityObject):
|
class OrderedCollectionPage(ActivityObject):
|
||||||
''' structure of an ordered collection activity '''
|
''' structure of an ordered collection activity '''
|
||||||
|
|
|
@ -140,20 +140,7 @@ class ActivitypubMixin:
|
||||||
|
|
||||||
def to_activity(self):
|
def to_activity(self):
|
||||||
''' convert from a model to an activity '''
|
''' convert from a model to an activity '''
|
||||||
activity = {}
|
activity = generate_activity(self)
|
||||||
for field in self.activity_fields:
|
|
||||||
field.set_activity_from_field(activity, self)
|
|
||||||
|
|
||||||
if hasattr(self, 'serialize_reverse_fields'):
|
|
||||||
# for example, editions of a work
|
|
||||||
for model_field_name, activity_field_name, sort_field in \
|
|
||||||
self.serialize_reverse_fields:
|
|
||||||
related_field = getattr(self, model_field_name)
|
|
||||||
activity[activity_field_name] = \
|
|
||||||
unfurl_related_field(related_field, sort_field)
|
|
||||||
|
|
||||||
if not activity.get('id'):
|
|
||||||
activity['id'] = self.get_remote_id()
|
|
||||||
return self.activity_serializer(**activity).serialize()
|
return self.activity_serializer(**activity).serialize()
|
||||||
|
|
||||||
|
|
||||||
|
@ -225,7 +212,7 @@ class OrderedCollectionPageMixin(ActivitypubMixin):
|
||||||
|
|
||||||
|
|
||||||
def to_ordered_collection(self, queryset, \
|
def to_ordered_collection(self, queryset, \
|
||||||
remote_id=None, page=False, **kwargs):
|
remote_id=None, page=False, collection_only=False, **kwargs):
|
||||||
''' an ordered collection of whatevers '''
|
''' an ordered collection of whatevers '''
|
||||||
if not queryset.ordered:
|
if not queryset.ordered:
|
||||||
raise RuntimeError('queryset must be ordered')
|
raise RuntimeError('queryset must be ordered')
|
||||||
|
@ -234,18 +221,24 @@ class OrderedCollectionPageMixin(ActivitypubMixin):
|
||||||
if page:
|
if page:
|
||||||
return to_ordered_collection_page(
|
return to_ordered_collection_page(
|
||||||
queryset, remote_id, **kwargs)
|
queryset, remote_id, **kwargs)
|
||||||
name = self.name if hasattr(self, 'name') else None
|
|
||||||
owner = self.user.remote_id if hasattr(self, 'user') else ''
|
if collection_only or not hasattr(self, 'activity_serializer'):
|
||||||
|
serializer = activitypub.OrderedCollection
|
||||||
|
activity = {}
|
||||||
|
else:
|
||||||
|
serializer = self.activity_serializer
|
||||||
|
# a dict from the model fields
|
||||||
|
activity = generate_activity(self)
|
||||||
|
if remote_id:
|
||||||
|
activity['id'] = remote_id
|
||||||
|
|
||||||
paginated = Paginator(queryset, PAGE_LENGTH)
|
paginated = Paginator(queryset, PAGE_LENGTH)
|
||||||
return activitypub.OrderedCollection(
|
# add computed fields specific to orderd collections
|
||||||
id=remote_id,
|
activity['totalItems'] = paginated.count
|
||||||
totalItems=paginated.count,
|
activity['first'] = '%s?page=1' % remote_id
|
||||||
name=name,
|
activity['last'] = '%s?page=%d' % (remote_id, paginated.num_pages)
|
||||||
owner=owner,
|
|
||||||
first='%s?page=1' % remote_id,
|
return serializer(**activity).serialize()
|
||||||
last='%s?page=%d' % (remote_id, paginated.num_pages)
|
|
||||||
).serialize()
|
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
|
@ -287,3 +280,22 @@ class OrderedCollectionMixin(OrderedCollectionPageMixin):
|
||||||
def to_activity(self, **kwargs):
|
def to_activity(self, **kwargs):
|
||||||
''' an ordered collection of the specified model queryset '''
|
''' an ordered collection of the specified model queryset '''
|
||||||
return self.to_ordered_collection(self.collection_queryset, **kwargs)
|
return self.to_ordered_collection(self.collection_queryset, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_activity(obj):
|
||||||
|
''' go through the fields on an object '''
|
||||||
|
activity = {}
|
||||||
|
for field in obj.activity_fields:
|
||||||
|
field.set_activity_from_field(activity, obj)
|
||||||
|
|
||||||
|
if hasattr(obj, 'serialize_reverse_fields'):
|
||||||
|
# for example, editions of a work
|
||||||
|
for model_field_name, activity_field_name, sort_field in \
|
||||||
|
obj.serialize_reverse_fields:
|
||||||
|
related_field = getattr(obj, model_field_name)
|
||||||
|
activity[activity_field_name] = \
|
||||||
|
unfurl_related_field(related_field, sort_field)
|
||||||
|
|
||||||
|
if not activity.get('id'):
|
||||||
|
activity['id'] = obj.get_remote_id()
|
||||||
|
return activity
|
||||||
|
|
|
@ -213,7 +213,10 @@ class PrivacyField(ActivitypubFieldMixin, models.CharField):
|
||||||
setattr(instance, self.name, 'followers')
|
setattr(instance, self.name, 'followers')
|
||||||
|
|
||||||
def set_activity_from_field(self, activity, instance):
|
def set_activity_from_field(self, activity, instance):
|
||||||
mentions = [u.remote_id for u in instance.mention_users.all()]
|
# explicitly to anyone mentioned (statuses only)
|
||||||
|
mentions = []
|
||||||
|
if hasattr(instance, 'mention_users'):
|
||||||
|
mentions = [u.remote_id for u in instance.mention_users.all()]
|
||||||
# this is a link to the followers list
|
# this is a link to the followers list
|
||||||
followers = instance.user.__class__._meta.get_field('followers')\
|
followers = instance.user.__class__._meta.get_field('followers')\
|
||||||
.field_to_activity(instance.user.followers)
|
.field_to_activity(instance.user.followers)
|
||||||
|
|
|
@ -33,6 +33,7 @@ class List(OrderedCollectionMixin, BookWyrmModel):
|
||||||
through='ListItem',
|
through='ListItem',
|
||||||
through_fields=('book_list', 'book'),
|
through_fields=('book_list', 'book'),
|
||||||
)
|
)
|
||||||
|
activity_serializer = activitypub.BookList
|
||||||
|
|
||||||
def get_remote_id(self):
|
def get_remote_id(self):
|
||||||
''' don't want the user to be in there in this case '''
|
''' don't want the user to be in there in this case '''
|
||||||
|
|
|
@ -94,6 +94,7 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
||||||
return self.to_ordered_collection(
|
return self.to_ordered_collection(
|
||||||
self.replies(self),
|
self.replies(self),
|
||||||
remote_id='%s/replies' % self.remote_id,
|
remote_id='%s/replies' % self.remote_id,
|
||||||
|
collection_only=True,
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue