diff --git a/bookwyrm/activitypub/ordered_collection.py b/bookwyrm/activitypub/ordered_collection.py index 9aeaf664..335723f4 100644 --- a/bookwyrm/activitypub/ordered_collection.py +++ b/bookwyrm/activitypub/ordered_collection.py @@ -1,5 +1,5 @@ ''' defines activitypub collections (lists) ''' -from dataclasses import dataclass +from dataclasses import dataclass, field from typing import List from .base_activity import ActivityObject @@ -10,9 +10,12 @@ class OrderedCollection(ActivityObject): ''' structure of an ordered collection activity ''' totalItems: int first: str - last: str = '' - name: str = '' - owner: str = '' + last: str = None + name: str = None + summary: str = None + owner: str = None + to: List[str] = field(default_factory=lambda: []) + cc: List[str] = field(default_factory=lambda: []) type: str = 'OrderedCollection' diff --git a/bookwyrm/activitypub/verbs.py b/bookwyrm/activitypub/verbs.py index 6977ee8e..5502ced0 100644 --- a/bookwyrm/activitypub/verbs.py +++ b/bookwyrm/activitypub/verbs.py @@ -18,7 +18,7 @@ class Create(Verb): ''' Create activity ''' to: List cc: List - signature: Signature + signature: Signature = None type: str = 'Create' diff --git a/bookwyrm/models/base_model.py b/bookwyrm/models/base_model.py index 3f1ed66d..889eb5f4 100644 --- a/bookwyrm/models/base_model.py +++ b/bookwyrm/models/base_model.py @@ -161,16 +161,18 @@ class ActivitypubMixin: ''' returns the object wrapped in a Create activity ''' activity_object = self.to_activity(**kwargs) - signer = pkcs1_15.new(RSA.import_key(user.key_pair.private_key)) - content = activity_object['content'] - signed_message = signer.sign(SHA256.new(content.encode('utf8'))) + signature = None create_id = self.remote_id + '/activity' + if 'content' in activity_object: + signer = pkcs1_15.new(RSA.import_key(user.key_pair.private_key)) + content = activity_object['content'] + signed_message = signer.sign(SHA256.new(content.encode('utf8'))) - signature = activitypub.Signature( - creator='%s#main-key' % user.remote_id, - created=activity_object['published'], - signatureValue=b64encode(signed_message).decode('utf8') - ) + signature = activitypub.Signature( + creator='%s#main-key' % user.remote_id, + created=activity_object['published'], + signatureValue=b64encode(signed_message).decode('utf8') + ) return activitypub.Create( id=create_id, diff --git a/bookwyrm/models/list.py b/bookwyrm/models/list.py index 6ade16de..801a3f2a 100644 --- a/bookwyrm/models/list.py +++ b/bookwyrm/models/list.py @@ -19,12 +19,9 @@ class List(OrderedCollectionMixin, BookWyrmModel): name = fields.CharField(max_length=100) user = fields.ForeignKey( 'User', on_delete=models.PROTECT, activitypub_field='owner') - description = fields.TextField(blank=True, null=True) - privacy = fields.CharField( - max_length=255, - default='public', - choices=fields.PrivacyLevels.choices - ) + description = fields.TextField( + blank=True, null=True, activitypub_field='summary') + privacy = fields.PrivacyField() curation = fields.CharField( max_length=255, default='closed', diff --git a/bookwyrm/models/shelf.py b/bookwyrm/models/shelf.py index 84575137..87200f38 100644 --- a/bookwyrm/models/shelf.py +++ b/bookwyrm/models/shelf.py @@ -15,11 +15,7 @@ class Shelf(OrderedCollectionMixin, BookWyrmModel): user = fields.ForeignKey( 'User', on_delete=models.PROTECT, activitypub_field='owner') editable = models.BooleanField(default=True) - privacy = fields.CharField( - max_length=255, - default='public', - choices=fields.PrivacyLevels.choices - ) + privacy = fields.PrivacyField() books = models.ManyToManyField( 'Edition', symmetrical=False, diff --git a/bookwyrm/views/goal.py b/bookwyrm/views/goal.py index ac7a1702..0496848f 100644 --- a/bookwyrm/views/goal.py +++ b/bookwyrm/views/goal.py @@ -71,10 +71,15 @@ class Goal(View): broadcast( request.user, status.to_create_activity(request.user), + privacy=status.privacy, software='bookwyrm') # re-format the activity for non-bookwyrm servers remote_activity = status.to_create_activity(request.user, pure=True) - broadcast(request.user, remote_activity, software='other') + broadcast( + request.user, + remote_activity, + privacy=status.privacy, + software='other') return redirect(request.headers.get('Referer', '/')) diff --git a/bookwyrm/views/list.py b/bookwyrm/views/list.py index b7a8dad0..ce0cedb4 100644 --- a/bookwyrm/views/list.py +++ b/bookwyrm/views/list.py @@ -11,6 +11,7 @@ from django.views.decorators.http import require_POST from bookwyrm import forms, models from bookwyrm.activitypub import ActivitypubResponse +from bookwyrm.broadcast import broadcast from bookwyrm.connectors import connector_manager from .helpers import is_api_request, object_visible_to_user, privacy_filter from .helpers import get_user_from_username @@ -48,6 +49,14 @@ class Lists(View): if not form.is_valid(): return redirect('lists') book_list = form.save() + + # let the world know + broadcast( + request.user, + book_list.to_create_activity(request.user), + privacy=book_list.privacy, + software='bookwyrm' + ) return redirect(book_list.local_path) class UserLists(View): @@ -128,6 +137,13 @@ class List(View): if not form.is_valid(): return redirect('list', book_list.id) book_list = form.save() + # let the world know + broadcast( + request.user, + book_list.to_update_activity(request.user), + privacy=book_list.privacy, + software='bookwyrm' + ) return redirect(book_list.local_path) @@ -161,6 +177,13 @@ class Curate(View): if approved: suggestion.approved = True suggestion.save() + # let the world know + broadcast( + request.user, + suggestion.to_add_activity(request.user), + privacy=book_list.privacy, + software='bookwyrm' + ) else: suggestion.delete() return redirect('list-curate', book_list.id) @@ -177,11 +200,18 @@ def add_book(request, list_id): # do you have permission to add to the list? if request.user == book_list.user or book_list.curation == 'open': # go ahead and add it - models.ListItem.objects.create( + item = models.ListItem.objects.create( book=book, book_list=book_list, added_by=request.user, ) + # let the world know + broadcast( + request.user, + item.to_add_activity(request.user), + privacy=book_list.privacy, + software='bookwyrm' + ) elif book_list.curation == 'curated': # make a pending entry models.ListItem.objects.create( @@ -206,5 +236,13 @@ def remove_book(request, list_id): if not book_list.user == request.user and not item.added_by == request.user: return HttpResponseNotFound() + activity = item.to_remove_activity(request.user) item.delete() + # let the world know + broadcast( + request.user, + activity, + privacy=book_list.privacy, + software='bookwyrm' + ) return redirect('list', list_id) diff --git a/bookwyrm/views/shelf.py b/bookwyrm/views/shelf.py index e4c49261..ebeb6b52 100644 --- a/bookwyrm/views/shelf.py +++ b/bookwyrm/views/shelf.py @@ -138,7 +138,12 @@ def shelve(request): pass shelfbook = models.ShelfBook.objects.create( book=book, shelf=desired_shelf, added_by=request.user) - broadcast(request.user, shelfbook.to_add_activity(request.user)) + broadcast( + request.user, + shelfbook.to_add_activity(request.user), + privacy=shelfbook.shelf.privacy, + software='bookwyrm' + ) # post about "want to read" shelves if desired_shelf.identifier == 'to-read': @@ -146,7 +151,6 @@ def shelve(request): request.user, desired_shelf, book, - privacy=desired_shelf.privacy ) return redirect('/') @@ -169,4 +173,4 @@ def handle_unshelve(user, book, shelf): activity = row.to_remove_activity(user) row.delete() - broadcast(user, activity) + broadcast(user, activity, privacy=shelf.privacy, software='bookwyrm')