Skip to content

Commit

Permalink
Merge pull request #147 from MerleLiuKun/feat-tweet-retweets
Browse files Browse the repository at this point in the history
Feat tweet retweets
  • Loading branch information
MerleLiuKun authored Nov 21, 2023
2 parents 1a069ce + c75c981 commit 739941d
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ Now covers these features:
- Tweet lookup
- Manage Tweets
- Quote Tweets
- Retweet Tweets
- Timelines
- Search Tweets
- Tweet counts
Expand Down
7 changes: 7 additions & 0 deletions docs/docs/usage/tweets/retweet.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,10 @@ my_api.remove_retweet_tweet(user_id=my_api.auth_user_id, tweet_id="target tweet
api.get_tweet_retweeted_users(tweet_id="target tweet id")
# Response(data=[User(id='1301152652357595137', name='realllkk520', username='realllkk520')])
```

## Tweet retweeted tweets

```python
api.get_tweet_retweeted_tweets(tweet_id="target tweet id")
# Response(data=[Tweet(id=1724975633908789418, text=RT @XDevelopers: You can now monitor your usage...), Tweet(id=1724805194280730931, text=RT @XDevelopers: You can now monitor your usage...)])
```
57 changes: 57 additions & 0 deletions pytwitter/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1272,6 +1272,63 @@ def get_tweet_quote_tweets(
return_json=return_json,
)

def get_tweet_retweeted_tweets(
self,
tweet_id: str,
*,
pagination_token: Optional[str] = None,
max_results: Optional[int] = None,
expansions: Optional[Union[str, List, Tuple]] = None,
tweet_fields: Optional[Union[str, List, Tuple]] = None,
media_fields: Optional[Union[str, List, Tuple]] = None,
place_fields: Optional[Union[str, List, Tuple]] = None,
poll_fields: Optional[Union[str, List, Tuple]] = None,
user_fields: Optional[Union[str, List, Tuple]] = None,
return_json: bool = False,
) -> Union[dict, md.Response]:
"""
Returns the Retweets for a given Tweet ID.
:param tweet_id: Unique identifier of the Tweet to request.
:param pagination_token: Token for the pagination.
:param max_results: The maximum number of results to be returned per page. Number between 5 and the 100.
By default, each page will return 100 results.
:param expansions: Fields for the expansions.
:param tweet_fields: Fields for the tweet object.
:param media_fields: Fields for the media object, Expansion required.
:param place_fields: Fields for the place object, Expansion required.
:param poll_fields: Fields for the poll object, Expansion required.
:param user_fields: Fields for the user object, Expansion required.
:param return_json: Type for returned data. If you set True JSON data will be returned.
:return:
- data: data for the target tweets.
- includes: expansions data.
- meta: pagination details
"""
args = {
"expansions": enf_comma_separated(name="expansions", value=expansions),
"tweet.fields": enf_comma_separated(
name="tweet_fields", value=tweet_fields
),
"user.fields": enf_comma_separated(name="user_fields", value=user_fields),
"media.fields": enf_comma_separated(
name="media_fields", value=media_fields
),
"place.fields": enf_comma_separated(
name="place_fields", value=place_fields
),
"poll.fields": enf_comma_separated(name="poll_fields", value=poll_fields),
"max_results": max_results,
"pagination_token": pagination_token,
}
return self._get(
url=f"{self.BASE_URL_V2}/tweets/{tweet_id}/retweets",
params=args,
cls=md.Tweet,
multi=True,
return_json=return_json,
)

def get_tweet_retweeted_users(
self,
tweet_id: str,
Expand Down
7 changes: 7 additions & 0 deletions pytwitter/rate_limit.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ def get_limit(self, auth_type, method="GET"):
LIMIT_USER_GET=75,
LIMIT_APP_GET=75,
)
TWEET_RETWEET_TWEETS = Endpoint(
resource="/tweets/:id/retweets",
regex=re.compile(r"/tweets/\d+/retweets"),
LIMIT_USER_GET=75,
LIMIT_APP_GET=75,
)
USER_TWEET_RETWEET = Endpoint(
resource="/users/:id/retweets",
regex=re.compile(r"/users/\d+/retweets"),
Expand Down Expand Up @@ -357,6 +363,7 @@ def get_limit(self, auth_type, method="GET"):
regex=re.compile(r"/dm_conversations"),
LIMIT_APP_GET=200,
)

MEDIA_UPLOAD = Endpoint(
resource="/media/upload.json",
regex=re.compile(r"/media/upload.json"),
Expand Down
1 change: 1 addition & 0 deletions testdata/apis/tweet/tweet_retweet_tweets_resp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"data":[{"public_metrics":{"retweet_count":49,"reply_count":0,"like_count":0,"quote_count":0,"bookmark_count":0,"impression_count":0},"created_at":"2023-11-16T02:20:14.000Z","edit_history_tweet_ids":["1724975633908789418"],"author_id":"1220870789794353155","id":"1724975633908789418","conversation_id":"1724975633908789418","text":"RT @XDevelopers: You can now monitor your usage programmatically using the new Usage endpoint in the X API v2 🎉\n\nWe are working on new feat…"},{"public_metrics":{"retweet_count":49,"reply_count":0,"like_count":0,"quote_count":0,"bookmark_count":0,"impression_count":0},"created_at":"2023-11-15T15:02:58.000Z","edit_history_tweet_ids":["1724805194280730931"],"author_id":"1703568081849913344","id":"1724805194280730931","conversation_id":"1724805194280730931","text":"RT @XDevelopers: You can now monitor your usage programmatically using the new Usage endpoint in the X API v2 🎉\n\nWe are working on new feat…"},{"public_metrics":{"retweet_count":49,"reply_count":0,"like_count":0,"quote_count":0,"bookmark_count":0,"impression_count":0},"created_at":"2023-11-15T14:26:42.000Z","edit_history_tweet_ids":["1724796066238018027"],"author_id":"1508209224643649537","id":"1724796066238018027","conversation_id":"1724796066238018027","text":"RT @XDevelopers: You can now monitor your usage programmatically using the new Usage endpoint in the X API v2 🎉\n\nWe are working on new feat…"},{"public_metrics":{"retweet_count":49,"reply_count":0,"like_count":0,"quote_count":0,"bookmark_count":0,"impression_count":0},"created_at":"2023-11-14T19:45:14.000Z","edit_history_tweet_ids":["1724513843391627715"],"author_id":"1520172548704522242","id":"1724513843391627715","conversation_id":"1724513843391627715","text":"RT @XDevelopers: You can now monitor your usage programmatically using the new Usage endpoint in the X API v2 🎉\n\nWe are working on new feat…"},{"public_metrics":{"retweet_count":49,"reply_count":0,"like_count":0,"quote_count":0,"bookmark_count":0,"impression_count":0},"created_at":"2023-11-11T10:27:12.000Z","edit_history_tweet_ids":["1723286245676322909"],"author_id":"1597464349","id":"1723286245676322909","conversation_id":"1723286245676322909","text":"RT @XDevelopers: You can now monitor your usage programmatically using the new Usage endpoint in the X API v2 🎉\n\nWe are working on new feat…"},{"public_metrics":{"retweet_count":49,"reply_count":0,"like_count":0,"quote_count":0,"bookmark_count":0,"impression_count":0},"created_at":"2023-11-10T19:10:57.000Z","edit_history_tweet_ids":["1723055663817818369"],"author_id":"1634677469629300737","id":"1723055663817818369","conversation_id":"1723055663817818369","text":"RT @XDevelopers: You can now monitor your usage programmatically using the new Usage endpoint in the X API v2 🎉\n\nWe are working on new feat…"},{"public_metrics":{"retweet_count":49,"reply_count":0,"like_count":0,"quote_count":0,"bookmark_count":0,"impression_count":2},"created_at":"2023-11-05T15:05:53.000Z","edit_history_tweet_ids":["1721182049565081649"],"author_id":"1580496415","id":"1721182049565081649","conversation_id":"1721182049565081649","text":"RT @XDevelopers: You can now monitor your usage programmatically using the new Usage endpoint in the X API v2 🎉\n\nWe are working on new feat…"},{"public_metrics":{"retweet_count":49,"reply_count":0,"like_count":0,"quote_count":0,"bookmark_count":0,"impression_count":0},"created_at":"2023-11-04T13:56:26.000Z","edit_history_tweet_ids":["1720802185506881778"],"author_id":"1543819489367666688","id":"1720802185506881778","conversation_id":"1720802185506881778","text":"RT @XDevelopers: You can now monitor your usage programmatically using the new Usage endpoint in the X API v2 🎉\n\nWe are working on new feat…"}],"includes":{"users":[{"created_at":"2020-01-25T00:47:45.000Z","username":"365Pathway","name":"Pathway 365","id":"1220870789794353155"},{"created_at":"2023-09-18T00:34:33.000Z","username":"dodemoeewaa","name":"ヤル気出ない𑁍𓏸𓈒#音楽(❁︎´꒳`❁︎)好き","id":"1703568081849913344"},{"created_at":"2022-03-27T22:28:16.000Z","username":"XPL1999","name":"XPL.779 🇻🇳","id":"1508209224643649537"},{"created_at":"2022-04-29T22:46:30.000Z","username":"apoolofthoughts","name":"Old Bird","id":"1520172548704522242"},{"created_at":"2013-07-16T03:47:14.000Z","username":"gurinder0005","name":"Ann 🔥🎊✨","id":"1597464349"},{"created_at":"2023-03-11T22:07:56.000Z","username":"2lidiaV","name":"lidia💙🌺🍭","id":"1634677469629300737"},{"created_at":"2013-07-09T14:08:07.000Z","username":"nurahmad73","name":"Monica","id":"1580496415"},{"created_at":"2022-07-04T04:50:33.000Z","username":"thePrajeet","name":"Prajeet","id":"1543819489367666688"}]},"meta":{"result_count":8,"next_token":"next_token"}}
34 changes: 34 additions & 0 deletions tests/apis/test_tweets.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,40 @@ def test_get_tweet_quote_tweets(api, helpers):
assert resp.includes.users[0].id == "29757971"


@responses.activate
def test_get_tweet_retweeted_tweets(api, helpers):
tweets_data = helpers.load_json_data(
"testdata/apis/tweet/tweet_retweet_tweets_resp.json"
)
tweet_id = "1720506615714213927"
responses.add(
responses.GET,
url=f"https://api.twitter.com/2/tweets/{tweet_id}/retweets",
json=tweets_data,
)

resp = api.get_tweet_retweeted_tweets(
tweet_id=tweet_id,
expansions=["author_id"],
tweet_fields=[
"created_at",
"author_id",
"conversation_id",
"public_metrics",
],
user_fields=[
"id",
"name",
"username",
"created_at",
],
max_results=10,
)
assert len(resp.data) == 8
assert resp.data[0].id == "1724975633908789418"
assert resp.includes.users[0].id == "1220870789794353155"


@responses.activate
def test_get_tweets_count(api, helpers):
recent_counts_data = helpers.load_json_data(
Expand Down

0 comments on commit 739941d

Please sign in to comment.