Extract mentions from Diaspora payloads that have text content

The mentions will be available in the entity as `_mentions` which is
a set of Diaspora ID's in URI format.
merge-requests/130/head
Jason Robinson 2018-06-23 21:57:47 +03:00
rodzic 8c7b1206c6
commit af920604a2
7 zmienionych plików z 61 dodań i 3 usunięć

Wyświetl plik

@ -20,6 +20,8 @@
The country information is fetched using the free `ipdata.co` service. NOTE! This service is rate limited to 1500 requests per day.
* Extract mentions from Diaspora payloads that have text content. The mentions will be available in the entity as `_mentions` which is a set of Diaspora ID's in URI format.
### Changed
* Send outbound Diaspora payloads in new format. Remove possibility to generate legacy MagicEnvelope payloads. ([related issue](https://github.com/jaywink/federation/issues/82))

Wyświetl plik

@ -23,6 +23,7 @@ class BaseEntity:
def __init__(self, *args, **kwargs):
self._required = []
self._children = []
self._mentions = set()
for key, value in kwargs.items():
if hasattr(self, key):
setattr(self, key, value)
@ -31,6 +32,9 @@ class BaseEntity:
self.__class__.__name__, key
))
def extract_mentions(self):
return set()
@property
def id(self):
"""Global network ID.

Wyświetl plik

@ -1,4 +1,5 @@
import importlib
import re
from lxml import etree
@ -8,7 +9,7 @@ from federation.entities.base import (
from federation.entities.diaspora.utils import format_dt, struct_to_xml, get_base_attributes, add_element_to_doc
from federation.exceptions import SignatureVerificationError
from federation.protocols.diaspora.signatures import verify_relayable_signature, create_relayable_signature
from federation.utils.diaspora import retrieve_and_parse_profile
from federation.utils.diaspora import retrieve_and_parse_profile, generate_diaspora_profile_id
CLASS_TO_TAG_MAPPING = {
Comment: "comment",
@ -27,6 +28,21 @@ class DiasporaEntityMixin(BaseEntity):
# Normally outbound document is generated from entity. Store one here if at some point we already have a doc
outbound_doc = None
def extract_mentions(self):
"""
Extract mentions from an entity with ``raw_content``.
:return: set
"""
if not hasattr(self, "raw_content"):
return set()
mentions = re.findall(r'@{[^;]+; [\w.-]+@[^}]+}', self.raw_content)
if not mentions:
return set()
mentions = {s.split(';')[1].strip(' }') for s in mentions}
mentions = {generate_diaspora_profile_id(s) for s in mentions}
return mentions
@property
def id(self):
"""Diaspora URI scheme format ID.

Wyświetl plik

@ -119,6 +119,8 @@ def element_to_objects(element, sender, sender_key_fetcher=None, user=None):
"transformed": transformed,
})
return []
# Extract mentions
entity._mentions = entity.extract_mentions()
# Do child elements
for child in element:
entity._children.extend(element_to_objects(child, sender))

Wyświetl plik

@ -110,6 +110,22 @@ class TestEntitiesConvertToXML:
assert etree.tostring(result).decode("utf-8") == converted
class TestEntitiesExtractMentions:
def test_extract_mentions__empty_set_if_no_raw_content(self, diasporacontact):
assert diasporacontact.extract_mentions() == set()
def test_extract_mentions__empty_set_if_no_mentions(self, diasporacomment):
assert diasporacomment.extract_mentions() == set()
def test_extract_mentions__set_contains_mentioned_handles(self, diasporapost):
diasporapost.raw_content = 'yeye @{Jason Robinson 🐍🍻; jaywink@jasonrobinson.me} foobar ' \
'@{bar; foo@example.com}'
assert diasporapost.extract_mentions() == {
'diaspora://jaywink@jasonrobinson.me/profile/',
'diaspora://foo@example.com/profile/',
}
class TestEntityAttributes:
def test_comment_ids(self, diasporacomment):
assert diasporacomment.id == "diaspora://handle/comment/guid"
@ -223,7 +239,7 @@ class TestDiasporaRelayableMixin:
b'TsLM+Yw==</parent_author_signature></comment>'
@patch("federation.entities.diaspora.mappers.DiasporaComment._validate_signatures")
def test_sign_with_parent(self, mock_validate):
def test_sign_with_parent__calls_to_xml(self, mock_validate):
entity = DiasporaComment()
with patch.object(entity, "to_xml") as mock_to_xml:
entity.sign_with_parent(get_dummy_private_key())

Wyświetl plik

@ -17,7 +17,7 @@ from federation.tests.fixtures.payloads import (
DIASPORA_REQUEST, DIASPORA_PROFILE, DIASPORA_POST_INVALID, DIASPORA_RETRACTION,
DIASPORA_POST_WITH_PHOTOS, DIASPORA_POST_LEGACY_TIMESTAMP, DIASPORA_POST_LEGACY, DIASPORA_CONTACT,
DIASPORA_LEGACY_REQUEST_RETRACTION, DIASPORA_POST_WITH_PHOTOS_2, DIASPORA_PROFILE_EMPTY_TAGS, DIASPORA_RESHARE,
DIASPORA_RESHARE_WITH_EXTRA_PROPERTIES, DIASPORA_RESHARE_LEGACY)
DIASPORA_RESHARE_WITH_EXTRA_PROPERTIES, DIASPORA_RESHARE_LEGACY, DIASPORA_POST_SIMPLE_WITH_MENTION)
def mock_fill(attributes):
@ -26,6 +26,12 @@ def mock_fill(attributes):
class TestDiasporaEntityMappersReceive:
def test_message_to_objects_mentions_are_extracted(self):
entities = message_to_objects(DIASPORA_POST_SIMPLE_WITH_MENTION, "alice@alice.diaspora.example.org")
assert len(entities) == 1
post = entities[0]
assert post._mentions == {'diaspora://jaywink@jasonrobinson.me/profile/'}
def test_message_to_objects_simple_post(self):
entities = message_to_objects(DIASPORA_POST_SIMPLE, "alice@alice.diaspora.example.org")
assert len(entities) == 1

Wyświetl plik

@ -73,6 +73,18 @@ DIASPORA_POST_SIMPLE = """
"""
DIASPORA_POST_SIMPLE_WITH_MENTION = """
<status_message>
<text>((status message)) @{Jason Robinson 🐍🍻; jaywink@jasonrobinson.me}</text>
<guid>((guidguidguidguidguidguidguid))</guid>
<author>alice@alice.diaspora.example.org</author>
<public>false</public>
<created_at>2011-07-20T01:36:07Z</created_at>
<provider_display_name>Socialhome</provider_display_name>
</status_message>
"""
DIASPORA_POST_LEGACY_TIMESTAMP = """
<status_message>
<text>((status message))</text>