From 2b70b6cce5042ee8e9cfa28242e4cc3cd2291df4 Mon Sep 17 00:00:00 2001 From: Harmon Date: Thu, 17 Mar 2022 17:45:43 -0500 Subject: [PATCH] Add Client.get_quote_tweets Resolves #1844 --- cassettes/test_get_quote_tweets.yaml | 79 ++++++++++++++++++++++++++++ docs/client.rst | 11 ++++ tests/test_client.py | 5 ++ tweepy/client.py | 65 +++++++++++++++++++++++ 4 files changed, 160 insertions(+) create mode 100644 cassettes/test_get_quote_tweets.yaml diff --git a/cassettes/test_get_quote_tweets.yaml b/cassettes/test_get_quote_tweets.yaml new file mode 100644 index 0000000..ab03389 --- /dev/null +++ b/cassettes/test_get_quote_tweets.yaml @@ -0,0 +1,79 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - Python/3.10.0 Requests/2.27.1 Tweepy/4.6.0 + method: GET + uri: https://api.twitter.com/2/tweets/1293593516040269825/quote_tweets + response: + body: + string: !!binary | + H4sIAAAAAAAAANSV0W7TMBSGX+WQXlI227GdpDesGoOBVDZNk0CiaPISl3hN7cx22mXTJJ6GB+NJ + OKmYtvIENBdWcmz/5zu/jp2HpFJRJZNvD4mpkklCuchFTohMGU9ZJlmeJ+Mk6ruIkxeXcHS5MTFq + Pz3/OIG/74AfsGYTOFG+6WFaljoE8LrRKuhqbuf20lWqh40GZa3rbKmr3bXRQaw1LIwPEbStWmds + DOAW27DVm5epXg2KIwz8/vkreRy/AKdcpoKSVOacFnsEnkkpqMxkWhCSsVQ8gx8rC73rINTKawhu + hUPptbahdphn43ysh2z58IgDvnwNXbt2UYe3mKqstfZd69WNQmFKAGOUkHeqD2eLY1dpGN2otUJF + 00YAGJ33sXZ2DKNF022p57aOsQ2Tw8N4ULpDeU/KxXs6veh2+ZngpBBECsIYl2JvjJcFZ7lMOc8E + +pfRvQFPecYF4QXLWU7wvD6Df8HMYbkVexJS1cpYE6JX0Tg7EISubbF1tqtUWSJnHAhm/gBOuxC0 + sTBt3pzc35sxqMVWo4xmjRoBalUusagXWwdIOHUtVuVwJdx2plyiKW3T48RlrXtYKWw2E6FEozzu + VRGuvUMN/29CqEwF1kVYG9eoqLeJ6m6FB8GbHzUClM5WZqgkoMcVhIij8hV6aJ9KntujGmWNVY1G + TQE7XSy+pm0+W84+zXbj3V1Pjz+fNWcfdrxmnNCUUIJdUqDr+9MkLGUF55QRkuaSCLk34LRgIueM + I3VW8D26yIlglGW5RPqc0Zz93+Dfx8lKDz//h8Tr0DXxanuckwkl48Qi91V0S22R/prc6rXLFm7R + 9Mnj4x8AAAD//wMA+ligKjUIAAA= + headers: + api-version: + - '2.38' + cache-control: + - no-cache, no-store, max-age=0 + content-disposition: + - attachment; filename=json.json + content-encoding: + - gzip + content-length: + - '647' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 17 Mar 2022 22:36:03 UTC + server: + - tsa_b + set-cookie: + - guest_id_marketing=v1%3A164755656286570056; Max-Age=63072000; Expires=Sat, + 16 Mar 2024 22:36:03 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None + - guest_id_ads=v1%3A164755656286570056; Max-Age=63072000; Expires=Sat, 16 Mar + 2024 22:36:03 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None + - personalization_id="v1_P3Oiv406PvpnkmH15uKI3A=="; Max-Age=63072000; Expires=Sat, + 16 Mar 2024 22:36:03 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None + - guest_id=v1%3A164755656286570056; Max-Age=63072000; Expires=Sat, 16 Mar 2024 + 22:36:03 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None + strict-transport-security: + - max-age=631138519 + x-access-level: + - read + x-connection-hash: + - f075da26aecd07d6597c14e21f39a06f2ac88fc9c0089ae7bddb700e85b3ba4b + x-content-type-options: + - nosniff + x-frame-options: + - SAMEORIGIN + x-rate-limit-limit: + - '75' + x-rate-limit-remaining: + - '74' + x-rate-limit-reset: + - '1647557462' + x-response-time: + - '660' + x-xss-protection: + - '0' + status: + code: 200 + message: OK +version: 1 diff --git a/docs/client.rst b/docs/client.rst index f6d11ad..169b610 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -38,6 +38,10 @@ +--------------------------------------------------------------+----------------------------------------+ | `POST /2/tweets`_ | :meth:`Client.create_tweet` | +--------------------------------------------------------------+----------------------------------------+ + | .. centered:: |Quote Tweets|_ | + +--------------------------------------------------------------+----------------------------------------+ + | `GET /2/tweets/:id/quote_tweets`_ | :meth:`Client.get_quote_tweets` | + +--------------------------------------------------------------+----------------------------------------+ | .. centered:: |Retweets|_ | +--------------------------------------------------------------+----------------------------------------+ | `DELETE /2/users/:id/retweets/:source_tweet_id`_ | :meth:`Client.unretweet` | @@ -197,6 +201,8 @@ .. |Manage Tweets| replace:: *Manage Tweets* .. _DELETE /2/tweets/:id: https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/delete-tweets-id .. _POST /2/tweets: https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets +.. |Quote Tweets| replace:: *Quote Tweets* +.. _GET /2/tweets/:id/quote_tweets: https://developer.twitter.com/en/docs/twitter-api/tweets/quote-tweets/api-reference/get-tweets-id-quote_tweets .. |Retweets| replace:: *Retweets* .. _DELETE /2/users/:id/retweets/:source_tweet_id: https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/delete-users-id-retweets-tweet_id .. _GET /2/tweets/:id/retweeted_by: https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/get-tweets-id-retweeted_by @@ -296,6 +302,11 @@ Manage Tweets .. automethod:: Client.create_tweet +Quote Tweets +------------ + +.. automethod:: Client.get_quote_tweets + Retweets -------- diff --git a/tests/test_client.py b/tests/test_client.py index e3197cc..c5393d5 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -43,6 +43,11 @@ class TweepyTestCase(unittest.TestCase): tweet_id = response.data["id"] self.client.delete_tweet(tweet_id) + @tape.use_cassette("test_get_quote_tweets.yaml", serializer="yaml") + def test_get_quote_tweets(self): + tweet_id = 1293593516040269825 # @TwitterDev Tweet announcing API v2 + self.client.get_quote_tweets(tweet_id) + @tape.use_cassette("test_retweet_and_unretweet.yaml", serializer="yaml") def test_retweet_and_unretweet(self): tweet_id = 1415348607813832708 # @TwitterDev Tweet announcing API v2 Retweet endpoints diff --git a/tweepy/client.py b/tweepy/client.py index 2650fe1..d83a464 100644 --- a/tweepy/client.py +++ b/tweepy/client.py @@ -596,6 +596,71 @@ class Client(BaseClient): "POST", f"/2/tweets", json=json, user_auth=user_auth ) + # Quote Tweets + + def get_quote_tweets(self, id, *, user_auth=False, **params): + """get_quote_tweets( \ + id, *, expansions=None, max_results=None, media_fields=None, \ + pagination_token=None, place_fields=None, poll_fields=None, \ + tweet_fields=None, user_fields=None, user_auth=False \ + ) + + Returns Quote Tweets for a Tweet specified by the requested Tweet ID. + + The Tweets returned by this endpoint count towards the Project-level + `Tweet cap`_. + + .. versionadded:: 4.7 + + Parameters + ---------- + id : int | str + Unique identifier of the Tweet to request. + expansions : list[str] | str | None + :ref:`expansions_parameter` + max_results : int | None + Specifies the number of Tweets to try and retrieve, up to a maximum + of 100 per distinct request. By default, 10 results are returned if + this parameter is not supplied. The minimum permitted value is 10. + It is possible to receive less than the ``max_results`` per request + throughout the pagination process. + media_fields : list[str] | str | None + :ref:`media_fields_parameter` + pagination_token : str | None + This parameter is used to move forwards through 'pages' of results, + based on the value of the ``next_token``. The value used with the + parameter is pulled directly from the response provided by the API, + and should not be modified. + place_fields : list[str] | str | None + :ref:`place_fields_parameter` + poll_fields : list[str] | str | None + :ref:`poll_fields_parameter` + tweet_fields : list[str] | str | None + :ref:`tweet_fields_parameter` + user_fields : list[str] | str | None + :ref:`user_fields_parameter` + user_auth : bool + Whether or not to use OAuth 1.0a User Context to authenticate + + Returns + ------- + dict | requests.Response | Response + + References + ---------- + https://developer.twitter.com/en/docs/twitter-api/tweets/quote-tweets/api-reference/get-tweets-id-quote_tweets + + .. _Tweet cap: https://developer.twitter.com/en/docs/projects/overview#tweet-cap + """ + return self._make_request( + "GET", f"/2/tweets/{id}/quote_tweets", params=params, + endpoint_parameters=( + "expansions", "max_results", "media.fields", + "pagination_token", "place.fields", "poll.fields", + "tweet.fields", "user.fields" + ), data_type=Tweet, user_auth=user_auth + ) + # Retweets def unretweet(self, source_tweet_id, *, user_auth=True): -- 2.25.1