Attach local images embedded into Post and Comment as attachments for AP

Rip out any embedded images for the senders domain into
entity._children list of Image objects.
merge-requests/155/head
Jason Robinson 2019-08-17 21:02:25 +03:00
rodzic b03be01e59
commit 00d243a785
5 zmienionych plików z 59 dodań i 3 usunięć

Wyświetl plik

@ -8,7 +8,7 @@ from federation.entities.activitypub.constants import (
CONTEXTS_DEFAULT, CONTEXT_MANUALLY_APPROVES_FOLLOWERS, CONTEXT_SENSITIVE, CONTEXT_HASHTAG, CONTEXTS_DEFAULT, CONTEXT_MANUALLY_APPROVES_FOLLOWERS, CONTEXT_SENSITIVE, CONTEXT_HASHTAG,
CONTEXT_LD_SIGNATURES) CONTEXT_LD_SIGNATURES)
from federation.entities.activitypub.enums import ActorType, ObjectType, ActivityType from federation.entities.activitypub.enums import ActorType, ObjectType, ActivityType
from federation.entities.activitypub.mixins import ActivitypubEntityMixin, CleanContentMixin from federation.entities.activitypub.mixins import ActivitypubEntityMixin, CleanContentMixin, AttachImagesMixin
from federation.entities.activitypub.objects import ImageObject from federation.entities.activitypub.objects import ImageObject
from federation.entities.base import Profile, Post, Follow, Accept, Comment, Retraction, Share from federation.entities.base import Profile, Post, Follow, Accept, Comment, Retraction, Share
from federation.outbound import handle_send from federation.outbound import handle_send
@ -33,7 +33,7 @@ class ActivitypubAccept(ActivitypubEntityMixin, Accept):
return as2 return as2
class ActivitypubComment(ActivitypubEntityMixin, CleanContentMixin, Comment): class ActivitypubComment(ActivitypubEntityMixin, AttachImagesMixin, CleanContentMixin, Comment):
_type = ObjectType.NOTE.value _type = ObjectType.NOTE.value
def to_as2(self) -> Dict: def to_as2(self) -> Dict:
@ -138,7 +138,7 @@ class ActivitypubFollow(ActivitypubEntityMixin, Follow):
return as2 return as2
class ActivitypubPost(ActivitypubEntityMixin, CleanContentMixin, Post): class ActivitypubPost(ActivitypubEntityMixin, AttachImagesMixin, CleanContentMixin, Post):
_type = ObjectType.NOTE.value _type = ObjectType.NOTE.value
def to_as2(self) -> Dict: def to_as2(self) -> Dict:

Wyświetl plik

@ -201,6 +201,9 @@ def get_outbound_entity(entity: BaseEntity, private_key):
# # in all situations but is apparently being removed. # # in all situations but is apparently being removed.
# # TODO: remove this once Diaspora removes the extra signature # # TODO: remove this once Diaspora removes the extra signature
# outbound.parent_signature = outbound.signature # outbound.parent_signature = outbound.signature
if getattr(outbound, "pre_send", None) and isinstance(getattr(outbound, "pre_send"), callable):
# noinspection PyUnresolvedReferences
outbound.pre_send()
return outbound return outbound

Wyświetl plik

@ -1,9 +1,31 @@
import re import re
from federation.entities.base import Image
from federation.entities.mixins import BaseEntity, RawContentMixin from federation.entities.mixins import BaseEntity, RawContentMixin
from federation.entities.utils import get_base_attributes from federation.entities.utils import get_base_attributes
class AttachImagesMixin(RawContentMixin):
def pre_send(self) -> None:
"""
Attach any embedded images from the sender server.
"""
actor_domain = re.match(r"https?://([\w.\-]+)", self.actor_id).groups()[0]
actor_domain = actor_domain.replace(".", "\\.")
regex = r"!\[([\w ]*)\]\((https?://%s[\w\/\-.]+\.[jpg|gif|jpeg|png]*)\)" % actor_domain
matches = re.finditer(regex, self.raw_content, re.MULTILINE | re.IGNORECASE)
for match in matches:
groups = match.groups()
self._children.append(
Image(
url=groups[1],
name=groups[0] or "",
)
)
self.raw_content = re.sub(regex, "", self.raw_content, re.MULTILINE | re.IGNORECASE)
self.raw_content = self.raw_content.strip()
class ActivitypubEntityMixin(BaseEntity): class ActivitypubEntityMixin(BaseEntity):
_type = None _type = None

Wyświetl plik

@ -209,3 +209,13 @@ class TestEntitiesPostReceive:
def test_post__post_receive__cleans_linkified_tags(self, activitypubpost_linkified_tags): def test_post__post_receive__cleans_linkified_tags(self, activitypubpost_linkified_tags):
activitypubpost_linkified_tags.post_receive() activitypubpost_linkified_tags.post_receive()
assert activitypubpost_linkified_tags.raw_content == '<p>👁️ foobar 👁️ </p><p>barfoo!<br>#fanart #mastoart</p>' assert activitypubpost_linkified_tags.raw_content == '<p>👁️ foobar 👁️ </p><p>barfoo!<br>#fanart #mastoart</p>'
class TestEntitiesPreSend:
def test_post_local_images_are_attached(self, activitypubpost_localimages):
activitypubpost_localimages.pre_send()
assert activitypubpost_localimages.raw_content == "#Cycling #lauttasaari #sea #sun"
assert len(activitypubpost_localimages._children) == 4
image = activitypubpost_localimages._children[3]
assert image.url == "https://jasonrobinson.me/media/uploads/2019/07/16/daa24d89-cedf-4fc7-bad8-74a902541479.jpg"
assert image.name == "foobar barfoo"

Wyświetl plik

@ -70,6 +70,27 @@ def activitypubpost():
) )
@pytest.fixture
def activitypubpost_localimages():
with freeze_time("2019-04-27"):
return ActivitypubPost(
raw_content="""
#Cycling #lauttasaari #sea #sun
![](https://jasonrobinson.me/media/uploads/2019/07/16/daa24d89-cedf-4fc7-bad8-74a902541476.jpg)![](https://jasonrobinson.me/media/uploads/2019/07/16/daa24d89-cedf-4fc7-bad8-74a902541477.jpg)
![foobar](https://jasonrobinson.me/media/uploads/2019/07/16/daa24d89-cedf-4fc7-bad8-74a902541478.jpg)
![foobar barfoo](https://jasonrobinson.me/media/uploads/2019/07/16/daa24d89-cedf-4fc7-bad8-74a902541479.jpg)
""",
public=True,
provider_display_name="Socialhome",
id=f"http://127.0.0.1:8000/post/123456/",
activity_id=f"http://127.0.0.1:8000/post/123456/#create",
actor_id=f"https://jasonrobinson.me/u/jaywink/",
)
@pytest.fixture @pytest.fixture
def activitypubpost_linkified_tags(): def activitypubpost_linkified_tags():
with freeze_time("2019-04-27"): with freeze_time("2019-04-27"):