Skip to content
This repository was archived by the owner on Aug 7, 2024. It is now read-only.

Commit 3d31088

Browse files
authored
Merge pull request #465 from bear/fix/issue421
add support for quoted statuses
2 parents 6ef28e4 + c9e2827 commit 3d31088

4 files changed

Lines changed: 33 additions & 2 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"in_reply_to_user_id": null, "favorite_count": 1477, "text": "1) Make album https://t.co/VS5PhdwUjd\n2) Release album\n3) Tour\n4) Make open source alternative to twitter\n\nPretty b\u2026 https://t.co/t2rFVWy6Fm", "in_reply_to_status_id_str": null, "id_str": "849424628401541121", "coordinates": null, "in_reply_to_screen_name": null, "entities": {"symbols": [], "user_mentions": [], "urls": [{"expanded_url": "http://wbr.ec/emperorofsand", "display_url": "wbr.ec/emperorofsand", "indices": [14, 37], "url": "https://t.co/VS5PhdwUjd"}, {"expanded_url": "https://twitter.com/i/web/status/849424628401541121", "display_url": "twitter.com/i/web/status/8\u2026", "indices": [117, 140], "url": "https://t.co/t2rFVWy6Fm"}], "hashtags": []}, "retweeted": true, "possibly_sensitive": false, "created_at": "Wed Apr 05 00:53:07 +0000 2017", "source": "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>", "quoted_status": {"in_reply_to_user_id": null, "favorite_count": 46, "text": "hard to believe @mastodonmusic created its own open source alternative to twitter to promote its new album", "in_reply_to_status_id_str": null, "id_str": "849412806835351552", "coordinates": null, "in_reply_to_screen_name": null, "entities": {"symbols": [], "user_mentions": [{"name": "Mastodon", "id": 18065572, "screen_name": "mastodonmusic", "indices": [16, 30], "id_str": "18065572"}], "urls": [], "hashtags": []}, "retweeted": false, "created_at": "Wed Apr 05 00:06:09 +0000 2017", "source": "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>", "id": 849412806835351552, "truncated": false, "in_reply_to_user_id_str": null, "in_reply_to_status_id": null, "is_quote_status": false, "user": {"name": "Kyle Seth Gray", "default_profile_image": false, "follow_request_sent": false, "notifications": false, "screen_name": "kylesethgray", "id_str": "29040347", "geo_enabled": false, "is_translation_enabled": false, "profile_image_url_https": "https://pbs.twimg.com/profile_images/851226055125880833/gJ9hGmvT_normal.jpg", "time_zone": "Mountain Time (US & Canada)", "has_extended_profile": true, "lang": "en", "profile_text_color": "666666", "profile_image_url": "http://pbs.twimg.com/profile_images/851226055125880833/gJ9hGmvT_normal.jpg", "url": "https://t.co/MEYeHWlrVg", "id": 29040347, "followers_count": 1304, "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme9/bg.gif", "verified": false, "friends_count": 764, "translator_type": "regular", "contributors_enabled": false, "entities": {"url": {"urls": [{"expanded_url": "http://kylesethgray.com", "display_url": "kylesethgray.com", "indices": [0, 23], "url": "https://t.co/MEYeHWlrVg"}]}, "description": {"urls": [{"expanded_url": "http://body.gray.sexy", "display_url": "body.gray.sexy", "indices": [63, 86], "url": "https://t.co/sZYwVfrKEU"}]}}, "favourites_count": 65806, "profile_background_color": "1A1B1F", "protected": false, "following": false, "is_translator": false, "default_profile": false, "location": "Utah, USA", "profile_sidebar_border_color": "FFFFFF", "utc_offset": -21600, "profile_background_tile": false, "created_at": "Sun Apr 05 19:06:40 +0000 2009", "profile_use_background_image": false, "description": "digital marketer. Cyclist\ud83d\udeb4\ud83c\udffc Website wizard \ud83d\udc68\ud83c\udffc\u200d\ud83d\udcbb \u231a\ufe0f #kylehealth https://t.co/sZYwVfrKEU Opinions are my own. You can't have them.", "statuses_count": 101830, "profile_background_image_url": "http://abs.twimg.com/images/themes/theme9/bg.gif", "profile_banner_url": "https://pbs.twimg.com/profile_banners/29040347/1491445985", "profile_link_color": "1B95E0", "profile_sidebar_fill_color": "252429", "listed_count": 100}, "place": null, "contributors": null, "lang": "en", "retweet_count": 10, "favorited": false, "geo": null}, "id": 849424628401541121, "quoted_status_id": 849412806835351552, "truncated": true, "current_user_retweet": {"id": 849736251708243969, "id_str": "849736251708243969"}, "in_reply_to_user_id_str": null, "in_reply_to_status_id": null, "is_quote_status": true, "user": {"name": "Mastodon", "default_profile_image": false, "follow_request_sent": false, "notifications": false, "screen_name": "mastodonmusic", "id_str": "18065572", "geo_enabled": false, "is_translation_enabled": false, "profile_image_url_https": "https://pbs.twimg.com/profile_images/824852402217955328/QrFAKTJY_normal.jpg", "time_zone": "Pacific Time (US & Canada)", "has_extended_profile": false, "lang": "en", "profile_text_color": "333333", "profile_image_url": "http://pbs.twimg.com/profile_images/824852402217955328/QrFAKTJY_normal.jpg", "url": "http://t.co/nlnr4wS9tt", "id": 18065572, "followers_count": 368872, "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme14/bg.gif", "verified": true, "friends_count": 7123, "translator_type": "none", "contributors_enabled": false, "entities": {"url": {"urls": [{"expanded_url": "http://mastodonrocks.com", "display_url": "mastodonrocks.com", "indices": [0, 22], "url": "http://t.co/nlnr4wS9tt"}]}, "description": {"urls": [{"expanded_url": "https://wbr.ec/emperorofsand", "display_url": "wbr.ec/emperorofsand", "indices": [37, 60], "url": "https://t.co/A9W7Z32dwO"}, {"expanded_url": "http://mastodonrocks.com/tour", "display_url": "mastodonrocks.com/tour", "indices": [84, 107], "url": "https://t.co/EkXk0Mn6qK"}]}}, "favourites_count": 1846, "profile_background_color": "131516", "protected": false, "following": true, "is_translator": false, "default_profile": false, "location": "Atlanta, GA", "profile_sidebar_border_color": "EEEEEE", "utc_offset": -25200, "profile_background_tile": true, "created_at": "Fri Dec 12 00:51:35 +0000 2008", "profile_use_background_image": true, "description": "New album 'Emperor of Sand' out now! https://t.co/A9W7Z32dwO | On tour this spring! https://t.co/EkXk0Mn6qK", "statuses_count": 1380, "profile_background_image_url": "http://abs.twimg.com/images/themes/theme14/bg.gif", "profile_banner_url": "https://pbs.twimg.com/profile_banners/18065572/1490932593", "profile_link_color": "009999", "profile_sidebar_fill_color": "EFEFEF", "listed_count": 2194}, "place": null, "quoted_status_id_str": "849412806835351552", "contributors": null, "lang": "en", "retweet_count": 877, "favorited": false, "geo": null, "possibly_sensitive_appealable": false}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"favorited": false, "lang": "en", "in_reply_to_user_id": null, "place": null, "in_reply_to_user_id_str": null, "user": {"follow_request_sent": false, "protected": false, "profile_image_url": "http://pbs.twimg.com/profile_images/851269441652260865/jAloD4WT_normal.jpg", "entities": {"description": {"urls": []}, "url": {"urls": [{"indices": [0, 23], "url": "https://t.co/AF1gbNeaRA", "expanded_url": "http://www.aclu.org", "display_url": "aclu.org"}]}}, "geo_enabled": true, "notifications": false, "profile_image_url_https": "https://pbs.twimg.com/profile_images/851269441652260865/jAloD4WT_normal.jpg", "has_extended_profile": true, "lang": "en", "url": "https://t.co/AF1gbNeaRA", "profile_text_color": "333333", "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png", "utc_offset": -10800, "profile_banner_url": "https://pbs.twimg.com/profile_banners/20944497/1491830455", "is_translator": false, "created_at": "Sun Feb 15 22:49:11 +0000 2009", "id_str": "20944497", "default_profile": true, "description": "Civil rights attorney @ACLU (views expressed here are my own)", "contributors_enabled": false, "statuses_count": 967, "listed_count": 103, "followers_count": 6248, "favourites_count": 431, "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png", "verified": false, "friends_count": 308, "following": false, "screen_name": "andresegura", "profile_sidebar_border_color": "C0DEED", "name": "Andre Segura", "location": "New York", "default_profile_image": false, "translator_type": "none", "profile_background_color": "C0DEED", "id": 20944497, "time_zone": "Atlantic Time (Canada)", "profile_use_background_image": true, "is_translation_enabled": false, "profile_sidebar_fill_color": "DDEEF6", "profile_link_color": "1DA1F2", "profile_background_tile": false}, "full_text": "Wrong. You use it initially and throughout to gain access to people's homes through deception. You're immigration agents. Not police. https://t.co/VMgFjuVbHC", "retweeted": true, "created_at": "Fri Apr 07 18:21:16 +0000 2017", "id_str": "850413178534211584", "display_text_range": [0, 134], "in_reply_to_status_id_str": null, "quoted_status": {"lang": "en", "display_text_range": [0, 142], "place": null, "extended_entities": {"media": [{"type": "photo", "expanded_url": "https://twitter.com/ICEgov/status/850408344175222784/photo/1", "id": 850399217826897920, "id_str": "850399217826897920", "sizes": {"small": {"h": 453, "resize": "fit", "w": 680}, "medium": {"h": 800, "resize": "fit", "w": 1200}, "thumb": {"h": 150, "resize": "crop", "w": 150}, "large": {"h": 1365, "resize": "fit", "w": 2048}}, "indices": [143, 166], "ext_alt_text": null, "media_url_https": "https://pbs.twimg.com/media/C805lT_XoAAHDZT.jpg", "url": "https://t.co/Z5dzK2wsMJ", "media_url": "http://pbs.twimg.com/media/C805lT_XoAAHDZT.jpg", "display_url": "pic.twitter.com/Z5dzK2wsMJ"}]}, "in_reply_to_user_id_str": "39384517", "user": {"follow_request_sent": false, "protected": false, "profile_image_url": "http://pbs.twimg.com/profile_images/500012751796707328/dNaKkGLY_normal.jpeg", "entities": {"description": {"urls": [{"indices": [85, 107], "url": "http://t.co/DMYVYOOBVn", "expanded_url": "http://www.ice.gov/tips", "display_url": "ice.gov/tips"}, {"indices": [137, 159], "url": "http://t.co/tdQSb7xnVs", "expanded_url": "http://go.usa.gov/Equ", "display_url": "go.usa.gov/Equ"}]}, "url": {"urls": [{"indices": [0, 22], "url": "http://t.co/adS5dzLUKP", "expanded_url": "http://www.ice.gov", "display_url": "ice.gov"}]}}, "geo_enabled": false, "notifications": false, "profile_image_url_https": "https://pbs.twimg.com/profile_images/500012751796707328/dNaKkGLY_normal.jpeg", "has_extended_profile": false, "lang": "en", "url": "http://t.co/adS5dzLUKP", "profile_text_color": "333333", "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme15/bg.png", "utc_offset": -18000, "profile_banner_url": "https://pbs.twimg.com/profile_banners/39384517/1488988182", "is_translator": false, "created_at": "Tue May 12 00:20:23 +0000 2009", "id_str": "39384517", "default_profile": false, "description": "ICE is the largest investigative agency in DHS. Report suspicious criminal activity: http://t.co/DMYVYOOBVn \r\nView our privacy policies: http://t.co/tdQSb7xnVs", "contributors_enabled": false, "statuses_count": 6359, "listed_count": 1926, "followers_count": 194270, "favourites_count": 290, "profile_background_image_url": "http://abs.twimg.com/images/themes/theme15/bg.png", "verified": true, "friends_count": 63, "following": false, "screen_name": "ICEgov", "profile_sidebar_border_color": "A8C7F7", "name": "ICE", "location": "Washington, DC", "default_profile_image": false, "translator_type": "none", "profile_background_color": "022330", "id": 39384517, "time_zone": "Quito", "profile_use_background_image": true, "is_translation_enabled": false, "profile_sidebar_fill_color": "C0DFEC", "profile_link_color": "0084B4", "profile_background_tile": false}, "full_text": "ICE agents &amp; officers may initially ID themselves as \u201cpolice\u201d in an encounter because it is the universally known term for law enforcement https://t.co/Z5dzK2wsMJ", "retweeted": false, "created_at": "Fri Apr 07 18:02:03 +0000 2017", "id_str": "850408344175222784", "in_reply_to_user_id": 39384517, "in_reply_to_status_id_str": "850397557939372032", "favorite_count": 381, "in_reply_to_status_id": 850397557939372032, "source": "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>", "is_quote_status": false, "contributors": null, "in_reply_to_screen_name": "ICEgov", "retweet_count": 178, "favorited": false, "geo": null, "id": 850408344175222784, "possibly_sensitive_appealable": false, "coordinates": null, "entities": {"urls": [], "user_mentions": [], "media": [{"type": "photo", "expanded_url": "https://twitter.com/ICEgov/status/850408344175222784/photo/1", "id": 850399217826897920, "id_str": "850399217826897920", "sizes": {"small": {"h": 453, "resize": "fit", "w": 680}, "medium": {"h": 800, "resize": "fit", "w": 1200}, "thumb": {"h": 150, "resize": "crop", "w": 150}, "large": {"h": 1365, "resize": "fit", "w": 2048}}, "indices": [143, 166], "media_url_https": "https://pbs.twimg.com/media/C805lT_XoAAHDZT.jpg", "url": "https://t.co/Z5dzK2wsMJ", "media_url": "http://pbs.twimg.com/media/C805lT_XoAAHDZT.jpg", "display_url": "pic.twitter.com/Z5dzK2wsMJ"}], "hashtags": [], "symbols": []}, "possibly_sensitive": false, "truncated": false}, "current_user_retweet": {"id": 850419611669495812, "id_str": "850419611669495812"}, "favorite_count": 4378, "in_reply_to_status_id": null, "source": "<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone</a>", "is_quote_status": true, "contributors": null, "in_reply_to_screen_name": null, "retweet_count": 2643, "quoted_status_id_str": "850408344175222784", "quoted_status_id": 850408344175222784, "geo": null, "id": 850413178534211584, "possibly_sensitive_appealable": false, "coordinates": null, "entities": {"urls": [{"indices": [135, 158], "url": "https://t.co/VMgFjuVbHC", "expanded_url": "https://twitter.com/icegov/status/850408344175222784", "display_url": "twitter.com/icegov/status/\u2026"}], "user_mentions": [], "hashtags": [], "symbols": []}, "possibly_sensitive": false, "truncated": false}

tests/test_models.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,14 @@ class ModelsTest(unittest.TestCase):
1717
LIST_SAMPLE_JSON = json.loads(f.read().decode('utf8'))
1818
with open('testdata/models/models_media.json', 'rb') as f:
1919
MEDIA_SAMPLE_JSON = json.loads(f.read().decode('utf8'))
20+
2021
with open('testdata/models/models_status.json', 'rb') as f:
2122
STATUS_SAMPLE_JSON = json.loads(f.read().decode('utf8'))
23+
with open('testdata/models/status_quoted_tweet.json', 'rb') as f:
24+
STATUS_QUOTED_TWEET_SAMPLE_JSON = json.loads(f.read().decode('utf8'))
25+
with open('testdata/models/status_quoted_tweet_with_media.json', 'rb') as f:
26+
STATUS_QUOTED_TWEET_WITH_MEDIA = json.loads(f.read().decode('utf8'))
27+
2228
with open('testdata/models/models_status_no_user.json', 'rb') as f:
2329
STATUS_NO_USER_SAMPLE_JSON = json.loads(f.read().decode('utf8'))
2430
with open('testdata/models/models_trend.json', 'rb') as f:
@@ -119,6 +125,18 @@ def test_status(self):
119125
self.assertEqual(status.id_str, "698657677329752065")
120126
self.assertTrue(isinstance(status.user, twitter.User))
121127

128+
def test_status_quoted_tweet(self):
129+
"""Test that quoted tweets are properly handled."""
130+
status = twitter.Status.NewFromJsonDict(self.STATUS_QUOTED_TWEET_SAMPLE_JSON)
131+
assert status.quoted_status_id == 849412806835351552
132+
assert status.quoted_status.id == 849412806835351552
133+
assert status.quoted_status.text == "hard to believe @mastodonmusic created its own open source alternative to twitter to promote its new album"
134+
135+
def test_status_quoted_tweet_with_media(self):
136+
"""Test that quoted tweet properly handles attached media."""
137+
status = twitter.Status.NewFromJsonDict(self.STATUS_QUOTED_TWEET_WITH_MEDIA)
138+
assert status.quoted_status.media is not None
139+
122140
def test_status_no_user(self):
123141
""" Test twitter.Status object which does not contain a 'user' entity. """
124142
status = twitter.Status.NewFromJsonDict(self.STATUS_NO_USER_SAMPLE_JSON)

twitter/models.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,9 @@ def __init__(self, **kwargs):
396396
'media': None,
397397
'place': None,
398398
'possibly_sensitive': None,
399+
'quoted_status': None,
400+
'quoted_status_id': None,
401+
'quoted_status_id_str': None,
399402
'retweet_count': None,
400403
'retweeted': None,
401404
'retweeted_status': None,
@@ -438,17 +441,21 @@ def __repr__(self):
438441
string: A string representation of this twitter.Status instance with
439442
the ID of status, username and datetime.
440443
"""
444+
if self.tweet_mode == 'extended':
445+
text = self.full_text
446+
else:
447+
text = self.text
441448
if self.user:
442449
return "Status(ID={0}, ScreenName={1}, Created={2}, Text={3!r})".format(
443450
self.id,
444451
self.user.screen_name,
445452
self.created_at,
446-
self.text)
453+
text)
447454
else:
448455
return u"Status(ID={0}, Created={1}, Text={2!r})".format(
449456
self.id,
450457
self.created_at,
451-
self.text)
458+
text)
452459

453460
@classmethod
454461
def NewFromJsonDict(cls, data, **kwargs):
@@ -463,6 +470,7 @@ def NewFromJsonDict(cls, data, **kwargs):
463470
current_user_retweet = None
464471
hashtags = None
465472
media = None
473+
quoted_status = None
466474
retweeted_status = None
467475
urls = None
468476
user = None
@@ -474,6 +482,8 @@ def NewFromJsonDict(cls, data, **kwargs):
474482
retweeted_status = Status.NewFromJsonDict(data['retweeted_status'])
475483
if 'current_user_retweet' in data:
476484
current_user_retweet = data['current_user_retweet']['id']
485+
if 'quoted_status' in data:
486+
quoted_status = Status.NewFromJsonDict(data.get('quoted_status'))
477487

478488
if 'entities' in data:
479489
if 'urls' in data['entities']:
@@ -494,6 +504,7 @@ def NewFromJsonDict(cls, data, **kwargs):
494504
current_user_retweet=current_user_retweet,
495505
hashtags=hashtags,
496506
media=media,
507+
quoted_status=quoted_status,
497508
retweeted_status=retweeted_status,
498509
urls=urls,
499510
user=user,

0 commit comments

Comments
 (0)