Move timelines to a service class
This commit is contained in:
parent
bf5a46df38
commit
e2371a3cd7
|
@ -1,2 +1,3 @@
|
||||||
from .post import PostService # noqa
|
from .post import PostService # noqa
|
||||||
from .search import SearchService # noqa
|
from .search import SearchService # noqa
|
||||||
|
from .timeline import TimelineService # noqa
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
from activities.models import Hashtag, Post, TimelineEvent
|
||||||
|
from users.models import Identity
|
||||||
|
|
||||||
|
|
||||||
|
class TimelineService:
|
||||||
|
"""
|
||||||
|
Timelines and stuff!
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, identity: Identity):
|
||||||
|
self.identity = identity
|
||||||
|
|
||||||
|
def home(self) -> models.QuerySet[TimelineEvent]:
|
||||||
|
return (
|
||||||
|
TimelineEvent.objects.filter(
|
||||||
|
identity=self.identity,
|
||||||
|
type__in=[TimelineEvent.Types.post, TimelineEvent.Types.boost],
|
||||||
|
)
|
||||||
|
.select_related(
|
||||||
|
"subject_post",
|
||||||
|
"subject_post__author",
|
||||||
|
"subject_post__author__domain",
|
||||||
|
"subject_identity",
|
||||||
|
"subject_identity__domain",
|
||||||
|
"subject_post_interaction",
|
||||||
|
"subject_post_interaction__identity",
|
||||||
|
"subject_post_interaction__identity__domain",
|
||||||
|
)
|
||||||
|
.prefetch_related(
|
||||||
|
"subject_post__attachments",
|
||||||
|
"subject_post__mentions",
|
||||||
|
"subject_post__emojis",
|
||||||
|
)
|
||||||
|
.order_by("-published")
|
||||||
|
)
|
||||||
|
|
||||||
|
def local(self) -> models.QuerySet[Post]:
|
||||||
|
return (
|
||||||
|
Post.objects.local_public()
|
||||||
|
.not_hidden()
|
||||||
|
.filter(author__restriction=Identity.Restriction.none)
|
||||||
|
.select_related("author", "author__domain")
|
||||||
|
.prefetch_related("attachments", "mentions", "emojis")
|
||||||
|
.order_by("-published")
|
||||||
|
)
|
||||||
|
|
||||||
|
def federated(self) -> models.QuerySet[Post]:
|
||||||
|
return (
|
||||||
|
Post.objects.public()
|
||||||
|
.not_hidden()
|
||||||
|
.filter(author__restriction=Identity.Restriction.none)
|
||||||
|
.select_related("author", "author__domain")
|
||||||
|
.prefetch_related("attachments", "mentions", "emojis")
|
||||||
|
.order_by("-published")
|
||||||
|
)
|
||||||
|
|
||||||
|
def hashtag(self, hashtag: str | Hashtag) -> models.QuerySet[Post]:
|
||||||
|
return (
|
||||||
|
Post.objects.public()
|
||||||
|
.not_hidden()
|
||||||
|
.filter(author__restriction=Identity.Restriction.none)
|
||||||
|
.tagged_with(hashtag)
|
||||||
|
.select_related("author", "author__domain")
|
||||||
|
.prefetch_related("attachments", "mentions")
|
||||||
|
.order_by("-published")
|
||||||
|
)
|
||||||
|
|
||||||
|
def notifications(self, types: list[str]) -> models.QuerySet[TimelineEvent]:
|
||||||
|
return (
|
||||||
|
TimelineEvent.objects.filter(identity=self.identity, type__in=types)
|
||||||
|
.order_by("-published")
|
||||||
|
.select_related(
|
||||||
|
"subject_post",
|
||||||
|
"subject_post__author",
|
||||||
|
"subject_post__author__domain",
|
||||||
|
"subject_identity",
|
||||||
|
"subject_identity__domain",
|
||||||
|
"subject_post_interaction",
|
||||||
|
"subject_post_interaction__identity",
|
||||||
|
"subject_post_interaction__identity__domain",
|
||||||
|
)
|
||||||
|
.prefetch_related(
|
||||||
|
"subject_post__emojis",
|
||||||
|
"subject_post__mentions",
|
||||||
|
"subject_post__attachments",
|
||||||
|
)
|
||||||
|
)
|
|
@ -3,10 +3,10 @@ from django.shortcuts import get_object_or_404, redirect
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
from django.views.generic import ListView, TemplateView
|
from django.views.generic import ListView, TemplateView
|
||||||
|
|
||||||
from activities.models import Hashtag, Post, PostInteraction, TimelineEvent
|
from activities.models import Hashtag, PostInteraction, TimelineEvent
|
||||||
|
from activities.services import TimelineService
|
||||||
from core.decorators import cache_page
|
from core.decorators import cache_page
|
||||||
from users.decorators import identity_required
|
from users.decorators import identity_required
|
||||||
from users.models import Identity
|
|
||||||
|
|
||||||
from .compose import Compose
|
from .compose import Compose
|
||||||
|
|
||||||
|
@ -22,28 +22,7 @@ class Home(TemplateView):
|
||||||
return self.form_class(request=self.request, **self.get_form_kwargs())
|
return self.form_class(request=self.request, **self.get_form_kwargs())
|
||||||
|
|
||||||
def get_context_data(self):
|
def get_context_data(self):
|
||||||
events = (
|
events = TimelineService(self.request.identity).home()
|
||||||
TimelineEvent.objects.filter(
|
|
||||||
identity=self.request.identity,
|
|
||||||
type__in=[TimelineEvent.Types.post, TimelineEvent.Types.boost],
|
|
||||||
)
|
|
||||||
.select_related(
|
|
||||||
"subject_post",
|
|
||||||
"subject_post__author",
|
|
||||||
"subject_post__author__domain",
|
|
||||||
"subject_identity",
|
|
||||||
"subject_identity__domain",
|
|
||||||
"subject_post_interaction",
|
|
||||||
"subject_post_interaction__identity",
|
|
||||||
"subject_post_interaction__identity__domain",
|
|
||||||
)
|
|
||||||
.prefetch_related(
|
|
||||||
"subject_post__attachments",
|
|
||||||
"subject_post__mentions",
|
|
||||||
"subject_post__emojis",
|
|
||||||
)
|
|
||||||
.order_by("-published")
|
|
||||||
)
|
|
||||||
paginator = Paginator(events, 50)
|
paginator = Paginator(events, 50)
|
||||||
page_number = self.request.GET.get("page")
|
page_number = self.request.GET.get("page")
|
||||||
context = {
|
context = {
|
||||||
|
@ -80,14 +59,7 @@ class Tag(ListView):
|
||||||
return super().get(request, *args, **kwargs)
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return (
|
return TimelineService(self.request.identity).hashtag(self.hashtag)
|
||||||
Post.objects.public()
|
|
||||||
.filter(author__restriction=Identity.Restriction.none)
|
|
||||||
.tagged_with(self.hashtag)
|
|
||||||
.select_related("author", "author__domain")
|
|
||||||
.prefetch_related("attachments", "mentions")
|
|
||||||
.order_by("-published")
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_context_data(self):
|
def get_context_data(self):
|
||||||
context = super().get_context_data()
|
context = super().get_context_data()
|
||||||
|
@ -111,13 +83,7 @@ class Local(ListView):
|
||||||
paginate_by = 50
|
paginate_by = 50
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return (
|
return TimelineService(self.request.identity).local()
|
||||||
Post.objects.local_public()
|
|
||||||
.filter(author__restriction=Identity.Restriction.none)
|
|
||||||
.select_related("author", "author__domain")
|
|
||||||
.prefetch_related("attachments", "mentions", "emojis")
|
|
||||||
.order_by("-published")
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_context_data(self):
|
def get_context_data(self):
|
||||||
context = super().get_context_data()
|
context = super().get_context_data()
|
||||||
|
@ -138,15 +104,7 @@ class Federated(ListView):
|
||||||
paginate_by = 50
|
paginate_by = 50
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return (
|
return TimelineService(self.request.identity).federated()
|
||||||
Post.objects.filter(
|
|
||||||
visibility=Post.Visibilities.public, in_reply_to__isnull=True
|
|
||||||
)
|
|
||||||
.filter(author__restriction=Identity.Restriction.none)
|
|
||||||
.select_related("author", "author__domain")
|
|
||||||
.prefetch_related("attachments", "mentions", "emojis")
|
|
||||||
.order_by("-published")
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_context_data(self):
|
def get_context_data(self):
|
||||||
context = super().get_context_data()
|
context = super().get_context_data()
|
||||||
|
@ -187,25 +145,7 @@ class Notifications(ListView):
|
||||||
for type_name, type in self.notification_types.items():
|
for type_name, type in self.notification_types.items():
|
||||||
if notification_options.get(type_name, True):
|
if notification_options.get(type_name, True):
|
||||||
types.append(type)
|
types.append(type)
|
||||||
return (
|
return TimelineService(self.request.identity).notifications(types)
|
||||||
TimelineEvent.objects.filter(identity=self.request.identity, type__in=types)
|
|
||||||
.order_by("-published")
|
|
||||||
.select_related(
|
|
||||||
"subject_post",
|
|
||||||
"subject_post__author",
|
|
||||||
"subject_post__author__domain",
|
|
||||||
"subject_identity",
|
|
||||||
"subject_identity__domain",
|
|
||||||
"subject_post_interaction",
|
|
||||||
"subject_post_interaction__identity",
|
|
||||||
"subject_post_interaction__identity__domain",
|
|
||||||
)
|
|
||||||
.prefetch_related(
|
|
||||||
"subject_post__emojis",
|
|
||||||
"subject_post__mentions",
|
|
||||||
"subject_post__attachments",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from activities.models import PostInteraction, TimelineEvent
|
from activities.models import PostInteraction, TimelineEvent
|
||||||
|
from activities.services import TimelineService
|
||||||
from api import schemas
|
from api import schemas
|
||||||
from api.decorators import identity_required
|
from api.decorators import identity_required
|
||||||
from api.pagination import MastodonPaginator
|
from api.pagination import MastodonPaginator
|
||||||
|
@ -28,13 +29,8 @@ def notifications(
|
||||||
requested_types = set(base_types.keys())
|
requested_types = set(base_types.keys())
|
||||||
requested_types.difference_update(excluded_types)
|
requested_types.difference_update(excluded_types)
|
||||||
# Use that to pull relevant events
|
# Use that to pull relevant events
|
||||||
queryset = (
|
queryset = TimelineService(request.identity).notifications(
|
||||||
TimelineEvent.objects.filter(
|
[base_types[r] for r in requested_types]
|
||||||
identity=request.identity,
|
|
||||||
type__in=[base_types[r] for r in requested_types],
|
|
||||||
)
|
|
||||||
.order_by("-published")
|
|
||||||
.select_related("subject_post", "subject_post__author", "subject_identity")
|
|
||||||
)
|
)
|
||||||
paginator = MastodonPaginator(TimelineEvent)
|
paginator = MastodonPaginator(TimelineEvent)
|
||||||
events = paginator.paginate(
|
events = paginator.paginate(
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
from activities.models import Post, PostInteraction, TimelineEvent
|
from activities.models import Post, PostInteraction
|
||||||
|
from activities.services import TimelineService
|
||||||
from api import schemas
|
from api import schemas
|
||||||
from api.decorators import identity_required
|
from api.decorators import identity_required
|
||||||
from api.pagination import MastodonPaginator
|
from api.pagination import MastodonPaginator
|
||||||
from api.views.base import api_router
|
from api.views.base import api_router
|
||||||
from users.models import Identity
|
|
||||||
|
|
||||||
|
|
||||||
@api_router.get("/v1/timelines/home", response=list[schemas.Status])
|
@api_router.get("/v1/timelines/home", response=list[schemas.Status])
|
||||||
|
@ -16,22 +16,7 @@ def home(
|
||||||
limit: int = 20,
|
limit: int = 20,
|
||||||
):
|
):
|
||||||
paginator = MastodonPaginator(Post)
|
paginator = MastodonPaginator(Post)
|
||||||
queryset = (
|
queryset = TimelineService(request.identity).home()
|
||||||
TimelineEvent.objects.filter(
|
|
||||||
identity=request.identity,
|
|
||||||
type__in=[TimelineEvent.Types.post],
|
|
||||||
)
|
|
||||||
.select_related(
|
|
||||||
"subject_post",
|
|
||||||
"subject_post__author",
|
|
||||||
"subject_post__author__domain",
|
|
||||||
)
|
|
||||||
.prefetch_related(
|
|
||||||
"subject_post__attachments",
|
|
||||||
"subject_post__mentions",
|
|
||||||
)
|
|
||||||
.order_by("-published")
|
|
||||||
)
|
|
||||||
events = paginator.paginate(
|
events = paginator.paginate(
|
||||||
queryset,
|
queryset,
|
||||||
min_id=min_id,
|
min_id=min_id,
|
||||||
|
@ -58,16 +43,11 @@ def public(
|
||||||
min_id: str | None = None,
|
min_id: str | None = None,
|
||||||
limit: int = 20,
|
limit: int = 20,
|
||||||
):
|
):
|
||||||
queryset = (
|
|
||||||
Post.objects.public()
|
|
||||||
.filter(author__restriction=Identity.Restriction.none)
|
|
||||||
.select_related("author")
|
|
||||||
.prefetch_related("attachments")
|
|
||||||
.order_by("-published")
|
|
||||||
)
|
|
||||||
if local:
|
if local:
|
||||||
queryset = queryset.filter(local=True)
|
queryset = TimelineService(request.identity).local()
|
||||||
elif remote:
|
else:
|
||||||
|
queryset = TimelineService(request.identity).federated()
|
||||||
|
if remote:
|
||||||
queryset = queryset.filter(local=False)
|
queryset = queryset.filter(local=False)
|
||||||
if only_media:
|
if only_media:
|
||||||
queryset = queryset.filter(attachments__id__isnull=True)
|
queryset = queryset.filter(attachments__id__isnull=True)
|
||||||
|
@ -97,14 +77,7 @@ def hashtag(
|
||||||
):
|
):
|
||||||
if limit > 40:
|
if limit > 40:
|
||||||
limit = 40
|
limit = 40
|
||||||
queryset = (
|
queryset = TimelineService(request.identity).hashtag(hashtag)
|
||||||
Post.objects.public()
|
|
||||||
.filter(author__restriction=Identity.Restriction.none)
|
|
||||||
.tagged_with(hashtag)
|
|
||||||
.select_related("author")
|
|
||||||
.prefetch_related("attachments")
|
|
||||||
.order_by("-published")
|
|
||||||
)
|
|
||||||
if local:
|
if local:
|
||||||
queryset = queryset.filter(local=True)
|
queryset = queryset.filter(local=True)
|
||||||
if only_media:
|
if only_media:
|
||||||
|
|
Loading…
Reference in New Issue