Skip to content

Commit

Permalink
Twitter create/preview: allow non-Twitter replies, convert to normal …
Browse files Browse the repository at this point in the history
…tweets

fixes snarfed/bridgy#1063
  • Loading branch information
snarfed committed Aug 31, 2021
1 parent 5e4b693 commit 164a542
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 19 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ Changelog
* Twitter:
* `create`/`preview`: [support large videos](https://twittercommunity.com/t/large-file-can-not-be-finalized-synchronously/82929/3) via async upload. We now pass `media_category=tweet_video` to the chunked upload `INIT` stage, and then make blocking `STATUS` calls until the video is finished processing. ([bridgy#1043](https://github.com/snarfed/bridgy/issues/1043))
* `create`/`preview`: allow bookmarks. ([bridgy#1045](https://github.com/snarfed/bridgy/issues/1045))
* `create`/`preview`: allow non-Twitter replies, ie activities that include `inReplyTo` URLs even if none of them point to a tweet. ([bridgy#1063](https://github.com/snarfed/bridgy/issues/1063))
* Bug fixes for removing t.co links to quoted tweets.
* Bug fix for multiple instances of the same link in tweet text.
* REST API: ported web framework from webapp2 to Flask. No user-visible behavior change expected.
Expand Down
22 changes: 14 additions & 8 deletions granary/tests/test_twitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2285,7 +2285,7 @@ def test_create_quote_tweet(self):

created = self.twitter.create(QUOTE_ACTIVITY['object'])
self.assert_equals({'url': 'http://posted/tweet', 'type': 'post'},
created.content, created)
created.content, created)

preview = self.twitter.preview_create(QUOTE_ACTIVITY['object'])
self.assertEqual('I agree with this <a href="https://twitter.com/snarfed_org/status/100">twitter.com/snarfed_org/st...</a>', preview.content)
Expand Down Expand Up @@ -2346,18 +2346,24 @@ def test_create_unsupported_type_error(self):
for msg in result.error_plain, result.error_html:
self.assertIn('Cannot publish type=activity, verb=react', msg)

def test_create_reply_without_in_reply_to(self):
def test_create_non_twitter_reply(self):
self.expect_urlopen(twitter.API_POST_TWEET, {}, params={'status': 'I reply!'})
self.mox.ReplayAll()

obj = {
'objectType': 'comment',
'inReplyTo': [{'url': 'http://foo.com/bar'},
{'url': 'http://baz.com/bat'}],
'content': '@foo reply'
'content': 'I reply!'
}
for fn in (self.twitter.preview_create, self.twitter.create):
preview = fn(obj)
self.assertTrue(preview.abort)
self.assertIn('Could not find a tweet to reply to', preview.error_plain)
self.assertIn('Could not find a tweet to', preview.error_html)

created = self.twitter.create(obj)
self.assertFalse(created.abort)
self.assert_equals({'type': 'post'}, created.content)

preview = self.twitter.preview_create(obj)
self.assertEqual('<span class="verb">tweet</span>:', preview.description)
self.assertEqual('I reply!', preview.content)

def test_create_like_without_object(self):
obj = {
Expand Down
13 changes: 2 additions & 11 deletions granary/twitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -761,15 +761,6 @@ def _create(self, obj, preview=None, include_link=source.OMIT_LINK,
if base_id and not base_url:
base_url = 'https://twitter.com/-/statuses/' + base_id

if is_reply and not base_url:
return source.creation_result(
abort=True,
error_plain='Could not find a tweet to reply to.',
error_html='Could not find a tweet to <a href="http://indiewebcamp.com/reply">reply to</a>. '
'Check that your post has an <a href="http://indiewebcamp.com/comment">in-reply-to</a> '
'link to a Twitter URL or to an original post that publishes a '
'<a href="http://indiewebcamp.com/rel-syndication">rel-syndication</a> link to Twitter.')

# truncate and ellipsize content if it's over the character
# count. URLs will be t.co-wrapped, so include that when counting.
content = self.truncate(content, obj.get('url'), include_link, type=type,
Expand Down Expand Up @@ -827,7 +818,7 @@ def _create(self, obj, preview=None, include_link=source.OMIT_LINK,
content = str(content).encode('utf-8')
data = [('status', content)]

if is_reply:
if is_reply and base_url:
preview_description += """\
<span class="verb">@-reply</span> to <a href="%s">this tweet</a>:
%s""" % (base_url, self.embed_post(base_obj))
Expand Down Expand Up @@ -876,7 +867,7 @@ def _create(self, obj, preview=None, include_link=source.OMIT_LINK,
description=preview_description)
else:
resp = self.urlopen(API_POST_TWEET, data=urllib.parse.urlencode(sorted(data)))
resp['type'] = 'comment' if is_reply else 'post'
resp['type'] = 'comment' if is_reply and base_url else 'post'

else:
return source.creation_result(
Expand Down

0 comments on commit 164a542

Please sign in to comment.