diff options
| author | Andrew Godwin | 2022-11-11 23:04:43 -0700 | 
|---|---|---|
| committer | Andrew Godwin | 2022-11-11 23:04:43 -0700 | 
| commit | 8fd5a9292c7d3aac352d3c0e96288bff8a79cb47 (patch) | |
| tree | 3a9199c1d35a77d209cf424141fd4aa0e0694118 /activities/models/post.py | |
| parent | feb5d9b74fa1e8454eaaf29afae3643c6d7c81f1 (diff) | |
| download | takahe-8fd5a9292c7d3aac352d3c0e96288bff8a79cb47.tar.gz takahe-8fd5a9292c7d3aac352d3c0e96288bff8a79cb47.tar.bz2 takahe-8fd5a9292c7d3aac352d3c0e96288bff8a79cb47.zip | |
Posting and fan-out both working
Diffstat (limited to 'activities/models/post.py')
| -rw-r--r-- | activities/models/post.py | 82 | 
1 files changed, 78 insertions, 4 deletions
| diff --git a/activities/models/post.py b/activities/models/post.py index f4d159f..4c40033 100644 --- a/activities/models/post.py +++ b/activities/models/post.py @@ -1,8 +1,13 @@ +from typing import Dict +  import urlman  from django.db import models +from django.utils import timezone +from activities.models.fan_out import FanOut  from activities.models.timeline_event import TimelineEvent  from core.html import sanitize_post +from core.ld import format_date  from stator.models import State, StateField, StateGraph, StatorModel  from users.models.follow import Follow  from users.models.identity import Identity @@ -19,7 +24,8 @@ class PostStates(StateGraph):          """          Creates all needed fan-out objects for a new Post.          """ -        pass +        await instance.afan_out() +        return cls.fanned_out  class Post(StatorModel): @@ -84,11 +90,21 @@ class Post(StatorModel):          blank=True,      ) +    # When the post was originally created (as opposed to when we received it) +    authored = models.DateTimeField(default=timezone.now) +      created = models.DateTimeField(auto_now_add=True)      updated = models.DateTimeField(auto_now=True)      class urls(urlman.Urls): -        view = "{self.identity.urls.view}posts/{self.id}/" +        view = "{self.author.urls.view}posts/{self.id}/" +        object_uri = "{self.author.urls.actor}posts/{self.id}/" + +        def get_scheme(self, url): +            return "https" + +        def get_hostname(self, url): +            return self.instance.author.domain.uri_domain      def __str__(self):          return f"{self.author} #{self.id}" @@ -97,6 +113,16 @@ class Post(StatorModel):      def safe_content(self):          return sanitize_post(self.content) +    ### Async helpers ### + +    async def afetch_full(self): +        """ +        Returns a version of the object with all relations pre-loaded +        """ +        return await Post.objects.select_related("author", "author__domain").aget( +            pk=self.pk +        ) +      ### Local creation ###      @classmethod @@ -111,9 +137,57 @@ class Post(StatorModel):          post.save()          return post -    ### ActivityPub (outgoing) ### +    ### ActivityPub (outbound) ### -    ### ActivityPub (incoming) ### +    async def afan_out(self): +        """ +        Creates FanOuts for a new post +        """ +        # Send a copy to all people who follow this user +        post = await self.afetch_full() +        async for follow in post.author.inbound_follows.all(): +            await FanOut.objects.acreate( +                identity_id=follow.source_id, +                type=FanOut.Types.post, +                subject_post=post, +            ) +        # And one for themselves +        await FanOut.objects.acreate( +            identity_id=post.author_id, +            type=FanOut.Types.post, +            subject_post=post, +        ) + +    def to_ap(self) -> Dict: +        """ +        Returns the AP JSON for this object +        """ +        value = { +            "type": "Note", +            "id": self.object_uri, +            "published": format_date(self.created), +            "attributedTo": self.author.actor_uri, +            "content": self.safe_content, +            "to": "as:Public", +            "as:sensitive": self.sensitive, +            "url": self.urls.view.full(),  # type: ignore +        } +        if self.summary: +            value["summary"] = self.summary +        return value + +    def to_create_ap(self): +        """ +        Returns the AP JSON to create this object +        """ +        return { +            "type": "Create", +            "id": self.object_uri + "#create", +            "actor": self.author.actor_uri, +            "object": self.to_ap(), +        } + +    ### ActivityPub (inbound) ###      @classmethod      def by_ap(cls, data, create=False) -> "Post": | 
