Runs black
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
''' defines relationships between users '''
|
||||
""" defines relationships between users """
|
||||
from django.apps import apps
|
||||
from django.db import models, transaction, IntegrityError
|
||||
from django.db.models import Q
|
||||
@ -11,71 +11,74 @@ from . import fields
|
||||
|
||||
|
||||
class UserRelationship(BookWyrmModel):
|
||||
''' many-to-many through table for followers '''
|
||||
""" many-to-many through table for followers """
|
||||
|
||||
user_subject = fields.ForeignKey(
|
||||
'User',
|
||||
"User",
|
||||
on_delete=models.PROTECT,
|
||||
related_name='%(class)s_user_subject',
|
||||
activitypub_field='actor',
|
||||
related_name="%(class)s_user_subject",
|
||||
activitypub_field="actor",
|
||||
)
|
||||
user_object = fields.ForeignKey(
|
||||
'User',
|
||||
"User",
|
||||
on_delete=models.PROTECT,
|
||||
related_name='%(class)s_user_object',
|
||||
activitypub_field='object',
|
||||
related_name="%(class)s_user_object",
|
||||
activitypub_field="object",
|
||||
)
|
||||
|
||||
@property
|
||||
def privacy(self):
|
||||
''' all relationships are handled directly with the participants '''
|
||||
return 'direct'
|
||||
""" all relationships are handled directly with the participants """
|
||||
return "direct"
|
||||
|
||||
@property
|
||||
def recipients(self):
|
||||
''' the remote user needs to recieve direct broadcasts '''
|
||||
""" the remote user needs to recieve direct broadcasts """
|
||||
return [u for u in [self.user_subject, self.user_object] if not u.local]
|
||||
|
||||
class Meta:
|
||||
''' relationships should be unique '''
|
||||
""" relationships should be unique """
|
||||
|
||||
abstract = True
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=['user_subject', 'user_object'],
|
||||
name='%(class)s_unique'
|
||||
fields=["user_subject", "user_object"], name="%(class)s_unique"
|
||||
),
|
||||
models.CheckConstraint(
|
||||
check=~models.Q(user_subject=models.F('user_object')),
|
||||
name='%(class)s_no_self'
|
||||
)
|
||||
check=~models.Q(user_subject=models.F("user_object")),
|
||||
name="%(class)s_no_self",
|
||||
),
|
||||
]
|
||||
|
||||
def get_remote_id(self, status=None):# pylint: disable=arguments-differ
|
||||
''' use shelf identifier in remote_id '''
|
||||
status = status or 'follows'
|
||||
def get_remote_id(self, status=None): # pylint: disable=arguments-differ
|
||||
""" use shelf identifier in remote_id """
|
||||
status = status or "follows"
|
||||
base_path = self.user_subject.remote_id
|
||||
return '%s#%s/%d' % (base_path, status, self.id)
|
||||
return "%s#%s/%d" % (base_path, status, self.id)
|
||||
|
||||
|
||||
class UserFollows(ActivityMixin, UserRelationship):
|
||||
''' Following a user '''
|
||||
status = 'follows'
|
||||
""" Following a user """
|
||||
|
||||
status = "follows"
|
||||
|
||||
def to_activity(self):
|
||||
''' overrides default to manually set serializer '''
|
||||
""" overrides default to manually set serializer """
|
||||
return activitypub.Follow(**generate_activity(self))
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
''' really really don't let a user follow someone who blocked them '''
|
||||
""" really really don't let a user follow someone who blocked them """
|
||||
# blocking in either direction is a no-go
|
||||
if UserBlocks.objects.filter(
|
||||
Q(
|
||||
user_subject=self.user_subject,
|
||||
user_object=self.user_object,
|
||||
) | Q(
|
||||
user_subject=self.user_object,
|
||||
user_object=self.user_subject,
|
||||
)
|
||||
).exists():
|
||||
Q(
|
||||
user_subject=self.user_subject,
|
||||
user_object=self.user_object,
|
||||
)
|
||||
| Q(
|
||||
user_subject=self.user_object,
|
||||
user_object=self.user_subject,
|
||||
)
|
||||
).exists():
|
||||
raise IntegrityError()
|
||||
# don't broadcast this type of relationship -- accepts and requests
|
||||
# are handled by the UserFollowRequest model
|
||||
@ -83,7 +86,7 @@ class UserFollows(ActivityMixin, UserRelationship):
|
||||
|
||||
@classmethod
|
||||
def from_request(cls, follow_request):
|
||||
''' converts a follow request into a follow relationship '''
|
||||
""" converts a follow request into a follow relationship """
|
||||
return cls.objects.create(
|
||||
user_subject=follow_request.user_subject,
|
||||
user_object=follow_request.user_object,
|
||||
@ -92,28 +95,30 @@ class UserFollows(ActivityMixin, UserRelationship):
|
||||
|
||||
|
||||
class UserFollowRequest(ActivitypubMixin, UserRelationship):
|
||||
''' following a user requires manual or automatic confirmation '''
|
||||
status = 'follow_request'
|
||||
""" following a user requires manual or automatic confirmation """
|
||||
|
||||
status = "follow_request"
|
||||
activity_serializer = activitypub.Follow
|
||||
|
||||
def save(self, *args, broadcast=True, **kwargs):
|
||||
''' make sure the follow or block relationship doesn't already exist '''
|
||||
""" make sure the follow or block relationship doesn't already exist """
|
||||
# don't create a request if a follow already exists
|
||||
if UserFollows.objects.filter(
|
||||
user_subject=self.user_subject,
|
||||
user_object=self.user_object,
|
||||
).exists():
|
||||
user_subject=self.user_subject,
|
||||
user_object=self.user_object,
|
||||
).exists():
|
||||
raise IntegrityError()
|
||||
# blocking in either direction is a no-go
|
||||
if UserBlocks.objects.filter(
|
||||
Q(
|
||||
user_subject=self.user_subject,
|
||||
user_object=self.user_object,
|
||||
) | Q(
|
||||
user_subject=self.user_object,
|
||||
user_object=self.user_subject,
|
||||
)
|
||||
).exists():
|
||||
Q(
|
||||
user_subject=self.user_subject,
|
||||
user_object=self.user_object,
|
||||
)
|
||||
| Q(
|
||||
user_subject=self.user_object,
|
||||
user_object=self.user_subject,
|
||||
)
|
||||
).exists():
|
||||
raise IntegrityError()
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
@ -125,39 +130,35 @@ class UserFollowRequest(ActivitypubMixin, UserRelationship):
|
||||
if not manually_approves:
|
||||
self.accept()
|
||||
|
||||
model = apps.get_model('bookwyrm.Notification', require_ready=True)
|
||||
notification_type = 'FOLLOW_REQUEST' if \
|
||||
manually_approves else 'FOLLOW'
|
||||
model = apps.get_model("bookwyrm.Notification", require_ready=True)
|
||||
notification_type = "FOLLOW_REQUEST" if manually_approves else "FOLLOW"
|
||||
model.objects.create(
|
||||
user=self.user_object,
|
||||
related_user=self.user_subject,
|
||||
notification_type=notification_type,
|
||||
)
|
||||
|
||||
|
||||
def accept(self):
|
||||
''' turn this request into the real deal'''
|
||||
""" turn this request into the real deal"""
|
||||
user = self.user_object
|
||||
if not self.user_subject.local:
|
||||
activity = activitypub.Accept(
|
||||
id=self.get_remote_id(status='accepts'),
|
||||
id=self.get_remote_id(status="accepts"),
|
||||
actor=self.user_object.remote_id,
|
||||
object=self.to_activity()
|
||||
object=self.to_activity(),
|
||||
).serialize()
|
||||
self.broadcast(activity, user)
|
||||
with transaction.atomic():
|
||||
UserFollows.from_request(self)
|
||||
self.delete()
|
||||
|
||||
|
||||
|
||||
def reject(self):
|
||||
''' generate a Reject for this follow request '''
|
||||
""" generate a Reject for this follow request """
|
||||
if self.user_object.local:
|
||||
activity = activitypub.Reject(
|
||||
id=self.get_remote_id(status='rejects'),
|
||||
id=self.get_remote_id(status="rejects"),
|
||||
actor=self.user_object.remote_id,
|
||||
object=self.to_activity()
|
||||
object=self.to_activity(),
|
||||
).serialize()
|
||||
self.broadcast(activity, self.user_object)
|
||||
|
||||
@ -165,19 +166,20 @@ class UserFollowRequest(ActivitypubMixin, UserRelationship):
|
||||
|
||||
|
||||
class UserBlocks(ActivityMixin, UserRelationship):
|
||||
''' prevent another user from following you and seeing your posts '''
|
||||
status = 'blocks'
|
||||
""" prevent another user from following you and seeing your posts """
|
||||
|
||||
status = "blocks"
|
||||
activity_serializer = activitypub.Block
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
''' remove follow or follow request rels after a block is created '''
|
||||
""" remove follow or follow request rels after a block is created """
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
UserFollows.objects.filter(
|
||||
Q(user_subject=self.user_subject, user_object=self.user_object) | \
|
||||
Q(user_subject=self.user_object, user_object=self.user_subject)
|
||||
Q(user_subject=self.user_subject, user_object=self.user_object)
|
||||
| Q(user_subject=self.user_object, user_object=self.user_subject)
|
||||
).delete()
|
||||
UserFollowRequest.objects.filter(
|
||||
Q(user_subject=self.user_subject, user_object=self.user_object) | \
|
||||
Q(user_subject=self.user_object, user_object=self.user_subject)
|
||||
Q(user_subject=self.user_subject, user_object=self.user_object)
|
||||
| Q(user_subject=self.user_object, user_object=self.user_subject)
|
||||
).delete()
|
||||
|
Reference in New Issue
Block a user