From e31e640ed1dcab90bd1ac987c051462568744dda Mon Sep 17 00:00:00 2001 From: Harmon Date: Sun, 3 Apr 2022 03:51:16 -0500 Subject: [PATCH] Add API.indicate_direct_message_typing and API.mark_direct_message_read Resolves #1856 --- .../testindicatedirectmessagetyping.yaml | 169 ++++++ docs/api.rst | 494 +++++++++--------- tests/test_api.py | 9 + tweepy/api.py | 54 ++ 4 files changed, 487 insertions(+), 239 deletions(-) create mode 100644 cassettes/testindicatedirectmessagetyping.yaml diff --git a/cassettes/testindicatedirectmessagetyping.yaml b/cassettes/testindicatedirectmessagetyping.yaml new file mode 100644 index 0000000..e7a8be2 --- /dev/null +++ b/cassettes/testindicatedirectmessagetyping.yaml @@ -0,0 +1,169 @@ +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.8.0 + method: GET + uri: https://api.twitter.com/1.1/account/verify_credentials.json + response: + body: + string: !!binary | + H4sIAAAAAAAAAOxX227jNhD9FUJ9aIsasURJtmygQFOki3a3aYOF0aJYBQIlUTYRitSSlLNukH/v + UJJl+ZZNN3noQ/0QhXPjzOgcDvXgsNyZe+4U49ANfTwJwtksCmeTESgSbZQzd05onZEjSElBubin + tNqgBdWGiSXIdaYoFcme+oquQcNlRgyTAsSwyilYsqoTXGaZrIVBtaY5MhIZiIe62N8QjSqiDJJF + J/paNwZ6jlbGVHoej+OxuchkPL7M/vrpUizSN/ffwh614hD70CZ/q9/+wa+qmxswocIww6h25g+t + efOA5YeHZ7l/qojIaZ4c2i6ZWdUpOJTg1yS9fdrama442XROT5oykbPMpvfBHWH/9vH28aB1n813 + 15Ivyzcep1ym8bgk2lAFUtv5eJxJUbDlRbX56lfP+xc1wWY1dvFkr7ZwMprObHFQXaWkoZmhgMuC + cE1HTiE5l/dU6aQBiTMPQaYYFXkv8TDgi0GC+VbijhxAIrESAkvnWgp0RTPkuQjjuevPAx9958IP + YdeLIJuCrGWtGJTXBwUEmSyRRaEpLEXN+cgxrKTJ31LQrWBJZUIFSfkg4zVVrGADgTbEALb70BhK + 4AQI0wVp9fZt7iW9WNXomiiEA4S9uRfMg6hPGmPbQsve0J16rj+Z4JnvB5Ef4umQvcda8DP0k43/ + foF++JmoUoppGN3UKWfZfEu7dXARXbhoBexLgdFIUU6Jpec9vFuk66qSwMlCKmRWFJyYAXigy5tf + 0BqjH6W8K4m60wjeUiWZMBpxUots1fA7JxsU13nkZ/C3iGaxOERtDxKjwIsM4TCkLGS3MmRpMXQL + XdyUqeTdAtqtktIaS9HyY/9oOqh7d6S1iq650xB6h91JEODJFHs48ga9PVbuodofeRbUoy1DLXc1 + YCyzu8S16/oZQStFi+/jARNLmTJOL0zb0IZCjm0+GAnZUiFuvem26X/SFF1WVRsyHpNW2+SSKFrx + TWJk0kIssUW1mDupbCs7Nmi6edq3U53z3Ot6T5ntv5mUKmcCXrDeiuAYyehOL4xiaW2k6g0UtUeJ + JclzaePNztImDDwQesHMn56gzVC7o81/giH43g/c6P3y9+I1WbJD67l5srfvF82Trk8wRCCpeNy2 + 8aUjxHPDETCwnZD/s+zlLGM6+VjDKO5J1gGrY18/ydrJaQfncDx3ovzQzUoArCCopNYshew1FRqg + uqa9bTsZAcLO40vycJ+Vx95mw0YcTXXIxCgiNCegPiUFDh05wXWmAKQlKcnulgoSszcUbv0dt/k5 + J21YSZZ0wKoGtCTVFrHlsmVFY2NZtKJl//TgvgbXsuYu/lTcpOHCHmdfIbyB9VHpJ2up9jfbs4XN + PD+cRBPfi9xZGPj+FEduPH6bv/vt3fUiS4RUJeEHaTxV2uvvlhIhgJGH596ZjVpru9PxxxQIJ950 + NgumUzzYgDNx10PFu7r03gy1muU0JSpJgdiQxllIbe1gwc9b2bl2XgtHzxGE+pcMsyUBb9pMgc6j + V+a0IDU3n5MfhGyPX/s5uS+B0+5jDV8f9sQwvU5IA3ft9tNydzrsiJqYTWVHgbB39pFjZ/OKcihD + tOeEaoZkMxhrXTV17GJTCt8Y1Qpck/ZOv/2EbQwe/wEAAP//AwCOsxgQPw8AAA== + headers: + cache-control: + - no-cache, no-store, must-revalidate, pre-check=0, post-check=0 + content-disposition: + - attachment; filename=json.json + content-encoding: + - gzip + content-length: + - '1243' + content-type: + - application/json;charset=utf-8 + date: + - Sun, 03 Apr 2022 08:49:40 GMT + expires: + - Tue, 31 Mar 1981 05:00:00 GMT + last-modified: + - Sun, 03 Apr 2022 08:49:40 GMT + pragma: + - no-cache + server: + - tsa_b + set-cookie: + - guest_id_marketing=v1%3A164897578037650380; Max-Age=63072000; Expires=Tue, + 02 Apr 2024 08:49:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None + - guest_id_ads=v1%3A164897578037650380; Max-Age=63072000; Expires=Tue, 02 Apr + 2024 08:49:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None + - personalization_id="v1_j4Z9yQ7csmtYO0dDDWt41g=="; Max-Age=63072000; Expires=Tue, + 02 Apr 2024 08:49:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None + - lang=en; Path=/ + - guest_id=v1%3A164897578037650380; Max-Age=63072000; Expires=Tue, 02 Apr 2024 + 08:49:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None + status: + - 200 OK + strict-transport-security: + - max-age=631138519 + x-access-level: + - read-write-directmessages + x-connection-hash: + - c6e61385a8ce7bb44a1f2b70e7252d65709b1854fc4362cc882adc809e2c455b + x-content-type-options: + - nosniff + x-frame-options: + - SAMEORIGIN + x-rate-limit-limit: + - '75' + x-rate-limit-remaining: + - '74' + x-rate-limit-reset: + - '1648976680' + x-response-time: + - '52' + x-transaction: + - 93b9113e8c49b1cc + x-twitter-response-tags: + - BouncerExempt + - BouncerCompliant + x-xss-protection: + - '0' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + Cookie: + - guest_id=v1%3A164897578037650380; guest_id_ads=v1%3A164897578037650380; guest_id_marketing=v1%3A164897578037650380; + personalization_id="v1_j4Z9yQ7csmtYO0dDDWt41g=="; lang=en + User-Agent: + - Python/3.10.0 Requests/2.27.1 Tweepy/4.8.0 + method: POST + uri: https://api.twitter.com/1.1/direct_messages/indicate_typing.json?recipient_id=1072250532645998596 + response: + body: + string: '' + headers: + cache-control: + - no-cache, no-store, must-revalidate, pre-check=0, post-check=0 + content-security-policy: + - default-src 'self'; connect-src 'self'; font-src 'self' https://*.twimg.com + https://twitter.com https://ton.twitter.com data:; frame-src 'self' https://*.twimg.com + https://twitter.com https://ton.twitter.com; img-src 'self' https://*.twimg.com + https://twitter.com https://ton.twitter.com data:; media-src 'self' https://*.twimg.com + https://twitter.com https://ton.twitter.com; object-src 'none'; script-src + 'self' https://*.twimg.com https://twitter.com https://ton.twitter.com; style-src + 'self' https://*.twimg.com https://twitter.com https://ton.twitter.com; report-uri + https://twitter.com/i/csp_report?a=NVQWGYLXFVSG2%3D%3D%3D&ro=false; + content-type: + - text/html;charset=utf-8 + date: + - Sun, 03 Apr 2022 08:49:40 GMT + expires: + - Tue, 31 Mar 1981 05:00:00 GMT + last-modified: + - Sun, 03 Apr 2022 08:49:40 GMT + pragma: + - no-cache + server: + - tsa_b + status: + - 204 No Content + strict-transport-security: + - max-age=631138519 + x-access-level: + - read-write-directmessages + x-connection-hash: + - a165c17d70f8bb53ea2bcc6d4ccae838f8e240fdc961c253bd20562ed881c742 + x-content-type-options: + - nosniff + x-frame-options: + - SAMEORIGIN + x-response-time: + - '14' + x-transaction: + - bb0fa2e18c728150 + x-twitter-response-tags: + - BouncerCompliant + x-xss-protection: + - '0' + status: + code: 204 + message: No Content +version: 1 diff --git a/docs/api.rst b/docs/api.rst index 34116bf..1124f8a 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -13,245 +13,251 @@ .. table:: :align: center - +------------------------------------------+--------------------------------------+ - | Twitter API v1.1 Endpoint | :class:`API` Method | - +==========================================+======================================+ - | .. centered:: :ref:`Premium Search APIs` | - +------------------------------------------+--------------------------------------+ - | `GET search/30day/:label`_ | :meth:`API.search_30_day` | - +------------------------------------------+--------------------------------------+ - | `GET search/fullarchive/:label`_ | :meth:`API.search_full_archive` | - +------------------------------------------+--------------------------------------+ - | .. centered:: :ref:`Tweets` | - +---------------------------------------------------------------------------------+ - | .. centered:: |Get Tweet timelines|_ | - +------------------------------------------+--------------------------------------+ - | `GET statuses/home_timeline`_ | :meth:`API.home_timeline` | - +------------------------------------------+--------------------------------------+ - | `GET statuses/mentions_timeline`_ | :meth:`API.mentions_timeline` | - +------------------------------------------+--------------------------------------+ - | `GET statuses/user_timeline`_ | :meth:`API.user_timeline` | - +------------------------------------------+--------------------------------------+ - | .. centered:: |Post, retrieve, and engage with Tweets|_ | - +------------------------------------------+--------------------------------------+ - | `GET favorites/list`_ | :meth:`API.get_favorites` | - +------------------------------------------+--------------------------------------+ - | `GET statuses/lookup`_ | :meth:`API.lookup_statuses` | - +------------------------------------------+--------------------------------------+ - | `GET statuses/oembed`_ | :meth:`API.get_oembed` | - +------------------------------------------+--------------------------------------+ - | `GET statuses/retweeters/ids`_ | :meth:`API.get_retweeter_ids` | - +------------------------------------------+--------------------------------------+ - | `GET statuses/retweets/:id`_ | :meth:`API.get_retweets` | - +------------------------------------------+--------------------------------------+ - | `GET statuses/retweets_of_me`_ | :meth:`API.get_retweets_of_me` | - +------------------------------------------+--------------------------------------+ - | `GET statuses/show/:id`_ | :meth:`API.get_status` | - +------------------------------------------+--------------------------------------+ - | `POST favorites/create`_ | :meth:`API.create_favorite` | - +------------------------------------------+--------------------------------------+ - | `POST favorites/destroy`_ | :meth:`API.destroy_favorite` | - +------------------------------------------+--------------------------------------+ - | `POST statuses/destroy/:id`_ | :meth:`API.destroy_status` | - +------------------------------------------+--------------------------------------+ - | `POST statuses/retweet/:id`_ | :meth:`API.retweet` | - +------------------------------------------+--------------------------------------+ - | `POST statuses/unretweet/:id`_ | :meth:`API.unretweet` | - +------------------------------------------+--------------------------------------+ - | `POST statuses/update`_ | :meth:`API.update_status` | - +------------------------------------------+--------------------------------------+ - | `POST statuses/update_with_media`_ | :meth:`API.update_status_with_media` | - +------------------------------------------+--------------------------------------+ - | .. centered:: |Search Tweets|_ | - +------------------------------------------+--------------------------------------+ - | `GET search/tweets`_ | :meth:`API.search_tweets` | - +------------------------------------------+--------------------------------------+ - | .. centered:: :ref:`Accounts and users` | - +---------------------------------------------------------------------------------+ - | .. centered:: |Create and manage lists|_ | - +------------------------------------------+--------------------------------------+ - | `GET lists/list`_ | :meth:`API.get_lists` | - +------------------------------------------+--------------------------------------+ - | `GET lists/members`_ | :meth:`API.get_list_members` | - +------------------------------------------+--------------------------------------+ - | `GET lists/members/show`_ | :meth:`API.get_list_member` | - +------------------------------------------+--------------------------------------+ - | `GET lists/memberships`_ | :meth:`API.get_list_memberships` | - +------------------------------------------+--------------------------------------+ - | `GET lists/ownerships`_ | :meth:`API.get_list_ownerships` | - +------------------------------------------+--------------------------------------+ - | `GET lists/show`_ | :meth:`API.get_list` | - +------------------------------------------+--------------------------------------+ - | `GET lists/statuses`_ | :meth:`API.list_timeline` | - +------------------------------------------+--------------------------------------+ - | `GET lists/subscribers`_ | :meth:`API.get_list_subscribers` | - +------------------------------------------+--------------------------------------+ - | `GET lists/subscribers/show`_ | :meth:`API.get_list_subscriber` | - +------------------------------------------+--------------------------------------+ - | `GET lists/subscriptions`_ | :meth:`API.get_list_subscriptions` | - +------------------------------------------+--------------------------------------+ - | `POST lists/create`_ | :meth:`API.create_list` | - +------------------------------------------+--------------------------------------+ - | `POST lists/destroy`_ | :meth:`API.destroy_list` | - +------------------------------------------+--------------------------------------+ - | `POST lists/members/create`_ | :meth:`API.add_list_member` | - +------------------------------------------+--------------------------------------+ - | `POST lists/members/create_all`_ | :meth:`API.add_list_members` | - +------------------------------------------+--------------------------------------+ - | `POST lists/members/destroy`_ | :meth:`API.remove_list_member` | - +------------------------------------------+--------------------------------------+ - | `POST lists/members/destroy_all`_ | :meth:`API.remove_list_members` | - +------------------------------------------+--------------------------------------+ - | `POST lists/subscribers/create`_ | :meth:`API.subscribe_list` | - +------------------------------------------+--------------------------------------+ - | `POST lists/subscribers/destroy`_ | :meth:`API.unsubscribe_list` | - +------------------------------------------+--------------------------------------+ - | `POST lists/update`_ | :meth:`API.update_list` | - +------------------------------------------+--------------------------------------+ - | .. centered:: |Follow, search, and get users|_ | - +------------------------------------------+--------------------------------------+ - | `GET followers/ids`_ | :meth:`API.get_follower_ids` | - +------------------------------------------+--------------------------------------+ - | `GET followers/list`_ | :meth:`API.get_followers` | - +------------------------------------------+--------------------------------------+ - | `GET friends/ids`_ | :meth:`API.get_friend_ids` | - +------------------------------------------+--------------------------------------+ - | `GET friends/list`_ | :meth:`API.get_friends` | - +------------------------------------------+--------------------------------------+ - | `GET friendships/incoming`_ | :meth:`API.incoming_friendships` | - +------------------------------------------+--------------------------------------+ - | `GET friendships/lookup`_ | :meth:`API.lookup_friendships` | - +------------------------------------------+--------------------------------------+ - | `GET friendships/no_retweets/ids`_ | :meth:`API.no_retweets_friendships` | - +------------------------------------------+--------------------------------------+ - | `GET friendships/outgoing`_ | :meth:`API.outgoing_friendships` | - +------------------------------------------+--------------------------------------+ - | `GET friendships/show`_ | :meth:`API.get_friendship` | - +------------------------------------------+--------------------------------------+ - | `GET users/lookup`_ | :meth:`API.lookup_users` | - +------------------------------------------+--------------------------------------+ - | `GET users/search`_ | :meth:`API.search_users` | - +------------------------------------------+--------------------------------------+ - | `GET users/show`_ | :meth:`API.get_user` | - +------------------------------------------+--------------------------------------+ - | `POST friendships/create`_ | :meth:`API.create_friendship` | - +------------------------------------------+--------------------------------------+ - | `POST friendships/destroy`_ | :meth:`API.destroy_friendship` | - +------------------------------------------+--------------------------------------+ - | `POST friendships/update`_ | :meth:`API.update_friendship` | - +------------------------------------------+--------------------------------------+ - | .. centered:: |Manage account settings and profile|_ | - +------------------------------------------+--------------------------------------+ - | `GET account/settings`_ | :meth:`API.get_settings` | - +------------------------------------------+--------------------------------------+ - | `GET account/verify_credentials`_ | :meth:`API.verify_credentials` | - +------------------------------------------+--------------------------------------+ - | `GET saved_searches/list`_ | :meth:`API.get_saved_searches` | - +------------------------------------------+--------------------------------------+ - | `GET saved_searches/show/:id`_ | :meth:`API.get_saved_search` | - +------------------------------------------+--------------------------------------+ - | `GET users/profile_banner`_ | :meth:`API.get_profile_banner` | - +------------------------------------------+--------------------------------------+ - | `POST account/remove_profile_banner`_ | :meth:`API.remove_profile_banner` | - +------------------------------------------+--------------------------------------+ - | `POST account/settings`_ | :meth:`API.set_settings` | - +------------------------------------------+--------------------------------------+ - | `POST account/update_profile`_ | :meth:`API.update_profile` | - +------------------------------------------+--------------------------------------+ - | `POST account/update_profile_banner`_ | :meth:`API.update_profile_banner` | - +------------------------------------------+--------------------------------------+ - | `POST account/update_profile_image`_ | :meth:`API.update_profile_image` | - +------------------------------------------+--------------------------------------+ - | `POST saved_searches/create`_ | :meth:`API.create_saved_search` | - +------------------------------------------+--------------------------------------+ - | `POST saved_searches/destroy/:id`_ | :meth:`API.destroy_saved_search` | - +------------------------------------------+--------------------------------------+ - | .. centered:: |Mute, block, and report users|_ | - +------------------------------------------+--------------------------------------+ - | `GET blocks/ids`_ | :meth:`API.get_blocked_ids` | - +------------------------------------------+--------------------------------------+ - | `GET blocks/list`_ | :meth:`API.get_blocks` | - +------------------------------------------+--------------------------------------+ - | `GET mutes/users/ids`_ | :meth:`API.get_muted_ids` | - +------------------------------------------+--------------------------------------+ - | `GET mutes/users/list`_ | :meth:`API.get_mutes` | - +------------------------------------------+--------------------------------------+ - | `POST blocks/create`_ | :meth:`API.create_block` | - +------------------------------------------+--------------------------------------+ - | `POST blocks/destroy`_ | :meth:`API.destroy_block` | - +------------------------------------------+--------------------------------------+ - | `POST mutes/users/create`_ | :meth:`API.create_mute` | - +------------------------------------------+--------------------------------------+ - | `POST mutes/users/destroy`_ | :meth:`API.destroy_mute` | - +------------------------------------------+--------------------------------------+ - | `POST users/report_spam`_ | :meth:`API.report_spam` | - +------------------------------------------+--------------------------------------+ - | .. centered:: :ref:`Direct Messages` | - +---------------------------------------------------------------------------------+ - | .. centered:: |Sending and receiving events|_ | - +------------------------------------------+--------------------------------------+ - | `DELETE direct_messages/events/destroy`_ | :meth:`API.delete_direct_message` | - +------------------------------------------+--------------------------------------+ - | `GET direct_messages/events/list`_ | :meth:`API.get_direct_messages` | - +------------------------------------------+--------------------------------------+ - | `GET direct_messages/events/show`_ | :meth:`API.get_direct_message` | - +------------------------------------------+--------------------------------------+ - | `POST direct_messages/events/new`_ | :meth:`API.send_direct_message` | - +------------------------------------------+--------------------------------------+ - | .. centered:: :ref:`Media` | - +---------------------------------------------------------------------------------+ - | .. centered:: |Upload media|_ | - +------------------------------------------+--------------------------------------+ - | `GET media/upload`_ | :meth:`API.get_media_upload_status` | - +------------------------------------------+--------------------------------------+ - | `POST media/metadata/create`_ | :meth:`API.create_media_metadata` | - +------------------------------------------+--------------------------------------+ - | | :meth:`API.media_upload` | - +------------------------------------------+--------------------------------------+ - | `POST media/upload`_ | :meth:`API.simple_upload` | - +------------------------------------------+--------------------------------------+ - | | :meth:`API.chunked_upload` | - +------------------------------------------+--------------------------------------+ - | `POST media/upload (APPEND)`_ | :meth:`API.chunked_upload_append` | - +------------------------------------------+--------------------------------------+ - | `POST media/upload (FINALIZE)`_ | :meth:`API.chunked_upload_finalize` | - +------------------------------------------+--------------------------------------+ - | `POST media/upload (INIT)`_ | :meth:`API.chunked_upload_init` | - +------------------------------------------+--------------------------------------+ - | .. centered:: :ref:`Trends` | - +---------------------------------------------------------------------------------+ - | .. centered:: |Get locations with trending topics|_ | - +------------------------------------------+--------------------------------------+ - | `GET trends/available`_ | :meth:`API.available_trends` | - +------------------------------------------+--------------------------------------+ - | `GET trends/closest`_ | :meth:`API.closest_trends` | - +------------------------------------------+--------------------------------------+ - | .. centered:: |Get trends near a location|_ | - +------------------------------------------+--------------------------------------+ - | `GET trends/place`_ | :meth:`API.get_place_trends` | - +------------------------------------------+--------------------------------------+ - | .. centered:: :ref:`Geo` | - +---------------------------------------------------------------------------------+ - | .. centered:: |Get information about a place|_ | - +------------------------------------------+--------------------------------------+ - | `GET geo/id/:place_id`_ | :meth:`API.geo_id` | - +------------------------------------------+--------------------------------------+ - | .. centered:: |Get places near a location|_ | - +------------------------------------------+--------------------------------------+ - | `GET geo/reverse_geocode`_ | :meth:`API.reverse_geocode` | - +------------------------------------------+--------------------------------------+ - | `GET geo/search`_ | :meth:`API.search_geo` | - +------------------------------------------+--------------------------------------+ - | .. centered:: :ref:`Developer utilities` | - +---------------------------------------------------------------------------------+ - | .. centered:: |Get Twitter supported languages|_ | - +------------------------------------------+--------------------------------------+ - | `GET help/languages`_ | :meth:`API.supported_languages` | - +------------------------------------------+--------------------------------------+ - | .. centered:: |Get app rate limit status|_ | - +------------------------------------------+--------------------------------------+ - | `GET application/rate_limit_status`_ | :meth:`API.rate_limit_status` | - +------------------------------------------+--------------------------------------+ + +------------------------------------------+--------------------------------------------+ + | Twitter API v1.1 Endpoint | :class:`API` Method | + +==========================================+============================================+ + | .. centered:: :ref:`Premium Search APIs` | + +------------------------------------------+--------------------------------------------+ + | `GET search/30day/:label`_ | :meth:`API.search_30_day` | + +------------------------------------------+--------------------------------------------+ + | `GET search/fullarchive/:label`_ | :meth:`API.search_full_archive` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: :ref:`Tweets` | + +---------------------------------------------------------------------------------------+ + | .. centered:: |Get Tweet timelines|_ | + +------------------------------------------+--------------------------------------------+ + | `GET statuses/home_timeline`_ | :meth:`API.home_timeline` | + +------------------------------------------+--------------------------------------------+ + | `GET statuses/mentions_timeline`_ | :meth:`API.mentions_timeline` | + +------------------------------------------+--------------------------------------------+ + | `GET statuses/user_timeline`_ | :meth:`API.user_timeline` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: |Post, retrieve, and engage with Tweets|_ | + +------------------------------------------+--------------------------------------------+ + | `GET favorites/list`_ | :meth:`API.get_favorites` | + +------------------------------------------+--------------------------------------------+ + | `GET statuses/lookup`_ | :meth:`API.lookup_statuses` | + +------------------------------------------+--------------------------------------------+ + | `GET statuses/oembed`_ | :meth:`API.get_oembed` | + +------------------------------------------+--------------------------------------------+ + | `GET statuses/retweeters/ids`_ | :meth:`API.get_retweeter_ids` | + +------------------------------------------+--------------------------------------------+ + | `GET statuses/retweets/:id`_ | :meth:`API.get_retweets` | + +------------------------------------------+--------------------------------------------+ + | `GET statuses/retweets_of_me`_ | :meth:`API.get_retweets_of_me` | + +------------------------------------------+--------------------------------------------+ + | `GET statuses/show/:id`_ | :meth:`API.get_status` | + +------------------------------------------+--------------------------------------------+ + | `POST favorites/create`_ | :meth:`API.create_favorite` | + +------------------------------------------+--------------------------------------------+ + | `POST favorites/destroy`_ | :meth:`API.destroy_favorite` | + +------------------------------------------+--------------------------------------------+ + | `POST statuses/destroy/:id`_ | :meth:`API.destroy_status` | + +------------------------------------------+--------------------------------------------+ + | `POST statuses/retweet/:id`_ | :meth:`API.retweet` | + +------------------------------------------+--------------------------------------------+ + | `POST statuses/unretweet/:id`_ | :meth:`API.unretweet` | + +------------------------------------------+--------------------------------------------+ + | `POST statuses/update`_ | :meth:`API.update_status` | + +------------------------------------------+--------------------------------------------+ + | `POST statuses/update_with_media`_ | :meth:`API.update_status_with_media` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: |Search Tweets|_ | + +------------------------------------------+--------------------------------------------+ + | `GET search/tweets`_ | :meth:`API.search_tweets` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: :ref:`Accounts and users` | + +---------------------------------------------------------------------------------------+ + | .. centered:: |Create and manage lists|_ | + +------------------------------------------+--------------------------------------------+ + | `GET lists/list`_ | :meth:`API.get_lists` | + +------------------------------------------+--------------------------------------------+ + | `GET lists/members`_ | :meth:`API.get_list_members` | + +------------------------------------------+--------------------------------------------+ + | `GET lists/members/show`_ | :meth:`API.get_list_member` | + +------------------------------------------+--------------------------------------------+ + | `GET lists/memberships`_ | :meth:`API.get_list_memberships` | + +------------------------------------------+--------------------------------------------+ + | `GET lists/ownerships`_ | :meth:`API.get_list_ownerships` | + +------------------------------------------+--------------------------------------------+ + | `GET lists/show`_ | :meth:`API.get_list` | + +------------------------------------------+--------------------------------------------+ + | `GET lists/statuses`_ | :meth:`API.list_timeline` | + +------------------------------------------+--------------------------------------------+ + | `GET lists/subscribers`_ | :meth:`API.get_list_subscribers` | + +------------------------------------------+--------------------------------------------+ + | `GET lists/subscribers/show`_ | :meth:`API.get_list_subscriber` | + +------------------------------------------+--------------------------------------------+ + | `GET lists/subscriptions`_ | :meth:`API.get_list_subscriptions` | + +------------------------------------------+--------------------------------------------+ + | `POST lists/create`_ | :meth:`API.create_list` | + +------------------------------------------+--------------------------------------------+ + | `POST lists/destroy`_ | :meth:`API.destroy_list` | + +------------------------------------------+--------------------------------------------+ + | `POST lists/members/create`_ | :meth:`API.add_list_member` | + +------------------------------------------+--------------------------------------------+ + | `POST lists/members/create_all`_ | :meth:`API.add_list_members` | + +------------------------------------------+--------------------------------------------+ + | `POST lists/members/destroy`_ | :meth:`API.remove_list_member` | + +------------------------------------------+--------------------------------------------+ + | `POST lists/members/destroy_all`_ | :meth:`API.remove_list_members` | + +------------------------------------------+--------------------------------------------+ + | `POST lists/subscribers/create`_ | :meth:`API.subscribe_list` | + +------------------------------------------+--------------------------------------------+ + | `POST lists/subscribers/destroy`_ | :meth:`API.unsubscribe_list` | + +------------------------------------------+--------------------------------------------+ + | `POST lists/update`_ | :meth:`API.update_list` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: |Follow, search, and get users|_ | + +------------------------------------------+--------------------------------------------+ + | `GET followers/ids`_ | :meth:`API.get_follower_ids` | + +------------------------------------------+--------------------------------------------+ + | `GET followers/list`_ | :meth:`API.get_followers` | + +------------------------------------------+--------------------------------------------+ + | `GET friends/ids`_ | :meth:`API.get_friend_ids` | + +------------------------------------------+--------------------------------------------+ + | `GET friends/list`_ | :meth:`API.get_friends` | + +------------------------------------------+--------------------------------------------+ + | `GET friendships/incoming`_ | :meth:`API.incoming_friendships` | + +------------------------------------------+--------------------------------------------+ + | `GET friendships/lookup`_ | :meth:`API.lookup_friendships` | + +------------------------------------------+--------------------------------------------+ + | `GET friendships/no_retweets/ids`_ | :meth:`API.no_retweets_friendships` | + +------------------------------------------+--------------------------------------------+ + | `GET friendships/outgoing`_ | :meth:`API.outgoing_friendships` | + +------------------------------------------+--------------------------------------------+ + | `GET friendships/show`_ | :meth:`API.get_friendship` | + +------------------------------------------+--------------------------------------------+ + | `GET users/lookup`_ | :meth:`API.lookup_users` | + +------------------------------------------+--------------------------------------------+ + | `GET users/search`_ | :meth:`API.search_users` | + +------------------------------------------+--------------------------------------------+ + | `GET users/show`_ | :meth:`API.get_user` | + +------------------------------------------+--------------------------------------------+ + | `POST friendships/create`_ | :meth:`API.create_friendship` | + +------------------------------------------+--------------------------------------------+ + | `POST friendships/destroy`_ | :meth:`API.destroy_friendship` | + +------------------------------------------+--------------------------------------------+ + | `POST friendships/update`_ | :meth:`API.update_friendship` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: |Manage account settings and profile|_ | + +------------------------------------------+--------------------------------------------+ + | `GET account/settings`_ | :meth:`API.get_settings` | + +------------------------------------------+--------------------------------------------+ + | `GET account/verify_credentials`_ | :meth:`API.verify_credentials` | + +------------------------------------------+--------------------------------------------+ + | `GET saved_searches/list`_ | :meth:`API.get_saved_searches` | + +------------------------------------------+--------------------------------------------+ + | `GET saved_searches/show/:id`_ | :meth:`API.get_saved_search` | + +------------------------------------------+--------------------------------------------+ + | `GET users/profile_banner`_ | :meth:`API.get_profile_banner` | + +------------------------------------------+--------------------------------------------+ + | `POST account/remove_profile_banner`_ | :meth:`API.remove_profile_banner` | + +------------------------------------------+--------------------------------------------+ + | `POST account/settings`_ | :meth:`API.set_settings` | + +------------------------------------------+--------------------------------------------+ + | `POST account/update_profile`_ | :meth:`API.update_profile` | + +------------------------------------------+--------------------------------------------+ + | `POST account/update_profile_banner`_ | :meth:`API.update_profile_banner` | + +------------------------------------------+--------------------------------------------+ + | `POST account/update_profile_image`_ | :meth:`API.update_profile_image` | + +------------------------------------------+--------------------------------------------+ + | `POST saved_searches/create`_ | :meth:`API.create_saved_search` | + +------------------------------------------+--------------------------------------------+ + | `POST saved_searches/destroy/:id`_ | :meth:`API.destroy_saved_search` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: |Mute, block, and report users|_ | + +------------------------------------------+--------------------------------------------+ + | `GET blocks/ids`_ | :meth:`API.get_blocked_ids` | + +------------------------------------------+--------------------------------------------+ + | `GET blocks/list`_ | :meth:`API.get_blocks` | + +------------------------------------------+--------------------------------------------+ + | `GET mutes/users/ids`_ | :meth:`API.get_muted_ids` | + +------------------------------------------+--------------------------------------------+ + | `GET mutes/users/list`_ | :meth:`API.get_mutes` | + +------------------------------------------+--------------------------------------------+ + | `POST blocks/create`_ | :meth:`API.create_block` | + +------------------------------------------+--------------------------------------------+ + | `POST blocks/destroy`_ | :meth:`API.destroy_block` | + +------------------------------------------+--------------------------------------------+ + | `POST mutes/users/create`_ | :meth:`API.create_mute` | + +------------------------------------------+--------------------------------------------+ + | `POST mutes/users/destroy`_ | :meth:`API.destroy_mute` | + +------------------------------------------+--------------------------------------------+ + | `POST users/report_spam`_ | :meth:`API.report_spam` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: :ref:`Direct Messages` | + +---------------------------------------------------------------------------------------+ + | .. centered:: |Sending and receiving events|_ | + +------------------------------------------+--------------------------------------------+ + | `DELETE direct_messages/events/destroy`_ | :meth:`API.delete_direct_message` | + +------------------------------------------+--------------------------------------------+ + | `GET direct_messages/events/list`_ | :meth:`API.get_direct_messages` | + +------------------------------------------+--------------------------------------------+ + | `GET direct_messages/events/show`_ | :meth:`API.get_direct_message` | + +------------------------------------------+--------------------------------------------+ + | `POST direct_messages/events/new`_ | :meth:`API.send_direct_message` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: |Typing indicator and read receipts|_ | + +------------------------------------------+--------------------------------------------+ + | `POST direct_messages/indicate_typing`_ | :meth:`API.indicate_direct_message_typing` | + +------------------------------------------+--------------------------------------------+ + | `POST direct_messages/mark_read`_ | :meth:`API.mark_direct_message_read` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: :ref:`Media` | + +---------------------------------------------------------------------------------------+ + | .. centered:: |Upload media|_ | + +------------------------------------------+--------------------------------------------+ + | `GET media/upload`_ | :meth:`API.get_media_upload_status` | + +------------------------------------------+--------------------------------------------+ + | `POST media/metadata/create`_ | :meth:`API.create_media_metadata` | + +------------------------------------------+--------------------------------------------+ + | | :meth:`API.media_upload` | + +------------------------------------------+--------------------------------------------+ + | `POST media/upload`_ | :meth:`API.simple_upload` | + +------------------------------------------+--------------------------------------------+ + | | :meth:`API.chunked_upload` | + +------------------------------------------+--------------------------------------------+ + | `POST media/upload (APPEND)`_ | :meth:`API.chunked_upload_append` | + +------------------------------------------+--------------------------------------------+ + | `POST media/upload (FINALIZE)`_ | :meth:`API.chunked_upload_finalize` | + +------------------------------------------+--------------------------------------------+ + | `POST media/upload (INIT)`_ | :meth:`API.chunked_upload_init` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: :ref:`Trends` | + +---------------------------------------------------------------------------------------+ + | .. centered:: |Get locations with trending topics|_ | + +------------------------------------------+--------------------------------------------+ + | `GET trends/available`_ | :meth:`API.available_trends` | + +------------------------------------------+--------------------------------------------+ + | `GET trends/closest`_ | :meth:`API.closest_trends` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: |Get trends near a location|_ | + +------------------------------------------+--------------------------------------------+ + | `GET trends/place`_ | :meth:`API.get_place_trends` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: :ref:`Geo` | + +---------------------------------------------------------------------------------------+ + | .. centered:: |Get information about a place|_ | + +------------------------------------------+--------------------------------------------+ + | `GET geo/id/:place_id`_ | :meth:`API.geo_id` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: |Get places near a location|_ | + +------------------------------------------+--------------------------------------------+ + | `GET geo/reverse_geocode`_ | :meth:`API.reverse_geocode` | + +------------------------------------------+--------------------------------------------+ + | `GET geo/search`_ | :meth:`API.search_geo` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: :ref:`Developer utilities` | + +---------------------------------------------------------------------------------------+ + | .. centered:: |Get Twitter supported languages|_ | + +------------------------------------------+--------------------------------------------+ + | `GET help/languages`_ | :meth:`API.supported_languages` | + +------------------------------------------+--------------------------------------------+ + | .. centered:: |Get app rate limit status|_ | + +------------------------------------------+--------------------------------------------+ + | `GET application/rate_limit_status`_ | :meth:`API.rate_limit_status` | + +------------------------------------------+--------------------------------------------+ .. _GET search/30day/:label: https://developer.twitter.com/en/docs/twitter-api/premium/search-api/api-reference/premium-search .. _GET search/fullarchive/:label: https://developer.twitter.com/en/docs/twitter-api/premium/search-api/api-reference/premium-search @@ -340,6 +346,9 @@ .. _GET direct_messages/events/list: https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/sending-and-receiving/api-reference/list-events .. _GET direct_messages/events/show: https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/sending-and-receiving/api-reference/get-event .. _POST direct_messages/events/new: https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/sending-and-receiving/api-reference/new-event +.. |Typing indicator and read receipts| replace:: *Typing indicator and read receipts* +.. _POST direct_messages/indicate_typing: https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/typing-indicator-and-read-receipts/api-reference/new-typing-indicator +.. _POST direct_messages/mark_read: https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/typing-indicator-and-read-receipts/api-reference/new-read-receipt .. |Upload media| replace:: *Upload media* .. _GET media/upload: https://developer.twitter.com/en/docs/twitter-api/v1/media/upload-media/api-reference/get-media-upload-status .. _POST media/metadata/create: https://developer.twitter.com/en/docs/twitter-api/v1/media/upload-media/api-reference/post-media-metadata-create @@ -556,6 +565,13 @@ Sending and receiving events .. automethod:: API.send_direct_message +Typing indicator and read receipts +---------------------------------- + +.. automethod:: API.indicate_direct_message_typing + +.. automethod:: API.mark_direct_message_read + Media ===== diff --git a/tests/test_api.py b/tests/test_api.py index a576ed1..ab6750b 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -147,6 +147,15 @@ class TweepyAPITests(TweepyTestCase): # destroy self.api.delete_direct_message(sent_dm.id) + @tape.use_cassette('testindicatedirectmessagetyping.yaml', + serializer='yaml') + def testindicatedirectmessagetyping(self): + me = self.api.verify_credentials() + + self.api.indicate_direct_message_typing(me.id) + + # TODO: Test API.mark_direct_message_read + @tape.use_cassette('testcreatedestroyfriendship.yaml', serializer='yaml') def testcreatedestroyfriendship(self): enemy = self.api.destroy_friendship(screen_name='Twitter') diff --git a/tweepy/api.py b/tweepy/api.py index 002ca62..5120894 100644 --- a/tweepy/api.py +++ b/tweepy/api.py @@ -3395,6 +3395,60 @@ class API: json_payload=json_payload, **kwargs ) + # Typing indicator and read receipts + + def indicate_direct_message_typing(self, recipient_id, **kwargs): + """indicate_direct_message_typing(recipient_id) + + Displays a visual typing indicator in the recipient’s Direct Message + conversation view with the sender. Each request triggers a typing + indicator animation with a duration of ~3 seconds. + + .. versionadded:: 4.9 + + Parameters + ---------- + recipient_id + The user ID of the user to receive the typing indicator. + + References + ---------- + https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/typing-indicator-and-read-receipts/api-reference/new-typing-indicator + """ + return self.request( + 'POST', 'direct_messages/indicate_typing', endpoint_parameters=( + 'recipient_id' + ), recipient_id=recipient_id, **kwargs + ) + + def mark_direct_message_read(self, last_read_event_id, recipient_id, + **kwargs): + """mark_direct_message_read(last_read_event_id, recipient_id) + + Marks a message as read in the recipient’s Direct Message conversation + view with the sender. + + .. versionadded:: 4.9 + + Parameters + ---------- + last_read_event_id + The message ID of the most recent message to be marked read. All + messages before it will be marked read as well. + recipient_id + The user ID of the user the message is from. + + References + ---------- + https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/typing-indicator-and-read-receipts/api-reference/new-read-receipt + """ + return self.request( + 'POST', 'direct_messages/mark_read', endpoint_parameters=( + 'last_read_event_id', 'recipient_id' + ), last_read_event_id=last_read_event_id, + recipient_id=recipient_id, **kwargs + ) + # Upload media @payload('media') -- 2.25.1