Skip to content

Commit

Permalink
atom_to_activity: convert link rel=self/alternate to url
Browse files Browse the repository at this point in the history
  • Loading branch information
snarfed committed Jan 11, 2024
1 parent 52b1ff0 commit a9cf068
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 19 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ Changelog
* Add new `extract_entries` function.
* `activity_to_atom`: default actor/author name to username.
* `atom_to_activities`: support top-level `entry` element as well as `feed`.
* `atom_to_activity/ies`: add `object.author`, default `objectType` to `article`/`note` and `verb` to `post`.
* `atom_to_activity/ies`: add `object.author`, default `objectType` to `article`/`note` and `verb` to `post`, convert `link rel=self`/`alternate` to `url`.
* If `entry.author` doesn't have id or url, default them to feed author's.
* `bluesky`:
* Fully support both `record` and `object` types in `from_as1` and `to_as1`. Use `to_as1`'s `type` kwarg and `from_as1`'s `out_type` kwarg to disambiguate.
Expand Down
8 changes: 7 additions & 1 deletion granary/atom.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,13 @@ def _atom_to_object(elem, feed_author=None):
Returns:
dict: ActivityStreams object
"""
uri = _text(elem, 'uri') or _text(elem)
self_links = [link for link in elem.iterfind('atom:link', NAMESPACES)
if link.get('rel') in ('self', 'alternate')
and link.get('type', '').split(';')[0] in ('text/html', '')]
uri = (_text(elem, 'uri')
or (self_links[0].get('href') if self_links else None)
or _text(elem))

title = _text(elem, 'title')
return {
'objectType': _as1_value(elem, 'object-type') or 'article' if title else 'note',
Expand Down
69 changes: 52 additions & 17 deletions granary/tests/test_atom.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from . import test_instagram
from . import test_twitter

INSTAGRAM_ENTRY_BODY = u"""\
INSTAGRAM_ENTRY_BODY = """\
<author>
<activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
<uri>https://www.instagram.com/snarfed/</uri>
Expand Down Expand Up @@ -47,7 +47,7 @@
<georss:featureName>Le Truc</georss:featureName>
<link rel="self" href="https://www.instagram.com/p/ABC123/" />
<link rel="enclosure" href="http://attach/image/big" type="" />"""
INSTAGRAM_ENTRY = u"""\
INSTAGRAM_ENTRY = """\
<?xml version="1.0" encoding="UTF-8"?>
<entry xml:lang="en-US"
xmlns="http://www.w3.org/2005/Atom"
Expand All @@ -59,7 +59,7 @@
""" + INSTAGRAM_ENTRY_BODY + """
</entry>
"""
INSTAGRAM_FEED = u"""\
INSTAGRAM_FEED = """\
<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US"
xmlns="http://www.w3.org/2005/Atom"
Expand All @@ -77,14 +77,16 @@
'objectType': 'activity',
'verb': 'post',
'id': 'tag:instagram.com:123_456',
'url': 'https://www.instagram.com/p/ABC123/',
'actor': {
'displayName': 'Ryan B',
'objectType': 'person',
'url': 'https://www.instagram.com/snarfed/',
},
'object': {
'id': 'tag:instagram.com:123_456',
'objectType': 'photo',
'id': 'tag:instagram.com:123_456',
'url': 'https://www.instagram.com/p/ABC123/',
'author': {
'displayName': 'Ryan B',
'objectType': 'person',
Expand Down Expand Up @@ -159,9 +161,9 @@ def test_atom_to_activity_like(self):
}, atom.atom_to_activity(f"""<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:activity="http://activitystrea.ms/spec/1.0/">
<uri>like-url</uri>
<activity:verb>http://activitystrea.ms/schema/1.0/like</activity:verb>
<activity:object>{atom_obj}</activity:object>
<uri>like-url</uri>
<activity:verb>http://activitystrea.ms/schema/1.0/like</activity:verb>
<activity:object>{atom_obj}</activity:object>
</entry>
"""))

Expand Down Expand Up @@ -231,13 +233,13 @@ def test_atom_to_activity_reply(self):
'inReplyTo': [{'id': 'foo-id', 'url': 'foo-url'}],
},
}
self.assert_equals(expected, atom.atom_to_activity(u"""\
self.assert_equals(expected, atom.atom_to_activity("""\
<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:thr="http://purl.org/syndication/thread/1.0">
<uri>reply-url</uri>
<thr:in-reply-to ref="foo-id" href="foo-url" />
<content>I hereby ☕ reply.</content>
<uri>reply-url</uri>
<thr:in-reply-to ref="foo-id" href="foo-url" />
<content>I hereby ☕ reply.</content>
</entry>
"""))

Expand All @@ -251,10 +253,10 @@ def test_atom_to_activity_in_reply_to_text(self):
'inReplyTo': [{'id': 'my-inreplyto', 'url': 'my-inreplyto'}],
},
}
self.assert_equals(expected, atom.atom_to_activity(u"""\
self.assert_equals(expected, atom.atom_to_activity("""\
<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns:thr="http://purl.org/syndication/thread/1.0">
<thr:in-reply-to>my-inreplyto</thr:in-reply-to>
<thr:in-reply-to>my-inreplyto</thr:in-reply-to>
</entry>
"""))

Expand All @@ -267,13 +269,46 @@ def test_atom_to_activity_unicode_title(self):
'objectType': 'article',
'title': 'How quill’s editor looks',
},
}, atom.atom_to_activity(u"""\
}, atom.atom_to_activity("""\
<?xml version='1.0' encoding='UTF-8'?>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>How quill’s editor looks</title>
<title>How quill’s editor looks</title>
</entry>
"""))

def test_atom_to_object_uri(self):
self.assert_equals({
'objectType': 'note',
'id': 'http://post',
'url': 'http://post',
}, atom.atom_to_activity("""\
<entry xmlns="http://www.w3.org/2005/Atom">
<uri>http://post</uri>
</entry>
""")['object'])

def test_atom_to_object_link_self(self):
self.assert_equals({
'objectType': 'note',
'id': 'http://post',
'url': 'http://post',
}, atom.atom_to_activity("""\
<entry xmlns="http://www.w3.org/2005/Atom">
<link rel="self" href="http://post" />
</entry>
""")['object'])

def test_atom_to_object_link_alternate(self):
self.assert_equals({
'objectType': 'note',
'id': 'http://post',
'url': 'http://post',
}, atom.atom_to_activity("""\
<entry xmlns="http://www.w3.org/2005/Atom">
<link rel="alternate" type="text/html" href="http://post" />
</entry>
""")['object'])

def test_atom_to_activity_use_feed_author_id_url(self):
expected_author = {
'id': 'id:ryan',
Expand Down Expand Up @@ -716,7 +751,7 @@ def test_html_to_atom_fetch_author(self):
# fetch_author requires url
atom.html_to_atom('', fetch_author=True)

html = u"""\
html = """\
<body class="h-card vcard">
<img class="photo u-photo" src="photo.jpg" alt=""/>
<a class="u-url u-uid" rel="author" href="/author"></a>
Expand All @@ -737,7 +772,7 @@ def test_html_to_atom_fetch_author(self):
self.mox.ReplayAll()

got = atom.html_to_atom(html, 'https://my.site/', fetch_author=True)
self.assert_multiline_in(u"""\
self.assert_multiline_in("""\
<author>
<activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
<uri>https://my.site/author</uri>
Expand Down
2 changes: 2 additions & 0 deletions test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ def test_url_atom_to_as1(self):
self.assert_equals({
'items': [{
'id': 'https://perma/link',
'url': 'https://perma/link',
'objectType': 'activity',
'verb': 'post',
'actor': {
Expand All @@ -545,6 +546,7 @@ def test_url_atom_to_as1(self):
},
'object': {
'id': 'https://perma/link',
'url': 'https://perma/link',
'objectType': 'note',
'author': {
'objectType': 'person',
Expand Down

0 comments on commit a9cf068

Please sign in to comment.