takahe/users/services/identity.py

90 lines
2.9 KiB
Python

from typing import cast
from django.db import models
from django.template.defaultfilters import linebreaks_filter
from core.html import strip_html
from users.models import Follow, FollowStates, Identity
class IdentityService:
"""
High-level helper methods for doing things to identities
"""
def __init__(self, identity: Identity):
self.identity = identity
def following(self) -> models.QuerySet[Identity]:
return (
Identity.objects.filter(inbound_follows__source=self.identity)
.not_deleted()
.order_by("username")
.select_related("domain")
)
def followers(self) -> models.QuerySet[Identity]:
return (
Identity.objects.filter(outbound_follows__target=self.identity)
.not_deleted()
.order_by("username")
.select_related("domain")
)
def follow_from(self, from_identity: Identity) -> Follow:
"""
Follows a user (or does nothing if already followed).
Returns the follow.
"""
existing_follow = Follow.maybe_get(from_identity, self.identity)
if not existing_follow:
return Follow.create_local(from_identity, self.identity)
elif existing_follow.state not in FollowStates.group_active():
existing_follow.transition_perform(FollowStates.unrequested)
return cast(Follow, existing_follow)
def unfollow_from(self, from_identity: Identity):
"""
Unfollows a user (or does nothing if not followed).
"""
existing_follow = Follow.maybe_get(from_identity, self.identity)
if existing_follow:
existing_follow.transition_perform(FollowStates.undone)
def mastodon_json_relationship(self, from_identity: Identity):
"""
Returns a Relationship object for the from_identity's relationship
with this identity.
"""
return {
"id": self.identity.pk,
"following": self.identity.inbound_follows.filter(
source=from_identity,
state__in=FollowStates.group_active(),
).exists(),
"followed_by": self.identity.outbound_follows.filter(
target=from_identity,
state__in=FollowStates.group_active(),
).exists(),
"showing_reblogs": True,
"notifying": False,
"blocking": False,
"blocked_by": False,
"muting": False,
"muting_notifications": False,
"requested": False,
"domain_blocking": False,
"endorsed": False,
"note": "",
}
def set_summary(self, summary: str):
"""
Safely sets a summary and turns linebreaks into HTML
"""
if summary:
self.identity.summary = linebreaks_filter(strip_html(summary))
else:
self.identity.summary = None
self.identity.save()