forked from mirrors/bookwyrm
Creates Privacy field that handles setting to/cc
This commit is contained in:
parent
c470aeb3ce
commit
b6907f39e9
5 changed files with 70 additions and 49 deletions
|
@ -17,13 +17,6 @@ from bookwyrm.settings import DOMAIN, PAGE_LENGTH
|
|||
from .fields import ImageField, ManyToManyField, RemoteIdField
|
||||
|
||||
|
||||
PrivacyLevels = models.TextChoices('Privacy', [
|
||||
'public',
|
||||
'unlisted',
|
||||
'followers',
|
||||
'direct'
|
||||
])
|
||||
|
||||
class BookWyrmModel(models.Model):
|
||||
''' shared fields '''
|
||||
created_date = models.DateTimeField(auto_now_add=True)
|
||||
|
@ -84,6 +77,9 @@ class ActivitypubMixin:
|
|||
else:
|
||||
self.simple_fields.append(field)
|
||||
|
||||
self.activity_fields = self.image_fields + \
|
||||
self.many_to_many_fields + self.simple_fields
|
||||
|
||||
self.deserialize_reverse_fields = self.deserialize_reverse_fields \
|
||||
if hasattr(self, 'deserialize_reverse_fields') else []
|
||||
self.serialize_reverse_fields = self.serialize_reverse_fields \
|
||||
|
@ -139,19 +135,8 @@ class ActivitypubMixin:
|
|||
def to_activity(self):
|
||||
''' convert from a model to an activity '''
|
||||
activity = {}
|
||||
for field in self._meta.get_fields():
|
||||
if not hasattr(field, 'field_to_activity'):
|
||||
continue
|
||||
value = field.field_to_activity(getattr(self, field.name))
|
||||
if value is None:
|
||||
continue
|
||||
|
||||
key = field.get_activitypub_field()
|
||||
if key in activity and isinstance(activity[key], list):
|
||||
# handles tags on status, which accumulate across fields
|
||||
activity[key] += value
|
||||
else:
|
||||
activity[key] = value
|
||||
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
|
||||
|
|
|
@ -49,6 +49,20 @@ class ActivitypubFieldMixin:
|
|||
setattr(instance, self.name, formatted)
|
||||
|
||||
|
||||
def set_activity_from_field(self, activity, instance):
|
||||
''' update the json object '''
|
||||
value = getattr(instance, self.name)
|
||||
formatted = self.field_to_activity(value)
|
||||
if formatted is None:
|
||||
return
|
||||
|
||||
key = self.get_activitypub_field()
|
||||
if isinstance(activity.get(key), list):
|
||||
activity[key] += formatted
|
||||
else:
|
||||
activity[key] = value
|
||||
|
||||
|
||||
def field_to_activity(self, value):
|
||||
''' formatter to convert a model value into activitypub '''
|
||||
if hasattr(self, 'activitypub_wrapper'):
|
||||
|
@ -134,6 +148,52 @@ class UsernameField(ActivitypubFieldMixin, models.CharField):
|
|||
return value.split('@')[0]
|
||||
|
||||
|
||||
PrivacyLevels = models.TextChoices('Privacy', [
|
||||
'public',
|
||||
'unlisted',
|
||||
'followers',
|
||||
'direct'
|
||||
])
|
||||
|
||||
class PrivacyField(ActivitypubFieldMixin, models.CharField):
|
||||
''' this maps to two differente activitypub fields '''
|
||||
public = 'https://www.w3.org/ns/activitystreams#Public'
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(
|
||||
*args, max_length=255,
|
||||
choices=PrivacyLevels.choices, default='public')
|
||||
|
||||
def set_field_from_activity(self, instance, data):
|
||||
to = data.to
|
||||
cc = data.cc
|
||||
if to == [self.public]:
|
||||
setattr(instance, self.name, 'public')
|
||||
elif cc == []:
|
||||
setattr(instance, self.name, 'direct')
|
||||
elif self.public in cc:
|
||||
setattr(instance, self.name, 'unlisted')
|
||||
else:
|
||||
setattr(instance, self.name, 'followers')
|
||||
|
||||
def set_activity_from_field(self, activity, instance):
|
||||
mentions = [u.remote_id for u in instance.mention_users.all()]
|
||||
# this is a link to the followers list
|
||||
followers = instance.user.__class__._meta.get_field('followers')\
|
||||
.field_to_activity(instance.user.followers)
|
||||
if self.privacy == 'public':
|
||||
activity['to'] = [self.public]
|
||||
activity['cc'] = [followers] + mentions
|
||||
elif self.privacy == 'unlisted':
|
||||
activity['to'] = [followers]
|
||||
activity['cc'] = [self.public] + mentions
|
||||
elif self.privacy == 'followers':
|
||||
activity['to'] = [followers]
|
||||
activity['cc'] = mentions
|
||||
if self.privacy == 'direct':
|
||||
activity['to'] = mentions
|
||||
activity['cc'] = []
|
||||
|
||||
|
||||
class ForeignKey(ActivitypubRelatedFieldMixin, models.ForeignKey):
|
||||
''' activitypub-aware foreign key field '''
|
||||
def field_to_activity(self, value):
|
||||
|
|
|
@ -8,7 +8,7 @@ from django.utils import timezone
|
|||
|
||||
from bookwyrm import books_manager
|
||||
from bookwyrm.models import ReadThrough, User, Book
|
||||
from .base_model import PrivacyLevels
|
||||
from .fields import PrivacyLevels
|
||||
|
||||
|
||||
# Mapping goodreads -> bookwyrm shelf titles.
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.db import models
|
|||
|
||||
from bookwyrm import activitypub
|
||||
from .base_model import BookWyrmModel
|
||||
from .base_model import OrderedCollectionMixin, PrivacyLevels
|
||||
from .base_model import OrderedCollectionMixin
|
||||
from . import fields
|
||||
|
||||
|
||||
|
@ -18,7 +18,7 @@ class Shelf(OrderedCollectionMixin, BookWyrmModel):
|
|||
privacy = fields.CharField(
|
||||
max_length=255,
|
||||
default='public',
|
||||
choices=PrivacyLevels.choices
|
||||
choices=fields.PrivacyLevels.choices
|
||||
)
|
||||
books = models.ManyToManyField(
|
||||
'Edition',
|
||||
|
|
|
@ -6,7 +6,7 @@ from model_utils.managers import InheritanceManager
|
|||
|
||||
from bookwyrm import activitypub
|
||||
from .base_model import ActivitypubMixin, OrderedCollectionPageMixin
|
||||
from .base_model import BookWyrmModel, PrivacyLevels
|
||||
from .base_model import BookWyrmModel
|
||||
from . import fields
|
||||
from .fields import image_serializer
|
||||
|
||||
|
@ -18,11 +18,7 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
|||
mention_users = fields.TagField('User', related_name='mention_user')
|
||||
mention_books = fields.TagField('Edition', related_name='mention_book')
|
||||
local = models.BooleanField(default=True)
|
||||
privacy = models.CharField(
|
||||
max_length=255,
|
||||
default='public',
|
||||
choices=PrivacyLevels.choices
|
||||
)
|
||||
privacy = fields.PrivacyField(max_length=255)
|
||||
sensitive = fields.BooleanField(default=False)
|
||||
# created date is different than publish date because of federated posts
|
||||
published_date = fields.DateTimeField(
|
||||
|
@ -48,7 +44,6 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
|||
serialize_reverse_fields = [('attachments', 'attachment')]
|
||||
deserialize_reverse_fields = [('attachments', 'attachment')]
|
||||
|
||||
#----- replies collection activitypub ----#
|
||||
@classmethod
|
||||
def replies(cls, status):
|
||||
''' load all replies to a status. idk if there's a better way
|
||||
|
@ -82,25 +77,6 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
|||
activity = ActivitypubMixin.to_activity(self)
|
||||
activity['replies'] = self.to_replies()
|
||||
|
||||
# privacy controls
|
||||
public = 'https://www.w3.org/ns/activitystreams#Public'
|
||||
mentions = [u.remote_id for u in self.mention_users.all()]
|
||||
# this is a link to the followers list:
|
||||
followers = self.user.__class__._meta.get_field('followers')\
|
||||
.field_to_activity(self.user.followers)
|
||||
if self.privacy == 'public':
|
||||
activity['to'] = [public]
|
||||
activity['cc'] = [followers] + mentions
|
||||
elif self.privacy == 'unlisted':
|
||||
activity['to'] = [followers]
|
||||
activity['cc'] = [public] + mentions
|
||||
elif self.privacy == 'followers':
|
||||
activity['to'] = [followers]
|
||||
activity['cc'] = mentions
|
||||
if self.privacy == 'direct':
|
||||
activity['to'] = mentions
|
||||
activity['cc'] = []
|
||||
|
||||
# "pure" serialization for non-bookwyrm instances
|
||||
if pure:
|
||||
activity['content'] = self.pure_content
|
||||
|
|
Loading…
Reference in a new issue