Add asynchronous.AsyncClient
authorHarmon <Harmon758@gmail.com>
Tue, 10 May 2022 03:14:46 +0000 (22:14 -0500)
committerHarmon <Harmon758@gmail.com>
Tue, 10 May 2022 03:14:46 +0000 (22:14 -0500)
Add async_lru as requirement for async extra

47 files changed:
.github/workflows/test.yml
cassettes/test_asyncclient_block_and_get_blocked_and unblock.yaml [new file with mode: 0644]
cassettes/test_asyncclient_bookmarks.yaml [new file with mode: 0644]
cassettes/test_asyncclient_create_and_delete_tweet.yaml [new file with mode: 0644]
cassettes/test_asyncclient_create_and_get_compliance_job_and_jobs.yaml [new file with mode: 0644]
cassettes/test_asyncclient_follow_and_unfollow_list.yaml [new file with mode: 0644]
cassettes/test_asyncclient_follow_and_unfollow_user.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_all_tweets_count.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_followed_lists.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_liked_tweets.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_liking_users.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_list.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_list_followers.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_list_members.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_list_memberships.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_list_tweets.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_me.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_owned_lists.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_quote_tweets.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_recent_tweets_count.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_retweeters.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_space.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_spaces.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_tweet.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_tweets.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_user.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_users.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_users_followers.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_users_following.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_users_mentions.yaml [new file with mode: 0644]
cassettes/test_asyncclient_get_users_tweets.yaml [new file with mode: 0644]
cassettes/test_asyncclient_hide_and_unhide_reply.yaml [new file with mode: 0644]
cassettes/test_asyncclient_like_and_unlike.yaml [new file with mode: 0644]
cassettes/test_asyncclient_manage_and_get_pinned_lists.yaml [new file with mode: 0644]
cassettes/test_asyncclient_mute_get_muted_and_unmute.yaml [new file with mode: 0644]
cassettes/test_asyncclient_retweet_and_unretweet.yaml [new file with mode: 0644]
cassettes/test_asyncclient_search_all_tweets.yaml [new file with mode: 0644]
cassettes/test_asyncclient_search_recent_tweets.yaml [new file with mode: 0644]
cassettes/test_asyncclient_search_spaces.yaml [new file with mode: 0644]
docs/asyncclient.rst [new file with mode: 0644]
docs/index.rst
setup.cfg
setup.py
tests/test_asyncclient.py [new file with mode: 0644]
tweepy/asynchronous/__init__.py
tweepy/asynchronous/client.py [new file with mode: 0644]
tweepy/errors.py

index fde7e8993282aafdde1bdbccee5f95fe8459b3c0..238ca3f37cbc01ffc59e407e1a32833a3515c72b 100644 (file)
@@ -18,7 +18,7 @@ jobs:
       - name: Install dependencies
         run: |
           python -m pip install --upgrade pip
-          pip install .[dev,test]
+          pip install .[async,dev,test]
       - name: Run tests
         run: |
           coverage run -m unittest discover tests
diff --git a/cassettes/test_asyncclient_block_and_get_blocked_and unblock.yaml b/cassettes/test_asyncclient_block_and_get_blocked_and unblock.yaml
new file mode 100644 (file)
index 0000000..2cd4817
--- /dev/null
@@ -0,0 +1,185 @@
+interactions:
+- request:
+    body:
+      target_user_id: '17874544'
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: POST
+    uri: https://api.twitter.com/2/users/1072250532645998596/blocking
+  response:
+    body:
+      string: '{"data":{"blocking":true}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '52'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:50 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965087916447; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:50 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965087916447; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:50 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_d6raK5hbnCFRKnII2kd5hQ=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:50 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965087916447; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:50 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - c9ce8c94ed937e66ed27655cc9cb540351079e5c38b952f0fe5622664320d42e
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651930550'
+      x-response-time:
+      - '41'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/blocking
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/1072250532645998596/blocking
+  response:
+    body:
+      string: '{"data":[{"id":"17874544","name":"Twitter Support","username":"TwitterSupport"}],"meta":{"result_count":1}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '111'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:51 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965103954945; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965103954945; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_i17sy7cUDAjsGIpFEiP82w=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965103954945; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - 6518b1ea1eedc55716aea9d3c3a7c13005142dd0edca34f50821728bda86965a
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '15'
+      x-rate-limit-remaining:
+      - '14'
+      x-rate-limit-reset:
+      - '1651930551'
+      x-response-time:
+      - '42'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/blocking
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: DELETE
+    uri: https://api.twitter.com/2/users/1072250532645998596/blocking/17874544
+  response:
+    body:
+      string: '{"data":{"blocking":false}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '53'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:51 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965123045517; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965123045517; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_VeY7KCW087dRYotZqyA/ig=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965123045517; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - 4e0af34f12925ee64848c60af7be02d98e38b2ee16eb71e16465cab2c32def2a
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651930551'
+      x-response-time:
+      - '38'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/blocking/17874544
+version: 1
diff --git a/cassettes/test_asyncclient_bookmarks.yaml b/cassettes/test_asyncclient_bookmarks.yaml
new file mode 100644 (file)
index 0000000..79ceb39
--- /dev/null
@@ -0,0 +1,250 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/me
+  response:
+    body:
+      string: '{"data":{"id":"1072250532645998596","name":"Tweepy Testing","username":"TweepyDev"}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '97'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:49:08 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165193134799749857; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165193134799749857; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_lkX47v1/wqpzmNqaQR/JrQ=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165193134799749857; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write
+      x-connection-hash:
+      - 313d4c500cc0442ad0c7b62b6e797e0eadb8dd161c09d94e9eeb1263dedf47c1
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '75'
+      x-rate-limit-remaining:
+      - '74'
+      x-rate-limit-reset:
+      - '1651932248'
+      x-response-time:
+      - '42'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/me
+- request:
+    body:
+      tweet_id: '1507070437557096461'
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: POST
+    uri: https://api.twitter.com/2/users/1072250532645998596/bookmarks
+  response:
+    body:
+      string: '{"data":{"bookmarked":true}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '54'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:49:08 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165193134820536706; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165193134820536706; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_eYLBFbzffKl18ocPpd0a5A=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165193134820536706; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write
+      x-connection-hash:
+      - 66e49ad2493f8aa414a9ce2b9a34df2495eaee86bd48b9df9d9c8288c7d53b84
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651932248'
+      x-response-time:
+      - '65'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/bookmarks
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/1072250532645998596/bookmarks
+  response:
+    body:
+      string: "{\"data\":[{\"id\":\"1507070437557096461\",\"text\":\"\\uD83D\\uDD16\
+        \ Bookmark this!\_\\n\\nToday we are launching new Bookmark endpoints, allowing\
+        \ you to build new ways for people to utilize and interact with their bookmarked\
+        \ Tweets - only available on the Twitter API v2.\\n\\nNot sure what to build?\
+        \ It\u2019s all in the forum post \\uD83D\\uDC40\\nhttps://t.co/vYayoqRtJE\"\
+        }],\"meta\":{\"result_count\":1}}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '313'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:49:08 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165193134839868944; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165193134839868944; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_6i55kkMQueSA+gvwrp7ozA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165193134839868944; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write
+      x-connection-hash:
+      - e4afc17615c4cf911769a7d48fd4888a2ba2a9dbebab798a94bd39712463cbcd
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '180'
+      x-rate-limit-remaining:
+      - '179'
+      x-rate-limit-reset:
+      - '1651932248'
+      x-response-time:
+      - '87'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/bookmarks
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: DELETE
+    uri: https://api.twitter.com/2/users/1072250532645998596/bookmarks/1507070437557096461
+  response:
+    body:
+      string: '{"data":{"bookmarked":false}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '55'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:49:08 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165193134861958660; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165193134861958660; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_Om7c+X1vXWC1IABwCnjUJw=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165193134861958660; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:49:08 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write
+      x-connection-hash:
+      - d16f69732531e18a5e61738729010d50f80a8fa6d5f94e37437cfc43fba642c4
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651932248'
+      x-response-time:
+      - '47'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/bookmarks/1507070437557096461
+version: 1
diff --git a/cassettes/test_asyncclient_create_and_delete_tweet.yaml b/cassettes/test_asyncclient_create_and_delete_tweet.yaml
new file mode 100644 (file)
index 0000000..45167e9
--- /dev/null
@@ -0,0 +1,127 @@
+interactions:
+- request:
+    body:
+      text: Test Tweet
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: POST
+    uri: https://api.twitter.com/2/tweets
+  response:
+    body:
+      string: '{"data":{"id":"1522929456142245888","text":"Test Tweet"}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '82'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:51 UTC
+      location:
+      - https://api.twitter.com/2/tweets/1522929456142245888
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965163646159; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965163646159; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_9kXZ5SQAhBTaIgPmqBYgDQ=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965163646159; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - ad8258d462cb70e11b962a871c336046ac01998967fa1d3b41986b40d17e5674
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '200'
+      x-rate-limit-remaining:
+      - '199'
+      x-rate-limit-reset:
+      - '1651930551'
+      x-response-time:
+      - '89'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 201
+      message: Created
+    url: https://api.twitter.com/2/tweets
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: DELETE
+    uri: https://api.twitter.com/2/tweets/1522929456142245888
+  response:
+    body:
+      string: '{"data":{"deleted":true}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '51'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:51 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965184974481; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965184974481; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_hwTY7sNphhl3RQZuVlgYPA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965184974481; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:51 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - c54d5361dcb16fe85709ffdb99c8394c81bd3e3118ae7652c8740bd8f2f397e3
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651930551'
+      x-response-time:
+      - '35'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/tweets/1522929456142245888
+version: 1
diff --git a/cassettes/test_asyncclient_create_and_get_compliance_job_and_jobs.yaml b/cassettes/test_asyncclient_create_and_get_compliance_job_and_jobs.yaml
new file mode 100644 (file)
index 0000000..275c4c7
--- /dev/null
@@ -0,0 +1,185 @@
+interactions:
+- request:
+    body:
+      type: tweets
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: POST
+    uri: https://api.twitter.com/2/compliance/jobs
+  response:
+    body:
+      string: '{"data":{"resumable":false,"upload_expires_at":"2022-05-07T13:35:52.000Z","download_expires_at":"2022-05-14T13:20:52.000Z","created_at":"2022-05-07T13:20:52.000Z","type":"tweets","download_url":"https://storage.googleapis.com/twttr-tweet-compliance/1522929458495242241/delivery/1168916625673924610_1522929458495242241?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=complianceapi-public-svc-acct%40twttr-compliance-public-prod.iam.gserviceaccount.com%2F20220507%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20220507T132052Z&X-Goog-Expires=604800&X-Goog-SignedHeaders=host&X-Goog-Signature=9fe139e270b7e08354d38f2a51d67403b9396fda6a319f09a078c9a02efe943156ee76282b04db4d4f58c32c7040822418ff26b248f09614f7afd73e75e3a8fcbf505a8a2d22fe5c62266c0a1f4787363012a5d5266c5b09fa8cfec3d07168b9742cb6e241c81e223121b055c2bfe0e52c17112b3d40624145fd0c7cb666de8f99423d4bf87c4f42c684a4936f901218125633bb746de857273a93e4378550a1090d38ba7182191ac4cb709e655b0b31c002e780a24173aa9a16c61e430fd65dbdd31a12fa30d2b9b02dbc12ea25e08d10f99e9c2006ed8420e69a9e0d5d14c22318325d91380260af1304ca734b6d41fda29cfb4b4b95d40ac082de74fad685","upload_url":"https://storage.googleapis.com/twttr-tweet-compliance/1522929458495242241/submission/1168916625673924610_1522929458495242241?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=complianceapi-public-svc-acct%40twttr-compliance-public-prod.iam.gserviceaccount.com%2F20220507%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20220507T132052Z&X-Goog-Expires=900&X-Goog-SignedHeaders=content-type%3Bhost&X-Goog-Signature=4ec29d5b214f019fbbc5b1e6fd643ef91ffe9231ee41b9f7569f0f0362d58ee5a13c168d8e190e59276708b4b491d91e0f00eb15cfaeba7db84ac92c9ac1ede66de3e278a649745cc7ad7a0eb010a96b94287a7435f73e7a2b5cfa3efddd2f6555b93a2f63ee036da4e8b58196dfe3d19c751081197296b85b1e74ecccdf82710d6b3fa4f17ba5c6c805f7903b0fd44c2ddaacc69f8c3976c5374a6bd96289239c29058ea15b8974e53ecd3ffff085deb18c650c963e7ead287e04afd8f7e3cd126ef15e068430f4124cddba16855c9c5fa4ce86e9fc233e2c36ee7eada3e451167a40be8c11b4b1ca20cc1f0a4f39aedcfca51cb6cf6a47c25dcd05bd9c01cd","status":"created","id":"1522929458495242241"}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '1056'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:53 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965216993797; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:53 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965216993797; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:53 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_ew0llXRK5SY93aChtlLxfw=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:53 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965216993797; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:53 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - a10a9fa46c9ce50e306bfc73dfece9d5e058bf55a02c00adfd7b4ad1832e4d55
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '150'
+      x-rate-limit-remaining:
+      - '149'
+      x-rate-limit-reset:
+      - '1651930552'
+      x-response-time:
+      - '1564'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/compliance/jobs
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/compliance/jobs/1522929458495242241
+  response:
+    body:
+      string: '{"data":{"download_url":"https://storage.googleapis.com/twttr-tweet-compliance/1522929458495242241/delivery/1168916625673924610_1522929458495242241?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=complianceapi-public-svc-acct%40twttr-compliance-public-prod.iam.gserviceaccount.com%2F20220507%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20220507T132052Z&X-Goog-Expires=604800&X-Goog-SignedHeaders=host&X-Goog-Signature=9fe139e270b7e08354d38f2a51d67403b9396fda6a319f09a078c9a02efe943156ee76282b04db4d4f58c32c7040822418ff26b248f09614f7afd73e75e3a8fcbf505a8a2d22fe5c62266c0a1f4787363012a5d5266c5b09fa8cfec3d07168b9742cb6e241c81e223121b055c2bfe0e52c17112b3d40624145fd0c7cb666de8f99423d4bf87c4f42c684a4936f901218125633bb746de857273a93e4378550a1090d38ba7182191ac4cb709e655b0b31c002e780a24173aa9a16c61e430fd65dbdd31a12fa30d2b9b02dbc12ea25e08d10f99e9c2006ed8420e69a9e0d5d14c22318325d91380260af1304ca734b6d41fda29cfb4b4b95d40ac082de74fad685","type":"tweets","resumable":false,"upload_expires_at":"2022-05-07T13:35:52.000Z","status":"created","download_expires_at":"2022-05-14T13:20:52.000Z","upload_url":"https://storage.googleapis.com/twttr-tweet-compliance/1522929458495242241/submission/1168916625673924610_1522929458495242241?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=complianceapi-public-svc-acct%40twttr-compliance-public-prod.iam.gserviceaccount.com%2F20220507%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20220507T132052Z&X-Goog-Expires=900&X-Goog-SignedHeaders=content-type%3Bhost&X-Goog-Signature=4ec29d5b214f019fbbc5b1e6fd643ef91ffe9231ee41b9f7569f0f0362d58ee5a13c168d8e190e59276708b4b491d91e0f00eb15cfaeba7db84ac92c9ac1ede66de3e278a649745cc7ad7a0eb010a96b94287a7435f73e7a2b5cfa3efddd2f6555b93a2f63ee036da4e8b58196dfe3d19c751081197296b85b1e74ecccdf82710d6b3fa4f17ba5c6c805f7903b0fd44c2ddaacc69f8c3976c5374a6bd96289239c29058ea15b8974e53ecd3ffff085deb18c650c963e7ead287e04afd8f7e3cd126ef15e068430f4124cddba16855c9c5fa4ce86e9fc233e2c36ee7eada3e451167a40be8c11b4b1ca20cc1f0a4f39aedcfca51cb6cf6a47c25dcd05bd9c01cd","id":"1522929458495242241","created_at":"2022-05-07T13:20:52.000Z"}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '1062'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:53 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965389038441; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:53 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965389038441; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:53 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_2xauOUTXnJkcZb/LToqSLA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:53 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965389038441; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:53 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 64316018686b7b2a222d5c2a3770bcfc7a33bf74b74eece75c9aae404ae25c4e
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '150'
+      x-rate-limit-remaining:
+      - '149'
+      x-rate-limit-reset:
+      - '1651930553'
+      x-response-time:
+      - '85'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/compliance/jobs/1522929458495242241
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/compliance/jobs?type=tweets
+  response:
+    body:
+      string: '{"data":[{"resumable":false,"upload_expires_at":"2022-05-07T13:35:52.000Z","download_expires_at":"2022-05-14T13:20:52.000Z","created_at":"2022-05-07T13:20:52.000Z","type":"tweets","download_url":"https://storage.googleapis.com/twttr-tweet-compliance/1522929458495242241/delivery/1168916625673924610_1522929458495242241?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=complianceapi-public-svc-acct%40twttr-compliance-public-prod.iam.gserviceaccount.com%2F20220507%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20220507T132052Z&X-Goog-Expires=604800&X-Goog-SignedHeaders=host&X-Goog-Signature=9fe139e270b7e08354d38f2a51d67403b9396fda6a319f09a078c9a02efe943156ee76282b04db4d4f58c32c7040822418ff26b248f09614f7afd73e75e3a8fcbf505a8a2d22fe5c62266c0a1f4787363012a5d5266c5b09fa8cfec3d07168b9742cb6e241c81e223121b055c2bfe0e52c17112b3d40624145fd0c7cb666de8f99423d4bf87c4f42c684a4936f901218125633bb746de857273a93e4378550a1090d38ba7182191ac4cb709e655b0b31c002e780a24173aa9a16c61e430fd65dbdd31a12fa30d2b9b02dbc12ea25e08d10f99e9c2006ed8420e69a9e0d5d14c22318325d91380260af1304ca734b6d41fda29cfb4b4b95d40ac082de74fad685","upload_url":"https://storage.googleapis.com/twttr-tweet-compliance/1522929458495242241/submission/1168916625673924610_1522929458495242241?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=complianceapi-public-svc-acct%40twttr-compliance-public-prod.iam.gserviceaccount.com%2F20220507%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20220507T132052Z&X-Goog-Expires=900&X-Goog-SignedHeaders=content-type%3Bhost&X-Goog-Signature=4ec29d5b214f019fbbc5b1e6fd643ef91ffe9231ee41b9f7569f0f0362d58ee5a13c168d8e190e59276708b4b491d91e0f00eb15cfaeba7db84ac92c9ac1ede66de3e278a649745cc7ad7a0eb010a96b94287a7435f73e7a2b5cfa3efddd2f6555b93a2f63ee036da4e8b58196dfe3d19c751081197296b85b1e74ecccdf82710d6b3fa4f17ba5c6c805f7903b0fd44c2ddaacc69f8c3976c5374a6bd96289239c29058ea15b8974e53ecd3ffff085deb18c650c963e7ead287e04afd8f7e3cd126ef15e068430f4124cddba16855c9c5fa4ce86e9fc233e2c36ee7eada3e451167a40be8c11b4b1ca20cc1f0a4f39aedcfca51cb6cf6a47c25dcd05bd9c01cd","status":"created","id":"1522929458495242241"}],"meta":{"result_count":1}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '1078'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:54 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965411055006; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965411055006; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_dW4iKogl9z0j/yggDMnn8A=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965411055006; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 03d8db1b261a059931d8fc87f9d1ecca0cfb4e83e68e5db5db7e7e03a62528e6
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '150'
+      x-rate-limit-remaining:
+      - '149'
+      x-rate-limit-reset:
+      - '1651930554'
+      x-response-time:
+      - '102'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/compliance/jobs?type=tweets
+version: 1
diff --git a/cassettes/test_asyncclient_follow_and_unfollow_list.yaml b/cassettes/test_asyncclient_follow_and_unfollow_list.yaml
new file mode 100644 (file)
index 0000000..1e655a1
--- /dev/null
@@ -0,0 +1,125 @@
+interactions:
+- request:
+    body:
+      list_id: '84839422'
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: POST
+    uri: https://api.twitter.com/2/users/1072250532645998596/followed_lists
+  response:
+    body:
+      string: '{"data":{"following":true}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '53'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:54 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965438101460; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965438101460; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_Z+/SOHbQSaRNRTchfkP+PA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965438101460; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - 466a2dcbb242fc5f3242134d1d3ebd07c0879ddd0c689fa2af1980070c1448c4
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651930554'
+      x-response-time:
+      - '61'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/followed_lists
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: DELETE
+    uri: https://api.twitter.com/2/users/1072250532645998596/followed_lists/84839422
+  response:
+    body:
+      string: '{"data":{"following":false}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '54'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:54 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965457290629; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965457290629; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_Q2d+R9WL3WKZtZcQuXSzHA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965457290629; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - 2c67e4422cda5589369e3d5d6b3742a9aca3a7ecd21a1cc2c48a62d6ddd22d00
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651930554'
+      x-response-time:
+      - '40'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/followed_lists/84839422
+version: 1
diff --git a/cassettes/test_asyncclient_follow_and_unfollow_user.yaml b/cassettes/test_asyncclient_follow_and_unfollow_user.yaml
new file mode 100644 (file)
index 0000000..6ad5271
--- /dev/null
@@ -0,0 +1,125 @@
+interactions:
+- request:
+    body:
+      target_user_id: '17874544'
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: POST
+    uri: https://api.twitter.com/2/users/1072250532645998596/following
+  response:
+    body:
+      string: '{"data":{"following":true,"pending_follow":false}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '71'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:54 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965480470897; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965480470897; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_ObiwRC+7xS0WwHOk3XXNEw=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965480470897; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:54 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - 4b9981fd25d378821f420b07a6ed61debdb3de5a5b734edc629c298343a98cb4
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '48'
+      x-rate-limit-reset:
+      - '1651930035'
+      x-response-time:
+      - '59'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/following
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: DELETE
+    uri: https://api.twitter.com/2/users/1072250532645998596/following/17874544
+  response:
+    body:
+      string: '{"data":{"following":false}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '54'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:55 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965500868082; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:55 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965500868082; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:55 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_ZvGN7rUqNeveNpOnc5EMAA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:55 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965500868082; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:55 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - 9ebd0e75bb76cf659d7013dd748e64e23159e3baedb5579b654e50c9aab07d55
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '48'
+      x-rate-limit-reset:
+      - '1651930050'
+      x-response-time:
+      - '48'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/following/17874544
+version: 1
diff --git a/cassettes/test_asyncclient_get_all_tweets_count.yaml b/cassettes/test_asyncclient_get_all_tweets_count.yaml
new file mode 100644 (file)
index 0000000..6e344f2
--- /dev/null
@@ -0,0 +1,62 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/tweets/counts/all?query=Tweepy
+  response:
+    body:
+      string: '{"data":[{"end":"2022-04-07T01:00:00.000Z","start":"2022-04-07T00:00:00.000Z","tweet_count":31},{"end":"2022-04-07T02:00:00.000Z","start":"2022-04-07T01:00:00.000Z","tweet_count":30},{"end":"2022-04-07T03:00:00.000Z","start":"2022-04-07T02:00:00.000Z","tweet_count":31},{"end":"2022-04-07T04:00:00.000Z","start":"2022-04-07T03:00:00.000Z","tweet_count":29},{"end":"2022-04-07T05:00:00.000Z","start":"2022-04-07T04:00:00.000Z","tweet_count":30},{"end":"2022-04-07T06:00:00.000Z","start":"2022-04-07T05:00:00.000Z","tweet_count":30},{"end":"2022-04-07T07:00:00.000Z","start":"2022-04-07T06:00:00.000Z","tweet_count":30},{"end":"2022-04-07T08:00:00.000Z","start":"2022-04-07T07:00:00.000Z","tweet_count":30},{"end":"2022-04-07T09:00:00.000Z","start":"2022-04-07T08:00:00.000Z","tweet_count":30},{"end":"2022-04-07T10:00:00.000Z","start":"2022-04-07T09:00:00.000Z","tweet_count":30},{"end":"2022-04-07T11:00:00.000Z","start":"2022-04-07T10:00:00.000Z","tweet_count":33},{"end":"2022-04-07T12:00:00.000Z","start":"2022-04-07T11:00:00.000Z","tweet_count":30},{"end":"2022-04-07T13:00:00.000Z","start":"2022-04-07T12:00:00.000Z","tweet_count":30},{"end":"2022-04-07T14:00:00.000Z","start":"2022-04-07T13:00:00.000Z","tweet_count":33},{"end":"2022-04-07T15:00:00.000Z","start":"2022-04-07T14:00:00.000Z","tweet_count":30},{"end":"2022-04-07T16:00:00.000Z","start":"2022-04-07T15:00:00.000Z","tweet_count":31},{"end":"2022-04-07T17:00:00.000Z","start":"2022-04-07T16:00:00.000Z","tweet_count":36},{"end":"2022-04-07T18:00:00.000Z","start":"2022-04-07T17:00:00.000Z","tweet_count":30},{"end":"2022-04-07T19:00:00.000Z","start":"2022-04-07T18:00:00.000Z","tweet_count":32},{"end":"2022-04-07T20:00:00.000Z","start":"2022-04-07T19:00:00.000Z","tweet_count":30},{"end":"2022-04-07T21:00:00.000Z","start":"2022-04-07T20:00:00.000Z","tweet_count":30},{"end":"2022-04-07T22:00:00.000Z","start":"2022-04-07T21:00:00.000Z","tweet_count":33},{"end":"2022-04-07T23:00:00.000Z","start":"2022-04-07T22:00:00.000Z","tweet_count":32},{"end":"2022-04-08T00:00:00.000Z","start":"2022-04-07T23:00:00.000Z","tweet_count":31},{"end":"2022-04-08T01:00:00.000Z","start":"2022-04-08T00:00:00.000Z","tweet_count":30},{"end":"2022-04-08T02:00:00.000Z","start":"2022-04-08T01:00:00.000Z","tweet_count":30},{"end":"2022-04-08T03:00:00.000Z","start":"2022-04-08T02:00:00.000Z","tweet_count":30},{"end":"2022-04-08T04:00:00.000Z","start":"2022-04-08T03:00:00.000Z","tweet_count":29},{"end":"2022-04-08T05:00:00.000Z","start":"2022-04-08T04:00:00.000Z","tweet_count":30},{"end":"2022-04-08T06:00:00.000Z","start":"2022-04-08T05:00:00.000Z","tweet_count":30},{"end":"2022-04-08T07:00:00.000Z","start":"2022-04-08T06:00:00.000Z","tweet_count":32},{"end":"2022-04-08T08:00:00.000Z","start":"2022-04-08T07:00:00.000Z","tweet_count":31},{"end":"2022-04-08T09:00:00.000Z","start":"2022-04-08T08:00:00.000Z","tweet_count":30},{"end":"2022-04-08T10:00:00.000Z","start":"2022-04-08T09:00:00.000Z","tweet_count":31},{"end":"2022-04-08T11:00:00.000Z","start":"2022-04-08T10:00:00.000Z","tweet_count":32},{"end":"2022-04-08T12:00:00.000Z","start":"2022-04-08T11:00:00.000Z","tweet_count":30},{"end":"2022-04-08T13:00:00.000Z","start":"2022-04-08T12:00:00.000Z","tweet_count":31},{"end":"2022-04-08T14:00:00.000Z","start":"2022-04-08T13:00:00.000Z","tweet_count":33},{"end":"2022-04-08T15:00:00.000Z","start":"2022-04-08T14:00:00.000Z","tweet_count":30},{"end":"2022-04-08T16:00:00.000Z","start":"2022-04-08T15:00:00.000Z","tweet_count":30},{"end":"2022-04-08T17:00:00.000Z","start":"2022-04-08T16:00:00.000Z","tweet_count":30},{"end":"2022-04-08T18:00:00.000Z","start":"2022-04-08T17:00:00.000Z","tweet_count":31},{"end":"2022-04-08T19:00:00.000Z","start":"2022-04-08T18:00:00.000Z","tweet_count":33},{"end":"2022-04-08T20:00:00.000Z","start":"2022-04-08T19:00:00.000Z","tweet_count":38},{"end":"2022-04-08T21:00:00.000Z","start":"2022-04-08T20:00:00.000Z","tweet_count":31},{"end":"2022-04-08T22:00:00.000Z","start":"2022-04-08T21:00:00.000Z","tweet_count":31},{"end":"2022-04-08T23:00:00.000Z","start":"2022-04-08T22:00:00.000Z","tweet_count":30},{"end":"2022-04-09T00:00:00.000Z","start":"2022-04-08T23:00:00.000Z","tweet_count":47},{"end":"2022-04-09T01:00:00.000Z","start":"2022-04-09T00:00:00.000Z","tweet_count":30},{"end":"2022-04-09T02:00:00.000Z","start":"2022-04-09T01:00:00.000Z","tweet_count":30},{"end":"2022-04-09T03:00:00.000Z","start":"2022-04-09T02:00:00.000Z","tweet_count":30},{"end":"2022-04-09T04:00:00.000Z","start":"2022-04-09T03:00:00.000Z","tweet_count":30},{"end":"2022-04-09T05:00:00.000Z","start":"2022-04-09T04:00:00.000Z","tweet_count":30},{"end":"2022-04-09T06:00:00.000Z","start":"2022-04-09T05:00:00.000Z","tweet_count":31},{"end":"2022-04-09T07:00:00.000Z","start":"2022-04-09T06:00:00.000Z","tweet_count":30},{"end":"2022-04-09T08:00:00.000Z","start":"2022-04-09T07:00:00.000Z","tweet_count":31},{"end":"2022-04-09T09:00:00.000Z","start":"2022-04-09T08:00:00.000Z","tweet_count":31},{"end":"2022-04-09T10:00:00.000Z","start":"2022-04-09T09:00:00.000Z","tweet_count":32},{"end":"2022-04-09T11:00:00.000Z","start":"2022-04-09T10:00:00.000Z","tweet_count":32},{"end":"2022-04-09T12:00:00.000Z","start":"2022-04-09T11:00:00.000Z","tweet_count":30},{"end":"2022-04-09T13:00:00.000Z","start":"2022-04-09T12:00:00.000Z","tweet_count":30},{"end":"2022-04-09T14:00:00.000Z","start":"2022-04-09T13:00:00.000Z","tweet_count":30},{"end":"2022-04-09T15:00:00.000Z","start":"2022-04-09T14:00:00.000Z","tweet_count":31},{"end":"2022-04-09T16:00:00.000Z","start":"2022-04-09T15:00:00.000Z","tweet_count":30},{"end":"2022-04-09T17:00:00.000Z","start":"2022-04-09T16:00:00.000Z","tweet_count":30},{"end":"2022-04-09T18:00:00.000Z","start":"2022-04-09T17:00:00.000Z","tweet_count":31},{"end":"2022-04-09T19:00:00.000Z","start":"2022-04-09T18:00:00.000Z","tweet_count":32},{"end":"2022-04-09T20:00:00.000Z","start":"2022-04-09T19:00:00.000Z","tweet_count":33},{"end":"2022-04-09T21:00:00.000Z","start":"2022-04-09T20:00:00.000Z","tweet_count":30},{"end":"2022-04-09T22:00:00.000Z","start":"2022-04-09T21:00:00.000Z","tweet_count":34},{"end":"2022-04-09T23:00:00.000Z","start":"2022-04-09T22:00:00.000Z","tweet_count":32},{"end":"2022-04-10T00:00:00.000Z","start":"2022-04-09T23:00:00.000Z","tweet_count":31},{"end":"2022-04-10T01:00:00.000Z","start":"2022-04-10T00:00:00.000Z","tweet_count":30},{"end":"2022-04-10T02:00:00.000Z","start":"2022-04-10T01:00:00.000Z","tweet_count":31},{"end":"2022-04-10T03:00:00.000Z","start":"2022-04-10T02:00:00.000Z","tweet_count":33},{"end":"2022-04-10T04:00:00.000Z","start":"2022-04-10T03:00:00.000Z","tweet_count":30},{"end":"2022-04-10T05:00:00.000Z","start":"2022-04-10T04:00:00.000Z","tweet_count":32},{"end":"2022-04-10T06:00:00.000Z","start":"2022-04-10T05:00:00.000Z","tweet_count":30},{"end":"2022-04-10T07:00:00.000Z","start":"2022-04-10T06:00:00.000Z","tweet_count":30},{"end":"2022-04-10T08:00:00.000Z","start":"2022-04-10T07:00:00.000Z","tweet_count":30},{"end":"2022-04-10T09:00:00.000Z","start":"2022-04-10T08:00:00.000Z","tweet_count":30},{"end":"2022-04-10T10:00:00.000Z","start":"2022-04-10T09:00:00.000Z","tweet_count":32},{"end":"2022-04-10T11:00:00.000Z","start":"2022-04-10T10:00:00.000Z","tweet_count":31},{"end":"2022-04-10T12:00:00.000Z","start":"2022-04-10T11:00:00.000Z","tweet_count":31},{"end":"2022-04-10T13:00:00.000Z","start":"2022-04-10T12:00:00.000Z","tweet_count":30},{"end":"2022-04-10T14:00:00.000Z","start":"2022-04-10T13:00:00.000Z","tweet_count":31},{"end":"2022-04-10T15:00:00.000Z","start":"2022-04-10T14:00:00.000Z","tweet_count":34},{"end":"2022-04-10T16:00:00.000Z","start":"2022-04-10T15:00:00.000Z","tweet_count":31},{"end":"2022-04-10T17:00:00.000Z","start":"2022-04-10T16:00:00.000Z","tweet_count":31},{"end":"2022-04-10T18:00:00.000Z","start":"2022-04-10T17:00:00.000Z","tweet_count":37},{"end":"2022-04-10T19:00:00.000Z","start":"2022-04-10T18:00:00.000Z","tweet_count":31},{"end":"2022-04-10T20:00:00.000Z","start":"2022-04-10T19:00:00.000Z","tweet_count":33},{"end":"2022-04-10T21:00:00.000Z","start":"2022-04-10T20:00:00.000Z","tweet_count":30},{"end":"2022-04-10T22:00:00.000Z","start":"2022-04-10T21:00:00.000Z","tweet_count":36},{"end":"2022-04-10T23:00:00.000Z","start":"2022-04-10T22:00:00.000Z","tweet_count":34},{"end":"2022-04-11T00:00:00.000Z","start":"2022-04-10T23:00:00.000Z","tweet_count":30},{"end":"2022-04-11T01:00:00.000Z","start":"2022-04-11T00:00:00.000Z","tweet_count":40},{"end":"2022-04-11T02:00:00.000Z","start":"2022-04-11T01:00:00.000Z","tweet_count":32},{"end":"2022-04-11T03:00:00.000Z","start":"2022-04-11T02:00:00.000Z","tweet_count":31},{"end":"2022-04-11T04:00:00.000Z","start":"2022-04-11T03:00:00.000Z","tweet_count":33},{"end":"2022-04-11T05:00:00.000Z","start":"2022-04-11T04:00:00.000Z","tweet_count":30},{"end":"2022-04-11T06:00:00.000Z","start":"2022-04-11T05:00:00.000Z","tweet_count":31},{"end":"2022-04-11T07:00:00.000Z","start":"2022-04-11T06:00:00.000Z","tweet_count":31},{"end":"2022-04-11T08:00:00.000Z","start":"2022-04-11T07:00:00.000Z","tweet_count":31},{"end":"2022-04-11T09:00:00.000Z","start":"2022-04-11T08:00:00.000Z","tweet_count":30},{"end":"2022-04-11T10:00:00.000Z","start":"2022-04-11T09:00:00.000Z","tweet_count":30},{"end":"2022-04-11T11:00:00.000Z","start":"2022-04-11T10:00:00.000Z","tweet_count":31},{"end":"2022-04-11T12:00:00.000Z","start":"2022-04-11T11:00:00.000Z","tweet_count":31},{"end":"2022-04-11T13:00:00.000Z","start":"2022-04-11T12:00:00.000Z","tweet_count":32},{"end":"2022-04-11T14:00:00.000Z","start":"2022-04-11T13:00:00.000Z","tweet_count":30},{"end":"2022-04-11T15:00:00.000Z","start":"2022-04-11T14:00:00.000Z","tweet_count":30},{"end":"2022-04-11T16:00:00.000Z","start":"2022-04-11T15:00:00.000Z","tweet_count":32},{"end":"2022-04-11T17:00:00.000Z","start":"2022-04-11T16:00:00.000Z","tweet_count":37},{"end":"2022-04-11T18:00:00.000Z","start":"2022-04-11T17:00:00.000Z","tweet_count":30},{"end":"2022-04-11T19:00:00.000Z","start":"2022-04-11T18:00:00.000Z","tweet_count":31},{"end":"2022-04-11T20:00:00.000Z","start":"2022-04-11T19:00:00.000Z","tweet_count":30},{"end":"2022-04-11T21:00:00.000Z","start":"2022-04-11T20:00:00.000Z","tweet_count":30},{"end":"2022-04-11T22:00:00.000Z","start":"2022-04-11T21:00:00.000Z","tweet_count":30},{"end":"2022-04-11T23:00:00.000Z","start":"2022-04-11T22:00:00.000Z","tweet_count":30},{"end":"2022-04-12T00:00:00.000Z","start":"2022-04-11T23:00:00.000Z","tweet_count":33},{"end":"2022-04-12T01:00:00.000Z","start":"2022-04-12T00:00:00.000Z","tweet_count":33},{"end":"2022-04-12T02:00:00.000Z","start":"2022-04-12T01:00:00.000Z","tweet_count":30},{"end":"2022-04-12T03:00:00.000Z","start":"2022-04-12T02:00:00.000Z","tweet_count":31},{"end":"2022-04-12T04:00:00.000Z","start":"2022-04-12T03:00:00.000Z","tweet_count":30},{"end":"2022-04-12T05:00:00.000Z","start":"2022-04-12T04:00:00.000Z","tweet_count":30},{"end":"2022-04-12T06:00:00.000Z","start":"2022-04-12T05:00:00.000Z","tweet_count":30},{"end":"2022-04-12T07:00:00.000Z","start":"2022-04-12T06:00:00.000Z","tweet_count":30},{"end":"2022-04-12T08:00:00.000Z","start":"2022-04-12T07:00:00.000Z","tweet_count":30},{"end":"2022-04-12T09:00:00.000Z","start":"2022-04-12T08:00:00.000Z","tweet_count":32},{"end":"2022-04-12T10:00:00.000Z","start":"2022-04-12T09:00:00.000Z","tweet_count":32},{"end":"2022-04-12T11:00:00.000Z","start":"2022-04-12T10:00:00.000Z","tweet_count":31},{"end":"2022-04-12T12:00:00.000Z","start":"2022-04-12T11:00:00.000Z","tweet_count":31},{"end":"2022-04-12T13:00:00.000Z","start":"2022-04-12T12:00:00.000Z","tweet_count":35},{"end":"2022-04-12T14:00:00.000Z","start":"2022-04-12T13:00:00.000Z","tweet_count":31},{"end":"2022-04-12T15:00:00.000Z","start":"2022-04-12T14:00:00.000Z","tweet_count":33},{"end":"2022-04-12T16:00:00.000Z","start":"2022-04-12T15:00:00.000Z","tweet_count":33},{"end":"2022-04-12T17:00:00.000Z","start":"2022-04-12T16:00:00.000Z","tweet_count":36},{"end":"2022-04-12T18:00:00.000Z","start":"2022-04-12T17:00:00.000Z","tweet_count":34},{"end":"2022-04-12T19:00:00.000Z","start":"2022-04-12T18:00:00.000Z","tweet_count":31},{"end":"2022-04-12T20:00:00.000Z","start":"2022-04-12T19:00:00.000Z","tweet_count":30},{"end":"2022-04-12T21:00:00.000Z","start":"2022-04-12T20:00:00.000Z","tweet_count":30},{"end":"2022-04-12T22:00:00.000Z","start":"2022-04-12T21:00:00.000Z","tweet_count":34},{"end":"2022-04-12T23:00:00.000Z","start":"2022-04-12T22:00:00.000Z","tweet_count":31},{"end":"2022-04-13T00:00:00.000Z","start":"2022-04-12T23:00:00.000Z","tweet_count":33},{"end":"2022-04-13T01:00:00.000Z","start":"2022-04-13T00:00:00.000Z","tweet_count":32},{"end":"2022-04-13T02:00:00.000Z","start":"2022-04-13T01:00:00.000Z","tweet_count":32},{"end":"2022-04-13T03:00:00.000Z","start":"2022-04-13T02:00:00.000Z","tweet_count":30},{"end":"2022-04-13T04:00:00.000Z","start":"2022-04-13T03:00:00.000Z","tweet_count":30},{"end":"2022-04-13T05:00:00.000Z","start":"2022-04-13T04:00:00.000Z","tweet_count":31},{"end":"2022-04-13T06:00:00.000Z","start":"2022-04-13T05:00:00.000Z","tweet_count":29},{"end":"2022-04-13T07:00:00.000Z","start":"2022-04-13T06:00:00.000Z","tweet_count":33},{"end":"2022-04-13T08:00:00.000Z","start":"2022-04-13T07:00:00.000Z","tweet_count":30},{"end":"2022-04-13T09:00:00.000Z","start":"2022-04-13T08:00:00.000Z","tweet_count":30},{"end":"2022-04-13T10:00:00.000Z","start":"2022-04-13T09:00:00.000Z","tweet_count":34},{"end":"2022-04-13T11:00:00.000Z","start":"2022-04-13T10:00:00.000Z","tweet_count":33},{"end":"2022-04-13T12:00:00.000Z","start":"2022-04-13T11:00:00.000Z","tweet_count":34},{"end":"2022-04-13T13:00:00.000Z","start":"2022-04-13T12:00:00.000Z","tweet_count":32},{"end":"2022-04-13T14:00:00.000Z","start":"2022-04-13T13:00:00.000Z","tweet_count":30},{"end":"2022-04-13T15:00:00.000Z","start":"2022-04-13T14:00:00.000Z","tweet_count":31},{"end":"2022-04-13T16:00:00.000Z","start":"2022-04-13T15:00:00.000Z","tweet_count":31},{"end":"2022-04-13T17:00:00.000Z","start":"2022-04-13T16:00:00.000Z","tweet_count":33},{"end":"2022-04-13T18:00:00.000Z","start":"2022-04-13T17:00:00.000Z","tweet_count":31},{"end":"2022-04-13T19:00:00.000Z","start":"2022-04-13T18:00:00.000Z","tweet_count":30},{"end":"2022-04-13T20:00:00.000Z","start":"2022-04-13T19:00:00.000Z","tweet_count":30},{"end":"2022-04-13T21:00:00.000Z","start":"2022-04-13T20:00:00.000Z","tweet_count":30},{"end":"2022-04-13T22:00:00.000Z","start":"2022-04-13T21:00:00.000Z","tweet_count":30},{"end":"2022-04-13T23:00:00.000Z","start":"2022-04-13T22:00:00.000Z","tweet_count":30},{"end":"2022-04-14T00:00:00.000Z","start":"2022-04-13T23:00:00.000Z","tweet_count":31},{"end":"2022-04-14T01:00:00.000Z","start":"2022-04-14T00:00:00.000Z","tweet_count":31},{"end":"2022-04-14T02:00:00.000Z","start":"2022-04-14T01:00:00.000Z","tweet_count":31},{"end":"2022-04-14T03:00:00.000Z","start":"2022-04-14T02:00:00.000Z","tweet_count":30},{"end":"2022-04-14T04:00:00.000Z","start":"2022-04-14T03:00:00.000Z","tweet_count":32},{"end":"2022-04-14T05:00:00.000Z","start":"2022-04-14T04:00:00.000Z","tweet_count":30},{"end":"2022-04-14T06:00:00.000Z","start":"2022-04-14T05:00:00.000Z","tweet_count":33},{"end":"2022-04-14T07:00:00.000Z","start":"2022-04-14T06:00:00.000Z","tweet_count":30},{"end":"2022-04-14T08:00:00.000Z","start":"2022-04-14T07:00:00.000Z","tweet_count":31},{"end":"2022-04-14T09:00:00.000Z","start":"2022-04-14T08:00:00.000Z","tweet_count":30},{"end":"2022-04-14T10:00:00.000Z","start":"2022-04-14T09:00:00.000Z","tweet_count":33},{"end":"2022-04-14T11:00:00.000Z","start":"2022-04-14T10:00:00.000Z","tweet_count":32},{"end":"2022-04-14T12:00:00.000Z","start":"2022-04-14T11:00:00.000Z","tweet_count":32},{"end":"2022-04-14T13:00:00.000Z","start":"2022-04-14T12:00:00.000Z","tweet_count":30},{"end":"2022-04-14T14:00:00.000Z","start":"2022-04-14T13:00:00.000Z","tweet_count":33},{"end":"2022-04-14T15:00:00.000Z","start":"2022-04-14T14:00:00.000Z","tweet_count":30},{"end":"2022-04-14T16:00:00.000Z","start":"2022-04-14T15:00:00.000Z","tweet_count":32},{"end":"2022-04-14T17:00:00.000Z","start":"2022-04-14T16:00:00.000Z","tweet_count":36},{"end":"2022-04-14T18:00:00.000Z","start":"2022-04-14T17:00:00.000Z","tweet_count":36},{"end":"2022-04-14T19:00:00.000Z","start":"2022-04-14T18:00:00.000Z","tweet_count":30},{"end":"2022-04-14T20:00:00.000Z","start":"2022-04-14T19:00:00.000Z","tweet_count":31},{"end":"2022-04-14T21:00:00.000Z","start":"2022-04-14T20:00:00.000Z","tweet_count":33},{"end":"2022-04-14T22:00:00.000Z","start":"2022-04-14T21:00:00.000Z","tweet_count":30},{"end":"2022-04-14T23:00:00.000Z","start":"2022-04-14T22:00:00.000Z","tweet_count":34},{"end":"2022-04-15T00:00:00.000Z","start":"2022-04-14T23:00:00.000Z","tweet_count":30},{"end":"2022-04-15T01:00:00.000Z","start":"2022-04-15T00:00:00.000Z","tweet_count":33},{"end":"2022-04-15T02:00:00.000Z","start":"2022-04-15T01:00:00.000Z","tweet_count":32},{"end":"2022-04-15T03:00:00.000Z","start":"2022-04-15T02:00:00.000Z","tweet_count":31},{"end":"2022-04-15T04:00:00.000Z","start":"2022-04-15T03:00:00.000Z","tweet_count":30},{"end":"2022-04-15T05:00:00.000Z","start":"2022-04-15T04:00:00.000Z","tweet_count":29},{"end":"2022-04-15T06:00:00.000Z","start":"2022-04-15T05:00:00.000Z","tweet_count":26},{"end":"2022-04-15T07:00:00.000Z","start":"2022-04-15T06:00:00.000Z","tweet_count":27},{"end":"2022-04-15T08:00:00.000Z","start":"2022-04-15T07:00:00.000Z","tweet_count":30},{"end":"2022-04-15T09:00:00.000Z","start":"2022-04-15T08:00:00.000Z","tweet_count":30},{"end":"2022-04-15T10:00:00.000Z","start":"2022-04-15T09:00:00.000Z","tweet_count":30},{"end":"2022-04-15T11:00:00.000Z","start":"2022-04-15T10:00:00.000Z","tweet_count":31},{"end":"2022-04-15T12:00:00.000Z","start":"2022-04-15T11:00:00.000Z","tweet_count":33},{"end":"2022-04-15T13:00:00.000Z","start":"2022-04-15T12:00:00.000Z","tweet_count":30},{"end":"2022-04-15T14:00:00.000Z","start":"2022-04-15T13:00:00.000Z","tweet_count":30},{"end":"2022-04-15T15:00:00.000Z","start":"2022-04-15T14:00:00.000Z","tweet_count":36},{"end":"2022-04-15T16:00:00.000Z","start":"2022-04-15T15:00:00.000Z","tweet_count":34},{"end":"2022-04-15T17:00:00.000Z","start":"2022-04-15T16:00:00.000Z","tweet_count":36},{"end":"2022-04-15T18:00:00.000Z","start":"2022-04-15T17:00:00.000Z","tweet_count":33},{"end":"2022-04-15T19:00:00.000Z","start":"2022-04-15T18:00:00.000Z","tweet_count":32},{"end":"2022-04-15T20:00:00.000Z","start":"2022-04-15T19:00:00.000Z","tweet_count":31},{"end":"2022-04-15T21:00:00.000Z","start":"2022-04-15T20:00:00.000Z","tweet_count":31},{"end":"2022-04-15T22:00:00.000Z","start":"2022-04-15T21:00:00.000Z","tweet_count":35},{"end":"2022-04-15T23:00:00.000Z","start":"2022-04-15T22:00:00.000Z","tweet_count":30},{"end":"2022-04-16T00:00:00.000Z","start":"2022-04-15T23:00:00.000Z","tweet_count":31},{"end":"2022-04-16T01:00:00.000Z","start":"2022-04-16T00:00:00.000Z","tweet_count":30},{"end":"2022-04-16T02:00:00.000Z","start":"2022-04-16T01:00:00.000Z","tweet_count":30},{"end":"2022-04-16T03:00:00.000Z","start":"2022-04-16T02:00:00.000Z","tweet_count":31},{"end":"2022-04-16T04:00:00.000Z","start":"2022-04-16T03:00:00.000Z","tweet_count":32},{"end":"2022-04-16T05:00:00.000Z","start":"2022-04-16T04:00:00.000Z","tweet_count":30},{"end":"2022-04-16T06:00:00.000Z","start":"2022-04-16T05:00:00.000Z","tweet_count":30},{"end":"2022-04-16T07:00:00.000Z","start":"2022-04-16T06:00:00.000Z","tweet_count":30},{"end":"2022-04-16T08:00:00.000Z","start":"2022-04-16T07:00:00.000Z","tweet_count":31},{"end":"2022-04-16T09:00:00.000Z","start":"2022-04-16T08:00:00.000Z","tweet_count":31},{"end":"2022-04-16T10:00:00.000Z","start":"2022-04-16T09:00:00.000Z","tweet_count":32},{"end":"2022-04-16T11:00:00.000Z","start":"2022-04-16T10:00:00.000Z","tweet_count":31},{"end":"2022-04-16T12:00:00.000Z","start":"2022-04-16T11:00:00.000Z","tweet_count":38},{"end":"2022-04-16T13:00:00.000Z","start":"2022-04-16T12:00:00.000Z","tweet_count":30},{"end":"2022-04-16T14:00:00.000Z","start":"2022-04-16T13:00:00.000Z","tweet_count":30},{"end":"2022-04-16T15:00:00.000Z","start":"2022-04-16T14:00:00.000Z","tweet_count":31},{"end":"2022-04-16T16:00:00.000Z","start":"2022-04-16T15:00:00.000Z","tweet_count":32},{"end":"2022-04-16T17:00:00.000Z","start":"2022-04-16T16:00:00.000Z","tweet_count":38},{"end":"2022-04-16T18:00:00.000Z","start":"2022-04-16T17:00:00.000Z","tweet_count":30},{"end":"2022-04-16T19:00:00.000Z","start":"2022-04-16T18:00:00.000Z","tweet_count":30},{"end":"2022-04-16T20:00:00.000Z","start":"2022-04-16T19:00:00.000Z","tweet_count":31},{"end":"2022-04-16T21:00:00.000Z","start":"2022-04-16T20:00:00.000Z","tweet_count":30},{"end":"2022-04-16T22:00:00.000Z","start":"2022-04-16T21:00:00.000Z","tweet_count":31},{"end":"2022-04-16T23:00:00.000Z","start":"2022-04-16T22:00:00.000Z","tweet_count":30},{"end":"2022-04-17T00:00:00.000Z","start":"2022-04-16T23:00:00.000Z","tweet_count":33},{"end":"2022-04-17T01:00:00.000Z","start":"2022-04-17T00:00:00.000Z","tweet_count":32},{"end":"2022-04-17T02:00:00.000Z","start":"2022-04-17T01:00:00.000Z","tweet_count":31},{"end":"2022-04-17T03:00:00.000Z","start":"2022-04-17T02:00:00.000Z","tweet_count":30},{"end":"2022-04-17T04:00:00.000Z","start":"2022-04-17T03:00:00.000Z","tweet_count":31},{"end":"2022-04-17T05:00:00.000Z","start":"2022-04-17T04:00:00.000Z","tweet_count":30},{"end":"2022-04-17T06:00:00.000Z","start":"2022-04-17T05:00:00.000Z","tweet_count":31},{"end":"2022-04-17T07:00:00.000Z","start":"2022-04-17T06:00:00.000Z","tweet_count":31},{"end":"2022-04-17T08:00:00.000Z","start":"2022-04-17T07:00:00.000Z","tweet_count":30},{"end":"2022-04-17T09:00:00.000Z","start":"2022-04-17T08:00:00.000Z","tweet_count":31},{"end":"2022-04-17T10:00:00.000Z","start":"2022-04-17T09:00:00.000Z","tweet_count":30},{"end":"2022-04-17T11:00:00.000Z","start":"2022-04-17T10:00:00.000Z","tweet_count":34},{"end":"2022-04-17T12:00:00.000Z","start":"2022-04-17T11:00:00.000Z","tweet_count":30},{"end":"2022-04-17T13:00:00.000Z","start":"2022-04-17T12:00:00.000Z","tweet_count":30},{"end":"2022-04-17T14:00:00.000Z","start":"2022-04-17T13:00:00.000Z","tweet_count":31},{"end":"2022-04-17T15:00:00.000Z","start":"2022-04-17T14:00:00.000Z","tweet_count":32},{"end":"2022-04-17T16:00:00.000Z","start":"2022-04-17T15:00:00.000Z","tweet_count":32},{"end":"2022-04-17T17:00:00.000Z","start":"2022-04-17T16:00:00.000Z","tweet_count":31},{"end":"2022-04-17T18:00:00.000Z","start":"2022-04-17T17:00:00.000Z","tweet_count":30},{"end":"2022-04-17T19:00:00.000Z","start":"2022-04-17T18:00:00.000Z","tweet_count":30},{"end":"2022-04-17T20:00:00.000Z","start":"2022-04-17T19:00:00.000Z","tweet_count":35},{"end":"2022-04-17T21:00:00.000Z","start":"2022-04-17T20:00:00.000Z","tweet_count":30},{"end":"2022-04-17T22:00:00.000Z","start":"2022-04-17T21:00:00.000Z","tweet_count":33},{"end":"2022-04-17T23:00:00.000Z","start":"2022-04-17T22:00:00.000Z","tweet_count":30},{"end":"2022-04-18T00:00:00.000Z","start":"2022-04-17T23:00:00.000Z","tweet_count":30},{"end":"2022-04-18T01:00:00.000Z","start":"2022-04-18T00:00:00.000Z","tweet_count":31},{"end":"2022-04-18T02:00:00.000Z","start":"2022-04-18T01:00:00.000Z","tweet_count":37},{"end":"2022-04-18T03:00:00.000Z","start":"2022-04-18T02:00:00.000Z","tweet_count":33},{"end":"2022-04-18T04:00:00.000Z","start":"2022-04-18T03:00:00.000Z","tweet_count":32},{"end":"2022-04-18T05:00:00.000Z","start":"2022-04-18T04:00:00.000Z","tweet_count":34},{"end":"2022-04-18T06:00:00.000Z","start":"2022-04-18T05:00:00.000Z","tweet_count":33},{"end":"2022-04-18T07:00:00.000Z","start":"2022-04-18T06:00:00.000Z","tweet_count":32},{"end":"2022-04-18T08:00:00.000Z","start":"2022-04-18T07:00:00.000Z","tweet_count":33},{"end":"2022-04-18T09:00:00.000Z","start":"2022-04-18T08:00:00.000Z","tweet_count":32},{"end":"2022-04-18T10:00:00.000Z","start":"2022-04-18T09:00:00.000Z","tweet_count":32},{"end":"2022-04-18T11:00:00.000Z","start":"2022-04-18T10:00:00.000Z","tweet_count":31},{"end":"2022-04-18T12:00:00.000Z","start":"2022-04-18T11:00:00.000Z","tweet_count":31},{"end":"2022-04-18T13:00:00.000Z","start":"2022-04-18T12:00:00.000Z","tweet_count":31},{"end":"2022-04-18T14:00:00.000Z","start":"2022-04-18T13:00:00.000Z","tweet_count":33},{"end":"2022-04-18T15:00:00.000Z","start":"2022-04-18T14:00:00.000Z","tweet_count":30},{"end":"2022-04-18T16:00:00.000Z","start":"2022-04-18T15:00:00.000Z","tweet_count":32},{"end":"2022-04-18T17:00:00.000Z","start":"2022-04-18T16:00:00.000Z","tweet_count":31},{"end":"2022-04-18T18:00:00.000Z","start":"2022-04-18T17:00:00.000Z","tweet_count":30},{"end":"2022-04-18T19:00:00.000Z","start":"2022-04-18T18:00:00.000Z","tweet_count":30},{"end":"2022-04-18T20:00:00.000Z","start":"2022-04-18T19:00:00.000Z","tweet_count":30},{"end":"2022-04-18T21:00:00.000Z","start":"2022-04-18T20:00:00.000Z","tweet_count":30},{"end":"2022-04-18T22:00:00.000Z","start":"2022-04-18T21:00:00.000Z","tweet_count":31},{"end":"2022-04-18T23:00:00.000Z","start":"2022-04-18T22:00:00.000Z","tweet_count":30},{"end":"2022-04-19T00:00:00.000Z","start":"2022-04-18T23:00:00.000Z","tweet_count":31},{"end":"2022-04-19T01:00:00.000Z","start":"2022-04-19T00:00:00.000Z","tweet_count":32},{"end":"2022-04-19T02:00:00.000Z","start":"2022-04-19T01:00:00.000Z","tweet_count":30},{"end":"2022-04-19T03:00:00.000Z","start":"2022-04-19T02:00:00.000Z","tweet_count":30},{"end":"2022-04-19T04:00:00.000Z","start":"2022-04-19T03:00:00.000Z","tweet_count":30},{"end":"2022-04-19T05:00:00.000Z","start":"2022-04-19T04:00:00.000Z","tweet_count":32},{"end":"2022-04-19T06:00:00.000Z","start":"2022-04-19T05:00:00.000Z","tweet_count":30},{"end":"2022-04-19T07:00:00.000Z","start":"2022-04-19T06:00:00.000Z","tweet_count":30},{"end":"2022-04-19T08:00:00.000Z","start":"2022-04-19T07:00:00.000Z","tweet_count":30},{"end":"2022-04-19T09:00:00.000Z","start":"2022-04-19T08:00:00.000Z","tweet_count":32},{"end":"2022-04-19T10:00:00.000Z","start":"2022-04-19T09:00:00.000Z","tweet_count":33},{"end":"2022-04-19T11:00:00.000Z","start":"2022-04-19T10:00:00.000Z","tweet_count":31},{"end":"2022-04-19T12:00:00.000Z","start":"2022-04-19T11:00:00.000Z","tweet_count":31},{"end":"2022-04-19T13:00:00.000Z","start":"2022-04-19T12:00:00.000Z","tweet_count":32},{"end":"2022-04-19T14:00:00.000Z","start":"2022-04-19T13:00:00.000Z","tweet_count":31},{"end":"2022-04-19T15:00:00.000Z","start":"2022-04-19T14:00:00.000Z","tweet_count":33},{"end":"2022-04-19T16:00:00.000Z","start":"2022-04-19T15:00:00.000Z","tweet_count":31},{"end":"2022-04-19T17:00:00.000Z","start":"2022-04-19T16:00:00.000Z","tweet_count":30},{"end":"2022-04-19T18:00:00.000Z","start":"2022-04-19T17:00:00.000Z","tweet_count":38},{"end":"2022-04-19T19:00:00.000Z","start":"2022-04-19T18:00:00.000Z","tweet_count":31},{"end":"2022-04-19T20:00:00.000Z","start":"2022-04-19T19:00:00.000Z","tweet_count":31},{"end":"2022-04-19T21:00:00.000Z","start":"2022-04-19T20:00:00.000Z","tweet_count":31},{"end":"2022-04-19T22:00:00.000Z","start":"2022-04-19T21:00:00.000Z","tweet_count":30},{"end":"2022-04-19T23:00:00.000Z","start":"2022-04-19T22:00:00.000Z","tweet_count":31},{"end":"2022-04-20T00:00:00.000Z","start":"2022-04-19T23:00:00.000Z","tweet_count":30},{"end":"2022-04-20T01:00:00.000Z","start":"2022-04-20T00:00:00.000Z","tweet_count":31},{"end":"2022-04-20T02:00:00.000Z","start":"2022-04-20T01:00:00.000Z","tweet_count":30},{"end":"2022-04-20T03:00:00.000Z","start":"2022-04-20T02:00:00.000Z","tweet_count":32},{"end":"2022-04-20T04:00:00.000Z","start":"2022-04-20T03:00:00.000Z","tweet_count":30},{"end":"2022-04-20T05:00:00.000Z","start":"2022-04-20T04:00:00.000Z","tweet_count":31},{"end":"2022-04-20T06:00:00.000Z","start":"2022-04-20T05:00:00.000Z","tweet_count":31},{"end":"2022-04-20T07:00:00.000Z","start":"2022-04-20T06:00:00.000Z","tweet_count":33},{"end":"2022-04-20T08:00:00.000Z","start":"2022-04-20T07:00:00.000Z","tweet_count":31},{"end":"2022-04-20T09:00:00.000Z","start":"2022-04-20T08:00:00.000Z","tweet_count":31},{"end":"2022-04-20T10:00:00.000Z","start":"2022-04-20T09:00:00.000Z","tweet_count":31},{"end":"2022-04-20T11:00:00.000Z","start":"2022-04-20T10:00:00.000Z","tweet_count":31},{"end":"2022-04-20T12:00:00.000Z","start":"2022-04-20T11:00:00.000Z","tweet_count":31},{"end":"2022-04-20T13:00:00.000Z","start":"2022-04-20T12:00:00.000Z","tweet_count":31},{"end":"2022-04-20T14:00:00.000Z","start":"2022-04-20T13:00:00.000Z","tweet_count":30},{"end":"2022-04-20T15:00:00.000Z","start":"2022-04-20T14:00:00.000Z","tweet_count":31},{"end":"2022-04-20T16:00:00.000Z","start":"2022-04-20T15:00:00.000Z","tweet_count":30},{"end":"2022-04-20T17:00:00.000Z","start":"2022-04-20T16:00:00.000Z","tweet_count":30},{"end":"2022-04-20T18:00:00.000Z","start":"2022-04-20T17:00:00.000Z","tweet_count":32},{"end":"2022-04-20T19:00:00.000Z","start":"2022-04-20T18:00:00.000Z","tweet_count":31},{"end":"2022-04-20T20:00:00.000Z","start":"2022-04-20T19:00:00.000Z","tweet_count":30},{"end":"2022-04-20T21:00:00.000Z","start":"2022-04-20T20:00:00.000Z","tweet_count":30},{"end":"2022-04-20T22:00:00.000Z","start":"2022-04-20T21:00:00.000Z","tweet_count":31},{"end":"2022-04-20T23:00:00.000Z","start":"2022-04-20T22:00:00.000Z","tweet_count":30},{"end":"2022-04-21T00:00:00.000Z","start":"2022-04-20T23:00:00.000Z","tweet_count":30},{"end":"2022-04-21T01:00:00.000Z","start":"2022-04-21T00:00:00.000Z","tweet_count":34},{"end":"2022-04-21T02:00:00.000Z","start":"2022-04-21T01:00:00.000Z","tweet_count":33},{"end":"2022-04-21T03:00:00.000Z","start":"2022-04-21T02:00:00.000Z","tweet_count":30},{"end":"2022-04-21T04:00:00.000Z","start":"2022-04-21T03:00:00.000Z","tweet_count":30},{"end":"2022-04-21T05:00:00.000Z","start":"2022-04-21T04:00:00.000Z","tweet_count":30},{"end":"2022-04-21T06:00:00.000Z","start":"2022-04-21T05:00:00.000Z","tweet_count":31},{"end":"2022-04-21T07:00:00.000Z","start":"2022-04-21T06:00:00.000Z","tweet_count":32},{"end":"2022-04-21T08:00:00.000Z","start":"2022-04-21T07:00:00.000Z","tweet_count":30},{"end":"2022-04-21T09:00:00.000Z","start":"2022-04-21T08:00:00.000Z","tweet_count":31},{"end":"2022-04-21T10:00:00.000Z","start":"2022-04-21T09:00:00.000Z","tweet_count":31},{"end":"2022-04-21T11:00:00.000Z","start":"2022-04-21T10:00:00.000Z","tweet_count":35},{"end":"2022-04-21T12:00:00.000Z","start":"2022-04-21T11:00:00.000Z","tweet_count":30},{"end":"2022-04-21T13:00:00.000Z","start":"2022-04-21T12:00:00.000Z","tweet_count":30},{"end":"2022-04-21T14:00:00.000Z","start":"2022-04-21T13:00:00.000Z","tweet_count":32},{"end":"2022-04-21T15:00:00.000Z","start":"2022-04-21T14:00:00.000Z","tweet_count":34},{"end":"2022-04-21T16:00:00.000Z","start":"2022-04-21T15:00:00.000Z","tweet_count":30},{"end":"2022-04-21T17:00:00.000Z","start":"2022-04-21T16:00:00.000Z","tweet_count":31},{"end":"2022-04-21T18:00:00.000Z","start":"2022-04-21T17:00:00.000Z","tweet_count":31},{"end":"2022-04-21T19:00:00.000Z","start":"2022-04-21T18:00:00.000Z","tweet_count":37},{"end":"2022-04-21T20:00:00.000Z","start":"2022-04-21T19:00:00.000Z","tweet_count":30},{"end":"2022-04-21T21:00:00.000Z","start":"2022-04-21T20:00:00.000Z","tweet_count":33},{"end":"2022-04-21T22:00:00.000Z","start":"2022-04-21T21:00:00.000Z","tweet_count":31},{"end":"2022-04-21T23:00:00.000Z","start":"2022-04-21T22:00:00.000Z","tweet_count":32},{"end":"2022-04-22T00:00:00.000Z","start":"2022-04-21T23:00:00.000Z","tweet_count":33},{"end":"2022-04-22T01:00:00.000Z","start":"2022-04-22T00:00:00.000Z","tweet_count":30},{"end":"2022-04-22T02:00:00.000Z","start":"2022-04-22T01:00:00.000Z","tweet_count":30},{"end":"2022-04-22T03:00:00.000Z","start":"2022-04-22T02:00:00.000Z","tweet_count":30},{"end":"2022-04-22T04:00:00.000Z","start":"2022-04-22T03:00:00.000Z","tweet_count":30},{"end":"2022-04-22T05:00:00.000Z","start":"2022-04-22T04:00:00.000Z","tweet_count":30},{"end":"2022-04-22T06:00:00.000Z","start":"2022-04-22T05:00:00.000Z","tweet_count":30},{"end":"2022-04-22T07:00:00.000Z","start":"2022-04-22T06:00:00.000Z","tweet_count":35},{"end":"2022-04-22T08:00:00.000Z","start":"2022-04-22T07:00:00.000Z","tweet_count":31},{"end":"2022-04-22T09:00:00.000Z","start":"2022-04-22T08:00:00.000Z","tweet_count":30},{"end":"2022-04-22T10:00:00.000Z","start":"2022-04-22T09:00:00.000Z","tweet_count":30},{"end":"2022-04-22T11:00:00.000Z","start":"2022-04-22T10:00:00.000Z","tweet_count":33},{"end":"2022-04-22T12:00:00.000Z","start":"2022-04-22T11:00:00.000Z","tweet_count":32},{"end":"2022-04-22T13:00:00.000Z","start":"2022-04-22T12:00:00.000Z","tweet_count":31},{"end":"2022-04-22T14:00:00.000Z","start":"2022-04-22T13:00:00.000Z","tweet_count":30},{"end":"2022-04-22T15:00:00.000Z","start":"2022-04-22T14:00:00.000Z","tweet_count":30},{"end":"2022-04-22T16:00:00.000Z","start":"2022-04-22T15:00:00.000Z","tweet_count":32},{"end":"2022-04-22T17:00:00.000Z","start":"2022-04-22T16:00:00.000Z","tweet_count":31},{"end":"2022-04-22T18:00:00.000Z","start":"2022-04-22T17:00:00.000Z","tweet_count":30},{"end":"2022-04-22T19:00:00.000Z","start":"2022-04-22T18:00:00.000Z","tweet_count":33},{"end":"2022-04-22T20:00:00.000Z","start":"2022-04-22T19:00:00.000Z","tweet_count":32},{"end":"2022-04-22T21:00:00.000Z","start":"2022-04-22T20:00:00.000Z","tweet_count":32},{"end":"2022-04-22T22:00:00.000Z","start":"2022-04-22T21:00:00.000Z","tweet_count":30},{"end":"2022-04-22T23:00:00.000Z","start":"2022-04-22T22:00:00.000Z","tweet_count":30},{"end":"2022-04-23T00:00:00.000Z","start":"2022-04-22T23:00:00.000Z","tweet_count":33},{"end":"2022-04-23T01:00:00.000Z","start":"2022-04-23T00:00:00.000Z","tweet_count":31},{"end":"2022-04-23T02:00:00.000Z","start":"2022-04-23T01:00:00.000Z","tweet_count":31},{"end":"2022-04-23T03:00:00.000Z","start":"2022-04-23T02:00:00.000Z","tweet_count":30},{"end":"2022-04-23T04:00:00.000Z","start":"2022-04-23T03:00:00.000Z","tweet_count":30},{"end":"2022-04-23T05:00:00.000Z","start":"2022-04-23T04:00:00.000Z","tweet_count":31},{"end":"2022-04-23T06:00:00.000Z","start":"2022-04-23T05:00:00.000Z","tweet_count":31},{"end":"2022-04-23T07:00:00.000Z","start":"2022-04-23T06:00:00.000Z","tweet_count":33},{"end":"2022-04-23T08:00:00.000Z","start":"2022-04-23T07:00:00.000Z","tweet_count":33},{"end":"2022-04-23T09:00:00.000Z","start":"2022-04-23T08:00:00.000Z","tweet_count":32},{"end":"2022-04-23T10:00:00.000Z","start":"2022-04-23T09:00:00.000Z","tweet_count":30},{"end":"2022-04-23T11:00:00.000Z","start":"2022-04-23T10:00:00.000Z","tweet_count":30},{"end":"2022-04-23T12:00:00.000Z","start":"2022-04-23T11:00:00.000Z","tweet_count":31},{"end":"2022-04-23T13:00:00.000Z","start":"2022-04-23T12:00:00.000Z","tweet_count":31},{"end":"2022-04-23T14:00:00.000Z","start":"2022-04-23T13:00:00.000Z","tweet_count":30},{"end":"2022-04-23T15:00:00.000Z","start":"2022-04-23T14:00:00.000Z","tweet_count":33},{"end":"2022-04-23T16:00:00.000Z","start":"2022-04-23T15:00:00.000Z","tweet_count":34},{"end":"2022-04-23T17:00:00.000Z","start":"2022-04-23T16:00:00.000Z","tweet_count":31},{"end":"2022-04-23T18:00:00.000Z","start":"2022-04-23T17:00:00.000Z","tweet_count":32},{"end":"2022-04-23T19:00:00.000Z","start":"2022-04-23T18:00:00.000Z","tweet_count":36},{"end":"2022-04-23T20:00:00.000Z","start":"2022-04-23T19:00:00.000Z","tweet_count":34},{"end":"2022-04-23T21:00:00.000Z","start":"2022-04-23T20:00:00.000Z","tweet_count":31},{"end":"2022-04-23T22:00:00.000Z","start":"2022-04-23T21:00:00.000Z","tweet_count":30},{"end":"2022-04-23T23:00:00.000Z","start":"2022-04-23T22:00:00.000Z","tweet_count":30},{"end":"2022-04-24T00:00:00.000Z","start":"2022-04-23T23:00:00.000Z","tweet_count":31},{"end":"2022-04-24T01:00:00.000Z","start":"2022-04-24T00:00:00.000Z","tweet_count":31},{"end":"2022-04-24T02:00:00.000Z","start":"2022-04-24T01:00:00.000Z","tweet_count":31},{"end":"2022-04-24T03:00:00.000Z","start":"2022-04-24T02:00:00.000Z","tweet_count":31},{"end":"2022-04-24T04:00:00.000Z","start":"2022-04-24T03:00:00.000Z","tweet_count":30},{"end":"2022-04-24T05:00:00.000Z","start":"2022-04-24T04:00:00.000Z","tweet_count":32},{"end":"2022-04-24T06:00:00.000Z","start":"2022-04-24T05:00:00.000Z","tweet_count":30},{"end":"2022-04-24T07:00:00.000Z","start":"2022-04-24T06:00:00.000Z","tweet_count":31},{"end":"2022-04-24T08:00:00.000Z","start":"2022-04-24T07:00:00.000Z","tweet_count":34},{"end":"2022-04-24T09:00:00.000Z","start":"2022-04-24T08:00:00.000Z","tweet_count":32},{"end":"2022-04-24T10:00:00.000Z","start":"2022-04-24T09:00:00.000Z","tweet_count":31},{"end":"2022-04-24T11:00:00.000Z","start":"2022-04-24T10:00:00.000Z","tweet_count":32},{"end":"2022-04-24T12:00:00.000Z","start":"2022-04-24T11:00:00.000Z","tweet_count":33},{"end":"2022-04-24T13:00:00.000Z","start":"2022-04-24T12:00:00.000Z","tweet_count":33},{"end":"2022-04-24T14:00:00.000Z","start":"2022-04-24T13:00:00.000Z","tweet_count":31},{"end":"2022-04-24T15:00:00.000Z","start":"2022-04-24T14:00:00.000Z","tweet_count":32},{"end":"2022-04-24T16:00:00.000Z","start":"2022-04-24T15:00:00.000Z","tweet_count":32},{"end":"2022-04-24T17:00:00.000Z","start":"2022-04-24T16:00:00.000Z","tweet_count":38},{"end":"2022-04-24T18:00:00.000Z","start":"2022-04-24T17:00:00.000Z","tweet_count":30},{"end":"2022-04-24T19:00:00.000Z","start":"2022-04-24T18:00:00.000Z","tweet_count":30},{"end":"2022-04-24T20:00:00.000Z","start":"2022-04-24T19:00:00.000Z","tweet_count":31},{"end":"2022-04-24T21:00:00.000Z","start":"2022-04-24T20:00:00.000Z","tweet_count":32},{"end":"2022-04-24T22:00:00.000Z","start":"2022-04-24T21:00:00.000Z","tweet_count":30},{"end":"2022-04-24T23:00:00.000Z","start":"2022-04-24T22:00:00.000Z","tweet_count":30},{"end":"2022-04-25T00:00:00.000Z","start":"2022-04-24T23:00:00.000Z","tweet_count":35},{"end":"2022-04-25T01:00:00.000Z","start":"2022-04-25T00:00:00.000Z","tweet_count":31},{"end":"2022-04-25T02:00:00.000Z","start":"2022-04-25T01:00:00.000Z","tweet_count":31},{"end":"2022-04-25T03:00:00.000Z","start":"2022-04-25T02:00:00.000Z","tweet_count":31},{"end":"2022-04-25T04:00:00.000Z","start":"2022-04-25T03:00:00.000Z","tweet_count":33},{"end":"2022-04-25T05:00:00.000Z","start":"2022-04-25T04:00:00.000Z","tweet_count":30},{"end":"2022-04-25T06:00:00.000Z","start":"2022-04-25T05:00:00.000Z","tweet_count":30},{"end":"2022-04-25T07:00:00.000Z","start":"2022-04-25T06:00:00.000Z","tweet_count":32},{"end":"2022-04-25T08:00:00.000Z","start":"2022-04-25T07:00:00.000Z","tweet_count":32},{"end":"2022-04-25T09:00:00.000Z","start":"2022-04-25T08:00:00.000Z","tweet_count":32},{"end":"2022-04-25T10:00:00.000Z","start":"2022-04-25T09:00:00.000Z","tweet_count":30},{"end":"2022-04-25T11:00:00.000Z","start":"2022-04-25T10:00:00.000Z","tweet_count":31},{"end":"2022-04-25T12:00:00.000Z","start":"2022-04-25T11:00:00.000Z","tweet_count":30},{"end":"2022-04-25T13:00:00.000Z","start":"2022-04-25T12:00:00.000Z","tweet_count":32},{"end":"2022-04-25T14:00:00.000Z","start":"2022-04-25T13:00:00.000Z","tweet_count":31},{"end":"2022-04-25T15:00:00.000Z","start":"2022-04-25T14:00:00.000Z","tweet_count":32},{"end":"2022-04-25T16:00:00.000Z","start":"2022-04-25T15:00:00.000Z","tweet_count":29},{"end":"2022-04-25T17:00:00.000Z","start":"2022-04-25T16:00:00.000Z","tweet_count":31},{"end":"2022-04-25T18:00:00.000Z","start":"2022-04-25T17:00:00.000Z","tweet_count":30},{"end":"2022-04-25T19:00:00.000Z","start":"2022-04-25T18:00:00.000Z","tweet_count":30},{"end":"2022-04-25T20:00:00.000Z","start":"2022-04-25T19:00:00.000Z","tweet_count":30},{"end":"2022-04-25T21:00:00.000Z","start":"2022-04-25T20:00:00.000Z","tweet_count":31},{"end":"2022-04-25T22:00:00.000Z","start":"2022-04-25T21:00:00.000Z","tweet_count":33},{"end":"2022-04-25T23:00:00.000Z","start":"2022-04-25T22:00:00.000Z","tweet_count":32},{"end":"2022-04-26T00:00:00.000Z","start":"2022-04-25T23:00:00.000Z","tweet_count":31},{"end":"2022-04-26T01:00:00.000Z","start":"2022-04-26T00:00:00.000Z","tweet_count":33},{"end":"2022-04-26T02:00:00.000Z","start":"2022-04-26T01:00:00.000Z","tweet_count":30},{"end":"2022-04-26T03:00:00.000Z","start":"2022-04-26T02:00:00.000Z","tweet_count":30},{"end":"2022-04-26T04:00:00.000Z","start":"2022-04-26T03:00:00.000Z","tweet_count":30},{"end":"2022-04-26T05:00:00.000Z","start":"2022-04-26T04:00:00.000Z","tweet_count":30},{"end":"2022-04-26T06:00:00.000Z","start":"2022-04-26T05:00:00.000Z","tweet_count":30},{"end":"2022-04-26T07:00:00.000Z","start":"2022-04-26T06:00:00.000Z","tweet_count":33},{"end":"2022-04-26T08:00:00.000Z","start":"2022-04-26T07:00:00.000Z","tweet_count":30},{"end":"2022-04-26T09:00:00.000Z","start":"2022-04-26T08:00:00.000Z","tweet_count":32},{"end":"2022-04-26T10:00:00.000Z","start":"2022-04-26T09:00:00.000Z","tweet_count":33},{"end":"2022-04-26T11:00:00.000Z","start":"2022-04-26T10:00:00.000Z","tweet_count":34},{"end":"2022-04-26T12:00:00.000Z","start":"2022-04-26T11:00:00.000Z","tweet_count":31},{"end":"2022-04-26T13:00:00.000Z","start":"2022-04-26T12:00:00.000Z","tweet_count":31},{"end":"2022-04-26T14:00:00.000Z","start":"2022-04-26T13:00:00.000Z","tweet_count":30},{"end":"2022-04-26T15:00:00.000Z","start":"2022-04-26T14:00:00.000Z","tweet_count":32},{"end":"2022-04-26T16:00:00.000Z","start":"2022-04-26T15:00:00.000Z","tweet_count":31},{"end":"2022-04-26T17:00:00.000Z","start":"2022-04-26T16:00:00.000Z","tweet_count":32},{"end":"2022-04-26T18:00:00.000Z","start":"2022-04-26T17:00:00.000Z","tweet_count":32},{"end":"2022-04-26T19:00:00.000Z","start":"2022-04-26T18:00:00.000Z","tweet_count":35},{"end":"2022-04-26T20:00:00.000Z","start":"2022-04-26T19:00:00.000Z","tweet_count":30},{"end":"2022-04-26T21:00:00.000Z","start":"2022-04-26T20:00:00.000Z","tweet_count":31},{"end":"2022-04-26T22:00:00.000Z","start":"2022-04-26T21:00:00.000Z","tweet_count":33},{"end":"2022-04-26T23:00:00.000Z","start":"2022-04-26T22:00:00.000Z","tweet_count":30},{"end":"2022-04-27T00:00:00.000Z","start":"2022-04-26T23:00:00.000Z","tweet_count":35},{"end":"2022-04-27T01:00:00.000Z","start":"2022-04-27T00:00:00.000Z","tweet_count":31},{"end":"2022-04-27T02:00:00.000Z","start":"2022-04-27T01:00:00.000Z","tweet_count":32},{"end":"2022-04-27T03:00:00.000Z","start":"2022-04-27T02:00:00.000Z","tweet_count":30},{"end":"2022-04-27T04:00:00.000Z","start":"2022-04-27T03:00:00.000Z","tweet_count":31},{"end":"2022-04-27T05:00:00.000Z","start":"2022-04-27T04:00:00.000Z","tweet_count":31},{"end":"2022-04-27T06:00:00.000Z","start":"2022-04-27T05:00:00.000Z","tweet_count":31},{"end":"2022-04-27T07:00:00.000Z","start":"2022-04-27T06:00:00.000Z","tweet_count":33},{"end":"2022-04-27T08:00:00.000Z","start":"2022-04-27T07:00:00.000Z","tweet_count":30},{"end":"2022-04-27T09:00:00.000Z","start":"2022-04-27T08:00:00.000Z","tweet_count":32},{"end":"2022-04-27T10:00:00.000Z","start":"2022-04-27T09:00:00.000Z","tweet_count":31},{"end":"2022-04-27T11:00:00.000Z","start":"2022-04-27T10:00:00.000Z","tweet_count":32},{"end":"2022-04-27T12:00:00.000Z","start":"2022-04-27T11:00:00.000Z","tweet_count":31},{"end":"2022-04-27T13:00:00.000Z","start":"2022-04-27T12:00:00.000Z","tweet_count":31},{"end":"2022-04-27T14:00:00.000Z","start":"2022-04-27T13:00:00.000Z","tweet_count":31},{"end":"2022-04-27T15:00:00.000Z","start":"2022-04-27T14:00:00.000Z","tweet_count":30},{"end":"2022-04-27T16:00:00.000Z","start":"2022-04-27T15:00:00.000Z","tweet_count":32},{"end":"2022-04-27T17:00:00.000Z","start":"2022-04-27T16:00:00.000Z","tweet_count":30},{"end":"2022-04-27T18:00:00.000Z","start":"2022-04-27T17:00:00.000Z","tweet_count":30},{"end":"2022-04-27T19:00:00.000Z","start":"2022-04-27T18:00:00.000Z","tweet_count":33},{"end":"2022-04-27T20:00:00.000Z","start":"2022-04-27T19:00:00.000Z","tweet_count":32},{"end":"2022-04-27T21:00:00.000Z","start":"2022-04-27T20:00:00.000Z","tweet_count":31},{"end":"2022-04-27T22:00:00.000Z","start":"2022-04-27T21:00:00.000Z","tweet_count":31},{"end":"2022-04-27T23:00:00.000Z","start":"2022-04-27T22:00:00.000Z","tweet_count":30},{"end":"2022-04-28T00:00:00.000Z","start":"2022-04-27T23:00:00.000Z","tweet_count":32},{"end":"2022-04-28T01:00:00.000Z","start":"2022-04-28T00:00:00.000Z","tweet_count":30},{"end":"2022-04-28T02:00:00.000Z","start":"2022-04-28T01:00:00.000Z","tweet_count":32},{"end":"2022-04-28T03:00:00.000Z","start":"2022-04-28T02:00:00.000Z","tweet_count":32},{"end":"2022-04-28T04:00:00.000Z","start":"2022-04-28T03:00:00.000Z","tweet_count":33},{"end":"2022-04-28T05:00:00.000Z","start":"2022-04-28T04:00:00.000Z","tweet_count":33},{"end":"2022-04-28T06:00:00.000Z","start":"2022-04-28T05:00:00.000Z","tweet_count":35},{"end":"2022-04-28T07:00:00.000Z","start":"2022-04-28T06:00:00.000Z","tweet_count":31},{"end":"2022-04-28T08:00:00.000Z","start":"2022-04-28T07:00:00.000Z","tweet_count":32},{"end":"2022-04-28T09:00:00.000Z","start":"2022-04-28T08:00:00.000Z","tweet_count":31},{"end":"2022-04-28T10:00:00.000Z","start":"2022-04-28T09:00:00.000Z","tweet_count":32},{"end":"2022-04-28T11:00:00.000Z","start":"2022-04-28T10:00:00.000Z","tweet_count":34},{"end":"2022-04-28T12:00:00.000Z","start":"2022-04-28T11:00:00.000Z","tweet_count":33},{"end":"2022-04-28T13:00:00.000Z","start":"2022-04-28T12:00:00.000Z","tweet_count":31},{"end":"2022-04-28T14:00:00.000Z","start":"2022-04-28T13:00:00.000Z","tweet_count":31},{"end":"2022-04-28T15:00:00.000Z","start":"2022-04-28T14:00:00.000Z","tweet_count":37},{"end":"2022-04-28T16:00:00.000Z","start":"2022-04-28T15:00:00.000Z","tweet_count":35},{"end":"2022-04-28T17:00:00.000Z","start":"2022-04-28T16:00:00.000Z","tweet_count":36},{"end":"2022-04-28T18:00:00.000Z","start":"2022-04-28T17:00:00.000Z","tweet_count":31},{"end":"2022-04-28T19:00:00.000Z","start":"2022-04-28T18:00:00.000Z","tweet_count":34},{"end":"2022-04-28T20:00:00.000Z","start":"2022-04-28T19:00:00.000Z","tweet_count":30},{"end":"2022-04-28T21:00:00.000Z","start":"2022-04-28T20:00:00.000Z","tweet_count":31},{"end":"2022-04-28T22:00:00.000Z","start":"2022-04-28T21:00:00.000Z","tweet_count":31},{"end":"2022-04-28T23:00:00.000Z","start":"2022-04-28T22:00:00.000Z","tweet_count":30},{"end":"2022-04-29T00:00:00.000Z","start":"2022-04-28T23:00:00.000Z","tweet_count":31},{"end":"2022-04-29T01:00:00.000Z","start":"2022-04-29T00:00:00.000Z","tweet_count":30},{"end":"2022-04-29T02:00:00.000Z","start":"2022-04-29T01:00:00.000Z","tweet_count":30},{"end":"2022-04-29T03:00:00.000Z","start":"2022-04-29T02:00:00.000Z","tweet_count":30},{"end":"2022-04-29T04:00:00.000Z","start":"2022-04-29T03:00:00.000Z","tweet_count":31},{"end":"2022-04-29T05:00:00.000Z","start":"2022-04-29T04:00:00.000Z","tweet_count":30},{"end":"2022-04-29T06:00:00.000Z","start":"2022-04-29T05:00:00.000Z","tweet_count":31},{"end":"2022-04-29T07:00:00.000Z","start":"2022-04-29T06:00:00.000Z","tweet_count":34},{"end":"2022-04-29T08:00:00.000Z","start":"2022-04-29T07:00:00.000Z","tweet_count":30},{"end":"2022-04-29T09:00:00.000Z","start":"2022-04-29T08:00:00.000Z","tweet_count":31},{"end":"2022-04-29T10:00:00.000Z","start":"2022-04-29T09:00:00.000Z","tweet_count":33},{"end":"2022-04-29T11:00:00.000Z","start":"2022-04-29T10:00:00.000Z","tweet_count":30},{"end":"2022-04-29T12:00:00.000Z","start":"2022-04-29T11:00:00.000Z","tweet_count":31},{"end":"2022-04-29T13:00:00.000Z","start":"2022-04-29T12:00:00.000Z","tweet_count":32},{"end":"2022-04-29T14:00:00.000Z","start":"2022-04-29T13:00:00.000Z","tweet_count":30},{"end":"2022-04-29T15:00:00.000Z","start":"2022-04-29T14:00:00.000Z","tweet_count":31},{"end":"2022-04-29T16:00:00.000Z","start":"2022-04-29T15:00:00.000Z","tweet_count":31},{"end":"2022-04-29T17:00:00.000Z","start":"2022-04-29T16:00:00.000Z","tweet_count":30},{"end":"2022-04-29T18:00:00.000Z","start":"2022-04-29T17:00:00.000Z","tweet_count":29},{"end":"2022-04-29T19:00:00.000Z","start":"2022-04-29T18:00:00.000Z","tweet_count":31},{"end":"2022-04-29T20:00:00.000Z","start":"2022-04-29T19:00:00.000Z","tweet_count":32},{"end":"2022-04-29T21:00:00.000Z","start":"2022-04-29T20:00:00.000Z","tweet_count":30},{"end":"2022-04-29T22:00:00.000Z","start":"2022-04-29T21:00:00.000Z","tweet_count":31},{"end":"2022-04-29T23:00:00.000Z","start":"2022-04-29T22:00:00.000Z","tweet_count":31},{"end":"2022-04-30T00:00:00.000Z","start":"2022-04-29T23:00:00.000Z","tweet_count":32},{"end":"2022-04-30T01:00:00.000Z","start":"2022-04-30T00:00:00.000Z","tweet_count":30},{"end":"2022-04-30T02:00:00.000Z","start":"2022-04-30T01:00:00.000Z","tweet_count":31},{"end":"2022-04-30T03:00:00.000Z","start":"2022-04-30T02:00:00.000Z","tweet_count":31},{"end":"2022-04-30T04:00:00.000Z","start":"2022-04-30T03:00:00.000Z","tweet_count":34},{"end":"2022-04-30T05:00:00.000Z","start":"2022-04-30T04:00:00.000Z","tweet_count":32},{"end":"2022-04-30T06:00:00.000Z","start":"2022-04-30T05:00:00.000Z","tweet_count":31},{"end":"2022-04-30T07:00:00.000Z","start":"2022-04-30T06:00:00.000Z","tweet_count":31},{"end":"2022-04-30T08:00:00.000Z","start":"2022-04-30T07:00:00.000Z","tweet_count":32},{"end":"2022-04-30T09:00:00.000Z","start":"2022-04-30T08:00:00.000Z","tweet_count":33},{"end":"2022-04-30T10:00:00.000Z","start":"2022-04-30T09:00:00.000Z","tweet_count":31},{"end":"2022-04-30T11:00:00.000Z","start":"2022-04-30T10:00:00.000Z","tweet_count":33},{"end":"2022-04-30T12:00:00.000Z","start":"2022-04-30T11:00:00.000Z","tweet_count":30},{"end":"2022-04-30T13:00:00.000Z","start":"2022-04-30T12:00:00.000Z","tweet_count":30},{"end":"2022-04-30T14:00:00.000Z","start":"2022-04-30T13:00:00.000Z","tweet_count":30},{"end":"2022-04-30T15:00:00.000Z","start":"2022-04-30T14:00:00.000Z","tweet_count":30},{"end":"2022-04-30T16:00:00.000Z","start":"2022-04-30T15:00:00.000Z","tweet_count":31},{"end":"2022-04-30T17:00:00.000Z","start":"2022-04-30T16:00:00.000Z","tweet_count":30},{"end":"2022-04-30T18:00:00.000Z","start":"2022-04-30T17:00:00.000Z","tweet_count":31},{"end":"2022-04-30T19:00:00.000Z","start":"2022-04-30T18:00:00.000Z","tweet_count":30},{"end":"2022-04-30T20:00:00.000Z","start":"2022-04-30T19:00:00.000Z","tweet_count":31},{"end":"2022-04-30T21:00:00.000Z","start":"2022-04-30T20:00:00.000Z","tweet_count":31},{"end":"2022-04-30T22:00:00.000Z","start":"2022-04-30T21:00:00.000Z","tweet_count":32},{"end":"2022-04-30T23:00:00.000Z","start":"2022-04-30T22:00:00.000Z","tweet_count":32},{"end":"2022-05-01T00:00:00.000Z","start":"2022-04-30T23:00:00.000Z","tweet_count":31},{"end":"2022-05-01T01:00:00.000Z","start":"2022-05-01T00:00:00.000Z","tweet_count":30},{"end":"2022-05-01T02:00:00.000Z","start":"2022-05-01T01:00:00.000Z","tweet_count":30},{"end":"2022-05-01T03:00:00.000Z","start":"2022-05-01T02:00:00.000Z","tweet_count":30},{"end":"2022-05-01T04:00:00.000Z","start":"2022-05-01T03:00:00.000Z","tweet_count":32},{"end":"2022-05-01T05:00:00.000Z","start":"2022-05-01T04:00:00.000Z","tweet_count":31},{"end":"2022-05-01T06:00:00.000Z","start":"2022-05-01T05:00:00.000Z","tweet_count":30},{"end":"2022-05-01T07:00:00.000Z","start":"2022-05-01T06:00:00.000Z","tweet_count":32},{"end":"2022-05-01T08:00:00.000Z","start":"2022-05-01T07:00:00.000Z","tweet_count":32},{"end":"2022-05-01T09:00:00.000Z","start":"2022-05-01T08:00:00.000Z","tweet_count":31},{"end":"2022-05-01T10:00:00.000Z","start":"2022-05-01T09:00:00.000Z","tweet_count":30},{"end":"2022-05-01T11:00:00.000Z","start":"2022-05-01T10:00:00.000Z","tweet_count":32},{"end":"2022-05-01T12:00:00.000Z","start":"2022-05-01T11:00:00.000Z","tweet_count":30},{"end":"2022-05-01T13:00:00.000Z","start":"2022-05-01T12:00:00.000Z","tweet_count":31},{"end":"2022-05-01T14:00:00.000Z","start":"2022-05-01T13:00:00.000Z","tweet_count":31},{"end":"2022-05-01T15:00:00.000Z","start":"2022-05-01T14:00:00.000Z","tweet_count":30},{"end":"2022-05-01T16:00:00.000Z","start":"2022-05-01T15:00:00.000Z","tweet_count":30},{"end":"2022-05-01T17:00:00.000Z","start":"2022-05-01T16:00:00.000Z","tweet_count":32},{"end":"2022-05-01T18:00:00.000Z","start":"2022-05-01T17:00:00.000Z","tweet_count":31},{"end":"2022-05-01T19:00:00.000Z","start":"2022-05-01T18:00:00.000Z","tweet_count":32},{"end":"2022-05-01T20:00:00.000Z","start":"2022-05-01T19:00:00.000Z","tweet_count":30},{"end":"2022-05-01T21:00:00.000Z","start":"2022-05-01T20:00:00.000Z","tweet_count":31},{"end":"2022-05-01T22:00:00.000Z","start":"2022-05-01T21:00:00.000Z","tweet_count":31},{"end":"2022-05-01T23:00:00.000Z","start":"2022-05-01T22:00:00.000Z","tweet_count":30},{"end":"2022-05-02T00:00:00.000Z","start":"2022-05-01T23:00:00.000Z","tweet_count":30},{"end":"2022-05-02T01:00:00.000Z","start":"2022-05-02T00:00:00.000Z","tweet_count":30},{"end":"2022-05-02T02:00:00.000Z","start":"2022-05-02T01:00:00.000Z","tweet_count":30},{"end":"2022-05-02T03:00:00.000Z","start":"2022-05-02T02:00:00.000Z","tweet_count":31},{"end":"2022-05-02T04:00:00.000Z","start":"2022-05-02T03:00:00.000Z","tweet_count":30},{"end":"2022-05-02T05:00:00.000Z","start":"2022-05-02T04:00:00.000Z","tweet_count":34},{"end":"2022-05-02T06:00:00.000Z","start":"2022-05-02T05:00:00.000Z","tweet_count":30},{"end":"2022-05-02T07:00:00.000Z","start":"2022-05-02T06:00:00.000Z","tweet_count":31},{"end":"2022-05-02T08:00:00.000Z","start":"2022-05-02T07:00:00.000Z","tweet_count":34},{"end":"2022-05-02T09:00:00.000Z","start":"2022-05-02T08:00:00.000Z","tweet_count":32},{"end":"2022-05-02T10:00:00.000Z","start":"2022-05-02T09:00:00.000Z","tweet_count":30},{"end":"2022-05-02T11:00:00.000Z","start":"2022-05-02T10:00:00.000Z","tweet_count":30},{"end":"2022-05-02T12:00:00.000Z","start":"2022-05-02T11:00:00.000Z","tweet_count":30},{"end":"2022-05-02T13:00:00.000Z","start":"2022-05-02T12:00:00.000Z","tweet_count":34},{"end":"2022-05-02T14:00:00.000Z","start":"2022-05-02T13:00:00.000Z","tweet_count":31},{"end":"2022-05-02T15:00:00.000Z","start":"2022-05-02T14:00:00.000Z","tweet_count":30},{"end":"2022-05-02T16:00:00.000Z","start":"2022-05-02T15:00:00.000Z","tweet_count":35},{"end":"2022-05-02T17:00:00.000Z","start":"2022-05-02T16:00:00.000Z","tweet_count":30},{"end":"2022-05-02T18:00:00.000Z","start":"2022-05-02T17:00:00.000Z","tweet_count":31},{"end":"2022-05-02T19:00:00.000Z","start":"2022-05-02T18:00:00.000Z","tweet_count":30},{"end":"2022-05-02T20:00:00.000Z","start":"2022-05-02T19:00:00.000Z","tweet_count":30},{"end":"2022-05-02T21:00:00.000Z","start":"2022-05-02T20:00:00.000Z","tweet_count":30},{"end":"2022-05-02T22:00:00.000Z","start":"2022-05-02T21:00:00.000Z","tweet_count":31},{"end":"2022-05-02T23:00:00.000Z","start":"2022-05-02T22:00:00.000Z","tweet_count":34},{"end":"2022-05-03T00:00:00.000Z","start":"2022-05-02T23:00:00.000Z","tweet_count":39},{"end":"2022-05-03T01:00:00.000Z","start":"2022-05-03T00:00:00.000Z","tweet_count":30},{"end":"2022-05-03T02:00:00.000Z","start":"2022-05-03T01:00:00.000Z","tweet_count":32},{"end":"2022-05-03T03:00:00.000Z","start":"2022-05-03T02:00:00.000Z","tweet_count":30},{"end":"2022-05-03T04:00:00.000Z","start":"2022-05-03T03:00:00.000Z","tweet_count":31},{"end":"2022-05-03T05:00:00.000Z","start":"2022-05-03T04:00:00.000Z","tweet_count":30},{"end":"2022-05-03T06:00:00.000Z","start":"2022-05-03T05:00:00.000Z","tweet_count":34},{"end":"2022-05-03T07:00:00.000Z","start":"2022-05-03T06:00:00.000Z","tweet_count":33},{"end":"2022-05-03T08:00:00.000Z","start":"2022-05-03T07:00:00.000Z","tweet_count":34},{"end":"2022-05-03T09:00:00.000Z","start":"2022-05-03T08:00:00.000Z","tweet_count":31},{"end":"2022-05-03T10:00:00.000Z","start":"2022-05-03T09:00:00.000Z","tweet_count":30},{"end":"2022-05-03T11:00:00.000Z","start":"2022-05-03T10:00:00.000Z","tweet_count":31},{"end":"2022-05-03T12:00:00.000Z","start":"2022-05-03T11:00:00.000Z","tweet_count":30},{"end":"2022-05-03T13:00:00.000Z","start":"2022-05-03T12:00:00.000Z","tweet_count":30},{"end":"2022-05-03T14:00:00.000Z","start":"2022-05-03T13:00:00.000Z","tweet_count":35},{"end":"2022-05-03T15:00:00.000Z","start":"2022-05-03T14:00:00.000Z","tweet_count":39},{"end":"2022-05-03T16:00:00.000Z","start":"2022-05-03T15:00:00.000Z","tweet_count":32},{"end":"2022-05-03T17:00:00.000Z","start":"2022-05-03T16:00:00.000Z","tweet_count":33},{"end":"2022-05-03T18:00:00.000Z","start":"2022-05-03T17:00:00.000Z","tweet_count":31},{"end":"2022-05-03T19:00:00.000Z","start":"2022-05-03T18:00:00.000Z","tweet_count":32},{"end":"2022-05-03T20:00:00.000Z","start":"2022-05-03T19:00:00.000Z","tweet_count":32},{"end":"2022-05-03T21:00:00.000Z","start":"2022-05-03T20:00:00.000Z","tweet_count":30},{"end":"2022-05-03T22:00:00.000Z","start":"2022-05-03T21:00:00.000Z","tweet_count":30},{"end":"2022-05-03T23:00:00.000Z","start":"2022-05-03T22:00:00.000Z","tweet_count":31},{"end":"2022-05-04T00:00:00.000Z","start":"2022-05-03T23:00:00.000Z","tweet_count":32},{"end":"2022-05-04T01:00:00.000Z","start":"2022-05-04T00:00:00.000Z","tweet_count":30},{"end":"2022-05-04T02:00:00.000Z","start":"2022-05-04T01:00:00.000Z","tweet_count":30},{"end":"2022-05-04T03:00:00.000Z","start":"2022-05-04T02:00:00.000Z","tweet_count":33},{"end":"2022-05-04T04:00:00.000Z","start":"2022-05-04T03:00:00.000Z","tweet_count":30},{"end":"2022-05-04T05:00:00.000Z","start":"2022-05-04T04:00:00.000Z","tweet_count":31},{"end":"2022-05-04T06:00:00.000Z","start":"2022-05-04T05:00:00.000Z","tweet_count":30},{"end":"2022-05-04T07:00:00.000Z","start":"2022-05-04T06:00:00.000Z","tweet_count":33},{"end":"2022-05-04T08:00:00.000Z","start":"2022-05-04T07:00:00.000Z","tweet_count":33},{"end":"2022-05-04T09:00:00.000Z","start":"2022-05-04T08:00:00.000Z","tweet_count":32},{"end":"2022-05-04T10:00:00.000Z","start":"2022-05-04T09:00:00.000Z","tweet_count":33},{"end":"2022-05-04T11:00:00.000Z","start":"2022-05-04T10:00:00.000Z","tweet_count":32},{"end":"2022-05-04T12:00:00.000Z","start":"2022-05-04T11:00:00.000Z","tweet_count":30},{"end":"2022-05-04T13:00:00.000Z","start":"2022-05-04T12:00:00.000Z","tweet_count":32},{"end":"2022-05-04T14:00:00.000Z","start":"2022-05-04T13:00:00.000Z","tweet_count":30},{"end":"2022-05-04T15:00:00.000Z","start":"2022-05-04T14:00:00.000Z","tweet_count":36},{"end":"2022-05-04T16:00:00.000Z","start":"2022-05-04T15:00:00.000Z","tweet_count":32},{"end":"2022-05-04T17:00:00.000Z","start":"2022-05-04T16:00:00.000Z","tweet_count":30},{"end":"2022-05-04T18:00:00.000Z","start":"2022-05-04T17:00:00.000Z","tweet_count":32},{"end":"2022-05-04T19:00:00.000Z","start":"2022-05-04T18:00:00.000Z","tweet_count":33},{"end":"2022-05-04T20:00:00.000Z","start":"2022-05-04T19:00:00.000Z","tweet_count":31},{"end":"2022-05-04T21:00:00.000Z","start":"2022-05-04T20:00:00.000Z","tweet_count":30},{"end":"2022-05-04T22:00:00.000Z","start":"2022-05-04T21:00:00.000Z","tweet_count":31},{"end":"2022-05-04T23:00:00.000Z","start":"2022-05-04T22:00:00.000Z","tweet_count":31},{"end":"2022-05-05T00:00:00.000Z","start":"2022-05-04T23:00:00.000Z","tweet_count":32},{"end":"2022-05-05T01:00:00.000Z","start":"2022-05-05T00:00:00.000Z","tweet_count":30},{"end":"2022-05-05T02:00:00.000Z","start":"2022-05-05T01:00:00.000Z","tweet_count":30},{"end":"2022-05-05T03:00:00.000Z","start":"2022-05-05T02:00:00.000Z","tweet_count":30},{"end":"2022-05-05T04:00:00.000Z","start":"2022-05-05T03:00:00.000Z","tweet_count":30},{"end":"2022-05-05T05:00:00.000Z","start":"2022-05-05T04:00:00.000Z","tweet_count":30},{"end":"2022-05-05T06:00:00.000Z","start":"2022-05-05T05:00:00.000Z","tweet_count":30},{"end":"2022-05-05T07:00:00.000Z","start":"2022-05-05T06:00:00.000Z","tweet_count":32},{"end":"2022-05-05T08:00:00.000Z","start":"2022-05-05T07:00:00.000Z","tweet_count":35},{"end":"2022-05-05T09:00:00.000Z","start":"2022-05-05T08:00:00.000Z","tweet_count":36},{"end":"2022-05-05T10:00:00.000Z","start":"2022-05-05T09:00:00.000Z","tweet_count":30},{"end":"2022-05-05T11:00:00.000Z","start":"2022-05-05T10:00:00.000Z","tweet_count":32},{"end":"2022-05-05T12:00:00.000Z","start":"2022-05-05T11:00:00.000Z","tweet_count":30},{"end":"2022-05-05T13:00:00.000Z","start":"2022-05-05T12:00:00.000Z","tweet_count":31},{"end":"2022-05-05T14:00:00.000Z","start":"2022-05-05T13:00:00.000Z","tweet_count":31},{"end":"2022-05-05T15:00:00.000Z","start":"2022-05-05T14:00:00.000Z","tweet_count":44},{"end":"2022-05-05T16:00:00.000Z","start":"2022-05-05T15:00:00.000Z","tweet_count":30},{"end":"2022-05-05T17:00:00.000Z","start":"2022-05-05T16:00:00.000Z","tweet_count":35},{"end":"2022-05-05T18:00:00.000Z","start":"2022-05-05T17:00:00.000Z","tweet_count":33},{"end":"2022-05-05T19:00:00.000Z","start":"2022-05-05T18:00:00.000Z","tweet_count":46},{"end":"2022-05-05T20:00:00.000Z","start":"2022-05-05T19:00:00.000Z","tweet_count":32},{"end":"2022-05-05T21:00:00.000Z","start":"2022-05-05T20:00:00.000Z","tweet_count":32},{"end":"2022-05-05T22:00:00.000Z","start":"2022-05-05T21:00:00.000Z","tweet_count":31},{"end":"2022-05-05T23:00:00.000Z","start":"2022-05-05T22:00:00.000Z","tweet_count":31},{"end":"2022-05-06T00:00:00.000Z","start":"2022-05-05T23:00:00.000Z","tweet_count":31},{"end":"2022-05-06T01:00:00.000Z","start":"2022-05-06T00:00:00.000Z","tweet_count":30},{"end":"2022-05-06T02:00:00.000Z","start":"2022-05-06T01:00:00.000Z","tweet_count":30},{"end":"2022-05-06T03:00:00.000Z","start":"2022-05-06T02:00:00.000Z","tweet_count":32},{"end":"2022-05-06T04:00:00.000Z","start":"2022-05-06T03:00:00.000Z","tweet_count":33},{"end":"2022-05-06T05:00:00.000Z","start":"2022-05-06T04:00:00.000Z","tweet_count":32},{"end":"2022-05-06T06:00:00.000Z","start":"2022-05-06T05:00:00.000Z","tweet_count":32},{"end":"2022-05-06T07:00:00.000Z","start":"2022-05-06T06:00:00.000Z","tweet_count":34},{"end":"2022-05-06T08:00:00.000Z","start":"2022-05-06T07:00:00.000Z","tweet_count":31},{"end":"2022-05-06T09:00:00.000Z","start":"2022-05-06T08:00:00.000Z","tweet_count":31},{"end":"2022-05-06T10:00:00.000Z","start":"2022-05-06T09:00:00.000Z","tweet_count":36},{"end":"2022-05-06T11:00:00.000Z","start":"2022-05-06T10:00:00.000Z","tweet_count":31},{"end":"2022-05-06T12:00:00.000Z","start":"2022-05-06T11:00:00.000Z","tweet_count":30},{"end":"2022-05-06T13:00:00.000Z","start":"2022-05-06T12:00:00.000Z","tweet_count":33},{"end":"2022-05-06T14:00:00.000Z","start":"2022-05-06T13:00:00.000Z","tweet_count":33},{"end":"2022-05-06T15:00:00.000Z","start":"2022-05-06T14:00:00.000Z","tweet_count":32},{"end":"2022-05-06T16:00:00.000Z","start":"2022-05-06T15:00:00.000Z","tweet_count":31},{"end":"2022-05-06T17:00:00.000Z","start":"2022-05-06T16:00:00.000Z","tweet_count":31},{"end":"2022-05-06T18:00:00.000Z","start":"2022-05-06T17:00:00.000Z","tweet_count":31},{"end":"2022-05-06T19:00:00.000Z","start":"2022-05-06T18:00:00.000Z","tweet_count":30},{"end":"2022-05-06T20:00:00.000Z","start":"2022-05-06T19:00:00.000Z","tweet_count":30},{"end":"2022-05-06T21:00:00.000Z","start":"2022-05-06T20:00:00.000Z","tweet_count":34},{"end":"2022-05-06T22:00:00.000Z","start":"2022-05-06T21:00:00.000Z","tweet_count":30},{"end":"2022-05-06T23:00:00.000Z","start":"2022-05-06T22:00:00.000Z","tweet_count":31},{"end":"2022-05-07T00:00:00.000Z","start":"2022-05-06T23:00:00.000Z","tweet_count":30},{"end":"2022-05-07T01:00:00.000Z","start":"2022-05-07T00:00:00.000Z","tweet_count":30},{"end":"2022-05-07T02:00:00.000Z","start":"2022-05-07T01:00:00.000Z","tweet_count":30},{"end":"2022-05-07T03:00:00.000Z","start":"2022-05-07T02:00:00.000Z","tweet_count":30},{"end":"2022-05-07T04:00:00.000Z","start":"2022-05-07T03:00:00.000Z","tweet_count":31},{"end":"2022-05-07T05:00:00.000Z","start":"2022-05-07T04:00:00.000Z","tweet_count":32},{"end":"2022-05-07T06:00:00.000Z","start":"2022-05-07T05:00:00.000Z","tweet_count":30},{"end":"2022-05-07T07:00:00.000Z","start":"2022-05-07T06:00:00.000Z","tweet_count":30},{"end":"2022-05-07T08:00:00.000Z","start":"2022-05-07T07:00:00.000Z","tweet_count":31},{"end":"2022-05-07T09:00:00.000Z","start":"2022-05-07T08:00:00.000Z","tweet_count":30},{"end":"2022-05-07T10:00:00.000Z","start":"2022-05-07T09:00:00.000Z","tweet_count":31},{"end":"2022-05-07T11:00:00.000Z","start":"2022-05-07T10:00:00.000Z","tweet_count":35},{"end":"2022-05-07T12:00:00.000Z","start":"2022-05-07T11:00:00.000Z","tweet_count":31},{"end":"2022-05-07T13:00:00.000Z","start":"2022-05-07T12:00:00.000Z","tweet_count":34},{"end":"2022-05-07T13:23:46.000Z","start":"2022-05-07T13:00:00.000Z","tweet_count":12}],"meta":{"total_tweet_count":23035}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '4691'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:23:56 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192983668515179; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:23:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192983668515179; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:23:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_+SEYjiP7LJvSa6B/3sKxPA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:23:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192983668515179; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:23:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 84cfccc75d41213fcb209940a8db38b37336a6573f7b295118171f0942236ed8
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '299'
+      x-rate-limit-reset:
+      - '1651930736'
+      x-response-time:
+      - '100'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/tweets/counts/all?query=Tweepy
+version: 1
diff --git a/cassettes/test_asyncclient_get_followed_lists.yaml b/cassettes/test_asyncclient_get_followed_lists.yaml
new file mode 100644 (file)
index 0000000..45e2c33
--- /dev/null
@@ -0,0 +1,63 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/3015271772/followed_lists
+  response:
+    body:
+      string: '{"data":[{"id":"210377275","name":"TNFL Chefs & Restaurants"},{"id":"195424361","name":"BlogHer
+        Food 15 Attendees"},{"id":"40473781","name":"Favorite Voices in Food"},{"id":"204763821","name":"JBFA2015"}],"meta":{"result_count":4}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '189'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 22:29:25 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165196256509578001; Max-Age=63072000; Expires=Mon,
+        06 May 2024 22:29:25 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165196256509578001; Max-Age=63072000; Expires=Mon, 06 May
+        2024 22:29:25 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_nc74ciBR2gbcKQ0Ce4splw=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 22:29:25 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165196256509578001; Max-Age=63072000; Expires=Mon, 06 May 2024
+        22:29:25 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 87babfa478fdac44c9476e512096008213ebe7b1a86f86c49771736ee8ac73fa
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '15'
+      x-rate-limit-remaining:
+      - '12'
+      x-rate-limit-reset:
+      - '1651963108'
+      x-response-time:
+      - '55'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/3015271772/followed_lists
+version: 1
diff --git a/cassettes/test_asyncclient_get_liked_tweets.yaml b/cassettes/test_asyncclient_get_liked_tweets.yaml
new file mode 100644 (file)
index 0000000..b478505
--- /dev/null
@@ -0,0 +1,212 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/783214/liked_tweets
+  response:
+    body:
+      string: "{\"data\":[{\"id\":\"1504123888086704128\",\"text\":\"Twitter is only\
+        \ following one person, and it's me.\"},{\"id\":\"1494046213137735681\",\"\
+        text\":\"avoir son projet en banni\xE8re de Twitter \u2705 https://t.co/evnwMQdFKc\"\
+        },{\"id\":\"1494042851000344581\",\"text\":\"@Twitter \\uD83D\\uDE1D squinting-tongue\
+        \ + \\uD83D\\uDE2D in-tears = https://t.co/h9VN3YOOSj\"},{\"id\":\"1494041387880304645\"\
+        ,\"text\":\"Time to celebrate the #GoodBots on Twitter!\\n\\nWe\u2019re launching\
+        \ labels for developer-created accounts so you can identify more of the good\
+        \ bots and their helpful Tweets. https://t.co/1K9tBYEpOR https://t.co/of6zFkck4n\"\
+        },{\"id\":\"1484655996404477952\",\"text\":\"I. Am. Crying. \\uD83E\\uDD72\
+        \ https://t.co/TatAG7K3WU https://t.co/KtJ2uzkIpg\"},{\"id\":\"1484544778297511937\"\
+        ,\"text\":\"Sending \\uD83D\\uDC9C right back to you too\\n@Twitter https://t.co/HRXKIo5Sus\"\
+        },{\"id\":\"1484606047306330119\",\"text\":\"Welcome to Cool Dogs @Twitter\
+        \ \\uD83E\\uDD1D\\uD83D\\uDC36 https://t.co/sVUTP57tQQ\"},{\"id\":\"1484287427388837888\"\
+        ,\"text\":\"\\uD83D\\uDE80\\uD83C\\uDF6A \\uD83D\\uDE0D\\uD83C\\uDF6D https://t.co/NJBo8hLt13\
+        \ https://t.co/1jkJU9DDYg\"},{\"id\":\"1484255399939350529\",\"text\":\"this\
+        \ is AMAAZZZZZINNNGG!!!! https://t.co/07vIQhYdPH\"},{\"id\":\"1484256184949432331\"\
+        ,\"text\":\"HOLY HECK!!!!!!!!!!!!! https://t.co/hqTRlQPFZe\"},{\"id\":\"1483785433607598081\"\
+        ,\"text\":\"@Twitter New car. New job in a healthy working environment \\\
+        uD83D\\uDD6F\\uD83D\\uDE4F\\uD83C\\uDFFD\"},{\"id\":\"1483883947612327944\"\
+        ,\"text\":\"@Twitter I would be a doctor in 2025 and a successful artist\"\
+        },{\"id\":\"1483908864693227532\",\"text\":\"@Twitter Can\u2019t wait to have\
+        \ a world tour soon!\"},{\"id\":\"1483738975768567808\",\"text\":\"@Twitter\
+        \ I will get a ep &amp; show runner for my animated show this year and get\
+        \ it green lit \\uD83D\\uDD25 \\uD83E\\uDD1E\\uD83C\\uDFFE\"},{\"id\":\"1483797315366567937\"\
+        ,\"text\":\"@Twitter I'm going to my dream college this year\"},{\"id\":\"\
+        1483676808650186753\",\"text\":\"@Twitter I dream of developing and shipping\
+        \ two software applications that actually solves problems \\uD83D\\uDE4F\\\
+        uD83C\\uDFFD\"},{\"id\":\"1483749641904697352\",\"text\":\"@Twitter New Car\
+        \ and Apartment, also a thriving university student \u2728\\uD83D\\uDE0A\"\
+        },{\"id\":\"1483563603433295874\",\"text\":\"@Twitter im going to thrive at\
+        \ university this year\"},{\"id\":\"1483640576289427459\",\"text\":\"@Twitter\
+        \ A tv show I create gets greenlit and we start filming in 2022 \u2728\"},{\"\
+        id\":\"1483751341977931776\",\"text\":\"@Twitter I'm going to become a sought\
+        \ after change lead at my current employer in years time. I'll oversee projects\
+        \ and people confidently and competently. My salary will increase x5 shem.\"\
+        },{\"id\":\"1483721331216719873\",\"text\":\"I'm going to be a successful\
+        \ music producer. https://t.co/daREG1BChM\"},{\"id\":\"1483863013572714501\"\
+        ,\"text\":\"@Twitter i\u2019ll get harry styles tickets for london in june\
+        \ with my friends \\uD83D\\uDD6F\\uD83D\\uDD6F\"},{\"id\":\"1483685568529645568\"\
+        ,\"text\":\"@Twitter I will facilitate a round table / panel for a TV show\
+        \ or film that I love.\"},{\"id\":\"1483676039469355010\",\"text\":\"@Twitter\
+        \ Sell a pilot, find true love, publish a novel. In no particular order,\"\
+        },{\"id\":\"1483702748751310853\",\"text\":\"@Twitter I am going to be happy\
+        \ and successful this year. Things are finally working out.\"},{\"id\":\"\
+        1483831080310480896\",\"text\":\"@Twitter By October 2023, I would be a lawyer.\"\
+        },{\"id\":\"1483859933934325768\",\"text\":\"Securing a job that will give\
+        \ me financial freedom and stability while growing my knowledge in my career.\
+        \ https://t.co/Hux2F4iGNJ\"},{\"id\":\"1483641091844976641\",\"text\":\"My\
+        \ feature \u2018Swimming in Cuba\u2019 will get made. https://t.co/bWTZxfJ9yY\"\
+        },{\"id\":\"1483771851302187012\",\"text\":\"I\u2019m getting a product marketing\
+        \ manager role in a leading SaaS/tech company in the next 6 months https://t.co/j4CT7KOVN0\"\
+        },{\"id\":\"1483796896795832334\",\"text\":\"my business will take off this\
+        \ year IJN\\uD83D\\uDE4F\\uD83C\\uDFFE\u2728 https://t.co/kIJRDbmaOs\"},{\"\
+        id\":\"1483638416386449411\",\"text\":\"ted lasso blooper reel https://t.co/8JfJWNF8rP\"\
+        },{\"id\":\"1483639606125862912\",\"text\":\"Directing TV episodes in 2022\
+        \ \\uD83C\\uDFA5\\uD83C\\uDF9E\\uD83C\\uDFAC https://t.co/kIlRQ98bnh\"},{\"\
+        id\":\"1483655876783312896\",\"text\":\"My first car and apartment will be\
+        \ bagged this year https://t.co/kkEmpklw11\"},{\"id\":\"1483709123376168960\"\
+        ,\"text\":\"I\u2019m directing my Cinema Debut this year \\uD83D\\uDE4F\\\
+        uD83D\\uDE4F https://t.co/COLcBGezR6\"},{\"id\":\"1483683921267081218\",\"\
+        text\":\"Shooting my first feature in 2022 \u2728 https://t.co/Q2ovHBsY9N\"\
+        },{\"id\":\"1483686510557900804\",\"text\":\"I will be on a cover of a magazine.\
+        \ \\n\\nOne day. https://t.co/wU2A2xaY8D\"},{\"id\":\"1483707037947244545\"\
+        ,\"text\":\"~ A cinema film this year. Amen \\uD83D\\uDE4F https://t.co/UuYixJWnCh\"\
+        },{\"id\":\"1483763412991684614\",\"text\":\"Entering grad school or getting\
+        \ a job this year \\uD83D\\uDE4F\\uD83D\\uDE4F. https://t.co/tCOcZi2cE8\"\
+        },{\"id\":\"1483793215773884418\",\"text\":\"I'm gonna open one of the biggest\
+        \ restaurants in Lagos. The food and aesthetics is gonna be amazing and everyone\
+        \ will love it \\uD83E\\uDD70\\uD83D\\uDE4F https://t.co/cUUqg5V77d\"},{\"\
+        id\":\"1483797446065070081\",\"text\":\"My idols will become my peers and\
+        \ I won\u2019t feel out of place \u2728 https://t.co/sDeqtXafIh\"},{\"id\"\
+        :\"1483804960349429766\",\"text\":\"By October 2022, I should be a lawyer.\
+        \ https://t.co/1w7iCijEwY\"},{\"id\":\"1483844443312738313\",\"text\":\"I\
+        \ will work at @Google as a Product Manager\\uD83D\\uDE4C\\uD83C\\uDFFE https://t.co/b5dwcqNzxz\"\
+        },{\"id\":\"1483713430645260289\",\"text\":\"My books getting over a million\
+        \ sales worldwide. https://t.co/gGHdKpA20x\"},{\"id\":\"1483838320874606597\"\
+        ,\"text\":\"Finna be the most sought after Musican / Icon from Ghana, few\
+        \ years from now IJMN So help me God. \\uD83D\\uDE4F\\uD83C\\uDFFE\\uD83D\\\
+        uDCAB https://t.co/8FMie575yB\"},{\"id\":\"1480583393981181961\",\"text\"\
+        :\"Hi everyone! I need 10k likes on this tweet to get an A on an assignment\
+        \ in my social networking class! Please help \\uD83E\\uDD70\"},{\"id\":\"\
+        1441766810961866761\",\"text\":\"I love that I don't have to be so proper\
+        \ on Twitter. Slang being used. Starting sentences without capitalizing. Emojis.\
+        \ Gifs. Twitter reigns supreme!!!\"},{\"id\":\"1438162359261016081\",\"text\"\
+        :\"\\uD83E\\uDD7A\\uD83E\\uDD7A\\uD83E\\uDD7A https://t.co/UcbvgPmeBi\"},{\"\
+        id\":\"1438162015609032720\",\"text\":\"WE DID IT!!!!!!!! \\n\\nThank you\
+        \ @Twitter!!! https://t.co/F72rBN7Uio\"},{\"id\":\"1431302172298338316\",\"\
+        text\":\"How it Started       vs.        How it\u2019s going https://t.co/ZsQBx8bRzi\"\
+        },{\"id\":\"1431342104874295296\",\"text\":\"thanks @Twitter for my new favourite\
+        \ hoodie! no apology necessary. https://t.co/3hLOhGqVLC\"},{\"id\":\"1431291336787996672\"\
+        ,\"text\":\"She\u2019s here and she\u2019s perfect.\\n\\nI love you, @Twitter.\
+        \ \\uD83D\\uDC99 https://t.co/FkCFTbjvSz\"},{\"id\":\"1431290252547837956\"\
+        ,\"text\":\"We're sorry or you're welcome. \\uD83D\\uDD25\\uD83D\\uDD25 \\\
+        n\\nThanks @Twitter \\uD83D\\uDC99 https://t.co/gE6nHEaA7C\"},{\"id\":\"1431306142605627393\"\
+        ,\"text\":\"I love it, @Twitter. Thank you. https://t.co/DaOX48QwaZ\"},{\"\
+        id\":\"1422593029332901889\",\"text\":\"I\u2019ve really made it, friends!!\
+        \ I\u2019m on the @Twitter account\u2019s header! https://t.co/KdWjfAkV8n\"\
+        },{\"id\":\"1417846280345341958\",\"text\":\"gm https://t.co/agyr81WIpJ\"\
+        },{\"id\":\"1417846802255126530\",\"text\":\"yeah https://t.co/jym3ONy5o7\"\
+        },{\"id\":\"1412927155290443777\",\"text\":\"@Twitter @Twitter thanks!! I'm\
+        \ a man of my word...stay tuned https://t.co/ywPuoH1K1q\"},{\"id\":\"1410325422609469441\"\
+        ,\"text\":\"@Twitter wow!!! holy moly\"},{\"id\":\"1400452227563622400\",\"\
+        text\":\"folders for bookmarks!\\nundo Tweet!\\nand more!\\n\\nnow available\
+        \ for @TwitterBlue subscribers\\n\\nbe one of the first to explore it in Australia\
+        \ on iOS https://t.co/DvFHovDsRp\"},{\"id\":\"1400452354042851328\",\"text\"\
+        :\"Hey \\uD83C\\uDDE8\\uD83C\\uDDE6, you\u2019re in.\\n\\nBe one of the first\
+        \ to explore @TwitterBlue, a new subscription service on iOS. https://t.co/wV2wn8lXln\"\
+        },{\"id\":\"1387067947663908868\",\"text\":\"@Twitter same\"},{\"id\":\"1379496673899085825\"\
+        ,\"text\":\"@Twitter they like dinosaurs\"},{\"id\":\"1375472671090167830\"\
+        ,\"text\":\"Many people within our community are using today as a day of healing\
+        \ and action. Please be mindful of your loved ones and colleagues who are\
+        \ participating and take action by sharing your commitment to #StopAsianHate\"\
+        },{\"id\":\"1364690287763800065\",\"text\":\"twitter in my dms \\uD83E\\uDD38\u200D\
+        \u2642\uFE0F https://t.co/rlkCo2T11K\"},{\"id\":\"1364612503796256771\",\"\
+        text\":\"OMG https://t.co/5NyWGMKi2x https://t.co/1jxfvUnl4X\"},{\"id\":\"\
+        1364612247251779588\",\"text\":\"so @twitter just followed me- https://t.co/SvApU4pTv2\"\
+        },{\"id\":\"1364610831061815297\",\"text\":\"SHUT UP TWITTER FOLLOWS ME BYE\
+        \ https://t.co/6XM17uZDdE\"},{\"id\":\"1356687762859024384\",\"text\":\"Feel\
+        \ like Twitter people can also be Instagram people, but Instagram people can\u2019\
+        t also be Twitter people.\"},{\"id\":\"1356408295234412545\",\"text\":\"https://t.co/eBPVyRL5g3\"\
+        },{\"id\":\"1350158867620122625\",\"text\":\"We're the three best friends\
+        \ that anybody could have \\uD83D\\uDC9A @Twitter https://t.co/wNTmTb8REp\"\
+        },{\"id\":\"1341797366203109377\",\"text\":\"Someone had to say it https://t.co/JZAg4ZLHia\"\
+        },{\"id\":\"1341514858475315200\",\"text\":\"guys who refused to call me their\
+        \ girlfriend in public are probably regretting that now that one of my tweets\
+        \ is on a billboard\"},{\"id\":\"1341514582821658626\",\"text\":\"aye they\
+        \ threw me onto a billboard in times square. can i hit the rt button on that?\
+        \ https://t.co/a588vyDvpU\"},{\"id\":\"1341514442635243520\",\"text\":\"HEY\
+        \ BESTIE @Twitter https://t.co/dp7JE8ibXc\"},{\"id\":\"1341514296711213056\"\
+        ,\"text\":\"silly little tweets get you serious BIG billboards https://t.co/yZ2XSEUjRZ\"\
+        },{\"id\":\"1341405876721225737\",\"text\":\"@Twitter Hey, 2020, your game\
+        \ is out of order\"},{\"id\":\"1341398978299105280\",\"text\":\"@Twitter 2020\
+        \ was like opening the fridge every five minutes to see if something new was\
+        \ in there. except there was always something new and it was bad\"},{\"id\"\
+        :\"1341164835220971522\",\"text\":\"can i get a W? \\uD83D\\uDE2D\\uD83D\\\
+        uDE2D\\uD83D\\uDE2D\\uD83D\\uDE2D\\uD83D\\uDE2D\\uD83D\\uDE2D https://t.co/QJXxDNYyPP\"\
+        },{\"id\":\"1341165523619311616\",\"text\":\"Yeah so this happened. Ty for\
+        \ the giant IRL RT @Twitter maybe I need to revise that review after all.\
+        \ https://t.co/PUiUhc65h9\"},{\"id\":\"1341159361792462848\",\"text\":\"@Twitter\
+        \ This is amazing \\uD83D\\uDE2D\u2764\"},{\"id\":\"1341160128364466176\"\
+        ,\"text\":\"Guys, my tweet is on a billboard! \\uD83D\\uDE2D\u2764\\nThank\
+        \ you @Twitter https://t.co/75xDYYrj4q\"},{\"id\":\"1341103644905775105\"\
+        ,\"text\":\"@Twitter That\u2019s awesome!  Thank you! It\u2019s still true.\"\
+        },{\"id\":\"1341107454000713729\",\"text\":\"@Twitter Haha, thank you for\
+        \ the recognition! \\uD83D\\uDE4C\\uD83C\\uDFFD\"},{\"id\":\"1341094355260612610\"\
+        ,\"text\":\"i- im on a billboard https://t.co/p9xXohuOC0\"},{\"id\":\"1341092973270982658\"\
+        ,\"text\":\"Aww \\uD83E\\uDD70 https://t.co/fzFqr5tenk\"},{\"id\":\"1341082656868507648\"\
+        ,\"text\":\"My Foolishness PSA has made it to print. Thank you, @Twitter!\
+        \ Leave it in 2020, y\u2019all. \\uD83D\\uDE4F\\uD83C\\uDFFD\u2764\uFE0F https://t.co/SUzl7VP8Un\"\
+        }],\"meta\":{\"result_count\":86,\"next_token\":\"7140dibdnow9c7btw453p178d9z2exz3w6smfcx8bml9z\"\
+        }}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '4769'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:23 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192818358586163; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:23 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192818358586163; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:23 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_+ekc729NZynLpXC+eT89Yg=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:23 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192818358586163; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:23 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - c11a73f7d204de13238156674a5e5dbc88adfedb4e178d3eb1e741321bb14fc7
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '75'
+      x-rate-limit-remaining:
+      - '74'
+      x-rate-limit-reset:
+      - '1651929083'
+      x-response-time:
+      - '395'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/783214/liked_tweets
+version: 1
diff --git a/cassettes/test_asyncclient_get_liking_users.yaml b/cassettes/test_asyncclient_get_liking_users.yaml
new file mode 100644 (file)
index 0000000..773c2ae
--- /dev/null
@@ -0,0 +1,160 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/tweets/1293593516040269825/liking_users
+  response:
+    body:
+      string: "{\"data\":[{\"id\":\"1266414623110189057\",\"name\":\"Ashley\",\"username\"\
+        :\"AshleyJones43\"},{\"id\":\"1238464017951309825\",\"name\":\"Lauren\",\"\
+        username\":\"Laurentrahan32\"},{\"id\":\"1000330089815392257\",\"name\":\"\
+        Meenakshi Ranjan / \\uD83D\\uDEA9\\uD83D\\uDEA9 Hindu / TTS \\uD83D\\uDEA9\\\
+        uD83D\\uDEA9\",\"username\":\"mran2608\"},{\"id\":\"1404606517580603393\"\
+        ,\"name\":\"Alex\",\"username\":\"Alex10711720\"},{\"id\":\"1316191764592521216\"\
+        ,\"name\":\"n\",\"username\":\"ever1ofus\"},{\"id\":\"1247490702931456001\"\
+        ,\"name\":\"Prasant kumar\",\"username\":\"decodeprasant\"},{\"id\":\"1452352777313787913\"\
+        ,\"name\":\"\u0644\u064A\u0644\u0649\",\"username\":\"lyly89185508\"},{\"\
+        id\":\"1445173703050817540\",\"name\":\"Somchai\",\"username\":\"Somchai80645792\"\
+        },{\"id\":\"1410586115975778313\",\"name\":\"Goran Smilevski\",\"username\"\
+        :\"GoranSmilevsk10\"},{\"id\":\"1444756838944317442\",\"name\":\"Zsolt Dudas\"\
+        ,\"username\":\"ZsoltDudas2\"},{\"id\":\"1252290569520533505\",\"name\":\"\
+        Priyanshu Ganorkar\",\"username\":\"Priyanshu02h\"},{\"id\":\"797260190441684993\"\
+        ,\"name\":\"Puneet Gupta\",\"username\":\"PuneetG88948560\"},{\"id\":\"3027643617\"\
+        ,\"name\":\"tony\",\"username\":\"cements\"},{\"id\":\"1422091449995120644\"\
+        ,\"name\":\"S\u0442yl\u03B9s\u043D S\u0442\u03B1\u044F Srinivas AADHF\",\"\
+        username\":\"SrinivasYl\"},{\"id\":\"1342483347302281217\",\"name\":\"\u305F\
+        \u307E\u3054\u307C\u30FC\u308D\",\"username\":\"hiro3pc\"},{\"id\":\"1014226329720406017\"\
+        ,\"name\":\"Movie Meter\",\"username\":\"MovieMeterOff\"},{\"id\":\"1432444950436794375\"\
+        ,\"name\":\"AnG3L-\\uD83E\\uDD20\\uD83D\\uDD25\\uD83D\\uDD25. \\uD83D\\uDD31\u264B\
+        \u2728\",\"username\":\"37h1j0d3m1am4\"},{\"id\":\"1430823251517657102\",\"\
+        name\":\"manthri sairaj\",\"username\":\"ManthriSairaj\"},{\"id\":\"1416602891356315649\"\
+        ,\"name\":\"embem\",\"username\":\"urungmati\"},{\"id\":\"1253691268351365129\"\
+        ,\"name\":\"Ganesh Arya\",\"username\":\"GaneshA76136457\"},{\"id\":\"1426591192645443591\"\
+        ,\"name\":\"god live love\",\"username\":\"MasasoK\"},{\"id\":\"2695678436\"\
+        ,\"name\":\"Jatin Poul\",\"username\":\"Jatin_Poul\"},{\"id\":\"1476145002\"\
+        ,\"name\":\"Dushyant vishwakarma\",\"username\":\"CoolDV235\"},{\"id\":\"\
+        1332876898888687616\",\"name\":\"XXXtentacles\",\"username\":\"XXXtent27404083\"\
+        },{\"id\":\"927527500959191040\",\"name\":\"Santosh Kumar Mishra\",\"username\"\
+        :\"Santosh80700635\"},{\"id\":\"876939801995464705\",\"name\":\"Kevin C\"\
+        ,\"username\":\"KClarkADSTech\"},{\"id\":\"1348294797723799552\",\"name\"\
+        :\"@luthfor57756838\",\"username\":\"luthfor57756816\"},{\"id\":\"1373555064288124935\"\
+        ,\"name\":\"Anonymous\",\"username\":\"Anonymous254581\"},{\"id\":\"1295979493719334918\"\
+        ,\"name\":\"Vivek Kumar\",\"username\":\"24VivekKumar24\"},{\"id\":\"1391474707564695552\"\
+        ,\"name\":\"\\uD83C\\uDF41\u2618\uFE0FSri\u2618\uFE0F\\uD83C\\uDF41\",\"username\"\
+        :\"Sritamilnadu\"},{\"id\":\"217853491\",\"name\":\"Diana Parra \\uD83D\\\
+        uDC9B\\uD83D\\uDC99\u2665\uFE0F 3148464665 \\uD83C\\uDDE8\\uD83C\\uDDF4\u2757\
+        \\uD83D\\uDC4D\\uD83D\\uDC4C\u270C\uFE0F\",\"username\":\"DIANA_MPAZ\"},{\"\
+        id\":\"1261651905660334081\",\"name\":\"Giasuddin Shah\",\"username\":\"Giasuddin1st\"\
+        },{\"id\":\"1376376326014205953\",\"name\":\"LIB ARTS\",\"username\":\"lib_arts10\"\
+        },{\"id\":\"59567346\",\"name\":\"\u043C\xFF\u0161\u0437\u0142f\",\"username\"\
+        :\"Henry_Casillas\"},{\"id\":\"876731188890742785\",\"name\":\"Pere Casas\"\
+        ,\"username\":\"CasasPerep\"},{\"id\":\"1378938013040844803\",\"name\":\"\
+        Whisper\",\"username\":\"4s8a15i16n23t42\"},{\"id\":\"211490924\",\"name\"\
+        :\"ayush dubey\",\"username\":\"ayushdb10\"},{\"id\":\"1314289069984276480\"\
+        ,\"name\":\"\u0627\u0644\u0635\u0639\u064A\u062F\u064A\",\"username\":\"MwQEv2pWOH0i4Af\"\
+        },{\"id\":\"98663431\",\"name\":\"Eduardo Rica\xF1o S.\",\"username\":\"eduardoricano\"\
+        },{\"id\":\"1193211611487592448\",\"name\":\"Driss Meloui\",\"username\":\"\
+        DMeloui\"},{\"id\":\"1399571635406004224\",\"name\":\"Zarka Saeed\",\"username\"\
+        :\"saeed_zarka\"},{\"id\":\"1365712383889539073\",\"name\":\"KHALEDKABDULAZ1\"\
+        ,\"username\":\"KHALEDKABDULAZ3\"},{\"id\":\"1250606831484821504\",\"name\"\
+        :\"SFI ( SECULAR FRONT OF INDIA)\",\"username\":\"SFI_NATIONAL\"},{\"id\"\
+        :\"1357428132685504512\",\"name\":\"Nadeem Ahmad\",\"username\":\"NadeemA12799685\"\
+        },{\"id\":\"1345244562374221827\",\"name\":\"Yolanda Machado\",\"username\"\
+        :\"Yolanda89247683\"},{\"id\":\"734043\",\"name\":\"Paul Jacobson\",\"username\"\
+        :\"pauljacobson\"},{\"id\":\"1073164113876930560\",\"name\":\"Mayank Taneja\"\
+        ,\"username\":\"MayankT65690131\"},{\"id\":\"923878212\",\"name\":\"Bluechip\"\
+        ,\"username\":\"Moshood__\"},{\"id\":\"1372864925136252928\",\"name\":\"Simon\
+        \ Agbey\",\"username\":\"SimonAgbey1\"},{\"id\":\"2613691657\",\"name\":\"\
+        Born Consultants\",\"username\":\"BornConsultants\"},{\"id\":\"1297851655631732737\"\
+        ,\"name\":\"Tweeter\",\"username\":\"Tweeter_th\"},{\"id\":\"473944971\",\"\
+        name\":\"Soutrik Neogi\",\"username\":\"soutrik_neogi\"},{\"id\":\"1273644164144603138\"\
+        ,\"name\":\"Ismael Antonio\",\"username\":\"ismaelixboy\"},{\"id\":\"1097927550309871616\"\
+        ,\"name\":\"Diana Helmi\",\"username\":\"DianaHelmi2\"},{\"id\":\"261141063\"\
+        ,\"name\":\"Barra hassan\",\"username\":\"barra_hassan\"},{\"id\":\"1337903212561625097\"\
+        ,\"name\":\"CyberRudy_25_2\",\"username\":\"2Cyberrudy\"},{\"id\":\"845305623591964672\"\
+        ,\"name\":\"CIS OPS\",\"username\":\"cis_ops_\"},{\"id\":\"1137018216931348480\"\
+        ,\"name\":\"Aditi Singh\",\"username\":\"AditiSi95197395\"},{\"id\":\"2457843772\"\
+        ,\"name\":\"George Carreiro\",\"username\":\"georgecarreiro\"},{\"id\":\"\
+        82348742\",\"name\":\"K \\uD83D\\uDC78\\uD83C\\uDFFC Duval\",\"username\"\
+        :\"Karen_Duval\"},{\"id\":\"3089614702\",\"name\":\"Kin Zikkygh\\uD83C\\uDDEC\\\
+        uD83C\\uDDED\",\"username\":\"kin_zikky\"},{\"id\":\"3320305690\",\"name\"\
+        :\"\u0E04fr\u0ED0 \u0E56\u0ED0y \\uD83E\\uDD13\",\"username\":\"AfroBoyUg\"\
+        },{\"id\":\"1353618346307158016\",\"name\":\"PyUG\",\"username\":\"PyUG10\"\
+        },{\"id\":\"1134486922921992192\",\"name\":\"dr.saeedo\",\"username\":\"saeedjodi\"\
+        },{\"id\":\"119252320\",\"name\":\"Ana Maria | Tech e Dev\",\"username\":\"\
+        _anamariasilva_\"},{\"id\":\"350328281\",\"name\":\"Brian Malcolm\",\"username\"\
+        :\"bmalcolmb\"},{\"id\":\"1277829953967382529\",\"name\":\"Gautam Arora \\\
+        uD83C\\uDFD3\",\"username\":\"Gautamarora24\"},{\"id\":\"808607324394885120\"\
+        ,\"name\":\"Anas Human\",\"username\":\"ianashuman\"},{\"id\":\"1350237854438461442\"\
+        ,\"name\":\"General Operations Director\",\"username\":\"GeneralOperati2\"\
+        },{\"id\":\"1261330852920745984\",\"name\":\"Ryu Legalize\",\"username\":\"\
+        GroundsEnt\"},{\"id\":\"370874908\",\"name\":\"Gabe Romero\",\"username\"\
+        :\"Babriel2011\"},{\"id\":\"7161032\",\"name\":\"\\uD83C\\uDDFA\\uD83C\\uDDE6\
+        \ V say: \\uD83D\\uDC0D + \\uD83D\\uDC18 + \\uD83D\\uDC27 = \\uD83D\\uDCBB\
+        \ moksha\",\"username\":\"vasudevram\"},{\"id\":\"1320200071695245315\",\"\
+        name\":\"Kinga \u017Buchewicz\",\"username\":\"KingaZuchewicz\"},{\"id\":\"\
+        1067040438236971010\",\"name\":\"ElectronDev\",\"username\":\"dev_electron\"\
+        },{\"id\":\"1320159258109902848\",\"name\":\"Lumid\\uD83E\\uDDCB\",\"username\"\
+        :\"lumidsan\"},{\"id\":\"1084838536208179200\",\"name\":\"who\",\"username\"\
+        :\"Itay_tmr\"},{\"id\":\"289026240\",\"name\":\"Ryan Husk\",\"username\":\"\
+        ryhu\"},{\"id\":\"941595428\",\"name\":\"Peter Rihn\",\"username\":\"PeterRihn\"\
+        },{\"id\":\"1320554856424345601\",\"name\":\"Trintler\",\"username\":\"TrintlerMint\"\
+        },{\"id\":\"1346932330758336516\",\"name\":\"v\xEDdeo_status\",\"username\"\
+        :\"Jp_costa12\"},{\"id\":\"1254285713090023424\",\"name\":\"\u30D6\u30E9\u30C3\
+        \u30AF\u30D1\u30F3\u30C0\u30FC\",\"username\":\"CHoA93uXks3Es5w\"}],\"meta\"\
+        :{\"result_count\":81,\"next_token\":\"7140dibdnow9c7btw453p5fslak0mzq7j06yu8hnt7a5w\"\
+        }}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '2825'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:24 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192818424319950; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:24 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192818424319950; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:24 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_S+bg88mSBS2UU11tHq1YIw=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:24 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192818424319950; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:24 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 774320d7798f6dba6d5788c9d73bfb2f6c44d29598f7a2f5faa8f0b7bd4bd85e
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '75'
+      x-rate-limit-remaining:
+      - '74'
+      x-rate-limit-reset:
+      - '1651929084'
+      x-response-time:
+      - '171'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/tweets/1293593516040269825/liking_users
+version: 1
diff --git a/cassettes/test_asyncclient_get_list.yaml b/cassettes/test_asyncclient_get_list.yaml
new file mode 100644 (file)
index 0000000..f347e6f
--- /dev/null
@@ -0,0 +1,62 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/lists/84839422
+  response:
+    body:
+      string: '{"data":{"id":"84839422","name":"Official Twitter Accounts"}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '86'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:24 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192818461144431; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:24 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192818461144431; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:24 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_Mc3vJnQyR/sLdjFGzexbPQ=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:24 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192818461144431; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:24 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 78ade1716d4d0ed306e90120dc4d7562b538b74c0a138d0fe5a984a4e9b5f030
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '75'
+      x-rate-limit-remaining:
+      - '74'
+      x-rate-limit-reset:
+      - '1651929084'
+      x-response-time:
+      - '31'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/lists/84839422
+version: 1
diff --git a/cassettes/test_asyncclient_get_list_followers.yaml b/cassettes/test_asyncclient_get_list_followers.yaml
new file mode 100644 (file)
index 0000000..e7d14c5
--- /dev/null
@@ -0,0 +1,190 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/lists/84839422/followers
+  response:
+    body:
+      string: "{\"data\":[{\"id\":\"69523768\",\"name\":\"Sungyeon Ellen Kim\",\"\
+        username\":\"neosiren\"},{\"id\":\"15806207\",\"name\":\"GR2550\",\"username\"\
+        :\"GR2550\"},{\"id\":\"555713608\",\"name\":\"Judee Brillante-Parnell\",\"\
+        username\":\"ilokana09\"},{\"id\":\"1520088559499329537\",\"name\":\"Chris\
+        \ Jr Williams\",\"username\":\"ChrisJrW87\"},{\"id\":\"1481525443782406147\"\
+        ,\"name\":\"Cole Hu\",\"username\":\"ColeHu8\"},{\"id\":\"1019307395816845313\"\
+        ,\"name\":\"\u0688\u0627\u06A9\u0679\u0631 \u0645\u06CC\u06A9\u06CC\u0646\u06A9\
+        \",\"username\":\"Amir19888611\"},{\"id\":\"1512114730676019228\",\"name\"\
+        :\"FFNF\",\"username\":\"FFNF17290894\"},{\"id\":\"1331482021135331330\",\"\
+        name\":\"@Claesson\",\"username\":\"CicciCenter\"},{\"id\":\"840180024183468032\"\
+        ,\"name\":\"Sukri Mohd\",\"username\":\"SukriMohd5\"},{\"id\":\"1378804937275101186\"\
+        ,\"name\":\"GK \\uD83D\\uDD34\\uD83D\\uDFE2\u26AA \u26AB\",\"username\":\"\
+        7Kilc\"},{\"id\":\"117141665\",\"name\":\"Lauren Olivia\",\"username\":\"\
+        flylaurenfly\"},{\"id\":\"70341202\",\"name\":\"Chronically Trill\",\"username\"\
+        :\"NiqFury\"},{\"id\":\"1506292480572104708\",\"name\":\"Miguel Nunes\",\"\
+        username\":\"MiguelNunesMCN\"},{\"id\":\"24402111\",\"name\":\"Sage \u2728\
+        Danielle (she/her)\",\"username\":\"SageDanielle\"},{\"id\":\"1076910089079062529\"\
+        ,\"name\":\"Matthew Brewer\",\"username\":\"TheBrewerGame\"},{\"id\":\"5387412\"\
+        ,\"name\":\"Ashnod\",\"username\":\"ashnod\"},{\"id\":\"1497866871466569731\"\
+        ,\"name\":\"Goran Kresovi\u0107\",\"username\":\"kresovicgoran1\"},{\"id\"\
+        :\"1496838257929121795\",\"name\":\"lolte88\",\"username\":\"lolte884\"},{\"\
+        id\":\"893449195272536064\",\"name\":\"\\uD83E\\uDD84\\uD835\\uDC42\\uD835\\\
+        uDC53 \\uD835\\uDC36\\uD835\\uDC5C\\uD835\\uDC62\\uD835\\uDC5F\\uD835\\uDC60\\\
+        uD835\\uDC52 \\uD835\\uDC3C \\uD835\\uDC46\\uD835\\uDC61\\uD835\\uDC56\\uD835\\\
+        uDC59\\uD835\\uDC59 \\uD835\\uDC3F\\uD835\\uDC5C\\uD835\\uDC63\\uD835\\uDC52\
+        \ \\uD835\\uDC4C\\uD835\\uDC5C\\uD835\\uDC62 \u2022 Official \uEA00 Account\\\
+        uD83C\\uDF10\u26AA\",\"username\":\"asonofthegods\"},{\"id\":\"1492733139969585157\"\
+        ,\"name\":\"Mitchell B\",\"username\":\"bmsaltz1\"},{\"id\":\"799009477\"\
+        ,\"name\":\"Subhash\\uD83C\\uDDEE\\uD83C\\uDDF3\\uD83C\\uDDFF\\uD83C\\uDDF2\"\
+        ,\"username\":\"666Jsubhash\"},{\"id\":\"1405682090926952453\",\"name\":\"\
+        \u30E2\u30F3\u30B9\u30FC\u30F3\u3000Monsoon\",\"username\":\"rjdkr4\"},{\"\
+        id\":\"56651127\",\"name\":\"Paolo Ganino\",\"username\":\"paologanino\"},{\"\
+        id\":\"805313900505755648\",\"name\":\"Madaben\",\"username\":\"Madaben2\"\
+        },{\"id\":\"18076517\",\"name\":\"chartmann \\uD83D\\uDD4A\",\"username\"\
+        :\"chartmann\"},{\"id\":\"1419246449385086981\",\"name\":\"\u6771\u90F7midori\"\
+        ,\"username\":\"KKhigashi3\"},{\"id\":\"1475793790199869443\",\"name\":\"\
+        Jpx Fred\",\"username\":\"JpxFred1\"},{\"id\":\"1424968862315933698\",\"name\"\
+        :\"RE Test\",\"username\":\"redefinetest\"},{\"id\":\"1339318566475223041\"\
+        ,\"name\":\"\u0645\u062D\u0645\u062F \u0627\u0644\u0635\u064A\u0627\u062F\"\
+        ,\"username\":\"mohamed_al_said\"},{\"id\":\"1458390146458570761\",\"name\"\
+        :\"cosimo.\",\"username\":\"cosimodebarcus\"},{\"id\":\"1351194092248715269\"\
+        ,\"name\":\"Infinite Catto\",\"username\":\"Infinite_Catto\"},{\"id\":\"58871116\"\
+        ,\"name\":\"avindra \\uD83C\\uDF3B\",\"username\":\"avindra\"},{\"id\":\"\
+        3144623732\",\"name\":\"thank you for one\",\"username\":\"thankyouforone\"\
+        },{\"id\":\"1441245171891404801\",\"name\":\"intent/tweet?screen_WilsonChong9/verif\"\
+        ,\"username\":\"wilsonchong903\"},{\"id\":\"1033656875886280705\",\"name\"\
+        :\"Iven Lichti\",\"username\":\"nichtiven\"},{\"id\":\"201935415\",\"name\"\
+        :\"Giovanni / Gjovani \\uD83D\\uDEF8\",\"username\":\"0xGio\"},{\"id\":\"\
+        1118440306397941760\",\"name\":\"Charles-Teddy-Birdy\",\"username\":\"CityTeddy235323\"\
+        },{\"id\":\"838098779404390400\",\"name\":\"Refael Cohen\",\"username\":\"\
+        RefaelCohe\"},{\"id\":\"1448440735800324097\",\"name\":\"@enjoy02059661\"\
+        ,\"username\":\"enjoy02059661\"},{\"id\":\"1067526730426998784\",\"name\"\
+        :\"NR12\",\"username\":\"natashariou\"},{\"id\":\"313384381\",\"name\":\"\
+        mik\xE6l\",\"username\":\"michaeltibay\"},{\"id\":\"491386276\",\"name\":\"\
+        \xA9\uFE0F\",\"username\":\"carstensss\"},{\"id\":\"1435655461\",\"name\"\
+        :\"Alexis Mitchell\",\"username\":\"LexisTV\"},{\"id\":\"1460679755544600579\"\
+        ,\"name\":\"\u0627\u0628\u0648 \u062A\u0631\u0643\u064A \u0627\u0644\u062E\
+        \u0648\u0644\u0627\u0646\u064A \u062E\u0648\u0644\u0627\u0646\",\"username\"\
+        :\"TrkyKhwlan\"},{\"id\":\"1324848235714736129\",\"name\":\"Alan Lee\",\"\
+        username\":\"alanbenlee\"},{\"id\":\"1328359963937259520\",\"name\":\"Xo Chong\"\
+        ,\"username\":\"xo_chong\"},{\"id\":\"1451609880113070085\",\"name\":\"Sumira\
+        \ Nazir\",\"username\":\"SumiraNazir\"},{\"id\":\"1420055293082415107\",\"\
+        name\":\"Bo\u0159ek \u0160indelka(he/him)\",\"username\":\"JustBorek\"},{\"\
+        id\":\"1409136449803325441\",\"name\":\"\u91D1\u4E95\u61B2\u53F8\",\"username\"\
+        :\"w22ZccksRpafZAx\"},{\"id\":\"1346392170933194753\",\"name\":\"Taadi KALYJAY\
+        \ \u2660\",\"username\":\"FrimpongDarko2\"},{\"id\":\"1265867302303485957\"\
+        ,\"name\":\"Lee Chak Yong\",\"username\":\"yong_chak\"},{\"id\":\"3164618335\"\
+        ,\"name\":\"\u2694MICHAEL WILLIAM KUEHN\u2694\",\"username\":\"2M4W5K1\"},{\"\
+        id\":\"199721895\",\"name\":\"mirandastweets\",\"username\":\"mirandastweets\"\
+        },{\"id\":\"1299026549094653953\",\"name\":\"Faisal Sahal Jama\",\"username\"\
+        :\"FaisalsahalJ\"},{\"id\":\"1338348975439671296\",\"name\":\"Cecilia Claesson\"\
+        ,\"username\":\"CeciliaClaesso7\"},{\"id\":\"1439982522297982981\",\"name\"\
+        :\"Inked Up\",\"username\":\"InkedupwetUp314\"},{\"id\":\"1274060515116015616\"\
+        ,\"name\":\"The EMPOWER Lab\",\"username\":\"TheEMPOWERLab\"},{\"id\":\"328785439\"\
+        ,\"name\":\"\u2122\u0623\u0628\u0648 \u0641\u0627\u0631\u0633\u2122\",\"username\"\
+        :\"llksa10ll\"},{\"id\":\"1377016002777640965\",\"name\":\"turkdevops\",\"\
+        username\":\"turkdevops\"},{\"id\":\"1425735780866031622\",\"name\":\"Wilson\
+        \ Chong\",\"username\":\"Will5Chong\"},{\"id\":\"1019540119395667968\",\"\
+        name\":\"Harry Brodo\",\"username\":\"Winnie_The_Flu\"},{\"id\":\"56071962\"\
+        ,\"name\":\"Ana Erika Lareza\",\"username\":\"aelareza\"},{\"id\":\"1430673134701711362\"\
+        ,\"name\":\"Rafael Francisco Silva\",\"username\":\"RafaelF41140154\"},{\"\
+        id\":\"61105343\",\"name\":\"Neil Varcoe\",\"username\":\"neilwrites\"},{\"\
+        id\":\"1417558312246136833\",\"name\":\"Mohd Pauzan\",\"username\":\"MohdPauzan6\"\
+        },{\"id\":\"1314368210842517506\",\"name\":\"@Flylhil\",\"username\":\"Flylhiyhl\"\
+        },{\"id\":\"1324027537874427904\",\"name\":\"cucu old account\",\"username\"\
+        :\"fincu_wincu\"},{\"id\":\"146867169\",\"name\":\"\u30CD\u30AF\u30BF\u30FC\
+        \ (\u30B9\u30C6\u30A4\u30DB\u30FC\u30E0 \u30D5\u30EB\u30EF\u30AF\u30C1\u30F3\
+        )\",\"username\":\"Bakakieldogla\"},{\"id\":\"1342483347302281217\",\"name\"\
+        :\"\u305F\u307E\u3054\u307C\u30FC\u308D\",\"username\":\"hiro3pc\"},{\"id\"\
+        :\"1397057487577108483\",\"name\":\"Flylhigh\",\"username\":\"FlyFlylhigh\"\
+        },{\"id\":\"1099276443178098689\",\"name\":\"selle\",\"username\":\"dxmnselle\"\
+        },{\"id\":\"1096522641777643521\",\"name\":\"\u5F20\u5FB7\u519B\",\"username\"\
+        :\"zhangdejunjmm\"},{\"id\":\"1416163873904865290\",\"name\":\"Alhnod\",\"\
+        username\":\"alhnodalsanan\"},{\"id\":\"64274168\",\"name\":\"Lew\",\"username\"\
+        :\"lesmith5\"},{\"id\":\"1416366830906658820\",\"name\":\"\\uD83D\\uDC80\\\
+        uD83D\\uDC80\\uD83D\\uDC80\\uD83D\\uDC80\",\"username\":\"Klickslut\"},{\"\
+        id\":\"1375584599456292868\",\"name\":\"Player\",\"username\":\"GameToonsPlayer\"\
+        },{\"id\":\"1246540463554924546\",\"name\":\"BAJ \uEA00\",\"username\":\"\
+        BAJ584\"},{\"id\":\"1401245726009610247\",\"name\":\"amogus\",\"username\"\
+        :\"amogus31816431\"},{\"id\":\"1024553310\",\"name\":\"Meze (Jenpasit P.)\"\
+        ,\"username\":\"jenpasit\"},{\"id\":\"1369633382083264515\",\"name\":\"Classy\
+        \ Valkyrie\",\"username\":\"ClassyValkyrie\"},{\"id\":\"1361861724308181004\"\
+        ,\"name\":\"Tigris\",\"username\":\"TigrisFaiyu\"},{\"id\":\"1405797023492632578\"\
+        ,\"name\":\"WILSON YouTube\",\"username\":\"wilson_youtube\"},{\"id\":\"1357423390462795779\"\
+        ,\"name\":\"Cat Trades\",\"username\":\"Cat_Trades\"},{\"id\":\"1386757299864281092\"\
+        ,\"name\":\"\\uD83C\\uDF3F Rubio \u2728\\uD83C\\uDF31\",\"username\":\"Rubio6321\"\
+        },{\"id\":\"1353693022899363840\",\"name\":\"Acaplla\",\"username\":\"Acaplla1\"\
+        },{\"id\":\"149712202\",\"name\":\"I Am Change \\uD83D\\uDD4A\uFE0F #MTFBWY\
+        \ \\uD83C\\uDDF8\\uD83C\\uDDE6 \\uD83C\\uDDE8\\uD83C\\uDDE6 \\uD83C\\uDDEC\\\
+        uD83C\\uDDE7 \\uD83C\\uDDF5\\uD83C\\uDDF0 \\uD83D\\uDE80\",\"username\":\"\
+        UnCappingAgate\"},{\"id\":\"954741494061064192\",\"name\":\"Jason Ellison\"\
+        ,\"username\":\"JasonEl57580524\"},{\"id\":\"938250076568391680\",\"name\"\
+        :\"\u0641\u062A\u062D \u0627\u0644\u0644\u0647\",\"username\":\"dehghon2701\"\
+        },{\"id\":\"457700940\",\"name\":\"Towhid\",\"username\":\"towhid_asif\"},{\"\
+        id\":\"1276148600649760769\",\"name\":\"\u0630\u0628\u062D\u0646\u064A \u063A\
+        \u062F\u0631\u0643\",\"username\":\"fpmBsF4pGHvNGd2\"},{\"id\":\"2347625577\"\
+        ,\"name\":\"JABER MAENI\",\"username\":\"jabermqm1\"},{\"id\":\"1093406187880697856\"\
+        ,\"name\":\"soyer\",\"username\":\"soyer_stone\"},{\"id\":\"16396276\",\"\
+        name\":\"Mandi Cox\",\"username\":\"mandicoxsc\"},{\"id\":\"275227815\",\"\
+        name\":\"Kimberly Ann COllins\",\"username\":\"Kimberlyanncol2\"},{\"id\"\
+        :\"1277984305721905154\",\"name\":\"WilsonChong\",\"username\":\"wilsonC32120471\"\
+        },{\"id\":\"111831298\",\"name\":\"Ghesa Setyo Hadi \\uD83D\\uDDFA\uFE0F\\\
+        uD83C\\uDF0F\\uD83C\\uDF0C\",\"username\":\"vjghesa\"},{\"id\":\"1376761860209344513\"\
+        ,\"name\":\"TrisManZR37\",\"username\":\"TrisManZR37\"},{\"id\":\"393509113\"\
+        ,\"name\":\"Olivia Naylor\",\"username\":\"oliviamnaylor\"},{\"id\":\"1340680531575500800\"\
+        ,\"name\":\"man\\uD83D\\uDDFF\",\"username\":\"MEKlausen\"},{\"id\":\"925114806251802624\"\
+        ,\"name\":\"Claire \\uD83C\\uDF0A\\uD83C\\uDDEA\\uD83C\\uDDFA\\uD83C\\uDDEB\\\
+        uD83C\\uDDF7\\uD83C\\uDF0D\",\"username\":\"ClBear31\"}],\"meta\":{\"result_count\"\
+        :100,\"next_token\":\"1695203059209389429\"}}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '3439'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:24 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192818480972799; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:24 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192818480972799; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:24 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_e3bpHhYUAsknPr+/WbqGvA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:24 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192818480972799; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:24 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 56addc5770428f564dba31c5e53cbe52c6fa19ccfd61afd611b476d1b4ab037a
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '180'
+      x-rate-limit-remaining:
+      - '179'
+      x-rate-limit-reset:
+      - '1651929084'
+      x-response-time:
+      - '167'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/lists/84839422/followers
+version: 1
diff --git a/cassettes/test_asyncclient_get_list_members.yaml b/cassettes/test_asyncclient_get_list_members.yaml
new file mode 100644 (file)
index 0000000..f254121
--- /dev/null
@@ -0,0 +1,178 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/lists/84839422/members
+  response:
+    body:
+      string: "{\"data\":[{\"id\":\"1319036828964454402\",\"name\":\"Birdwatch\",\"\
+        username\":\"birdwatch\"},{\"id\":\"1244731491088809984\",\"name\":\"Twitter\
+        \ Thailand\",\"username\":\"TwitterThailand\"},{\"id\":\"1194267639100723200\"\
+        ,\"name\":\"Twitter Retweets\",\"username\":\"TwitterRetweets\"},{\"id\":\"\
+        1168976680867762177\",\"name\":\"Twitter Able\",\"username\":\"TwitterAble\"\
+        },{\"id\":\"1065249714214457345\",\"name\":\"Spaces\",\"username\":\"TwitterSpaces\"\
+        },{\"id\":\"1049385226424786944\",\"name\":\"Twitter Miami\",\"username\"\
+        :\"TwitterMiami\"},{\"id\":\"1004367799588880384\",\"name\":\"Twitter M\xE9\
+        xico\",\"username\":\"TwitterMexico\"},{\"id\":\"773578328498372608\",\"name\"\
+        :\"Twitter Together\",\"username\":\"TwitterTogether\"},{\"id\":\"766296039036948480\"\
+        ,\"name\":\"Moments MENA\",\"username\":\"momentsmena\"},{\"id\":\"738118487122419712\"\
+        ,\"name\":\"Twitter Asians\",\"username\":\"TwitterAsians\"},{\"id\":\"738118115595165697\"\
+        ,\"name\":\"Twitter Stripes\",\"username\":\"TwitterStripes\"},{\"id\":\"\
+        738117623737552896\",\"name\":\"Twitter Parents\",\"username\":\"TwitterParents\"\
+        },{\"id\":\"738115375477362688\",\"name\":\"Twitter Moments India\",\"username\"\
+        :\"MomentsIndia\"},{\"id\":\"717465714357972992\",\"name\":\"Twitter Video\
+        \ India\",\"username\":\"TwitterVideoIN\"},{\"id\":\"717463776170119169\"\
+        ,\"name\":\"Twitter Detroit\",\"username\":\"TwitterDetroit\"},{\"id\":\"\
+        717462990983856129\",\"name\":\"Twitter Paris\",\"username\":\"TwitterParis\"\
+        },{\"id\":\"4588114813\",\"name\":\"Twitter Moments Australia\",\"username\"\
+        :\"MomentsAU\"},{\"id\":\"4172587277\",\"name\":\"Twitter Moments Brasil\"\
+        ,\"username\":\"MomentsBrasil\"},{\"id\":\"3896350692\",\"name\":\"Twitter\
+        \ \u30E2\u30FC\u30E1\u30F3\u30C8\",\"username\":\"MomentsJapan\"},{\"id\"\
+        :\"3873984133\",\"name\":\"Twitter Moments Canada\",\"username\":\"CanadaMoments\"\
+        },{\"id\":\"3873965293\",\"name\":\"Twitter Moments en Espa\xF1ol\",\"username\"\
+        :\"MomentsES\"},{\"id\":\"3873936134\",\"name\":\"Twitter Gaming\",\"username\"\
+        :\"TwitterGaming\"},{\"id\":\"3873867072\",\"name\":\"Twitter Philippines\"\
+        ,\"username\":\"TwitterPH\"},{\"id\":\"3282898525\",\"name\":\"Twitter Marketing\
+        \ SG\",\"username\":\"TwitterMktgSG\"},{\"id\":\"3282860300\",\"name\":\"\
+        Twitter Marketing IN\",\"username\":\"TwitterMktgIN\"},{\"id\":\"3282859598\"\
+        ,\"name\":\"Twitter Creators\",\"username\":\"TwitterCreators\"},{\"id\":\"\
+        3282802674\",\"name\":\"Twitter Marketing MENA\",\"username\":\"TwitterMktgMENA\"\
+        },{\"id\":\"3260518932\",\"name\":\"Twitter Moments\",\"username\":\"TwitterMoments\"\
+        },{\"id\":\"3260517252\",\"name\":\"Twitter Marketing ID\",\"username\":\"\
+        TwitterMktgID\"},{\"id\":\"3099993704\",\"name\":\"Periscope Help\",\"username\"\
+        :\"PeriscopeHelp\"},{\"id\":\"3015734250\",\"name\":\"Twitter Marketing AU\"\
+        ,\"username\":\"TwitterMktgAU\"},{\"id\":\"3015301350\",\"name\":\"Twitter\
+        \ Stage\",\"username\":\"TwitterStage\"},{\"id\":\"3015271772\",\"name\":\"\
+        Twitter Food\",\"username\":\"TwitterFood\"},{\"id\":\"3001165942\",\"name\"\
+        :\"Revue\",\"username\":\"revue\"},{\"id\":\"2861317614\",\"name\":\"Twitter\
+        \ \u30D5\u30A1\u30C3\u30B7\u30E7\u30F3\",\"username\":\"TwitterFashnJP\"},{\"\
+        id\":\"2796700846\",\"name\":\"TwisitorLA\",\"username\":\"TwisitorLA\"},{\"\
+        id\":\"2551015628\",\"name\":\"Twitter\u30D3\u30B8\u30CD\u30B9\",\"username\"\
+        :\"TwitterBizJP\"},{\"id\":\"2551000952\",\"name\":\"Twitter Marketing DACH\"\
+        ,\"username\":\"TwitterMktgDACH\"},{\"id\":\"2551000568\",\"name\":\"Twitter\
+        \ Mktg Latam\",\"username\":\"TwitterMktLatam\"},{\"id\":\"2550997820\",\"\
+        name\":\"Twitter Indonesia\",\"username\":\"TwitterID\"},{\"id\":\"2549011969\"\
+        ,\"name\":\"Twitter NeighborNest\",\"username\":\"NeighborNest\"},{\"id\"\
+        :\"2548985366\",\"name\":\"Twitter Blackbirds\",\"username\":\"Blackbirds\"\
+        },{\"id\":\"2548979088\",\"name\":\"Twitter Alas\",\"username\":\"TwitterAlas\"\
+        },{\"id\":\"2548977510\",\"name\":\"Twitter Careers Brasil\",\"username\"\
+        :\"JoinTheFlockBR\"},{\"id\":\"2445809510\",\"name\":\"Periscope\",\"username\"\
+        :\"PeriscopeCo\",\"withheld\":{\"country_codes\":[\"TR\"]}},{\"id\":\"2328002822\"\
+        ,\"name\":\"Twitter Women\",\"username\":\"TwitterWomen\"},{\"id\":\"2296297326\"\
+        ,\"name\":\"Twitter Moments UK & Ireland\",\"username\":\"UKMoments\"},{\"\
+        id\":\"2249227634\",\"name\":\"Twitter Boulder\",\"username\":\"TwitterBoulder\"\
+        },{\"id\":\"2249227194\",\"name\":\"Twitter Sports\",\"username\":\"TwitterSportsAU\"\
+        },{\"id\":\"2244997579\",\"name\":\"Twitter Marketing BR\",\"username\":\"\
+        TwitterMktgBR\"},{\"id\":\"2244994945\",\"name\":\"Twitter Dev\",\"username\"\
+        :\"TwitterDev\"},{\"id\":\"2244983430\",\"name\":\"Twitter Singapore\",\"\
+        username\":\"TwitterSG\"},{\"id\":\"2244981348\",\"name\":\"Twitter\u30E9\u30A4\
+        \u30D5\u30E9\u30A4\u30F3\",\"username\":\"TwitterLifeline\"},{\"id\":\"2228891959\"\
+        ,\"name\":\"Twitter MENA\",\"username\":\"TwitterMENA\"},{\"id\":\"1884191208\"\
+        ,\"name\":\"Twitter For Good\",\"username\":\"TwitterForGood\"},{\"id\":\"\
+        1705676064\",\"name\":\"Twitter\u516C\u5F0F\u63A1\u7528\u30A2\u30AB\u30A6\u30F3\
+        \u30C8\",\"username\":\"JoinTheFlockJP\"},{\"id\":\"1665823832\",\"name\"\
+        :\"Twitter University\",\"username\":\"University\"},{\"id\":\"1640990204\"\
+        ,\"name\":\"Twitter Marketing ES\",\"username\":\"TwitterMktgES\"},{\"id\"\
+        :\"1639309946\",\"name\":\"Twitter Marketing FR\",\"username\":\"TwitterMktgFR\"\
+        },{\"id\":\"1636762128\",\"name\":\"Twitter Marketing Korea \uD2B8\uC704\uD130\
+        \ \uB9C8\uCF00\uD305\",\"username\":\"TwitterMktgKR\"},{\"id\":\"1631299117\"\
+        ,\"name\":\"Twitter Accessibility\",\"username\":\"TwitterA11y\"},{\"id\"\
+        :\"1603818258\",\"name\":\"Twitter Investor Relations\",\"username\":\"TwitterIR\"\
+        },{\"id\":\"1533573656\",\"name\":\"Twitter Dublin\",\"username\":\"TwitterDublin\"\
+        },{\"id\":\"1526228120\",\"name\":\"Twitter Data\",\"username\":\"TwitterData\"\
+        },{\"id\":\"1524832640\",\"name\":\"ArtHouse\",\"username\":\"ArtHouse\"},{\"\
+        id\":\"1462327554\",\"name\":\"Twitter \u30E1\u30C7\u30A3\u30A2\",\"username\"\
+        :\"TwitterMediaJP\"},{\"id\":\"1411434049\",\"name\":\"Event Parrot\",\"username\"\
+        :\"eventparrot\"},{\"id\":\"1347756012\",\"name\":\"Twitter Espa\xF1a\",\"\
+        username\":\"TwitterEspana\"},{\"id\":\"1347713256\",\"name\":\"Twitter Canada\"\
+        ,\"username\":\"TwitterCanada\"},{\"id\":\"1287248143\",\"name\":\"Twitter\
+        \ REW\",\"username\":\"TwitterREW\"},{\"id\":\"1228433617\",\"name\":\"Twitter\
+        \ Seattle\",\"username\":\"TwitterSeattle\"},{\"id\":\"1225933934\",\"name\"\
+        :\"Twitter Ads API\",\"username\":\"AdsAPI\"},{\"id\":\"1173514177\",\"name\"\
+        :\"Twitter Boston\",\"username\":\"TwitterBoston\"},{\"id\":\"1159458169\"\
+        ,\"name\":\"Twitter \u516C\u5171\u653F\u7B56\",\"username\":\"TwitterGovJP\"\
+        },{\"id\":\"1159422488\",\"name\":\"Twitter \u30CB\u30E5\u30FC\u30B9\",\"\
+        username\":\"TwitterNewsJP\"},{\"id\":\"1159274324\",\"name\":\"Twitter \u30B9\
+        \u30DD\u30FC\u30C4\",\"username\":\"TwitterSportsJP\"},{\"id\":\"1137751093\"\
+        ,\"name\":\"Twitter Security\",\"username\":\"twittersecurity\"},{\"id\":\"\
+        1117573164\",\"name\":\"Hadoop @Twitter\",\"username\":\"TwitterHadoop\"},{\"\
+        id\":\"1077914569\",\"name\":\"Twitter Marketing UK\",\"username\":\"TwitterMktgUK\"\
+        },{\"id\":\"1072232960\",\"name\":\"Twisitor\",\"username\":\"twisitor\"},{\"\
+        id\":\"905409822\",\"name\":\"Twitter SRE\",\"username\":\"TwitterSRE\"},{\"\
+        id\":\"862314223\",\"name\":\"Twitter \u30DF\u30E5\u30FC\u30B8\u30C3\u30AF\
+        \",\"username\":\"TwitterMusicJP\"},{\"id\":\"818212956\",\"name\":\"Twitter\
+        \ Australia\",\"username\":\"TwitterAU\"},{\"id\":\"791978718\",\"name\":\"\
+        Twitter Official Partner\",\"username\":\"OfficialPartner\"},{\"id\":\"726960710\"\
+        ,\"name\":\"Twitter Media\",\"username\":\"TwitterMedia\"},{\"id\":\"707249550\"\
+        ,\"name\":\"Twitter Atlanta\",\"username\":\"TwitterATL\"},{\"id\":\"632708673\"\
+        ,\"name\":\"Twitter \u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\",\"username\"\
+        :\"TwitterMktgJP\"},{\"id\":\"627222883\",\"name\":\"Join The Flock EMEA\"\
+        ,\"username\":\"JoinTheFlockEU\"},{\"id\":\"593893034\",\"name\":\"Twitter\
+        \ DC\",\"username\":\"TwitterDC\"},{\"id\":\"586198217\",\"name\":\"TwitterTV\"\
+        ,\"username\":\"TwitterTV\"},{\"id\":\"544524144\",\"name\":\"Twitter Research\"\
+        ,\"username\":\"TwitterResearch\"},{\"id\":\"495309159\",\"name\":\"Twitter\
+        \ New York City\",\"username\":\"TwitterNYC\"},{\"id\":\"484495045\",\"name\"\
+        :\"Twitter Los Angeles\",\"username\":\"TwitterLA\"},{\"id\":\"437698597\"\
+        ,\"name\":\"Twitter Women Eng\",\"username\":\"womeng\"},{\"id\":\"436266454\"\
+        ,\"name\":\"Twitter Movies\",\"username\":\"TwitterMovies\"},{\"id\":\"427475002\"\
+        ,\"name\":\"Twitter Books\",\"username\":\"TwitterBooks\"},{\"id\":\"414869890\"\
+        ,\"name\":\"Twitter Faith\",\"username\":\"TwitterFaith\"},{\"id\":\"376825877\"\
+        ,\"name\":\"Twitter Open Source\",\"username\":\"TwitterOSS\"},{\"id\":\"\
+        373471064\",\"name\":\"Twitter Music is listening to Bad Bunny\",\"username\"\
+        :\"TwitterMusic\"},{\"id\":\"372575989\",\"name\":\"Twitter News\",\"username\"\
+        :\"TwitterNews\"}],\"meta\":{\"result_count\":100,\"next_token\":\"4611686018799963893\"\
+        }}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '2230'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:25 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192818517027233; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:25 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192818517027233; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:25 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_jMDTobLXZMynQ3kty4W62A=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:25 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192818517027233; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:25 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - c87d718315833591c683ee19a131d186ccd519847214b8c044fd86b3517fff68
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '900'
+      x-rate-limit-remaining:
+      - '899'
+      x-rate-limit-reset:
+      - '1651929085'
+      x-response-time:
+      - '137'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/lists/84839422/members
+version: 1
diff --git a/cassettes/test_asyncclient_get_list_memberships.yaml b/cassettes/test_asyncclient_get_list_memberships.yaml
new file mode 100644 (file)
index 0000000..c60ae10
--- /dev/null
@@ -0,0 +1,135 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/783214/list_memberships
+  response:
+    body:
+      string: "{\"data\":[{\"id\":\"70971664\",\"name\":\"\u63A8\u7279 \u7684\u7FFB\
+        \u8B6F\"},{\"id\":\"1522184089851203584\",\"name\":\"NEWS\"},{\"id\":\"1522777513478479872\"\
+        ,\"name\":\"Bangladesh\"},{\"id\":\"1522745259867971588\",\"name\":\"Twitter\"\
+        },{\"id\":\"1522115752559489025\",\"name\":\"TW Ciencia y Tecnolog\xEDa\"\
+        },{\"id\":\"1520491249714667521\",\"name\":\"TW galindowinda\"},{\"id\":\"\
+        1522689035180949505\",\"name\":\"Important Message Read\"},{\"id\":\"1497342910198468611\"\
+        ,\"name\":\"Biased News\"},{\"id\":\"1522604085798658059\",\"name\":\"Cindy\"\
+        },{\"id\":\"1512837725644283905\",\"name\":\"\\uD83D\\uDD14primary main\"\
+        },{\"id\":\"1522564973930631170\",\"name\":\"Tech\"},{\"id\":\"1522516685814747137\"\
+        ,\"name\":\"Interesting\"},{\"id\":\"1522369960240160768\",\"name\":\"Companies\"\
+        },{\"id\":\"1522354337065840640\",\"name\":\"Test list\"},{\"id\":\"1522139848726880256\"\
+        ,\"name\":\"\u5916\u8BED\"},{\"id\":\"1522113331313532928\",\"name\":\"madrid\
+        \ & media\"},{\"id\":\"1214902330426085377\",\"name\":\"#News\"},{\"id\":\"\
+        1492585777661988864\",\"name\":\"Media/News\"},{\"id\":\"1522044324686581761\"\
+        ,\"name\":\"Socio Eco\"},{\"id\":\"1522031993714020352\",\"name\":\"Twitter\"\
+        },{\"id\":\"1519399393434439681\",\"name\":\"\\uD83C\\uDF08lmaginative Dickhead!\\\
+        uD83E\\uDD84\"},{\"id\":\"1252750272524402688\",\"name\":\"#P\xF8\xF8l\"},{\"\
+        id\":\"1521500202930253825\",\"name\":\"\\uD83D\\uDC99\"},{\"id\":\"1513200462471827459\"\
+        ,\"name\":\"\u041D\u0435\u0442 \u0432\u043E\u0439\u043D\u0435!\"},{\"id\"\
+        :\"1521591465268420611\",\"name\":\"pages\"},{\"id\":\"1521827110775578624\"\
+        ,\"name\":\"Twitter\"},{\"id\":\"1521772474937098241\",\"name\":\"News Twitter\"\
+        },{\"id\":\"1521769049474043905\",\"name\":\"Azad\"},{\"id\":\"1520650194039181314\"\
+        ,\"name\":\"\u4E92\u8054\u7F51\u516C\u53F8\"},{\"id\":\"1521665629274591232\"\
+        ,\"name\":\"\\uD83D\\uDC23 T W I T T E R\"},{\"id\":\"1519376358299738113\"\
+        ,\"name\":\"Clients\"},{\"id\":\"1375227324896006145\",\"name\":\"Private\
+        \ list.\"},{\"id\":\"1511804952909422596\",\"name\":\"Accounts to follow\"\
+        },{\"id\":\"1521550241031458816\",\"name\":\"Social Media\"},{\"id\":\"1521446669300076546\"\
+        ,\"name\":\"Invest\"},{\"id\":\"1521426614759960577\",\"name\":\"Corporate\"\
+        },{\"id\":\"1521216508252147717\",\"name\":\"Elon Musk\"},{\"id\":\"1521180623829823488\"\
+        ,\"name\":\"\\uD83D\\uDFE2 utopian-misfits\"},{\"id\":\"1521174316150571009\"\
+        ,\"name\":\"aboutTwitters\"},{\"id\":\"1511171519891841031\",\"name\":\"Twitter\
+        \ crushes\"},{\"id\":\"1520913390948032515\",\"name\":\"Degen coins\"},{\"\
+        id\":\"1520371185426513920\",\"name\":\"Dijital Pazarlama - SEO\"},{\"id\"\
+        :\"1520883829111762951\",\"name\":\"Top 50\"},{\"id\":\"1445727542573293580\"\
+        ,\"name\":\"Latest\"},{\"id\":\"1520814225932886019\",\"name\":\"De H\xE9\
+        roes, Espadas y Magi\"},{\"id\":\"1520808563907731456\",\"name\":\"NFT I HAVE\"\
+        },{\"id\":\"1520807143464701957\",\"name\":\"ALPHA people\"},{\"id\":\"1520805698472456195\"\
+        ,\"name\":\"Invested\"},{\"id\":\"1520804858961567745\",\"name\":\"Projects\
+        \ of Interest\"},{\"id\":\"1520802589859885057\",\"name\":\"Traders\"},{\"\
+        id\":\"1520794764949573635\",\"name\":\"Gaming\"},{\"id\":\"1520792663921995777\"\
+        ,\"name\":\"!Twitter\"},{\"id\":\"1520764004909850625\",\"name\":\"Indonesian\
+        \ sahabat\"},{\"id\":\"1520754524922728449\",\"name\":\"Twitter\"},{\"id\"\
+        :\"1520726320052797440\",\"name\":\"Integrated Transport\"},{\"id\":\"1520669648387076097\"\
+        ,\"name\":\"Twitter\"},{\"id\":\"1520055648272228353\",\"name\":\"Companies\"\
+        },{\"id\":\"1520340390880100352\",\"name\":\"New Best\"},{\"id\":\"1261767416071303168\"\
+        ,\"name\":\"Tec\"},{\"id\":\"1519634998822940677\",\"name\":\"code\"},{\"\
+        id\":\"1520255974627418113\",\"name\":\"\u90E8\u95E8\u4F01\u4E1A\"},{\"id\"\
+        :\"1519076588020977664\",\"name\":\"\u53CB\u9054\"},{\"id\":\"1520211492821344257\"\
+        ,\"name\":\"Woke Companies to Avoid\"},{\"id\":\"1487908525380567040\",\"\
+        name\":\"\u516C\u5F0F\"},{\"id\":\"1520152971979468800\",\"name\":\"elon\"\
+        },{\"id\":\"1520089362066718720\",\"name\":\"ChrisJr4Eva87\"},{\"id\":\"1520072028199346176\"\
+        ,\"name\":\"Interesting men and stuff\"},{\"id\":\"1520028006546391042\",\"\
+        name\":\"Social, Internet News\"},{\"id\":\"1520016831016316930\",\"name\"\
+        :\"testnet\"},{\"id\":\"1278225618170269697\",\"name\":\"art c-j\"},{\"id\"\
+        :\"1519997741178535937\",\"name\":\"Redes Sociales\"},{\"id\":\"1519939509739270145\"\
+        ,\"name\":\"Stonks\"},{\"id\":\"1360802683012186116\",\"name\":\"Dimensione\
+        \ JI\"},{\"id\":\"1519905191042109441\",\"name\":\"Knowledge\"},{\"id\":\"\
+        223040231\",\"name\":\"\\uD83D\\uDD38\\uD83C\\uDFB5\\uD83C\\uDFAC\\uD83D\\\
+        uDC84\\uD83C\\uDFAE\\uD83D\\uDD38\"},{\"id\":\"1123334741086883840\",\"name\"\
+        :\"Tv internet\"},{\"id\":\"1519809572961239040\",\"name\":\"Most Followed\"\
+        },{\"id\":\"1394412729696464901\",\"name\":\"important\"},{\"id\":\"1515845731449417729\"\
+        ,\"name\":\"The list of shame.\"},{\"id\":\"1511773608942739457\",\"name\"\
+        :\"\\uD83D\\uDD2Cprojects\"},{\"id\":\"1519624407861317639\",\"name\":\"Digital\
+        \ Marketing\"},{\"id\":\"1433101162903900160\",\"name\":\"TwitterComunication\"\
+        },{\"id\":\"1516201946327228428\",\"name\":\"Ongoing Musk BS\"},{\"id\":\"\
+        1519518935607308290\",\"name\":\"hbjhjjhjhjhjhjhjhjhjhjhjj\"},{\"id\":\"1519484348201902080\"\
+        ,\"name\":\"Elon Musk\"},{\"id\":\"1519453588866613248\",\"name\":\"Q\"},{\"\
+        id\":\"1519452706284261378\",\"name\":\"Elon Musk\"},{\"id\":\"1519432174696636417\"\
+        ,\"name\":\"CM\"},{\"id\":\"1519374370799456256\",\"name\":\"GiveAway Marathon\"\
+        },{\"id\":\"1519357294026571776\",\"name\":\"GiveAway Marathon\"},{\"id\"\
+        :\"1519353035449077760\",\"name\":\"GiveAway Marathon\"},{\"id\":\"1519348103123456000\"\
+        ,\"name\":\"\\uD83D\\uDCF1 social media\"},{\"id\":\"1519321279660457984\"\
+        ,\"name\":\"Technology\"}],\"meta\":{\"result_count\":93,\"next_token\":\"\
+        1731271766573010389\"}}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '2047'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:25 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192818547920045; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:25 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192818547920045; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:25 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_5QRHBZVW+HdG6bvDzoeNnQ=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:25 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192818547920045; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:25 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - bca579e94165a7c1eccb2fe870df66f2b9dd2ebca006e1cc7b96c2d2cb925b3b
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '75'
+      x-rate-limit-remaining:
+      - '74'
+      x-rate-limit-reset:
+      - '1651929085'
+      x-response-time:
+      - '155'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/783214/list_memberships
+version: 1
diff --git a/cassettes/test_asyncclient_get_list_tweets.yaml b/cassettes/test_asyncclient_get_list_tweets.yaml
new file mode 100644 (file)
index 0000000..57e1c59
--- /dev/null
@@ -0,0 +1,377 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/lists/84839422/tweets
+  response:
+    body:
+      string: "{\"data\":[{\"id\":\"1522916670209146881\",\"text\":\"RT @fotogramas_es:\
+        \ \u26A1\uFE0F  Estas son las 15 series recientes m\xE1s adictivas que han\
+        \ llegado recientemente a Netflix \\uD83D\\uDC47  https://t.co/qhMORyMwkw\"\
+        },{\"id\":\"1522916648138723329\",\"text\":\"RT @elperiodico: Chanel brilla\
+        \ en su segundo ensayo \\n\\n\u27A1\uFE0FLas redes han explotado de orgullo\
+        \ ante el segundo ensayo de @ChanelTerrero con su\u2026\"},{\"id\":\"1522916629134381057\"\
+        ,\"text\":\"RT @Cosmopolitan_es: \u26A1\uFE0F \u201CEvaluna comparte las primeras\
+        \ im\xE1genes de Camilo e \xCDndigo bailando juntos\u201D de @Cosmopolitan_es\
+        \ https://t.co/BKIVx9\u2026\"},{\"id\":\"1522904538428153858\",\"text\":\"\
+        \u0623\u0639\u0644\u0646\u062A \u0648\u0633\u0627\u0626\u0644 \u0625\u0639\
+        \u0644\u0627\u0645 \u0633\u0648\u0631\u064A\u0629 \u0648\u0639\u0631\u0628\
+        \u064A\u0629 \u0639\u0646 \u063A\u0627\u0631\u0629 \u062C\u0648\u064A\u0629\
+        \ \u0627\u0633\u062A\u0647\u062F\u0641\u062A #\u062D\u0648\u064A\u062C\u0629\
+        _\u0643\u0627\u0637\u0639 \u0642\u0631\u0628 \u0627\u0644\u062C\u0633\u0631\
+        \ \u0627\u0644\u0645\u0639\u0644\u0642 \u0628\u0645\u062F\u064A\u0646\u0629\
+        \ #\u062F\u064A\u0631_\u0627\u0644\u0632\u0648\u0631. \u062A\u0627\u0628\u0639\
+        \u0648\u0627 \u0645\u0639\u0646\u0627 \u0627\u0644\u062A\u0641\u0627\u0635\
+        \u064A\u0644\\n\\n#\u0633\u0648\u0631\u064A\u0627\\n\\nhttps://t.co/lCIETODISf\"\
+        },{\"id\":\"1522894062277513216\",\"text\":\"#TwitterBlueroom LIVE Q&amp;A\
+        \ with CLASS:y\\nCLASS:y(\uD074\uB77C\uC528)\uC640 \uBE14\uB8E8\uB8F8\uC5D0\
+        \uC11C \uB9CC\uB098\uC694 \\uD83D\\uDC9E \\n\\n#CLASSy #\uD074\uB77C\uC528\
+        \ \\n#CLASSISOVER #SHUTDOWN\\n\\nhttps://t.co/vlJ28rN9un\"},{\"id\":\"1522893995147669504\"\
+        ,\"text\":\"RT @M25_CLASSy: [\\uD83D\\uDCFA]\\n\\n\u2728 CLASS:y &amp; #TwitterBlueroom\
+        \ LIVE Q&amp;A \u2728\\n\\nCLASS:y(\uD074\uB77C\uC528)\uC640 \\n\uBE14\uB8E8\
+        \uB8F8\uC5D0\uC11C \uB9CC\uB098\uC694 \\uD83D\\uDC9E \\n\\n#CLASSy #\uD074\
+        \uB77C\uC528 \\n#CLASSISOVER #SHUTDOWN https://t.c\u2026\"},{\"id\":\"1522889824407101440\"\
+        ,\"text\":\"\u0627\u0644\u0645\u0639\u0632 \u0639\u0644\u064A \u064A\u0643\
+        \u0634\u0641 \u0639\u0646 \u062A\u0634\u062C\u0639\u064A\u0647 \u0627\u0644\
+        \u0647\u0644\u0627\u0644 \u0648\u064A\u062E\u062A\u0627\u0631 \u0623\u0641\
+        \u0636\u0644 \u0627\u0644\u0644\u0627\u0639\u0628\u064A\u0646 \u0628\u0627\
+        \u0644\u062F\u0648\u0631\u064A \u0627\u0644\u0633\u0639\u0648\u062F\u064A\
+        \ - \u0639\u0628\u0631 @GoalSA\\n\\nhttps://t.co/iiCUE27bxF\"},{\"id\":\"\
+        1522885735325515776\",\"text\":\"\u0644\u0644\u062D\u0641\u0627\u0638 \u0639\
+        \u0644\u0649 \u0627\u0644\u0647\u0648\u064A\u0629 \u0648\u0635\u0648\u0646\
+        \ \u0627\u0644\u062A\u0631\u0627\u062B.. \u0645\u0647\u0631\u062C\u0627\u0646\
+        \ \u0633\u0628\u0627\u0642 \u062F\u0644\u0645\u0627 \u0627\u0644\u062A\u0627\
+        \u0631\u064A\u062E\u064A \u064A\u0646\u0637\u0644\u0642 - \u0639\u0628\u0631\
+        \ @Baynounahtv \\n\\nhttps://t.co/D8r02jniXb\"},{\"id\":\"1522884083734433792\"\
+        ,\"text\":\"Captain @mayankcricket won the toss and @PunjabKingsIPL have elected\
+        \ to bat first against @rajasthanroyals. Follow along for all the updates\
+        \ as #PBKSvRR gets underway.\\nhttps://t.co/WFk6VucCJs\"},{\"id\":\"1522884046916931586\"\
+        ,\"text\":\"Captain @mayankcricket won the toss and @PunjabKingsIPL have elected\
+        \ to bat first against @rajasthanroyals. Follow along for all the updates\
+        \ as #PBKSvRR gets underway.\\nhttps://t.co/3ZKFRDDliV\"},{\"id\":\"1522883968940400640\"\
+        ,\"text\":\"Captain @mayankcricket won the toss and @PunjabKingsIPL have elected\
+        \ to bat first against @rajasthanroyals. Follow along for all the updates\
+        \ as #PBKSvRR gets underway.\\nhttps://t.co/EV0VOO13i9\"},{\"id\":\"1522883965983539200\"\
+        ,\"text\":\"\u0628\u064A\u0646\u0647\u0627 \u0623\u0628\u0637\u0627\u0644\
+        \ \u0641\u064A \u0645\u0635\u0631 \u0648\u0625\u0646\u062C\u0644\u062A\u0631\
+        \u0627 \u0648\u0641\u0631\u0646\u0633\u0627.. \u0641\u0631\u0642 \\\"\u0639\
+        \u064E\u0644\u0650\u0642\u064E\u062A\\\" \u0641\u064A \\\"\u0642\u0627\u0639\
+        \\\" \u0627\u0644\u062F\u0648\u0631\u064A\u0627\u062A! \u2693\\uD83D\\uDE25\
+        \ - \u0639\u0628\u0631 @alittihadSport \\n\\nhttps://t.co/WehyU8d0kk\"},{\"\
+        id\":\"1522883546712522752\",\"text\":\"IPL 2022: @PunjabKingsIPL - @rajasthanroyals\
+        \ \u0B87\u0B9F\u0BC8\u0BAF\u0BC7 \u0BAE\u0BCB\u0BA4\u0BB2\u0BCD. \u0BAA\u0BCB\
+        \u0B9F\u0BCD\u0B9F\u0BBF\u0BAF\u0BBF\u0BA9\u0BCD \u0B85\u0BAA\u0BCD\u0B9F\u0BC7\
+        \u0B9F\u0BCD\u0B95\u0BB3\u0BC1\u0B95\u0BCD\u0B95\u0BC1 \u0B87\u0BA8\u0BCD\u0BA4\
+        \u0BAA\u0BCD \u0BAA\u0B95\u0BCD\u0B95\u0BA4\u0BCD\u0BA4\u0BC8\u0BAA\u0BCD\
+        \ \u0BAA\u0BBF\u0BA9\u0BCD\u0BA4\u0BCA\u0B9F\u0BB0\u0BB5\u0BC1\u0BAE\u0BCD\
+        . #PBKSvRR\\nhttps://t.co/EV0VOOiEGJ\"},{\"id\":\"1522883149323288577\",\"\
+        text\":\"\u091F\u0949\u0938 \u091C\u0940\u0924\u0915\u0930 @PunjabKingsIPL\
+        \ \u0928\u0947 @rajasthanroyals \u0915\u0947 \u0916\u093F\u0932\u093E\u092B\
+        \ \u092A\u0939\u0932\u0947 \u092C\u0932\u094D\u0932\u0947\u092C\u093E\u091C\
+        \u0940 \u0915\u0930\u0928\u0947 \u0915\u093E \u092B\u0948\u0938\u0932\u093E\
+        \ \u0915\u093F\u092F\u093E \u0939\u0948\u0964 #PBKSvRR \u092E\u0948\u091A\
+        \ \u0915\u0947 \u0938\u092D\u0940 \u0905\u092A\u0921\u0947\u091F\u094D\u0938\
+        \ \u0914\u0930 \u0939\u093E\u0907\u0932\u093E\u0907\u091F\u094D\u0938 \u092F\
+        \u0939\u093E\u0902 \u0926\u0947\u0916\u0947\u0902\u0964\\nhttps://t.co/EV0VOOiEGJ\"\
+        },{\"id\":\"1522882537319714816\",\"text\":\"\u0641\u064A \u0645\u0631\u0627\
+        \u0633\u0645 \u0628\u0633\u064A\u0637\u0629.. \u0625\u064A\u0645\u0627\u0646\
+        \u0648\u064A\u0644 \u0645\u0627\u0643\u0631\u0648\u0646 \u0631\u0626\u064A\
+        \u0633\u0627 \u0644\u0641\u0631\u0646\u0633\u0627 \u0644\u0648\u0644\u0627\
+        \u064A\u0629 \u062B\u0627\u0646\u064A\u0629 \\uD83C\\uDDEB\\uD83C\\uDDF7 -\
+        \ \u0639\u0628\u0631 @aletihadae \\n\\nhttps://t.co/JwCaKgHme0\"},{\"id\"\
+        :\"1522879014293188609\",\"text\":\"\u0645\u0646 \u0647\u0648 \u062A\u0648\
+        \u062F \u0628\u0648\u064A\u0644\u064A \u062E\u0644\u064A\u0641\u0629 \u0623\
+        \u0628\u0631\u0627\u0645\u0648\u0641\u064A\u062A\u0634 \u0641\u064A \u062A\
+        \u0634\u064A\u0644\u0633\u064A\u061F - \u0639\u0628\u0631 @ArrajolM \\n\\\
+        nhttps://t.co/8UOz7KprZP\"},{\"id\":\"1522874032089145344\",\"text\":\"RT\
+        \ @eltelevisero: \u26A1\uFE0F \\\"Lista completa de concursantes de la s\xE9\
+        ptima edici\xF3n de #MasterChefCelebrity\\uD83D\\uDC68\\uD83C\\uDFFB\u200D\
+        \\uD83C\\uDF73 \\\"\\nhttps://t.co/xgluld3cUw\"},{\"id\":\"1522874019921510400\"\
+        ,\"text\":\"RT @elperiodico: \\uD83D\\uDC60Dakota Johnson o como triunfar\
+        \ en bata en la  \\n#MetGala2022 \\n\\nhttps://t.co/UWTp24MpR5\"},{\"id\"\
+        :\"1522873505636929538\",\"text\":\"RT @CNTravelerSpain: La mejor ruta ciclista\
+        \ (y senderista) de Europa de 2022 est\xE1 en Irlanda \\uD83D\\uDEB5\u200D\
+        \u2640\uFE0F https://t.co/vZE0GYLw38\"},{\"id\":\"1522873475987349507\",\"\
+        text\":\"RT @elperiodico: \u26A1\uFE0F Marat\xF3n de Barcelona: afectaciones\
+        \ al tr\xE1fico y transporte p\xFAblico para este domingo\\n\\n https://t.co/ibzEpzBJaW\"\
+        },{\"id\":\"1522841955419447296\",\"text\":\"\u062A\u0634\u064A\u0644\u0633\
+        \u064A \u064A\u0639\u0644\u0646 \u0639\u0646 \u0627\u062A\u0641\u0627\u0642\
+        \ \u0644\u0627\u0633\u062A\u062D\u0648\u0627\u0630 \u0645\u0644\u0627\u0643\
+        \ \u062C\u062F\u062F \u0639\u0644\u0649 \u0627\u0644\u0646\u0627\u062F\u064A\
+        \ \u0645\u0642\u0627\u0628\u0644 4.25 \u0645\u0644\u064A\u0627\u0631 \u0625\
+        \u0633\u062A\u0631\u0644\u064A\u0646\u064A \\uD83D\\uDD35 - \u0639\u0628\u0631\
+        \ @akhbar\\n\\nhttps://t.co/KaBHgxO3k9\"},{\"id\":\"1522838639344078849\"\
+        ,\"text\":\"\u0645\u062D\u0645\u062F \u0639\u0628\u062F\u0647 \u0648\u0645\
+        \u0627\u062C\u062F \u0627\u0644\u0645\u0647\u0646\u062F\u0633 \u0648\u0631\
+        \u0627\u0628\u062D \u0635\u0642\u0631 \u064A\u0634\u0639\u0644\u0648\u0646\
+        \ \u062D\u0641\u0644\u0627\u062A \u0627\u0644\u0639\u064A\u062F \u0628\u0627\
+        \u0644\u0633\u0639\u0648\u062F\u064A\u0629 - \u0639\u0628\u0631 @hiamag\\\
+        n\\nhttps://t.co/kaz1802sS8\"},{\"id\":\"1522828848898854912\",\"text\":\"\
+        Tomorrow is #MothersDay and we\u2019re here for it \u2764\uFE0F\\n\\nJoin\
+        \ in the conversation! https://t.co/xxHFC46Ql1\"},{\"id\":\"1522811173946728451\"\
+        ,\"text\":\"\u5185\u95A3\u5B98\u623F\u306F\u3001\u5317\u671D\u9BAE\u304B\u3089\
+        \u5F3E\u9053\u30DF\u30B5\u30A4\u30EB\u306E\u53EF\u80FD\u6027\u304C\u3042\u308B\
+        \u3082\u306E\u304C\u767A\u5C04\u3055\u308C\u305F\u3068\u767A\u8868\u3057\u307E\
+        \u3057\u305F\\nhttps://t.co/ds2df3jtaC\"},{\"id\":\"1522776988666134529\"\
+        ,\"text\":\"\u30D0\u30E9\u30A8\u30C6\u30A3\u30FC\u756A\u7D44\u300EKing \uFF06\
+        \ Prince\u308B\u3002\u300F\u304C\u300113\u664230\u5206\u304B\u3089\u653E\u9001\
+        \u3055\u308C\u307E\u3059\\uD83D\\uDCFA\\n#KingandPrince  #\u30AD\u30F3\u30D7\
+        \u308B\\nhttps://t.co/XhUuUHpvfm\"},{\"id\":\"1522776321503338496\",\"text\"\
+        :\"RT @UNICEFinJapan: \u56FD\u9023\u306E #\u6C17\u5019\u5909\u52D5 \u5BFE\u7B56\
+        \u306B\u3001\u5B50\u3069\u3082\u305F\u3061\u306E\u58F0\u3092\uFF01\\n\u300C\
+        #\u5B50\u3069\u3082\u30D1\u30D6\u30B3\u30E12022\u300D5\u67085\u65E5\u304B\u3089\
+        \u52DF\u96C6\u958B\u59CB\\n\u27A1\uFE0Fhttps://t.co/powAomSATL\\n\\n\\uD83D\\\
+        uDCE3\u5B50\u3069\u3082\u30D1\u30D6\u30B3\u30E12022 \u7279\u8A2D\u30DA\u30FC\
+        \u30B8\u27A1\uFE0Fhttps://t.co/TKVYOPGCsn\u2026\"},{\"id\":\"1522765702071042048\"\
+        ,\"text\":\"\u7C73\u56FD\u52D9\u7701\u306E\u30DD\u30FC\u30BF\u30FC\u526F\u5831\
+        \u9053\u5B98\u306F\u3001\u5317\u671D\u9BAE\u304C\u5317\u6771\u90E8\u8C4A\u6E13\
+        \u91CC\uFF08\u30D7\u30F3\u30B2\u30EA\uFF09\u30675\u6708\u4E2D\u306B\u3082\u6838\
+        \u5B9F\u9A13\u3092\u884C\u3046\u6E96\u5099\u304C\u6574\u3046\u53EF\u80FD\u6027\
+        \u304C\u3042\u308B\u3068\u306E\u5206\u6790\u3092\u660E\u3089\u304B\u306B\u3057\
+        \u307E\u3057\u305F\\nhttps://t.co/fnmQEX2ddf\"},{\"id\":\"1522765347450851328\"\
+        ,\"text\":\"RT @AztecaNoticias: \xBFTe toc\xF3 la granizada de este viernes\
+        \ en la #CDMX? Comp\xE1rtenos tus videos o fotograf\xEDas. \\n\\nhttps://t.co/zMMRjtzV06\"\
+        },{\"id\":\"1522765337288003584\",\"text\":\"RT @politicomx: \u26A1A menos\
+        \ de un mes de que las #Elecciones2022 se lleven a cabo en Quintana Roo, conoce\
+        \ todo lo que debes saber de este proc\u2026\"},{\"id\":\"1522762324066533376\"\
+        ,\"text\":\"RT @WNBA: Watch the @minnesotalynx take on the @seattlestorm right\
+        \ here \u2B07\uFE0F https://t.co/px0MpNAyMu\"},{\"id\":\"1522761645616893953\"\
+        ,\"text\":\"The ending of Sky-Sparks https://t.co/42ew9L3rLS\"},{\"id\":\"\
+        1522758927582044161\",\"text\":\"RT @JoelEmbiid: https://t.co/X6PE3IxTQj\"\
+        },{\"id\":\"1522742571046481920\",\"text\":\"Covid-19: Brasil registra 176\
+        \ mortes e 19.447 casos em 24 horas\\n\\nhttps://t.co/me133Bjpo3\"},{\"id\"\
+        :\"1522736537246388224\",\"text\":\"RT @NBATV: Natasha Cloud put her on skates\
+        \ \u26F8 https://t.co/CB6lFgk92o\"},{\"id\":\"1522711676285759488\",\"text\"\
+        :\"Pelo menos oito pessoas morreram ap\xF3s uma explos\xE3o no hotel Saratoga,\
+        \ um edif\xEDcio hist\xF3rico em Cuba\\n\\nhttps://t.co/iGrSkhd1wf\"},{\"\
+        id\":\"1522692948244246528\",\"text\":\"we'll go first: yellowstone meets\
+        \ stranger things\"},{\"id\":\"1522692671743172609\",\"text\":\"RT @arrogantkei:\
+        \ the topic was range \\uD83C\\uDFF9 https://t.co/m9hMN8G8CE\"},{\"id\":\"\
+        1522692649114906626\",\"text\":\"describe #outerrange in four words https://t.co/poA9ux7oex\"\
+        },{\"id\":\"1522691547308900359\",\"text\":\"RT @TwitterVoices: It is #CultureCon\
+        \ eve! And #TwitterVoices are ready to take the stage and keep it all the\
+        \ way \\uD83D\\uDCAF with the convos that mat\u2026\"},{\"id\":\"1522688916213878784\"\
+        ,\"text\":\"the best protagonist\"},{\"id\":\"1522688844470300672\",\"text\"\
+        :\"O l\xEDder ind\xEDgena J\xFAnior Hekurari afirmou nesta sexta que o grupo\
+        \ de yanomamis que estava desaparecido em Roraima foi encontrado. A Pol\xED\
+        cia investiga o caso \\n\\nhttps://t.co/kBfT5icol3\"},{\"id\":\"1522681857351036929\"\
+        ,\"text\":\"RT @EW: We're heading back to the #TheWilds! To join the fun,\
+        \ be ready to press play on the season 2 premiere with us TODAY at 6pm ET/3pm\
+        \ P\u2026\"},{\"id\":\"1522681764161937408\",\"text\":\"Quer saber como sua\
+        \ marca pode se conectar com as principais paix\xF5es, eventos e tend\xEA\
+        ncias da timeline? Descubra o poder do formato Pre-roll no Twitter, com publishers\
+        \ verificados e seguros. Leia o artigo! #BrandSafety\"},{\"id\":\"1522673615505874952\"\
+        ,\"text\":\"Dos operarios que estaba desaparecidos fueron encontrados muertos\
+        \ por la explosi\xF3n en Salamanca, Madrid \\nhttps://t.co/jmmk2vvrvK\"},{\"\
+        id\":\"1522668933072969728\",\"text\":\"RT @FUCCl: Twitter is really the pinnacle\
+        \ of social media. They wouldn\u2019t know what to do without y\u2019all.\"\
+        },{\"id\":\"1522664021601697793\",\"text\":\"RT @JacobiMyles: Runway baddie\
+        \ #AdutAkech \\uD83C\\uDF39 https://t.co/blhwVHdPMd\"},{\"id\":\"1522654064286257152\"\
+        ,\"text\":\"RT @NiusDiario: \u26A1\uFE0F#Moments | Alejandra Su\xE1rez Barcala,\
+        \ el personaje del d\xEDa en seis tuits\\nhttps://t.co/ZKXvpm3B7H\"},{\"id\"\
+        :\"1522653949714644994\",\"text\":\"RT @elperiodico: \u26A1\uFE0FAs\xED afectar\xE1\
+        \ este domingo la Marat\xF3n de Barcelona\\nhttps://t.co/ibzEpzBJaW\"},{\"\
+        id\":\"1522653823617097730\",\"text\":\"RT @torreon: #MOMENTO \u26A1\uFE0F\
+        \xBFQui\xE9nes son todos los artistas que colaboraron en #UnVeranoSinTi de\
+        \ Bad Bunny?\\nhttps://t.co/0Sx63dOG3M\"},{\"id\":\"1522653425908998145\"\
+        ,\"text\":\"RT @PuckNews: Join @juliaioffe in conversation w/ legendary photojournalist\
+        \ @lynseyaddario and Pulitzer Prize-winning journalist @mschwirtz\u2026\"\
+        },{\"id\":\"1522653348100513795\",\"text\":\"RT @yotele: \u26A1\uFE0F Marta\
+        \ Riesco no volver\xE1 a trabajar como colaboradora en Telecinco tras una\
+        \ tensa reuni\xF3n con sus jefes https://t.co/bHmenuDb\u2026\"},{\"id\":\"\
+        1522653192617705477\",\"text\":\"RT @fotogramas_es: \u26A1\uFE0F Celebramos\
+        \ 20 a\xF1os de #SpiderMan , la pel\xEDcula en la que Sony y Sam Raimi revolucionaron\
+        \ el cine de superh\xE9roes con u\u2026\"},{\"id\":\"1522653131884142603\"\
+        ,\"text\":\"Honey @jackharlow Come Home The Kids Miss You https://t.co/ygdc95aSIH\"\
+        },{\"id\":\"1522653034521804800\",\"text\":\"RT @EsquireEs: \u26A1\uFE0F Desde\
+        \ luego, el trabajo de estos actores es digno de admirar...\\nhttps://t.co/UecHyeUnyn\"\
+        },{\"id\":\"1522652669759864833\",\"text\":\"RT @elle_es: Un bob corto y rizado\
+        \ que ya nos chifla \\uD83D\\uDE0D\\nhttps://t.co/3NLwwzGPbr\"},{\"id\":\"\
+        1522652469079289868\",\"text\":\"RT @menshealthESP: Tener unos abdominales\
+        \ como los de @channingtatum es posible. Si quieres un 'six pack' como el\
+        \ suyo pon atenci\xF3n a su en\u2026\"},{\"id\":\"1522652419728936960\",\"\
+        text\":\"If you\u2019re a #SmallBusiness on Twitter looking to grow, check\
+        \ out these useful tips from @mizizishop, @seescandies, and @boxebristol \u2B07\
+        \uFE0F\"},{\"id\":\"1522652291513425921\",\"text\":\"RT @Newtral: \\uD83D\\\
+        uDCF2 Las claves de las recientes denuncias de espionaje a m\xF3viles con\
+        \ el programa Pegasus.\\n\\nTe lo explicamos en este @MomentsES\u2026\"},{\"\
+        id\":\"1522651673830862849\",\"text\":\"RT @Cosmopolitan_es: \u26A1\uFE0F\
+        \ Las 5 acusaciones m\xE1s graves de Amber Heard contra Johnny Depp \\uD83D\\\
+        uDE41 \\nhttps://t.co/ygj3qL3xLT\"},{\"id\":\"1522651531601924099\",\"text\"\
+        :\"RT @elperiodico: El espectacular traje de la firma Palomo Spain que Chanel\
+        \ llevar\xE1 a Eurovisi\xF3n 2022 https://t.co/p4g3Jx76OM\"},{\"id\":\"1522645438188466176\"\
+        ,\"text\":\"RT @HuffPost: Hear from some of these abortion providers and advocates\
+        \ on Spaces at 2:30 p.m. ET \\uD83D\\uDC47 https://t.co/2cRq5YIB4C\"},{\"\
+        id\":\"1522644753074036742\",\"text\":\"Varias personas resultaron heridas\
+        \ y otras murieron tras la explosi\xF3n en el Hotel Saratoga de La Habana,\
+        \ Cuba, este viernes\\nhttps://t.co/8NGL2R5PUA\"},{\"id\":\"1522643344731615233\"\
+        ,\"text\":\"when Spaces hosts meet in real life https://t.co/0xdFKKYVM2\"\
+        },{\"id\":\"1522642806032019456\",\"text\":\"\u0BAE\u0BC7\u0B9F\u0BCD\u0B9A\
+        \u0BC8 \u0BB5\u0BC6\u0BA9\u0BCD\u0BB1\u0BA4\u0BC1 @mipaltan! \u0BB9\u0BC8\u0BB2\
+        \u0BC8\u0B9F\u0BCD\u0B9A\u0BC8 \u0B87\u0B99\u0BCD\u0B95\u0BC1 \u0BAA\u0BC6\
+        \u0BB1\u0BB5\u0BC1\u0BAE\u0BCD. #GTvMI\\nhttps://t.co/7iFVCaGCSH\"},{\"id\"\
+        :\"1522642552972795906\",\"text\":\"#ScarletWitch is too powerful\"},{\"id\"\
+        :\"1522642324781633536\",\"text\":\"If you\u2019d like to apply, or would\
+        \ like to nominate someone else for the program, please feel free to fill\
+        \ out the following form:\\n\\nhttps://t.co/LUuWj24HLu\"},{\"id\":\"1522642323535847424\"\
+        ,\"text\":\"We\u2019ve gone into more detail on each Insider in our forum\
+        \ post.\_\\n\\nJoin us in congratulating the new additions! \\uD83E\\uDD73\\\
+        n\\nhttps://t.co/0r5maYEjPJ\"},{\"id\":\"1522642322449608704\",\"text\":\"\
+        Today, we\u2019re excited to expand this group with the addition of 8 new\
+        \ developers!\\n\\nWelcome to the program, kings and queens \\uD83D\\uDC51\\\
+        n\\n@andreitr, @dara_tobi, @Harmon758Public, @RedouaneBali, @ryanjgallag,\
+        \ @fourtonfish, @v21, @VeldaKiara\"},{\"id\":\"1522642320910282753\",\"text\"\
+        :\"Last October, we announced the launch of the Twitter Developer Insider\
+        \ Program \\uD83D\\uDE80\\n\\nSince then, this group of developers has helped\
+        \ us build better, learn faster, and support the community in new and exciting\
+        \ ways.\\nhttps://t.co/nTuXs7BjDp\"},{\"id\":\"1522641609493467136\",\"text\"\
+        :\"The @mipaltan clinch their second win in a row. Catch all the reactions\
+        \ to the #GTvMI match here.\\nhttps://t.co/7iFVCaGCSH\"},{\"id\":\"1522641041198919681\"\
+        ,\"text\":\"\u092E\u0941\u0902\u092C\u0908 \u0915\u0947 \u092C\u094D\u0930\
+        \u0947\u092C\u094B\u0930\u094D\u0928 \u0938\u094D\u091F\u0947\u0921\u093F\u092F\
+        \u092E \u092E\u0947\u0902 \u0916\u0947\u0932\u0947 \u0917\u090F #GTvMI \u092E\
+        \u0948\u091A \u092E\u0947\u0902 @mipaltan \u0928\u0947 @gujarat_titans \u0915\
+        \u094B 5 \u0930\u0928\u094B\u0902 \u0938\u0947 \u0939\u0930\u093E \u0926\u093F\
+        \u092F\u093E \u0939\u0948\u0964 \u0907\u0938 \u092E\u0948\u091A \u092A\u0930\
+        \ \u0938\u092D\u0940 \u092A\u094D\u0930\u0924\u093F\u0915\u094D\u0930\u093F\
+        \u092F\u093E \u0914\u0930 \u0939\u093E\u0907\u0932\u093E\u0907\u091F\u094D\
+        \u0938 \u092F\u0939\u093E\u0902 \u092B\u0949\u0932\u094B \u0915\u0930\u0947\
+        \u0902\u0964\\nhttps://t.co/7iFVCaGCSH\"},{\"id\":\"1522640520262074369\"\
+        ,\"text\":\"RT @canaltech: Quer saber tudo sobre a queda do NFT? Confira nesse\
+        \ moments que criamos: https://t.co/8oX1jJFFo9\"},{\"id\":\"1522639549519831043\"\
+        ,\"text\":\"Feliz #UnVeranoSinTi https://t.co/3EV5oC2VIX\"},{\"id\":\"1522639030315278338\"\
+        ,\"text\":\"RT @tangerinanews: Confira nove estreias da semana nos cinemas\
+        \ e streamings pra assistir no fim de semana https://t.co/XUtpidH8pl\"},{\"\
+        id\":\"1522634733867487234\",\"text\":\"The finance conversation has become\
+        \ more open (and fun!) than ever before.\\n\\nLearn how Finance Goes Social\
+        \ during our Twitter Trends chat this Thursday, 5/12 at 1pm ET/10am PT with\
+        \ @iamrrr, @Anu__Dave, @JNSilva_, and @RhysDurrellW.\\n\\nSet a reminder\\\
+        uD83D\\uDC47\\nhttps://t.co/VL8VbHsjHG\"},{\"id\":\"1522632435179171840\"\
+        ,\"text\":\"when the morning coffee finally hits &gt;\"},{\"id\":\"1522629147297787905\"\
+        ,\"text\":\"\u26A1\uFE0F \u201C\u062E\u0633\u0627\u0626\u0631 \u0628\u0627\
+        \u0644\u0645\u0644\u064A\u0627\u0631\u0627\u062A.. \u0639\u0627\u0635\u0641\
+        \u0629 \u0627\u0631\u062A\u0641\u0627\u0639 \u0627\u0644\u0641\u0627\u0626\
+        \u062F\u0629 \u062A\u0636\u0631\u0628 \u0627\u0644\u0623\u0633\u0647\u0645\
+        \ \u062D\u0648\u0644 \u0627\u0644\u0639\u0627\u0644\u0645\u201D by @Baynounahtv\
+        \ https://t.co/Tn0NzisB4o\"},{\"id\":\"1522624786983264257\",\"text\":\"RT\
+        \ @gridnews: What will May 9th mean for the war in Ukraine? \\n\\nJoin @TomNagorski\
+        \ and @joshuakeating now on @TwitterSpaces for a chat. https\u2026\"},{\"\
+        id\":\"1522624483705692162\",\"text\":\"Tenemos que confesar algo: decir que\
+        \ el ni\xF1o se siente mal, pero lo cierto es que lo dejamos quedarse en casa\
+        \ porque lo quer\xEDamos consentir. #SorryNotSorry https://t.co/Futc3dWQ1F\"\
+        },{\"id\":\"1522623574397407234\",\"text\":\"\\uD83C\\uDFB5 \\\"Eu tenho tanto\
+        \ pra lhe falar, mas com palavras n\xE3o sei dizer\u2026\\\". Quem j\xE1 cantou\
+        \ essa m\xFAsica pra m\xE3e? E que m\xE3e sabe a letra de cor? Nos Tweets\
+        \ sobre m\xE3es, m\xFAsica \xE9 um dos temas mais mencionados. Como o Dia\
+        \ das M\xE3es t\xE1 chegando, conta a\xED que #musicademae te vem \xE0 cabe\xE7\
+        a! \\uD83D\\uDC99\"},{\"id\":\"1522623247208095745\",\"text\":\"RT @Cilla_Presley:\
+        \ Here is an exclusive clip! #ElvisMovie https://t.co/s2DktfLGGh\"},{\"id\"\
+        :\"1522622842940149760\",\"text\":\"Querida gente de @TwitterParents, \xBF\
+        qu\xE9 piensan o qu\xE9 consejo tienen para esto? \\uD83D\\uDC40\\uD83D\\\
+        uDC47 #Mam\xE1SinFiltro https://t.co/NjMDsh1aSG\"},{\"id\":\"1522622469290352640\"\
+        ,\"text\":\"Pues @TwitterParents tiene una \u2728gran\u2728 biograf\xEDa:\
+        \ \\\"Menos culpa. M\xE1s flexibilidad. Cero juicios. Todo amor\\\".\\n\\\
+        nAs\xED que, \xBFpor qu\xE9 no hablar sobre lo que te hace ser una madre que\
+        \ *no* se siente culpable? \\n\\nEmpezamos nosotros: dar pizza\\uD83C\\uDF55\
+        \ en la cena. \\uD83E\\uDD2D #Mam\xE1SinFiltro https://t.co/gIxQEN8m4I\"},{\"\
+        id\":\"1522619837620572160\",\"text\":\"Se hizo historia en el tenis espa\xF1\
+        ol. Carlos Alcaraz ha derrotado por primera vez a Rafa Nadal en los cuartos\
+        \ de final del Mutua Madrid Open \\uD83C\\uDFBE\\nhttps://t.co/M1K1Z5egrV\"\
+        },{\"id\":\"1522618586342301697\",\"text\":\"this Tweet is your permission\
+        \ to stop working and start gaming\"},{\"id\":\"1522615452052205580\",\"text\"\
+        :\"What a fantastic way of highlighting how easy it can be to ignore the symptoms\
+        \ of ovarian cancer. \\n\\nMust watch \\uD83D\\uDC40\\uD83D\\uDC47 https://t.co/ftuHn7EOID\"\
+        },{\"id\":\"1522615136388743168\",\"text\":\"WNBA IS BACK https://t.co/5FXJ7jzIWm\"\
+        },{\"id\":\"1522614227692883970\",\"text\":\"La fuerza estuvo del lado de\
+        \ las marcas esta semana, \u2728 descubre c\xF3mo conectaron en nuestro moment\
+        \ semanal.\\uD83D\\uDC47\\uD83D\\uDC47 https://t.co/4n9k9TkS1H\"},{\"id\"\
+        :\"1522611450874929153\",\"text\":\"Analistas repudiam fala de Bolsonaro sobre\
+        \ papel das For\xE7as Armadas no processo eleitoral. Presidente disse que\
+        \ militares n\xE3o ser\xE3o apenas \u201Cespectadores\u201D da elei\xE7\xE3\
+        o\\nhttps://t.co/lW7Txor8ff\"},{\"id\":\"1522592048733425665\",\"text\":\"\
+        For this and more \\uD83D\\uDC47\\n\\nhttps://t.co/7kNaDm1tsu\"},{\"id\":\"\
+        1522592041666072576\",\"text\":\"We asked @adamm0rgan for his advice on starting\
+        \ a newsletter. https://t.co/OYwadDezzM\"},{\"id\":\"1522592028709769217\"\
+        ,\"text\":\"\u2018The Frontlist\u2019 is a newsletter by Adam Morgan (@adamm0rgan),\
+        \ featuring monthly book previews, reading recommendations, and exclusive\
+        \ interviews with writers, book designers, and publishers.\\n\\nhttps://t.co/ppetL3CIad\"\
+        },{\"id\":\"1522587339113050113\",\"text\":\"\\uD83D\\uDD02 Bad Bunny's #UnVeranoSinTi\
+        \ https://t.co/7veiS7hffx\"},{\"id\":\"1522586052346667009\",\"text\":\"Ter\
+        \ aten\xE7\xE3o \xE0s conversas sobre datas comemorativas e grandes eventos\
+        \ \xE9 essencial para marcas que desejam fazer parte do que est\xE1 acontecendo.\
+        \ @rafaelcamilo, l\xEDder de Twitter Next no Brasil, listou 5 estrat\xE9gias\
+        \ para alcan\xE7ar esse objetivo. Confira: https://t.co/8dcRpvM3iX\"},{\"\
+        id\":\"1522584700660895744\",\"text\":\"\u26A1\uFE0F \u201C\u0623\u0632\u0645\
+        \u0629 \u063A\u0630\u0627\u0621 \u062A\u0647\u062F\u062F \u0627\u0644\u0639\
+        \u0627\u0644\u0645.. \u0648\u0631\u0628\u0639 \u0645\u0644\u064A\u0627\u0631\
+        \ \u0637\u0646 \u062D\u0628\u0648\u0628 \\\"\u0639\u0627\u0644\u0642\u0629\
+        \\\" \u0641\u064A \u0623\u0648\u0643\u0631\u0627\u0646\u064A\u0627\\uD83C\\\
+        uDF3E\u201D by @aletihadae https://t.co/fWn9LjlMMi\"},{\"id\":\"1522584062262718467\"\
+        ,\"text\":\"\u26A1\uFE0F \u201C46 \u0639\u0627\u0645\u064B\u0627 \u0645\u0646\
+        \ \u0627\u0644\u0633\u0644\u0627\u0645 \u0648\u0627\u0644\u0623\u0645\u0646\
+        .. \u0627\u0644\u0625\u0645\u0627\u0631\u0627\u062A \u062A\u062D\u062A\u0641\
+        \u064A \u0628\u0630\u0643\u0631\u0649 \u062A\u0648\u062D\u064A\u062F \u0627\
+        \u0644\u0642\u0648\u0627\u062A \u0627\u0644\u0645\u0633\u0644\u062D\u0629\u201D\
+        \ by @Forsan_UAE https://t.co/KWXo1TCx5C\"},{\"id\":\"1522583275063152641\"\
+        ,\"text\":\"RT @bpolitics: TUNE IN: Chief Justice Roberts called the leak\
+        \ of a draft opinion \u201Cabsolutely appalling,\u201D but it has sparked\
+        \ a conversation\u2026\"},{\"id\":\"1522582884095303680\",\"text\":\"Moms,\
+        \ *hypothetically* let's say your kids/partner are a little late in getting\
+        \ you a gift this year--what's the one thing you want for #MothersDay?\"},{\"\
+        id\":\"1522582421744631808\",\"text\":\"jaw on the floor #TheWilds https://t.co/1pgWOsO0sy\"\
+        }],\"meta\":{\"result_count\":99,\"next_token\":\"7140dibdnow9c7btw421dyyvx5wstfnjsb2wjd99prxo8\"\
+        }}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '9301'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:26 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192818587096810; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192818587096810; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_1zhvH3Yb+Y5pjcfiQdAZbA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192818587096810; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 38cec82348a245e54ee0a15d839280f6295cab1a91153daeeec6f1c25289c228
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '900'
+      x-rate-limit-remaining:
+      - '899'
+      x-rate-limit-reset:
+      - '1651929085'
+      x-response-time:
+      - '517'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/lists/84839422/tweets
+version: 1
diff --git a/cassettes/test_asyncclient_get_me.yaml b/cassettes/test_asyncclient_get_me.yaml
new file mode 100644 (file)
index 0000000..5d995a0
--- /dev/null
@@ -0,0 +1,62 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/me
+  response:
+    body:
+      string: '{"data":{"id":"1072250532645998596","name":"Tweepy Testing","username":"TweepyDev"}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '97'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:26 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192818656734496; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192818656734496; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_t8emqhYAFotFm37iC/Urxw=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192818656734496; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - a8515bcd01b3dc34b8b8070eb1bcc5d50a15da1c7066edecd9d04e8a909c3cf1
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '75'
+      x-rate-limit-remaining:
+      - '74'
+      x-rate-limit-reset:
+      - '1651929086'
+      x-response-time:
+      - '38'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/me
+version: 1
diff --git a/cassettes/test_asyncclient_get_owned_lists.yaml b/cassettes/test_asyncclient_get_owned_lists.yaml
new file mode 100644 (file)
index 0000000..a312413
--- /dev/null
@@ -0,0 +1,66 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/783214/owned_lists
+  response:
+    body:
+      string: '{"data":[{"id":"1207354259852820480","name":"Tweets by Twitter"},{"id":"1015240715587158021","name":"Interests
+        on Twitter"},{"id":"815255107788906496","name":"Moments"},{"id":"214727905","name":"Developers"},{"id":"99925800","name":"Global
+        Country Accounts"},{"id":"99924643","name":"Support"},{"id":"99924211","name":"Media"},{"id":"99923132","name":"Engineering"},{"id":"99922622","name":"Offices
+        & Culture"},{"id":"99921778","name":"Business & Marketing"},{"id":"84839422","name":"Official
+        Twitter Accounts"}],"meta":{"result_count":11}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '297'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:26 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192818678348972; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192818678348972; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_myOcWCiqfNqcFbOEnSRMuw=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192818678348972; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 210d4292e615d000ff0833b02f9d8e324c838c5b666f1188fc7a77300314d3b9
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '15'
+      x-rate-limit-remaining:
+      - '14'
+      x-rate-limit-reset:
+      - '1651929086'
+      x-response-time:
+      - '64'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/783214/owned_lists
+version: 1
diff --git a/cassettes/test_asyncclient_get_quote_tweets.yaml b/cassettes/test_asyncclient_get_quote_tweets.yaml
new file mode 100644 (file)
index 0000000..52bfdd9
--- /dev/null
@@ -0,0 +1,91 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/tweets/1293593516040269825/quote_tweets
+  response:
+    body:
+      string: "{\"data\":[{\"id\":\"1458146351036841988\",\"text\":\"RT @TwitterAPI:\
+        \ Twitter API v2: Early Access released\\n\\nToday we announced Early Access\
+        \ to the first endpoints of the new Twitter API!\\n\\n#Twi\u2026\"},{\"id\"\
+        :\"1457665167639007235\",\"text\":\"Can you share some screenshots worth of\
+        \ 888885.4k+ upvotes?\\n#cheerupraja00710 \\n#100DaysOfCode #javascript  \
+        \ #Python, #flutter \\nhttps://t.co/6z0cfF1ARu\"},{\"id\":\"1456942863447588871\"\
+        ,\"text\":\"RT @TwitterAPI: Twitter API v2: Early Access released\\n\\nToday\
+        \ we announced Early Access to the first endpoints of the new Twitter API!\\\
+        n\\n#Twi\u2026\"},{\"id\":\"1453474504928280580\",\"text\":\"We ask the Twitter\
+        \ administration to support the account of Mr. Hussein Al-Ezzi, after activists\
+        \ hacked the account\\n\\n Hope for a quick reply\\n They made it clear that\
+        \ brother Hussein Al-Ezzi did not violate the human rights conditions and\
+        \ standards on Twitter\\n@hussinalezzi5 https://t.co/5X3p8MkMJM https://t.co/uxy1CNOlOG\"\
+        },{\"id\":\"1452401301044797451\",\"text\":\"RT @TwitterAPI: Twitter API v2:\
+        \ Early Access released\\n\\nToday we announced Early Access to the first\
+        \ endpoints of the new Twitter API!\\n\\n#Twi\u2026\"},{\"id\":\"1452329441200386056\"\
+        ,\"text\":\"RT @TwitterAPI: Twitter API v2: Early Access released\\n\\nToday\
+        \ we announced Early Access to the first endpoints of the new Twitter API!\\\
+        n\\n#Twi\u2026\"},{\"id\":\"1451925842486079488\",\"text\":\"RT @TwitterAPI:\
+        \ Twitter API v2: Early Access released\\n\\nToday we announced Early Access\
+        \ to the first endpoints of the new Twitter API!\\n\\n#Twi\u2026\"},{\"id\"\
+        :\"1450521278658482182\",\"text\":\"RT @TwitterAPI: Twitter API v2: Early\
+        \ Access released\\n\\nToday we announced Early Access to the first endpoints\
+        \ of the new Twitter API!\\n\\n#Twi\u2026\"},{\"id\":\"1449081128837603330\"\
+        ,\"text\":\"RT @TwitterAPI: Twitter API v2: Early Access released\\n\\nToday\
+        \ we announced Early Access to the first endpoints of the new Twitter API!\\\
+        n\\n#Twi\u2026\"},{\"id\":\"1447635166986375173\",\"text\":\"RT @TwitterAPI:\
+        \ Twitter API v2: Early Access released\\n\\nToday we announced Early Access\
+        \ to the first endpoints of the new Twitter API!\\n\\n#Twi\u2026\"}],\"meta\"\
+        :{\"result_count\":10,\"next_token\":\"azxzu6t3auit\"}}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '649'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:27 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192818703462878; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:27 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192818703462878; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:27 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_eq3/aA2PFceD0Lxdsj935g=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:27 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192818703462878; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:27 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 49167ff567fea5cccdb26883976813160a77cb1158867714393d89a5be2e1634
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '75'
+      x-rate-limit-remaining:
+      - '74'
+      x-rate-limit-reset:
+      - '1651929087'
+      x-response-time:
+      - '243'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/tweets/1293593516040269825/quote_tweets
+version: 1
diff --git a/cassettes/test_asyncclient_get_recent_tweets_count.yaml b/cassettes/test_asyncclient_get_recent_tweets_count.yaml
new file mode 100644 (file)
index 0000000..a6af596
--- /dev/null
@@ -0,0 +1,62 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/tweets/counts/recent?query=Tweepy
+  response:
+    body:
+      string: '{"data":[{"end":"2022-04-30T13:00:00.000Z","start":"2022-04-30T12:56:17.000Z","tweet_count":1},{"end":"2022-04-30T14:00:00.000Z","start":"2022-04-30T13:00:00.000Z","tweet_count":30},{"end":"2022-04-30T15:00:00.000Z","start":"2022-04-30T14:00:00.000Z","tweet_count":30},{"end":"2022-04-30T16:00:00.000Z","start":"2022-04-30T15:00:00.000Z","tweet_count":31},{"end":"2022-04-30T17:00:00.000Z","start":"2022-04-30T16:00:00.000Z","tweet_count":30},{"end":"2022-04-30T18:00:00.000Z","start":"2022-04-30T17:00:00.000Z","tweet_count":31},{"end":"2022-04-30T19:00:00.000Z","start":"2022-04-30T18:00:00.000Z","tweet_count":30},{"end":"2022-04-30T20:00:00.000Z","start":"2022-04-30T19:00:00.000Z","tweet_count":31},{"end":"2022-04-30T21:00:00.000Z","start":"2022-04-30T20:00:00.000Z","tweet_count":31},{"end":"2022-04-30T22:00:00.000Z","start":"2022-04-30T21:00:00.000Z","tweet_count":32},{"end":"2022-04-30T23:00:00.000Z","start":"2022-04-30T22:00:00.000Z","tweet_count":32},{"end":"2022-05-01T00:00:00.000Z","start":"2022-04-30T23:00:00.000Z","tweet_count":31},{"end":"2022-05-01T01:00:00.000Z","start":"2022-05-01T00:00:00.000Z","tweet_count":30},{"end":"2022-05-01T02:00:00.000Z","start":"2022-05-01T01:00:00.000Z","tweet_count":30},{"end":"2022-05-01T03:00:00.000Z","start":"2022-05-01T02:00:00.000Z","tweet_count":30},{"end":"2022-05-01T04:00:00.000Z","start":"2022-05-01T03:00:00.000Z","tweet_count":32},{"end":"2022-05-01T05:00:00.000Z","start":"2022-05-01T04:00:00.000Z","tweet_count":31},{"end":"2022-05-01T06:00:00.000Z","start":"2022-05-01T05:00:00.000Z","tweet_count":30},{"end":"2022-05-01T07:00:00.000Z","start":"2022-05-01T06:00:00.000Z","tweet_count":32},{"end":"2022-05-01T08:00:00.000Z","start":"2022-05-01T07:00:00.000Z","tweet_count":32},{"end":"2022-05-01T09:00:00.000Z","start":"2022-05-01T08:00:00.000Z","tweet_count":31},{"end":"2022-05-01T10:00:00.000Z","start":"2022-05-01T09:00:00.000Z","tweet_count":30},{"end":"2022-05-01T11:00:00.000Z","start":"2022-05-01T10:00:00.000Z","tweet_count":32},{"end":"2022-05-01T12:00:00.000Z","start":"2022-05-01T11:00:00.000Z","tweet_count":30},{"end":"2022-05-01T13:00:00.000Z","start":"2022-05-01T12:00:00.000Z","tweet_count":31},{"end":"2022-05-01T14:00:00.000Z","start":"2022-05-01T13:00:00.000Z","tweet_count":31},{"end":"2022-05-01T15:00:00.000Z","start":"2022-05-01T14:00:00.000Z","tweet_count":30},{"end":"2022-05-01T16:00:00.000Z","start":"2022-05-01T15:00:00.000Z","tweet_count":30},{"end":"2022-05-01T17:00:00.000Z","start":"2022-05-01T16:00:00.000Z","tweet_count":32},{"end":"2022-05-01T18:00:00.000Z","start":"2022-05-01T17:00:00.000Z","tweet_count":31},{"end":"2022-05-01T19:00:00.000Z","start":"2022-05-01T18:00:00.000Z","tweet_count":32},{"end":"2022-05-01T20:00:00.000Z","start":"2022-05-01T19:00:00.000Z","tweet_count":30},{"end":"2022-05-01T21:00:00.000Z","start":"2022-05-01T20:00:00.000Z","tweet_count":31},{"end":"2022-05-01T22:00:00.000Z","start":"2022-05-01T21:00:00.000Z","tweet_count":31},{"end":"2022-05-01T23:00:00.000Z","start":"2022-05-01T22:00:00.000Z","tweet_count":30},{"end":"2022-05-02T00:00:00.000Z","start":"2022-05-01T23:00:00.000Z","tweet_count":30},{"end":"2022-05-02T01:00:00.000Z","start":"2022-05-02T00:00:00.000Z","tweet_count":30},{"end":"2022-05-02T02:00:00.000Z","start":"2022-05-02T01:00:00.000Z","tweet_count":30},{"end":"2022-05-02T03:00:00.000Z","start":"2022-05-02T02:00:00.000Z","tweet_count":31},{"end":"2022-05-02T04:00:00.000Z","start":"2022-05-02T03:00:00.000Z","tweet_count":30},{"end":"2022-05-02T05:00:00.000Z","start":"2022-05-02T04:00:00.000Z","tweet_count":34},{"end":"2022-05-02T06:00:00.000Z","start":"2022-05-02T05:00:00.000Z","tweet_count":30},{"end":"2022-05-02T07:00:00.000Z","start":"2022-05-02T06:00:00.000Z","tweet_count":31},{"end":"2022-05-02T08:00:00.000Z","start":"2022-05-02T07:00:00.000Z","tweet_count":34},{"end":"2022-05-02T09:00:00.000Z","start":"2022-05-02T08:00:00.000Z","tweet_count":32},{"end":"2022-05-02T10:00:00.000Z","start":"2022-05-02T09:00:00.000Z","tweet_count":30},{"end":"2022-05-02T11:00:00.000Z","start":"2022-05-02T10:00:00.000Z","tweet_count":30},{"end":"2022-05-02T12:00:00.000Z","start":"2022-05-02T11:00:00.000Z","tweet_count":30},{"end":"2022-05-02T13:00:00.000Z","start":"2022-05-02T12:00:00.000Z","tweet_count":34},{"end":"2022-05-02T14:00:00.000Z","start":"2022-05-02T13:00:00.000Z","tweet_count":31},{"end":"2022-05-02T15:00:00.000Z","start":"2022-05-02T14:00:00.000Z","tweet_count":30},{"end":"2022-05-02T16:00:00.000Z","start":"2022-05-02T15:00:00.000Z","tweet_count":35},{"end":"2022-05-02T17:00:00.000Z","start":"2022-05-02T16:00:00.000Z","tweet_count":30},{"end":"2022-05-02T18:00:00.000Z","start":"2022-05-02T17:00:00.000Z","tweet_count":31},{"end":"2022-05-02T19:00:00.000Z","start":"2022-05-02T18:00:00.000Z","tweet_count":30},{"end":"2022-05-02T20:00:00.000Z","start":"2022-05-02T19:00:00.000Z","tweet_count":30},{"end":"2022-05-02T21:00:00.000Z","start":"2022-05-02T20:00:00.000Z","tweet_count":30},{"end":"2022-05-02T22:00:00.000Z","start":"2022-05-02T21:00:00.000Z","tweet_count":31},{"end":"2022-05-02T23:00:00.000Z","start":"2022-05-02T22:00:00.000Z","tweet_count":34},{"end":"2022-05-03T00:00:00.000Z","start":"2022-05-02T23:00:00.000Z","tweet_count":39},{"end":"2022-05-03T01:00:00.000Z","start":"2022-05-03T00:00:00.000Z","tweet_count":30},{"end":"2022-05-03T02:00:00.000Z","start":"2022-05-03T01:00:00.000Z","tweet_count":32},{"end":"2022-05-03T03:00:00.000Z","start":"2022-05-03T02:00:00.000Z","tweet_count":30},{"end":"2022-05-03T04:00:00.000Z","start":"2022-05-03T03:00:00.000Z","tweet_count":31},{"end":"2022-05-03T05:00:00.000Z","start":"2022-05-03T04:00:00.000Z","tweet_count":30},{"end":"2022-05-03T06:00:00.000Z","start":"2022-05-03T05:00:00.000Z","tweet_count":34},{"end":"2022-05-03T07:00:00.000Z","start":"2022-05-03T06:00:00.000Z","tweet_count":33},{"end":"2022-05-03T08:00:00.000Z","start":"2022-05-03T07:00:00.000Z","tweet_count":34},{"end":"2022-05-03T09:00:00.000Z","start":"2022-05-03T08:00:00.000Z","tweet_count":31},{"end":"2022-05-03T10:00:00.000Z","start":"2022-05-03T09:00:00.000Z","tweet_count":30},{"end":"2022-05-03T11:00:00.000Z","start":"2022-05-03T10:00:00.000Z","tweet_count":31},{"end":"2022-05-03T12:00:00.000Z","start":"2022-05-03T11:00:00.000Z","tweet_count":30},{"end":"2022-05-03T13:00:00.000Z","start":"2022-05-03T12:00:00.000Z","tweet_count":30},{"end":"2022-05-03T14:00:00.000Z","start":"2022-05-03T13:00:00.000Z","tweet_count":35},{"end":"2022-05-03T15:00:00.000Z","start":"2022-05-03T14:00:00.000Z","tweet_count":39},{"end":"2022-05-03T16:00:00.000Z","start":"2022-05-03T15:00:00.000Z","tweet_count":32},{"end":"2022-05-03T17:00:00.000Z","start":"2022-05-03T16:00:00.000Z","tweet_count":33},{"end":"2022-05-03T18:00:00.000Z","start":"2022-05-03T17:00:00.000Z","tweet_count":31},{"end":"2022-05-03T19:00:00.000Z","start":"2022-05-03T18:00:00.000Z","tweet_count":32},{"end":"2022-05-03T20:00:00.000Z","start":"2022-05-03T19:00:00.000Z","tweet_count":32},{"end":"2022-05-03T21:00:00.000Z","start":"2022-05-03T20:00:00.000Z","tweet_count":30},{"end":"2022-05-03T22:00:00.000Z","start":"2022-05-03T21:00:00.000Z","tweet_count":30},{"end":"2022-05-03T23:00:00.000Z","start":"2022-05-03T22:00:00.000Z","tweet_count":31},{"end":"2022-05-04T00:00:00.000Z","start":"2022-05-03T23:00:00.000Z","tweet_count":32},{"end":"2022-05-04T01:00:00.000Z","start":"2022-05-04T00:00:00.000Z","tweet_count":30},{"end":"2022-05-04T02:00:00.000Z","start":"2022-05-04T01:00:00.000Z","tweet_count":30},{"end":"2022-05-04T03:00:00.000Z","start":"2022-05-04T02:00:00.000Z","tweet_count":33},{"end":"2022-05-04T04:00:00.000Z","start":"2022-05-04T03:00:00.000Z","tweet_count":30},{"end":"2022-05-04T05:00:00.000Z","start":"2022-05-04T04:00:00.000Z","tweet_count":31},{"end":"2022-05-04T06:00:00.000Z","start":"2022-05-04T05:00:00.000Z","tweet_count":30},{"end":"2022-05-04T07:00:00.000Z","start":"2022-05-04T06:00:00.000Z","tweet_count":33},{"end":"2022-05-04T08:00:00.000Z","start":"2022-05-04T07:00:00.000Z","tweet_count":33},{"end":"2022-05-04T09:00:00.000Z","start":"2022-05-04T08:00:00.000Z","tweet_count":32},{"end":"2022-05-04T10:00:00.000Z","start":"2022-05-04T09:00:00.000Z","tweet_count":33},{"end":"2022-05-04T11:00:00.000Z","start":"2022-05-04T10:00:00.000Z","tweet_count":32},{"end":"2022-05-04T12:00:00.000Z","start":"2022-05-04T11:00:00.000Z","tweet_count":30},{"end":"2022-05-04T13:00:00.000Z","start":"2022-05-04T12:00:00.000Z","tweet_count":32},{"end":"2022-05-04T14:00:00.000Z","start":"2022-05-04T13:00:00.000Z","tweet_count":30},{"end":"2022-05-04T15:00:00.000Z","start":"2022-05-04T14:00:00.000Z","tweet_count":36},{"end":"2022-05-04T16:00:00.000Z","start":"2022-05-04T15:00:00.000Z","tweet_count":32},{"end":"2022-05-04T17:00:00.000Z","start":"2022-05-04T16:00:00.000Z","tweet_count":30},{"end":"2022-05-04T18:00:00.000Z","start":"2022-05-04T17:00:00.000Z","tweet_count":32},{"end":"2022-05-04T19:00:00.000Z","start":"2022-05-04T18:00:00.000Z","tweet_count":33},{"end":"2022-05-04T20:00:00.000Z","start":"2022-05-04T19:00:00.000Z","tweet_count":31},{"end":"2022-05-04T21:00:00.000Z","start":"2022-05-04T20:00:00.000Z","tweet_count":30},{"end":"2022-05-04T22:00:00.000Z","start":"2022-05-04T21:00:00.000Z","tweet_count":31},{"end":"2022-05-04T23:00:00.000Z","start":"2022-05-04T22:00:00.000Z","tweet_count":31},{"end":"2022-05-05T00:00:00.000Z","start":"2022-05-04T23:00:00.000Z","tweet_count":32},{"end":"2022-05-05T01:00:00.000Z","start":"2022-05-05T00:00:00.000Z","tweet_count":30},{"end":"2022-05-05T02:00:00.000Z","start":"2022-05-05T01:00:00.000Z","tweet_count":30},{"end":"2022-05-05T03:00:00.000Z","start":"2022-05-05T02:00:00.000Z","tweet_count":30},{"end":"2022-05-05T04:00:00.000Z","start":"2022-05-05T03:00:00.000Z","tweet_count":30},{"end":"2022-05-05T05:00:00.000Z","start":"2022-05-05T04:00:00.000Z","tweet_count":30},{"end":"2022-05-05T06:00:00.000Z","start":"2022-05-05T05:00:00.000Z","tweet_count":30},{"end":"2022-05-05T07:00:00.000Z","start":"2022-05-05T06:00:00.000Z","tweet_count":32},{"end":"2022-05-05T08:00:00.000Z","start":"2022-05-05T07:00:00.000Z","tweet_count":35},{"end":"2022-05-05T09:00:00.000Z","start":"2022-05-05T08:00:00.000Z","tweet_count":36},{"end":"2022-05-05T10:00:00.000Z","start":"2022-05-05T09:00:00.000Z","tweet_count":30},{"end":"2022-05-05T11:00:00.000Z","start":"2022-05-05T10:00:00.000Z","tweet_count":32},{"end":"2022-05-05T12:00:00.000Z","start":"2022-05-05T11:00:00.000Z","tweet_count":30},{"end":"2022-05-05T13:00:00.000Z","start":"2022-05-05T12:00:00.000Z","tweet_count":31},{"end":"2022-05-05T14:00:00.000Z","start":"2022-05-05T13:00:00.000Z","tweet_count":31},{"end":"2022-05-05T15:00:00.000Z","start":"2022-05-05T14:00:00.000Z","tweet_count":44},{"end":"2022-05-05T16:00:00.000Z","start":"2022-05-05T15:00:00.000Z","tweet_count":30},{"end":"2022-05-05T17:00:00.000Z","start":"2022-05-05T16:00:00.000Z","tweet_count":35},{"end":"2022-05-05T18:00:00.000Z","start":"2022-05-05T17:00:00.000Z","tweet_count":33},{"end":"2022-05-05T19:00:00.000Z","start":"2022-05-05T18:00:00.000Z","tweet_count":46},{"end":"2022-05-05T20:00:00.000Z","start":"2022-05-05T19:00:00.000Z","tweet_count":32},{"end":"2022-05-05T21:00:00.000Z","start":"2022-05-05T20:00:00.000Z","tweet_count":32},{"end":"2022-05-05T22:00:00.000Z","start":"2022-05-05T21:00:00.000Z","tweet_count":31},{"end":"2022-05-05T23:00:00.000Z","start":"2022-05-05T22:00:00.000Z","tweet_count":31},{"end":"2022-05-06T00:00:00.000Z","start":"2022-05-05T23:00:00.000Z","tweet_count":31},{"end":"2022-05-06T01:00:00.000Z","start":"2022-05-06T00:00:00.000Z","tweet_count":30},{"end":"2022-05-06T02:00:00.000Z","start":"2022-05-06T01:00:00.000Z","tweet_count":30},{"end":"2022-05-06T03:00:00.000Z","start":"2022-05-06T02:00:00.000Z","tweet_count":32},{"end":"2022-05-06T04:00:00.000Z","start":"2022-05-06T03:00:00.000Z","tweet_count":33},{"end":"2022-05-06T05:00:00.000Z","start":"2022-05-06T04:00:00.000Z","tweet_count":32},{"end":"2022-05-06T06:00:00.000Z","start":"2022-05-06T05:00:00.000Z","tweet_count":32},{"end":"2022-05-06T07:00:00.000Z","start":"2022-05-06T06:00:00.000Z","tweet_count":34},{"end":"2022-05-06T08:00:00.000Z","start":"2022-05-06T07:00:00.000Z","tweet_count":31},{"end":"2022-05-06T09:00:00.000Z","start":"2022-05-06T08:00:00.000Z","tweet_count":31},{"end":"2022-05-06T10:00:00.000Z","start":"2022-05-06T09:00:00.000Z","tweet_count":36},{"end":"2022-05-06T11:00:00.000Z","start":"2022-05-06T10:00:00.000Z","tweet_count":31},{"end":"2022-05-06T12:00:00.000Z","start":"2022-05-06T11:00:00.000Z","tweet_count":30},{"end":"2022-05-06T13:00:00.000Z","start":"2022-05-06T12:00:00.000Z","tweet_count":33},{"end":"2022-05-06T14:00:00.000Z","start":"2022-05-06T13:00:00.000Z","tweet_count":33},{"end":"2022-05-06T15:00:00.000Z","start":"2022-05-06T14:00:00.000Z","tweet_count":32},{"end":"2022-05-06T16:00:00.000Z","start":"2022-05-06T15:00:00.000Z","tweet_count":31},{"end":"2022-05-06T17:00:00.000Z","start":"2022-05-06T16:00:00.000Z","tweet_count":31},{"end":"2022-05-06T18:00:00.000Z","start":"2022-05-06T17:00:00.000Z","tweet_count":31},{"end":"2022-05-06T19:00:00.000Z","start":"2022-05-06T18:00:00.000Z","tweet_count":30},{"end":"2022-05-06T20:00:00.000Z","start":"2022-05-06T19:00:00.000Z","tweet_count":30},{"end":"2022-05-06T21:00:00.000Z","start":"2022-05-06T20:00:00.000Z","tweet_count":34},{"end":"2022-05-06T22:00:00.000Z","start":"2022-05-06T21:00:00.000Z","tweet_count":30},{"end":"2022-05-06T23:00:00.000Z","start":"2022-05-06T22:00:00.000Z","tweet_count":31},{"end":"2022-05-07T00:00:00.000Z","start":"2022-05-06T23:00:00.000Z","tweet_count":30},{"end":"2022-05-07T01:00:00.000Z","start":"2022-05-07T00:00:00.000Z","tweet_count":30},{"end":"2022-05-07T02:00:00.000Z","start":"2022-05-07T01:00:00.000Z","tweet_count":30},{"end":"2022-05-07T03:00:00.000Z","start":"2022-05-07T02:00:00.000Z","tweet_count":30},{"end":"2022-05-07T04:00:00.000Z","start":"2022-05-07T03:00:00.000Z","tweet_count":31},{"end":"2022-05-07T05:00:00.000Z","start":"2022-05-07T04:00:00.000Z","tweet_count":32},{"end":"2022-05-07T06:00:00.000Z","start":"2022-05-07T05:00:00.000Z","tweet_count":30},{"end":"2022-05-07T07:00:00.000Z","start":"2022-05-07T06:00:00.000Z","tweet_count":30},{"end":"2022-05-07T08:00:00.000Z","start":"2022-05-07T07:00:00.000Z","tweet_count":31},{"end":"2022-05-07T09:00:00.000Z","start":"2022-05-07T08:00:00.000Z","tweet_count":30},{"end":"2022-05-07T10:00:00.000Z","start":"2022-05-07T09:00:00.000Z","tweet_count":31},{"end":"2022-05-07T11:00:00.000Z","start":"2022-05-07T10:00:00.000Z","tweet_count":35},{"end":"2022-05-07T12:00:00.000Z","start":"2022-05-07T11:00:00.000Z","tweet_count":31},{"end":"2022-05-07T12:56:17.000Z","start":"2022-05-07T12:00:00.000Z","tweet_count":32}],"meta":{"total_tweet_count":5299}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '1163'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:27 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192818751213475; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:27 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192818751213475; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:27 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_15fpY2NNiLNHwD669+lK9A=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:27 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192818751213475; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:27 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 8119334f570c14f6ca1af7109092f75de06c43cdc3d067cf1445dc4ca44c1c3a
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '299'
+      x-rate-limit-reset:
+      - '1651929087'
+      x-response-time:
+      - '36'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/tweets/counts/recent?query=Tweepy
+version: 1
diff --git a/cassettes/test_asyncclient_get_retweeters.yaml b/cassettes/test_asyncclient_get_retweeters.yaml
new file mode 100644 (file)
index 0000000..d7c70e4
--- /dev/null
@@ -0,0 +1,132 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/tweets/1415348607813832708/retweeted_by
+  response:
+    body:
+      string: "{\"data\":[{\"id\":\"861889145303515136\",\"name\":\"Slava\",\"username\"\
+        :\"Astafieff_Slava\"},{\"id\":\"1516366969590759424\",\"name\":\"Yana Gencheva\"\
+        ,\"username\":\"YanaGencheva\"},{\"id\":\"1494665199260942339\",\"name\":\"\
+        Marcelo Fonseca\",\"username\":\"MarceloF1111\"},{\"id\":\"1516808822257553416\"\
+        ,\"name\":\"Crystal Bot\",\"username\":\"CrystalBot_\"},{\"id\":\"4762610299\"\
+        ,\"name\":\"TechnoKofe\",\"username\":\"technokofe\"},{\"id\":\"1514738371654037513\"\
+        ,\"name\":\"DevStreamers\",\"username\":\"DevStreamersBOT\"},{\"id\":\"1510148015465668612\"\
+        ,\"name\":\"Polite Troll\",\"username\":\"veryPoliteTroll\"},{\"id\":\"63046977\"\
+        ,\"name\":\"Emily Waligoske \\uD83C\\uDFD5\",\"username\":\"happycamper\"\
+        },{\"id\":\"1105800825631195136\",\"name\":\"suranjan\",\"username\":\"suranja19463352\"\
+        },{\"id\":\"1489094513737953281\",\"name\":\"Tasteless Degenerate\",\"username\"\
+        :\"TastelessDegen\"},{\"id\":\"1496859152546766853\",\"name\":\"I RT TARKOV\"\
+        ,\"username\":\"TarkovRt\"},{\"id\":\"1493107956434489350\",\"name\":\"RootSystems\"\
+        ,\"username\":\"RootSystemBot\"},{\"id\":\"1415549637931327488\",\"name\"\
+        :\"Teff\",\"username\":\"TeffLLC\"},{\"id\":\"64397778\",\"name\":\"Marketing\
+        \ Forum\",\"username\":\"markettingforum\"},{\"id\":\"1482329284677193729\"\
+        ,\"name\":\"zaven yt\",\"username\":\"zaven_ltr_yt\"},{\"id\":\"2508492511\"\
+        ,\"name\":\"Kakashi Sensei\",\"username\":\"NBA_Brawler\"},{\"id\":\"1308136039651844096\"\
+        ,\"name\":\"Vamshi\",\"username\":\"vamshi17892148\"},{\"id\":\"1466190483613528064\"\
+        ,\"name\":\"Spectra Analytical Hawaii\",\"username\":\"SpectraHawaii\"},{\"\
+        id\":\"1469684914803064833\",\"name\":\"pbtTest\",\"username\":\"PbtTest\"\
+        },{\"id\":\"1332626888674537474\",\"name\":\"Jacob Caldino Cardel Professional\
+        \ & Independent \\uD83D\\uDCBC\",\"username\":\"JacobCardel\"},{\"id\":\"\
+        323581124\",\"name\":\"Audry Hsu\",\"username\":\"Audryhsu\"},{\"id\":\"1446021847800160259\"\
+        ,\"name\":\"OPENLINK\",\"username\":\"openlinkk\"},{\"id\":\"909629468758740993\"\
+        ,\"name\":\"luuty\",\"username\":\"LuuTyZao\"},{\"id\":\"1466510666609664001\"\
+        ,\"name\":\"SRS\",\"username\":\"SRS54869025\"},{\"id\":\"711921243528757248\"\
+        ,\"name\":\"addyir\",\"username\":\"AddyirKenya\"},{\"id\":\"46759779\",\"\
+        name\":\"Ian Lenny\",\"username\":\"_opensourced\"},{\"id\":\"1454113941693599747\"\
+        ,\"name\":\"Aleksandar Kocev\",\"username\":\"kocev2906\"},{\"id\":\"2360617692\"\
+        ,\"name\":\"SocialProfit\",\"username\":\"pasivincome\"},{\"id\":\"1454352311334027267\"\
+        ,\"name\":\"Data Science Tweets\",\"username\":\"JustDataScience\"},{\"id\"\
+        :\"263744389\",\"name\":\"Eugene Sherlaimov \\uD83C\\uDDFA\\uD83C\\uDDE6\"\
+        ,\"username\":\"sherlaimov\"},{\"id\":\"1167617348661997568\",\"name\":\"\
+        jeannie\",\"username\":\"blueberryjeanz\"},{\"id\":\"1438363597428572167\"\
+        ,\"name\":\"iamsurya\",\"username\":\"iamsury71020583\"},{\"id\":\"118589107\"\
+        ,\"name\":\"Debashree Pati\",\"username\":\"d_pati\"},{\"id\":\"82333252\"\
+        ,\"name\":\"Nooh Noah\",\"username\":\"thenoahnooh\"},{\"id\":\"1429492556702703617\"\
+        ,\"name\":\"Quotinder | The Tech Bot\",\"username\":\"quotinder\"},{\"id\"\
+        :\"1337051132313686016\",\"name\":\"Aditya Rawat\",\"username\":\"CsAdityaRawat\"\
+        },{\"id\":\"815169466199703552\",\"name\":\"Love Simplicity\",\"username\"\
+        :\"simplify4me123\"},{\"id\":\"1294870848197799936\",\"name\":\"Shijath Ali\"\
+        ,\"username\":\"ShijathA\"},{\"id\":\"1425663002867494915\",\"name\":\"Prafful\
+        \ Sharma\",\"username\":\"hashencoder\"},{\"id\":\"1424971375882637312\",\"\
+        name\":\"okuda_dev\",\"username\":\"okuda_dev\"},{\"id\":\"1241593057394348034\"\
+        ,\"name\":\"Katie\",\"username\":\"Katie180scripty\"},{\"id\":\"2947616673\"\
+        ,\"name\":\"Lucas\",\"username\":\"lucasoppc\"},{\"id\":\"1159627369\",\"\
+        name\":\"\u3042\u3058\u3055\u3044\",\"username\":\"Hg_hatter\"},{\"id\":\"\
+        1026694159\",\"name\":\"Joe Rice\",\"username\":\"josephlrice\"},{\"id\":\"\
+        1283319060114149376\",\"name\":\"Muhammad Faiq\",\"username\":\"MFaiqSA\"\
+        },{\"id\":\"2678783982\",\"name\":\"Roopretelcham\",\"username\":\"like_keyboard\"\
+        },{\"id\":\"4926042247\",\"name\":\"Sanho Chung \u937E\u71CA\u8C6A\",\"username\"\
+        :\"sanhochung\"},{\"id\":\"351847987\",\"name\":\"punter\",\"username\":\"\
+        esiattorney\"},{\"id\":\"308771061\",\"name\":\"Fahim Hassan\",\"username\"\
+        :\"hassanfahim\"},{\"id\":\"1746216745\",\"name\":\"mirza \\uD83C\\uDF27\"\
+        ,\"username\":\"muhdmirzamz\"},{\"id\":\"292670084\",\"name\":\"Dave Carroll\"\
+        ,\"username\":\"thedavecarroll\"},{\"id\":\"1324848235714736129\",\"name\"\
+        :\"Alan Lee\",\"username\":\"alanbenlee\"},{\"id\":\"4428305440\",\"name\"\
+        :\"Andr\xE9 Verzaal\",\"username\":\"Andre3Verzaal\"},{\"id\":\"1392430706807263238\"\
+        ,\"name\":\"Raduan\",\"username\":\"Raduan63778303\"},{\"id\":\"4689073459\"\
+        ,\"name\":\"Hyeseong Kim\",\"username\":\"KrComet\"},{\"id\":\"1090139690\"\
+        ,\"name\":\"nath\xE1lia\",\"username\":\"nathaliapls\"},{\"id\":\"130175843\"\
+        ,\"name\":\"Mohi Us Sunnat\",\"username\":\"sunnat629\"},{\"id\":\"1116743997987287045\"\
+        ,\"name\":\"beaftermath\",\"username\":\"beaftermath\"},{\"id\":\"156725468\"\
+        ,\"name\":\"Gilad\",\"username\":\"giladgershoni\"},{\"id\":\"413901074\"\
+        ,\"name\":\"Uhud\",\"username\":\"dancingislands\"},{\"id\":\"4055587647\"\
+        ,\"name\":\"Nate \\uD83E\\uDD35 \\uD83C\\uDDEC\\uD83C\\uDDE7\",\"username\"\
+        :\"nathansmith7713\"},{\"id\":\"183193079\",\"name\":\"M \\uD83D\\uDC97\\\
+        uD83D\\uDC9B\\uD83D\\uDC99 \\uD83C\\uDFF3\uFE0F\u200D\\uD83C\\uDF08 BLACK\
+        \ LIVES MATTER!!!\",\"username\":\"lmaookaysure\"}],\"meta\":{\"result_count\"\
+        :62,\"next_token\":\"7140dibdnow9c7btw4803m6o8pzwynsnjtwm1p2yirqcz\"}}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '2024'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:27 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192818772161287; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:27 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192818772161287; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:27 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_jvrawVEidkBnMtjNzLNrKQ=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:27 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192818772161287; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:27 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 612a40a0ce1ea4276ef6ec878858ec6e66b63bf8bc3dc68c5821ad74f406a419
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '75'
+      x-rate-limit-remaining:
+      - '74'
+      x-rate-limit-reset:
+      - '1651929087'
+      x-response-time:
+      - '181'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/tweets/1415348607813832708/retweeted_by
+version: 1
diff --git a/cassettes/test_asyncclient_get_space.yaml b/cassettes/test_asyncclient_get_space.yaml
new file mode 100644 (file)
index 0000000..6f0e3a3
--- /dev/null
@@ -0,0 +1,62 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/spaces/1ynKOZVRyOwxR
+  response:
+    body:
+      string: '{"data":{"id":"1ynKOZVRyOwxR","state":"ended"}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '72'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 14:32:11 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165193393138988240; Max-Age=63072000; Expires=Mon,
+        06 May 2024 14:32:11 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165193393138988240; Max-Age=63072000; Expires=Mon, 06 May
+        2024 14:32:11 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_ong0ieJfSTqXkwKLt8GYuA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 14:32:11 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165193393138988240; Max-Age=63072000; Expires=Mon, 06 May 2024
+        14:32:11 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - b82ae6123b6ceb1290a00ce7d27c85a5fe0604efd57b866f7cd82e582ee75059
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '298'
+      x-rate-limit-reset:
+      - '1651934149'
+      x-response-time:
+      - '299'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/spaces/1ynKOZVRyOwxR
+version: 1
diff --git a/cassettes/test_asyncclient_get_spaces.yaml b/cassettes/test_asyncclient_get_spaces.yaml
new file mode 100644 (file)
index 0000000..bdbe4c5
--- /dev/null
@@ -0,0 +1,122 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/spaces?ids=1ynKOZVRyOwxR,1mrGmanRNNkGy
+  response:
+    body:
+      string: '{"data":[{"id":"1ynKOZVRyOwxR","state":"ended"},{"id":"1mrGmanRNNkGy","state":"scheduled"}]}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '100'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 14:51:11 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165193507132913246; Max-Age=63072000; Expires=Mon,
+        06 May 2024 14:51:11 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165193507132913246; Max-Age=63072000; Expires=Mon, 06 May
+        2024 14:51:11 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_OL+eCN/skJtUBxUFM+pSFA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 14:51:11 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165193507132913246; Max-Age=63072000; Expires=Mon, 06 May 2024
+        14:51:11 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - b8232abe0fc52e9f37bac5e72cc04d153df8d45cc8c1fdd4bca702e1fb3dcf7f
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '298'
+      x-rate-limit-reset:
+      - '1651935870'
+      x-response-time:
+      - '307'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/spaces?ids=1ynKOZVRyOwxR,1mrGmanRNNkGy
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/spaces/by/creator_ids?user_ids=357750891,1517225601463205888
+  response:
+    body:
+      string: '{"data":[{"id":"1mrGmanRNNkGy","state":"scheduled"},{"id":"1zqJVBLLyQpJB","state":"scheduled"}],"meta":{"result_count":2}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '119'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 14:51:12 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165193507178703398; Max-Age=63072000; Expires=Mon,
+        06 May 2024 14:51:12 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165193507178703398; Max-Age=63072000; Expires=Mon, 06 May
+        2024 14:51:12 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_38YAqA3DBK9l0Cu7O5XTbA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 14:51:12 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165193507178703398; Max-Age=63072000; Expires=Mon, 06 May 2024
+        14:51:12 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - de293e8206e55a37aa93bfb91c40181db1d2dc769730bb274e89c0f7333c5e2c
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '298'
+      x-rate-limit-reset:
+      - '1651935871'
+      x-response-time:
+      - '654'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/spaces/by/creator_ids?user_ids=357750891,1517225601463205888
+version: 1
diff --git a/cassettes/test_asyncclient_get_tweet.yaml b/cassettes/test_asyncclient_get_tweet.yaml
new file mode 100644 (file)
index 0000000..b56cec6
--- /dev/null
@@ -0,0 +1,66 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/tweets/1293593516040269825
+  response:
+    body:
+      string: "{\"data\":{\"id\":\"1293593516040269825\",\"text\":\"It\u2019s finally\
+        \ here! \\uD83E\\uDD41 Say hello to the new #TwitterAPI.\\n\\nWe\u2019re rebuilding\
+        \ the Twitter API v2 from the ground up to better serve our developer community.\
+        \ And today\u2019s launch is only the beginning.\\n\\nhttps://t.co/32VrwpGaJw\
+        \ https://t.co/KaFSbjWUA8\"}}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '264'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:29 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192818945389592; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:29 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192818945389592; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:29 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_CAK8JfjPoWUIu55o10qCLw=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:29 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192818945389592; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:29 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - c75ed40fbc73ae85021606923b280c404fc6afbceaa54bcdc3d5fd8cb64096b0
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '299'
+      x-rate-limit-reset:
+      - '1651929089'
+      x-response-time:
+      - '52'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/tweets/1293593516040269825
+version: 1
diff --git a/cassettes/test_asyncclient_get_tweets.yaml b/cassettes/test_asyncclient_get_tweets.yaml
new file mode 100644 (file)
index 0000000..8855697
--- /dev/null
@@ -0,0 +1,69 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/tweets?ids=1293593516040269825,1293595870563381249
+  response:
+    body:
+      string: "{\"data\":[{\"id\":\"1293593516040269825\",\"text\":\"It\u2019s finally\
+        \ here! \\uD83E\\uDD41 Say hello to the new #TwitterAPI.\\n\\nWe\u2019re rebuilding\
+        \ the Twitter API v2 from the ground up to better serve our developer community.\
+        \ And today\u2019s launch is only the beginning.\\n\\nhttps://t.co/32VrwpGaJw\
+        \ https://t.co/KaFSbjWUA8\"},{\"id\":\"1293595870563381249\",\"text\":\"Twitter\
+        \ API v2: Early Access released\\n\\nToday we announced Early Access to the\
+        \ first endpoints of the new Twitter API!\\n\\n#TwitterAPI #EarlyAccess #VersionBump\
+        \ https://t.co/g7v3aeIbtQ\"}]}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '363'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:29 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192818967416184; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:29 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192818967416184; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:29 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_lv98VGQ6jqZT+OlkHJxq0A=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:29 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192818967416184; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:29 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 40def0bceb71dd3f4552e35b0a8a983ff2fb68f4339691f7a2222d1a134c183c
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '299'
+      x-rate-limit-reset:
+      - '1651929089'
+      x-response-time:
+      - '63'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/tweets?ids=1293593516040269825,1293595870563381249
+version: 1
diff --git a/cassettes/test_asyncclient_get_user.yaml b/cassettes/test_asyncclient_get_user.yaml
new file mode 100644 (file)
index 0000000..dbbdcbc
--- /dev/null
@@ -0,0 +1,62 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/by/username/Twitter
+  response:
+    body:
+      string: '{"data":{"id":"783214","name":"Twitter","username":"Twitter"}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '73'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:29 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192818992863415; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:29 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192818992863415; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:29 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_RXqkaexfzGfAIANAUB4pyg=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:29 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192818992863415; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:29 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - cf9384a9473b99bba9e88fe100cb6677dc8a4d5acdd30f5195897eabc609683b
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '299'
+      x-rate-limit-reset:
+      - '1651929089'
+      x-response-time:
+      - '26'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/by/username/Twitter
+version: 1
diff --git a/cassettes/test_asyncclient_get_users.yaml b/cassettes/test_asyncclient_get_users.yaml
new file mode 100644 (file)
index 0000000..d161344
--- /dev/null
@@ -0,0 +1,63 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/by?usernames=Twitter,TwitterDev
+  response:
+    body:
+      string: '{"data":[{"id":"783214","name":"Twitter","username":"Twitter"},{"id":"2244994945","name":"Twitter
+        Dev","username":"TwitterDev"}]}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '99'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:30 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192819013260786; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:30 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192819013260786; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:30 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_19updJA0Ppg7AHxqbxxRrg=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:30 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192819013260786; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:30 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - bb43009521ce2245752101b8d74474db851d78c3a04a7dac4142eb8ae37f385d
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '299'
+      x-rate-limit-reset:
+      - '1651929090'
+      x-response-time:
+      - '34'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/by?usernames=Twitter,TwitterDev
+version: 1
diff --git a/cassettes/test_asyncclient_get_users_followers.yaml b/cassettes/test_asyncclient_get_users_followers.yaml
new file mode 100644 (file)
index 0000000..7e24d32
--- /dev/null
@@ -0,0 +1,156 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/783214/followers
+  response:
+    body:
+      string: "{\"data\":[{\"id\":\"1255778080372785152\",\"name\":\"DANIEL BRIGHT\"\
+        ,\"username\":\"DANIELB07927694\"},{\"id\":\"1462773540948623366\",\"name\"\
+        :\"Beluga Meow\",\"username\":\"meow_beluga\"},{\"id\":\"1522919346275766272\"\
+        ,\"name\":\"Libby\",\"username\":\"LibbyAllen82\"},{\"id\":\"1522922353583222787\"\
+        ,\"name\":\"Gojou Satoru\",\"username\":\"GojouSa25412582\"},{\"id\":\"1028780699808030721\"\
+        ,\"name\":\"Alan Li\",\"username\":\"alanyilunli\"},{\"id\":\"1522920894066266113\"\
+        ,\"name\":\"Killari Upendra\",\"username\":\"killariupendra9\"},{\"id\":\"\
+        1155297256708419584\",\"name\":\"Bryan Boza\",\"username\":\"BryanBoza3\"\
+        },{\"id\":\"1522920363801280512\",\"name\":\"Nabila\",\"username\":\"Nabila23991601\"\
+        },{\"id\":\"1522918728844906496\",\"name\":\"Sonia Tiwari\",\"username\":\"\
+        sonia21singh\"},{\"id\":\"1354917691782541320\",\"name\":\"Dawid\",\"username\"\
+        :\"Dawid77288862\"},{\"id\":\"90854461\",\"name\":\"Trevor J Harding\",\"\
+        username\":\"trevorjharding\"},{\"id\":\"1522677227070103553\",\"name\":\"\
+        Arpad Buksa\",\"username\":\"ArpadBuksa\"},{\"id\":\"1522922162201497601\"\
+        ,\"name\":\"nisha\",\"username\":\"es_shaa\"},{\"id\":\"1522917148582158337\"\
+        ,\"name\":\"vk.cos\",\"username\":\"vk_cos\"},{\"id\":\"761311855507800064\"\
+        ,\"name\":\"Denys\",\"username\":\"Denyys013\"},{\"id\":\"1522921453938745345\"\
+        ,\"name\":\"Aly Fayad\",\"username\":\"AlyFayad8\"},{\"id\":\"1522922707943317509\"\
+        ,\"name\":\"Ali Ali Uijk\",\"username\":\"AliUijk\"},{\"id\":\"1276728746943434752\"\
+        ,\"name\":\"Elizabeth\",\"username\":\"Elizabe16316426\"},{\"id\":\"1522922371069448193\"\
+        ,\"name\":\"hmada gzal\",\"username\":\"GzalHmada\"},{\"id\":\"1393093303193595908\"\
+        ,\"name\":\"ABHILASH\",\"username\":\"ABHILAS57609614\"},{\"id\":\"1522920967902744576\"\
+        ,\"name\":\"Ankit Pal Abvp\",\"username\":\"Abvp1Ankit\"},{\"id\":\"1522922578033188864\"\
+        ,\"name\":\"Ogs\",\"username\":\"Ogs81495003\"},{\"id\":\"1135628004296708097\"\
+        ,\"name\":\"Just A Green Guy\",\"username\":\"Iamtheo61257418\"},{\"id\":\"\
+        1423271671\",\"name\":\"Claudio Vallan \\uD83D\\uDC99\\uD83D\\uDC9B\",\"username\"\
+        :\"stygiansting\"},{\"id\":\"1522920362576695299\",\"name\":\"Tala\",\"username\"\
+        :\"Tala12060381\"},{\"id\":\"1445294982814863364\",\"name\":\"i love satan\
+        \ from obey me (az)\",\"username\":\"azcvqs\"},{\"id\":\"1461100404742275074\"\
+        ,\"name\":\"Ali-ElRosY\",\"username\":\"AliElRosY3\"},{\"id\":\"1522922242497290242\"\
+        ,\"name\":\"Congkang\",\"username\":\"Congkang17\"},{\"id\":\"1522913125477097473\"\
+        ,\"name\":\"Norma Edith\",\"username\":\"Momai1963\"},{\"id\":\"3013164348\"\
+        ,\"name\":\"Joe Chia\",\"username\":\"Joechiacw\"},{\"id\":\"1522691603621634053\"\
+        ,\"name\":\"Joseph\",\"username\":\"JosephAS34\"},{\"id\":\"1348543445665804288\"\
+        ,\"name\":\"Momin.\u30C4\",\"username\":\"itxMomin\"},{\"id\":\"1522921862472286209\"\
+        ,\"name\":\"Axel Ang\",\"username\":\"Bruh1919810\"},{\"id\":\"1495524662474063872\"\
+        ,\"name\":\"Tiaraseptiasya\",\"username\":\"tiaraseptiasya\"},{\"id\":\"1522919505059618816\"\
+        ,\"name\":\"Anny Maymo\",\"username\":\"AnnyMaymo\"},{\"id\":\"1522921968810565632\"\
+        ,\"name\":\"Leonid Burlacu\",\"username\":\"BurlacuLeonid\"},{\"id\":\"1522820494365499393\"\
+        ,\"name\":\"Elemi Mercy\",\"username\":\"mercy_elemi\"},{\"id\":\"1522919728284672001\"\
+        ,\"name\":\"@blessingdino90\",\"username\":\"blessingdino90\"},{\"id\":\"\
+        1448170394360299528\",\"name\":\"weijun duan\",\"username\":\"xinwoda\"},{\"\
+        id\":\"1522921257385271298\",\"name\":\"Juuf Toumany\",\"username\":\"JToumany\"\
+        },{\"id\":\"235963742\",\"name\":\"Leoberto Baggio Caon\",\"username\":\"\
+        leobertocaon\"},{\"id\":\"1442541074136780802\",\"name\":\"Julio\",\"username\"\
+        :\"Julio23982268\"},{\"id\":\"1522922067456319488\",\"name\":\"_d_r_a_c_o_s_h_a\
+        \ _\",\"username\":\"d_r_a_c_o_s_h_a\"},{\"id\":\"1521855897416388610\",\"\
+        name\":\"Star\",\"username\":\"Starluva06\"},{\"id\":\"1520845805850087429\"\
+        ,\"name\":\"Angel Carmona\",\"username\":\"AngelCa56855952\"},{\"id\":\"1522915184741953536\"\
+        ,\"name\":\"Chriph Kakuru\",\"username\":\"ChriphKakuru\"},{\"id\":\"1522921056461373441\"\
+        ,\"name\":\"Osman\",\"username\":\"Osman93264189\"},{\"id\":\"2999630648\"\
+        ,\"name\":\"Binod pyakurel\",\"username\":\"Iverson_binod\"},{\"id\":\"1522921227303759872\"\
+        ,\"name\":\"Wasay Waien\",\"username\":\"wasaywaien48\"},{\"id\":\"1522921603956363266\"\
+        ,\"name\":\"MusicCrazy\",\"username\":\"zhaoarchineer\"},{\"id\":\"1522921399664398338\"\
+        ,\"name\":\"Jun Gao\",\"username\":\"FenLanQinMo\"},{\"id\":\"1409673021762244608\"\
+        ,\"name\":\"BORO Issouf\",\"username\":\"BOROIssouf8\"},{\"id\":\"1520606381170114561\"\
+        ,\"name\":\"Tina Mason Johnson\",\"username\":\"Christi80278288\"},{\"id\"\
+        :\"1522921743253393409\",\"name\":\"Wizzy1122\",\"username\":\"Wizzy11221\"\
+        },{\"id\":\"1507837142214529028\",\"name\":\"Danny\",\"username\":\"Danny_571\"\
+        },{\"id\":\"1522915591841107968\",\"name\":\"Ben Richards\",\"username\":\"\
+        BenRich45548044\"},{\"id\":\"1522912713156014082\",\"name\":\"United Blood\"\
+        ,\"username\":\"unitedbloo\"},{\"id\":\"1522919923894427649\",\"name\":\"\
+        Achraf Akhatas\",\"username\":\"akhatas_achraf\"},{\"id\":\"1271534344377708548\"\
+        ,\"name\":\"\u0124\xEBm\u0101\",\"username\":\"m71819277\"},{\"id\":\"1522921799754911744\"\
+        ,\"name\":\"BetterrPakistan\",\"username\":\"BetterrPakistan\"},{\"id\":\"\
+        1522920226517659652\",\"name\":\"Natalie Emily Gianna\",\"username\":\"Natalieemily001\"\
+        },{\"id\":\"1476295714623918091\",\"name\":\"Betty\",\"username\":\"SlickBitchBetty\"\
+        },{\"id\":\"1520958299356684294\",\"name\":\"Mouhamed Wagne\",\"username\"\
+        :\"MouhamedWagne1\"},{\"id\":\"1088434602207776768\",\"name\":\"Altamash347\"\
+        ,\"username\":\"Altamash347\"},{\"id\":\"1390256063258181634\",\"name\":\"\
+        yanyuming\",\"username\":\"yanyuming_cn\"},{\"id\":\"1522919561938579457\"\
+        ,\"name\":\"Erica Katembo\",\"username\":\"erica_katembo\"},{\"id\":\"1522921812857917450\"\
+        ,\"name\":\"Loludontknowme\",\"username\":\"Loludontknowme6\"},{\"id\":\"\
+        1517029138867142657\",\"name\":\"Jake\",\"username\":\"Jakechels\"},{\"id\"\
+        :\"1418965160467763212\",\"name\":\"yyi\",\"username\":\"lily_rzy\"},{\"id\"\
+        :\"1522920389004910592\",\"name\":\"Kareman Hassan\",\"username\":\"KaremanHassan42\"\
+        },{\"id\":\"1521935402143166464\",\"name\":\"Sukis Manto\",\"username\":\"\
+        SukisMa19829531\"},{\"id\":\"1519564080243044352\",\"name\":\"Rishikumar Ray\"\
+        ,\"username\":\"ray_rishikumar\"},{\"id\":\"1522920015535742976\",\"name\"\
+        :\"theagstno\",\"username\":\"theagstno\"},{\"id\":\"1522920221560000512\"\
+        ,\"name\":\"Novair Samir\",\"username\":\"Noversamir2007\"},{\"id\":\"1522921262770753536\"\
+        ,\"name\":\"\u0627\u062D\u0645\u062F \u0633\u0644\u0627\u0645\",\"username\"\
+        :\"ahmdsla01729946\"},{\"id\":\"2681003001\",\"name\":\"Ahmed Ezzat\",\"username\"\
+        :\"ElZoooZ62768\"},{\"id\":\"1522915939767005188\",\"name\":\"aung nhkum10\"\
+        ,\"username\":\"nhkum10\"},{\"id\":\"1522920468147286017\",\"name\":\"Noor\
+        \ Eldin\",\"username\":\"NoorEld12997723\"},{\"id\":\"1462018688572395526\"\
+        ,\"name\":\"Francis Agyare-Bray\",\"username\":\"BrayAgyare\"},{\"id\":\"\
+        858986300551999488\",\"name\":\"Luna Rufi\",\"username\":\"luna_rufi\"},{\"\
+        id\":\"1100797048624898048\",\"name\":\"\u305F\u307E\u3054\u3063\u3061\u3087\
+        25\uFF20\u304F\u3059\u3050\u308Atickle (tamagotcho25)\",\"username\":\"t7nGi9BKhz9ooZY\"\
+        },{\"id\":\"1522916374879821829\",\"name\":\"BrickZhuan\",\"username\":\"\
+        BrickZhuan\"},{\"id\":\"1522657574948163585\",\"name\":\"Just.saying\",\"\
+        username\":\"Justsaying2025\"},{\"id\":\"1522920651132178434\",\"name\":\"\
+        JORD@N_73\",\"username\":\"JORDN7333\"}],\"meta\":{\"result_count\":84,\"\
+        next_token\":\"KFQ7D80IT44HGZZZ\"}}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '2569'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:30 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192819034759943; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:30 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192819034759943; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:30 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_1P4Y12gUU/iXYaWo+m/8ZA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:30 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192819034759943; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:30 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 97b059f27063de82ee117dd6228b1116e8c24f2203384d54bdb02af733b9977c
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '15'
+      x-rate-limit-remaining:
+      - '14'
+      x-rate-limit-reset:
+      - '1651929090'
+      x-response-time:
+      - '145'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/783214/followers
+version: 1
diff --git a/cassettes/test_asyncclient_get_users_following.yaml b/cassettes/test_asyncclient_get_users_following.yaml
new file mode 100644 (file)
index 0000000..cdea4e2
--- /dev/null
@@ -0,0 +1,174 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/2244994945/following
+  response:
+    body:
+      string: "{\"data\":[{\"id\":\"44196397\",\"name\":\"Elon Musk\",\"username\"\
+        :\"elonmusk\"},{\"id\":\"633050374\",\"name\":\"Aba Micah\",\"username\":\"\
+        2006legend\"},{\"id\":\"15772978\",\"name\":\"Jessica Garson\",\"username\"\
+        :\"jessicagarson\"},{\"id\":\"4839528448\",\"name\":\"Bitcoin Core Project\"\
+        ,\"username\":\"bitcoincoreorg\"},{\"id\":\"25029451\",\"name\":\"Elon Musk\
+        \ has cop energy\",\"username\":\"Punkaboo\"},{\"id\":\"1009484430250053632\"\
+        ,\"name\":\"cora\",\"username\":\"coraF256\"},{\"id\":\"108209516\",\"name\"\
+        :\"Amir Shevat\",\"username\":\"ashevat\"},{\"id\":\"1062359582\",\"name\"\
+        :\"Sheryl Klein Lavi\\uD83C\\uDFF4\\uDB40\\uDC67\\uDB40\\uDC62\\uDB40\\uDC73\\\
+        uDB40\\uDC63\\uDB40\\uDC74\\uDB40\\uDC7F\",\"username\":\"TheSherylKlein\"\
+        },{\"id\":\"243665363\",\"name\":\"Liliana Aid\xE9 Monge\",\"username\":\"\
+        mongeliliana\"},{\"id\":\"459860328\",\"name\":\"julie\u2728\",\"username\"\
+        :\"JulieMendoza206\"},{\"id\":\"273830767\",\"name\":\"\uEA00 \\uD83C\\uDD3F\\\
+        uD83C\\uDD44\\uD83C\\uDD42\\uD83C\\uDD37 \uEA00\",\"username\":\"rahul_pushkarna\"\
+        },{\"id\":\"2240152338\",\"name\":\"Max\",\"username\":\"maxfwinter\"},{\"\
+        id\":\"1191670412033196032\",\"name\":\"jason comer\",\"username\":\"jason_in_japan\"\
+        },{\"id\":\"2638518929\",\"name\":\"Jen Powers\",\"username\":\"jenkpowers\"\
+        },{\"id\":\"3007236186\",\"name\":\"Si\",\"username\":\"Si_ximujin\"},{\"\
+        id\":\"838824636158627840\",\"name\":\"mimi\",\"username\":\"FindingMeeemo\"\
+        },{\"id\":\"2997635012\",\"name\":\"Jared Podnos \\uD83D\\uDC33\",\"username\"\
+        :\"jpodnos\"},{\"id\":\"1596449330\",\"name\":\"Michael Horan\",\"username\"\
+        :\"HoranMikeS\"},{\"id\":\"22178537\",\"name\":\"Eric Martin \\uD83D\\uDC4D\\\
+        uD83C\\uDFFC\",\"username\":\"ericmartinyc\"},{\"id\":\"853388192\",\"name\"\
+        :\"Haim Vaturi\",\"username\":\"haimvat\"},{\"id\":\"13130832\",\"name\":\"\
+        Brian Kahrs\",\"username\":\"briankahrs\"},{\"id\":\"49936717\",\"name\":\"\
+        Vince K. Sam \\uD83D\\uDCBB\",\"username\":\"vincethecoder\"},{\"id\":\"1171940098687950848\"\
+        ,\"name\":\"#PartnerCup \u26F3\\uD83C\\uDFCC\uFE0F\u200D\u2640\uFE0F\\uD83C\\\
+        uDFCC\uFE0F\u200D\u2642\uFE0F\",\"username\":\"HackerScorer\"},{\"id\":\"\
+        137535997\",\"name\":\"sunscreenpapi\",\"username\":\"sunscreenpapi\"},{\"\
+        id\":\"15824980\",\"name\":\"Khalil Hammami\",\"username\":\"khammami\"},{\"\
+        id\":\"61467706\",\"name\":\"miss mixtape\",\"username\":\"miss_mixtape\"\
+        },{\"id\":\"211637915\",\"name\":\"Maria (ela, ella, she)\",\"username\":\"\
+        imaria20_\"},{\"id\":\"1484826829\",\"name\":\"Twum Jnr\",\"username\":\"\
+        twum_jnr\"},{\"id\":\"75263523\",\"name\":\"Sprinklr\",\"username\":\"Sprinklr\"\
+        },{\"id\":\"2584784815\",\"name\":\"Ryan J. Gallagher\",\"username\":\"ryanjgallag\"\
+        },{\"id\":\"2990106209\",\"name\":\"John M. Spallanzani\",\"username\":\"\
+        JohnSpall247\"},{\"id\":\"2533768586\",\"name\":\"Selynna Sun\",\"username\"\
+        :\"selynnasun\"},{\"id\":\"1637021982\",\"name\":\"Raina Merchant, MD MSHP\
+        \ FAHA\",\"username\":\"RainaMerchant\"},{\"id\":\"1280128841550311424\",\"\
+        name\":\"Syas\",\"username\":\"SyasCode\"},{\"id\":\"2425259995\",\"name\"\
+        :\"Md Nahid Islam\",\"username\":\"nahidofficialbd\"},{\"id\":\"685863\",\"\
+        name\":\"Mike Zitek\",\"username\":\"mjzitek\"},{\"id\":\"952837155818176512\"\
+        ,\"name\":\"Jaime\",\"username\":\"JaimeOtraVez\"},{\"id\":\"248869046\",\"\
+        name\":\"Antoine Danois\",\"username\":\"Antoinedroid\"},{\"id\":\"104236352\"\
+        ,\"name\":\"Matthieu V\",\"username\":\"Mistermatt007\"},{\"id\":\"1615654896\"\
+        ,\"name\":\"Penn Med CDH\",\"username\":\"PennMedCDH\"},{\"id\":\"29970507\"\
+        ,\"name\":\"Royce\",\"username\":\"roycehaynes\"},{\"id\":\"1168345391135371267\"\
+        ,\"name\":\"Donna Virga\",\"username\":\"deevirga\"},{\"id\":\"124005464\"\
+        ,\"name\":\"kelly-ayo\",\"username\":\"KellyAyo\"},{\"id\":\"3921628635\"\
+        ,\"name\":\"James Loduca (he/him/\xE9l)\",\"username\":\"JamesLoduca\"},{\"\
+        id\":\"31898295\",\"name\":\"Matt Derella\",\"username\":\"Derella\"},{\"\
+        id\":\"2397965574\",\"name\":\"Rebecca\",\"username\":\"RebeccaW\"},{\"id\"\
+        :\"760738503370084352\",\"name\":\"Chels \\uD83D\\uDC85\\uD83C\\uDFFE\",\"\
+        username\":\"ChelseaHipwood\"},{\"id\":\"41204968\",\"name\":\"Andy Antos\"\
+        ,\"username\":\"andyantos\"},{\"id\":\"2276100433\",\"name\":\"Mirela Anghel\"\
+        ,\"username\":\"_mirels_\"},{\"id\":\"495741050\",\"name\":\"Arielle Schwartz\
+        \ \\uD83C\\uDF64\",\"username\":\"arisirenita\"},{\"id\":\"340611224\",\"\
+        name\":\"Mauro Piano\",\"username\":\"mauropiano\"},{\"id\":\"16981198\",\"\
+        name\":\"A Knee\",\"username\":\"anniehanannie\"},{\"id\":\"32416361\",\"\
+        name\":\"Matt \\uD83E\\uDD95\",\"username\":\"mattjbones\"},{\"id\":\"379455191\"\
+        ,\"name\":\"albertico\u2728\",\"username\":\"artxbel\"},{\"id\":\"6453472\"\
+        ,\"name\":\"Farez \\uD83C\\uDFC4\\uD83C\\uDFFD\u200D\u2642\uFE0F\",\"username\"\
+        :\"farez\"},{\"id\":\"292670084\",\"name\":\"Dave Carroll\",\"username\":\"\
+        thedavecarroll\"},{\"id\":\"1700547000\",\"name\":\"Fl\xE1vio Santos \\uD83C\\\
+        uDDE7\\uD83C\\uDDF7\",\"username\":\"Sr__Half\"},{\"id\":\"3347115521\",\"\
+        name\":\"Elisabeth \\uD83C\\uDFB5\\uD83C\\uDFB6\\uD83C\\uDF0D\\uD83D\\uDD2D\\\
+        uD83C\\uDF0C\\uD83D\\uDCAB Instagram @betymaisvc2010\",\"username\":\"vice_elisabete\"\
+        },{\"id\":\"783677076951924739\",\"name\":\"Luis Francisco\",\"username\"\
+        :\"_luisf02\"},{\"id\":\"88262421\",\"name\":\"Gibby\",\"username\":\"GibbyBlogger\"\
+        },{\"id\":\"3349202854\",\"name\":\"Sanji\",\"username\":\"Sanji4579094169\"\
+        },{\"id\":\"14184976\",\"name\":\"Evan Holt\",\"username\":\"evanholt\"},{\"\
+        id\":\"160348679\",\"name\":\"Bene and the Gesserit\",\"username\":\"not_stin\"\
+        },{\"id\":\"154236280\",\"name\":\"Shagun Chopra\",\"username\":\"Chopra_Shagun\"\
+        },{\"id\":\"948097629409263616\",\"name\":\"Tian Z\",\"username\":\"tianz_zzz\"\
+        },{\"id\":\"2469856424\",\"name\":\"Bol\xE1\",\"username\":\"bolaboss\"},{\"\
+        id\":\"866879520359448577\",\"name\":\"Wooju oppa\\uD83D\\uDC7D He/Him\",\"\
+        username\":\"WoojuGG\"},{\"id\":\"490980933\",\"name\":\"tyler\",\"username\"\
+        :\"replylord\"},{\"id\":\"1140344288082944000\",\"name\":\"Lauren Pinnella\
+        \ Traylor\",\"username\":\"laur_tray\"},{\"id\":\"1181081146227970049\",\"\
+        name\":\"Amber Brown\",\"username\":\"AmberAlBrown\"},{\"id\":\"261034930\"\
+        ,\"name\":\"kiran paul\",\"username\":\"kdspaul\"},{\"id\":\"1565770556\"\
+        ,\"name\":\"TwitPane(\u3064\u3044\u3063\u3068\u307A\u30FC\u3093)\",\"username\"\
+        :\"twitpane\"},{\"id\":\"1438844202\",\"name\":\"Duraid Abdul\",\"username\"\
+        :\"duraidabdul\"},{\"id\":\"76540643\",\"name\":\"Ramiro\",\"username\":\"\
+        ramiro__nd\"},{\"id\":\"265104070\",\"name\":\"Amy Lee Bennett\",\"username\"\
+        :\"amyleebenn\"},{\"id\":\"2349201699\",\"name\":\"Niklas\",\"username\":\"\
+        NiklasBuelow\"},{\"id\":\"2776322588\",\"name\":\"Mohd Danish\",\"username\"\
+        :\"mddanishyusuf\"},{\"id\":\"712198542\",\"name\":\"Boris Holzer\",\"username\"\
+        :\"boris_holzer\"},{\"id\":\"49054165\",\"name\":\"Beno\xEEt\",\"username\"\
+        :\"benoitsan\"},{\"id\":\"3064903881\",\"name\":\"miguel \u7C73\u683C\u5C14\
+        \",\"username\":\"migueloiro\"},{\"id\":\"2894082393\",\"name\":\"ivanna\"\
+        ,\"username\":\"ivnnapna\"},{\"id\":\"19081905\",\"name\":\"Chris\",\"username\"\
+        :\"ChrisTeso\"},{\"id\":\"105224601\",\"name\":\"Joe Masilotti \\uD83D\\uDCD7\"\
+        ,\"username\":\"joemasilotti\"},{\"id\":\"2308474213\",\"name\":\"Josh W.\
+        \ Comeau\",\"username\":\"JoshWComeau\"},{\"id\":\"1090221700913029123\",\"\
+        name\":\"Matias \\uD83D\\uDFE0\",\"username\":\"matiNotFound\"},{\"id\":\"\
+        14089924\",\"name\":\"george shaheen\",\"username\":\"gshaheen\"},{\"id\"\
+        :\"2206101780\",\"name\":\"Ignacio Chiazzo\",\"username\":\"IgnacioChiazzo\"\
+        },{\"id\":\"1140621092006051840\",\"name\":\"Alvin\",\"username\":\"raia_alvin\"\
+        },{\"id\":\"252824570\",\"name\":\"Matthew Sunner\",\"username\":\"sunnermatt\"\
+        },{\"id\":\"326849698\",\"name\":\"Makenna Smutz\",\"username\":\"KenzSmutz\"\
+        },{\"id\":\"37522774\",\"name\":\"Ralph Brooks\",\"username\":\"ralphbrooks\"\
+        },{\"id\":\"277202420\",\"name\":\"Seun\",\"username\":\"seunoyebode\"},{\"\
+        id\":\"2359333566\",\"name\":\"\\uD83D\\uDD2CArv!nd Kumar\",\"username\":\"\
+        1amarvind\"},{\"id\":\"19489255\",\"name\":\"David Stockley\",\"username\"\
+        :\"WDUK\"},{\"id\":\"19536178\",\"name\":\"webmonkey\",\"username\":\"sebastianroming\"\
+        },{\"id\":\"761569626685833216\",\"name\":\"Jannik Schwade\",\"username\"\
+        :\"jannik_schwade\"},{\"id\":\"715071139\",\"name\":\"Hussain\",\"username\"\
+        :\"_7aso0on\"},{\"id\":\"839668676\",\"name\":\"\u30AA\u30FC\u30A6\u30A7\u30F3\
+        \",\"username\":\"DarylOwenJ\"},{\"id\":\"618029513\",\"name\":\"Hatice Edis\
+        \ \\uD83D\\uDCDF\",\"username\":\"edisdev\"},{\"id\":\"1934669329\",\"name\"\
+        :\"Ian Kirker\",\"username\":\"ikirker\"}],\"meta\":{\"result_count\":100,\"\
+        next_token\":\"KNBGDJ8PVCQ1EZZZ\"}}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '2869'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 22:29:26 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165196256684642210; Max-Age=63072000; Expires=Mon,
+        06 May 2024 22:29:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165196256684642210; Max-Age=63072000; Expires=Mon, 06 May
+        2024 22:29:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_b9Wz3vKgel8g4wLdPM+IKQ=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 22:29:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165196256684642210; Max-Age=63072000; Expires=Mon, 06 May 2024
+        22:29:26 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 6067f4f380bfed3e1309a6547fa1db35a0a2810828e73aa2e037055403f783fc
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '15'
+      x-rate-limit-remaining:
+      - '14'
+      x-rate-limit-reset:
+      - '1651963466'
+      x-response-time:
+      - '133'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/2244994945/following
+version: 1
diff --git a/cassettes/test_asyncclient_get_users_mentions.yaml b/cassettes/test_asyncclient_get_users_mentions.yaml
new file mode 100644 (file)
index 0000000..64cb38d
--- /dev/null
@@ -0,0 +1,74 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/783214/mentions
+  response:
+    body:
+      string: "{\"data\":[{\"id\":\"1522923263990579201\",\"text\":\"@1ruthieann @elonmusk\
+        \ Yes..! @TIME...\\noops!\\ntime will tell...\\nbut don't forget...\\njust\
+        \ a few years ago...\\nSurely @elonmusk had a reason for doing that...\\njust\
+        \ like a #reason for purchasing @Twitter... https://t.co/EI3YL89vFo\"},{\"\
+        id\":\"1522923221103820801\",\"text\":\"@dunjusol @TwitterDE @Twitter damn\
+        \ he probably dead or sum\"},{\"id\":\"1522923132910247937\",\"text\":\"Fuck\
+        \ all the way off, @Twitter @elonmusk let\u2019s us talk this way now \\uD83D\\\
+        uDE02 https://t.co/lHsF1yqq0T\"},{\"id\":\"1522923129785389056\",\"text\"\
+        :\"@Timidzn @kauisiki @elonmusk @MrBeast @Twitter I dont have friends ;-;\"\
+        },{\"id\":\"1522923125695926272\",\"text\":\"@Kiran_Kalyan_ @Twitter Thankyou\
+        \ So Much Bro\"}],\"meta\":{\"next_token\":\"7140dibdnow9c7btw421dz02trvwav4lfrb4owz7joppu\"\
+        ,\"result_count\":5,\"newest_id\":\"1522923263990579201\",\"oldest_id\":\"\
+        1522923125695926272\"}}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '528'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:30 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192819086097862; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:30 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192819086097862; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:30 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_n+OGNRpnJW6kmTKaUCoKmw=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:30 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192819086097862; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:30 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 60c3de84e9259d0057c56947127a52ca6cee51a34ba98d4a721dd00d918c71f0
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '450'
+      x-rate-limit-remaining:
+      - '449'
+      x-rate-limit-reset:
+      - '1651929090'
+      x-response-time:
+      - '131'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/783214/mentions
+version: 1
diff --git a/cassettes/test_asyncclient_get_users_tweets.yaml b/cassettes/test_asyncclient_get_users_tweets.yaml
new file mode 100644 (file)
index 0000000..6f8105a
--- /dev/null
@@ -0,0 +1,75 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/783214/tweets
+  response:
+    body:
+      string: "{\"data\":[{\"id\":\"1509951255388504066\",\"text\":\"we are working\
+        \ on an edit button\"},{\"id\":\"1509216629695168512\",\"text\":\"@McDonalds\
+        \ we ordered those 5 months ago\u2026 we want snack wraps now\"},{\"id\":\"\
+        1509209405937627143\",\"text\":\"@lwtsphh he's defrosting for the single drop\"\
+        },{\"id\":\"1509208980035457030\",\"text\":\"@jeffbcraven yay jeff\"},{\"\
+        id\":\"1509208967792238592\",\"text\":\"@BTS_Factss the bird has to Tweet\
+        \ too\"},{\"id\":\"1509208694596190213\",\"text\":\"@blackprints yeah that's\
+        \ why we had to check on you\"},{\"id\":\"1509208291246805002\",\"text\":\"\
+        @praatyy are we friends?\"},{\"id\":\"1509208278680715265\",\"text\":\"@eihsip\
+        \ hahahahahahahahahahahaha \\uD83D\\uDE2D\"},{\"id\":\"1509207786256744452\"\
+        ,\"text\":\"@lennisminuit can confirm, not a good feeling\"},{\"id\":\"1509207707307417602\"\
+        ,\"text\":\"@SPARTlNN not showing it at all!\"}],\"meta\":{\"result_count\"\
+        :10,\"newest_id\":\"1509951255388504066\",\"oldest_id\":\"1509207707307417602\"\
+        ,\"next_token\":\"7140dibdnow9c7btw420k2n6ezlpvoembdd33gb1wkp4i\"}}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '541'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:31 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192819114625522; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:31 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192819114625522; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:31 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_1hnwhgMUhO1vefnhNGXkng=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:31 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192819114625522; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:31 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 783ebc71f5281df00e6678527f0d2c4986e9c60ac059d1e4c5167bab85a50a0a
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '1500'
+      x-rate-limit-remaining:
+      - '1499'
+      x-rate-limit-reset:
+      - '1651929091'
+      x-response-time:
+      - '99'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/783214/tweets
+version: 1
diff --git a/cassettes/test_asyncclient_hide_and_unhide_reply.yaml b/cassettes/test_asyncclient_hide_and_unhide_reply.yaml
new file mode 100644 (file)
index 0000000..1d68741
--- /dev/null
@@ -0,0 +1,128 @@
+interactions:
+- request:
+    body:
+      hidden: true
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: PUT
+    uri: https://api.twitter.com/2/tweets/1344794616005066752/hidden
+  response:
+    body:
+      string: '{"data":{"hidden":true}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '50'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:10:39 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192903939632794; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:39 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192903939632794; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:10:39 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_kmnYDP87kJ6zcxCJym7GEQ=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:39 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192903939632794; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:10:39 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - 9d11623f5480991b1d0d01fb0e8b7bff083558597f7b8cd6ba3059693d1f10d4
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651929939'
+      x-response-time:
+      - '42'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/tweets/1344794616005066752/hidden
+- request:
+    body:
+      hidden: false
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: PUT
+    uri: https://api.twitter.com/2/tweets/1344794616005066752/hidden
+  response:
+    body:
+      string: '{"data":{"hidden":false}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '51'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:10:39 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192903963018545; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:39 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192903963018545; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:10:39 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_2m3jOSmB7lHBCNpiwrXI0g=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:39 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192903963018545; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:10:39 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - f8c0aa04a58993ed930856cf74d11e0a0ff680c2bf4f9c8f944480cb8e093769
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '48'
+      x-rate-limit-reset:
+      - '1651929939'
+      x-response-time:
+      - '76'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/tweets/1344794616005066752/hidden
+version: 1
diff --git a/cassettes/test_asyncclient_like_and_unlike.yaml b/cassettes/test_asyncclient_like_and_unlike.yaml
new file mode 100644 (file)
index 0000000..0f506eb
--- /dev/null
@@ -0,0 +1,125 @@
+interactions:
+- request:
+    body:
+      tweet_id: '1293593516040269825'
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: POST
+    uri: https://api.twitter.com/2/users/1072250532645998596/likes
+  response:
+    body:
+      string: '{"data":{"liked":true}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '49'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:56 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965623613478; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965623613478; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_WtYqk+AmDk5GSykgPrb8OA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965623613478; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - e718f4e08192982a8cafe45a2707a63b59752998fd68985a1075ecf351392c6e
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651930556'
+      x-response-time:
+      - '63'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/likes
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: DELETE
+    uri: https://api.twitter.com/2/users/1072250532645998596/likes/1293593516040269825
+  response:
+    body:
+      string: '{"data":{"liked":false}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '50'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:56 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965643125936; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965643125936; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_fMAdrJT+SvcjqQE1vP5KEA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965643125936; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - a69bda724ace225c197b1844c6efbd086238ac17ca5b713c73692638a1e11398
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651930556'
+      x-response-time:
+      - '32'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/likes/1293593516040269825
+version: 1
diff --git a/cassettes/test_asyncclient_manage_and_get_pinned_lists.yaml b/cassettes/test_asyncclient_manage_and_get_pinned_lists.yaml
new file mode 100644 (file)
index 0000000..a72aead
--- /dev/null
@@ -0,0 +1,497 @@
+interactions:
+- request:
+    body:
+      name: Test List
+      private: true
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: POST
+    uri: https://api.twitter.com/2/lists
+  response:
+    body:
+      string: '{"data":{"id":"1522926890658549760","name":"Test List"}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '81'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:10:40 UTC
+      location:
+      - https://api.twitter.com/2/lists/1522926890658549760
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192903997590235; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192903997590235; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_wGQelggKLvhGKpx71l+GLw=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192903997590235; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - 53865f42f71347c3fd774633286f3e8452e23961a02b88c1a9c5129d3fc45441
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '299'
+      x-rate-limit-reset:
+      - '1651929939'
+      x-response-time:
+      - '101'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 201
+      message: Created
+    url: https://api.twitter.com/2/lists
+- request:
+    body:
+      user_id: '783214'
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: POST
+    uri: https://api.twitter.com/2/lists/1522926890658549760/members
+  response:
+    body:
+      string: '{"data":{"is_member":true}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '53'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:10:40 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192904020718624; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192904020718624; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_FVgGDs4hscYe5v///bsxow=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192904020718624; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - 1d3f65cd2901f5b0a7230c2f2995f146237dfab202ebe2ebb96e5daeccf2a99c
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '299'
+      x-rate-limit-reset:
+      - '1651929940'
+      x-response-time:
+      - '150'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/lists/1522926890658549760/members
+- request:
+    body:
+      list_id: '1522926890658549760'
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: POST
+    uri: https://api.twitter.com/2/users/1072250532645998596/pinned_lists
+  response:
+    body:
+      string: '{"data":{"pinned":true}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '50'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:10:40 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192904050810303; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192904050810303; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_0QnGzt+/CIAC8SIFVTFOMg=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192904050810303; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - 222f71e9909a89b92fb23801fa0db3e631fced257e27641d376ec54fc488bd71
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651929940'
+      x-response-time:
+      - '45'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/pinned_lists
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/1072250532645998596/pinned_lists
+  response:
+    body:
+      string: '{"data":[{"id":"1522926890658549760","name":"Test List"}],"meta":{"result_count":1}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '107'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:10:40 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192904067434012; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192904067434012; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_9siUsfrjgrcOrORghEukcg=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192904067434012; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - 0a6b9bdcf24f2b3f7ee5d0986e2acc3c31a84c3825dcc2d2f58d38205f229d1f
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '15'
+      x-rate-limit-remaining:
+      - '14'
+      x-rate-limit-reset:
+      - '1651929940'
+      x-response-time:
+      - '38'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/pinned_lists
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: DELETE
+    uri: https://api.twitter.com/2/lists/1522926890658549760/members/783214
+  response:
+    body:
+      string: '{"data":{"is_member":false}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '54'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:10:40 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192904085863539; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192904085863539; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_4KaIQ2znfjUeF1ViaNkjPg=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192904085863539; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:10:40 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - 1dac578113411b466c871dc467844c997cc65b99ab4ab74c7be6902648b7c454
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '299'
+      x-rate-limit-reset:
+      - '1651929940'
+      x-response-time:
+      - '53'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/lists/1522926890658549760/members/783214
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: DELETE
+    uri: https://api.twitter.com/2/users/1072250532645998596/pinned_lists/1522926890658549760
+  response:
+    body:
+      string: '{"data":{"pinned":false}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '51'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:10:41 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192904103640091; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:41 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192904103640091; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:10:41 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_vYq+OfCqs9TxuKJ4B8ZxTg=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:41 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192904103640091; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:10:41 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - a5c50aad0fc0267172267a0d932147e89f95f3d4494e8334e195243bb552a13c
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651929941'
+      x-response-time:
+      - '41'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/pinned_lists/1522926890658549760
+- request:
+    body:
+      description: Test List Description
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: PUT
+    uri: https://api.twitter.com/2/lists/1522926890658549760
+  response:
+    body:
+      string: '{"data":{"updated":true}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '50'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:10:41 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192904121292350; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:41 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192904121292350; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:10:41 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_ea7Gw0RaDt14sj7o0kQekQ=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:41 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192904121292350; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:10:41 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - 195580370cb6f783bbf235e681f14e7534ad8d426f274aa4b0997eb52265e8d5
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '299'
+      x-rate-limit-reset:
+      - '1651929941'
+      x-response-time:
+      - '139'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/lists/1522926890658549760
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: DELETE
+    uri: https://api.twitter.com/2/lists/1522926890658549760
+  response:
+    body:
+      string: '{"data":{"deleted":true}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '51'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:10:41 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192904146699471; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:41 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192904146699471; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:10:41 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_7PSAIgEvhgWfky6oM/5z/Q=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:10:41 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192904146699471; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:10:41 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - ff6e6177df4770204ceecf5bda01e24eec552dbf282e125e1465613193ccb59b
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '299'
+      x-rate-limit-reset:
+      - '1651929941'
+      x-response-time:
+      - '41'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/lists/1522926890658549760
+version: 1
diff --git a/cassettes/test_asyncclient_mute_get_muted_and_unmute.yaml b/cassettes/test_asyncclient_mute_get_muted_and_unmute.yaml
new file mode 100644 (file)
index 0000000..39361ec
--- /dev/null
@@ -0,0 +1,185 @@
+interactions:
+- request:
+    body:
+      target_user_id: '17874544'
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: POST
+    uri: https://api.twitter.com/2/users/1072250532645998596/muting
+  response:
+    body:
+      string: '{"data":{"muting":true}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '50'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:56 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965673856333; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965673856333; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_KG7qTFbgHFzw7AZ3/pzqdw=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965673856333; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - 7c86d8516e17431b9960fb51f31cb456c0a4dc499a8ec41fd6ae417a306fa8a6
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651930556'
+      x-response-time:
+      - '36'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/muting
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/users/1072250532645998596/muting
+  response:
+    body:
+      string: '{"data":[{"id":"17874544","name":"Twitter Support","username":"TwitterSupport"}],"meta":{"result_count":1}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '111'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:56 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965693827462; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965693827462; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_HkJhfMa0A7fx5CntBa2aVA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965693827462; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:56 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - e2957ee144af1a445358aa23816bf4ab6abd72c27a797df690e629e7c7f95d4c
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '15'
+      x-rate-limit-remaining:
+      - '14'
+      x-rate-limit-reset:
+      - '1651930556'
+      x-response-time:
+      - '56'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/muting
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: DELETE
+    uri: https://api.twitter.com/2/users/1072250532645998596/muting/17874544
+  response:
+    body:
+      string: '{"data":{"muting":false}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '51'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:57 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965713821650; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:57 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965713821650; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:57 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_DcKz4N8ILiHBiRyf6aoWTA=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:57 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965713821650; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:57 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - 30b1698cfa84b10629bbeb3cafe829efdca4b05bbaf67d6fcc7dc47b8edf989f
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651930557'
+      x-response-time:
+      - '40'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/muting/17874544
+version: 1
diff --git a/cassettes/test_asyncclient_retweet_and_unretweet.yaml b/cassettes/test_asyncclient_retweet_and_unretweet.yaml
new file mode 100644 (file)
index 0000000..83bf87e
--- /dev/null
@@ -0,0 +1,125 @@
+interactions:
+- request:
+    body:
+      tweet_id: '1415348607813832708'
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: POST
+    uri: https://api.twitter.com/2/users/1072250532645998596/retweets
+  response:
+    body:
+      string: '{"data":{"retweeted":true}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '53'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:57 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965735409439; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:57 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965735409439; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:57 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_JFX3PbdQgVt4tByh1LWNJQ=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:57 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965735409439; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:57 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - a8b01f0ab3544328655dd84b38094f971f21f0aee0c26a0a66163a5a46e62970
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651930557'
+      x-response-time:
+      - '93'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/retweets
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: DELETE
+    uri: https://api.twitter.com/2/users/1072250532645998596/retweets/1415348607813832708
+  response:
+    body:
+      string: '{"data":{"retweeted":false}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '54'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:20:57 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192965776573083; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:57 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192965776573083; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:20:57 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_GT6t/b0tcc/6y0UDdF5Owg=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:20:57 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192965776573083; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:20:57 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read-write-directmessages
+      x-connection-hash:
+      - f9d2c9e8004bdd0153199bebefab5dcca60e9cd88652f8829747c8d032489da0
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '50'
+      x-rate-limit-remaining:
+      - '49'
+      x-rate-limit-reset:
+      - '1651930557'
+      x-response-time:
+      - '65'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/users/1072250532645998596/retweets/1415348607813832708
+version: 1
diff --git a/cassettes/test_asyncclient_search_all_tweets.yaml b/cassettes/test_asyncclient_search_all_tweets.yaml
new file mode 100644 (file)
index 0000000..11fed99
--- /dev/null
@@ -0,0 +1,69 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/tweets/search/all?query=Tweepy
+  response:
+    body:
+      string: '{"data":[{"id":"1522929868509437952","text":"2022-05-07 13:22:29.902422
+        tweepy"},{"id":"1522929365373579264","text":"2022-05-07 13:20:29.902484 tweepy"},{"id":"1522928861910028289","text":"2022-05-07
+        13:18:29.902580 tweepy"},{"id":"1522928358576820225","text":"2022-05-07 13:16:29.902426
+        tweepy"},{"id":"1522927855256096768","text":"2022-05-07 13:14:29.902355 tweepy"},{"id":"1522927351952289799","text":"2022-05-07
+        13:12:29.902680 tweepy"},{"id":"1522926848660975618","text":"2022-05-07 13:10:29.902925
+        tweepy"},{"id":"1522926345306660864","text":"2022-05-07 13:08:29.902352 tweepy"},{"id":"1522925842040602626","text":"2022-05-07
+        13:06:29.905305 tweepy"},{"id":"1522925338669596675","text":"2022-05-07 13:04:29.902253
+        tweepy"}],"meta":{"newest_id":"1522929868509437952","oldest_id":"1522925338669596675","result_count":10,"next_token":"b26v89c19zqg8o3fpywln8q05w1r0v8k2muddlynw2rul"}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '325'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 13:23:58 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192983819611364; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:23:58 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192983819611364; Max-Age=63072000; Expires=Mon, 06 May
+        2024 13:23:58 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_CAD+nBJqeYigK+oQRrzVog=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 13:23:58 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192983819611364; Max-Age=63072000; Expires=Mon, 06 May 2024
+        13:23:58 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 2035902175090892923bb3bdcd2d2ce4009f0e1f4dc1a83bdffdaa524e5e2eb8
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '299'
+      x-rate-limit-reset:
+      - '1651930738'
+      x-response-time:
+      - '76'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/tweets/search/all?query=Tweepy
+version: 1
diff --git a/cassettes/test_asyncclient_search_recent_tweets.yaml b/cassettes/test_asyncclient_search_recent_tweets.yaml
new file mode 100644 (file)
index 0000000..7e1551c
--- /dev/null
@@ -0,0 +1,77 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/tweets/search/recent?query=Tweepy
+  response:
+    body:
+      string: "{\"data\":[{\"id\":\"1522922822112358400\",\"text\":\"2022-05-07 12:54:29.902322\
+        \ tweepy\"},{\"id\":\"1522922318758137858\",\"text\":\"2022-05-07 12:52:29.902272\
+        \ tweepy\"},{\"id\":\"1522921815437418498\",\"text\":\"2022-05-07 12:50:29.902263\
+        \ tweepy\"},{\"id\":\"1522921723120734208\",\"text\":\"RT @iamukasa: Coolest\
+        \ two talks I've sat in today , an IBM package to find deviations in your\
+        \ dataset with fairness implications by @tanya_\u2026\"},{\"id\":\"1522921312125132800\"\
+        ,\"text\":\"2022-05-07 12:48:29.902318 tweepy\"},{\"id\":\"1522920929042571264\"\
+        ,\"text\":\"RT @iamukasa: Coolest two talks I've sat in today , an IBM package\
+        \ to find deviations in your dataset with fairness implications by @tanya_\u2026\
+        \"},{\"id\":\"1522920808804405253\",\"text\":\"2022-05-07 12:46:29.902321\
+        \ tweepy\"},{\"id\":\"1522920305525669890\",\"text\":\"2022-05-07 12:44:29.902362\
+        \ tweepy\"},{\"id\":\"1522919802196664321\",\"text\":\"2022-05-07 12:42:29.902274\
+        \ tweepy\"},{\"id\":\"1522919298876030977\",\"text\":\"2022-05-07 12:40:29.902508\
+        \ tweepy\"}],\"meta\":{\"newest_id\":\"1522922822112358400\",\"oldest_id\"\
+        :\"1522919298876030977\",\"result_count\":10,\"next_token\":\"b26v89c19zqg8o3fpywln8ppjiyeilz63dj4j19roxqbh\"\
+        }}"
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '441'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:32 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192819189407595; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:32 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192819189407595; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:32 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_J6fOm+ReYv7nrnsoid6fIg=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:32 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192819189407595; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:32 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - 4d16f0105ed8b5eff1c6e9fd2acdc4df7505183b69055d6d993a54c3327e553b
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '450'
+      x-rate-limit-remaining:
+      - '449'
+      x-rate-limit-reset:
+      - '1651929091'
+      x-response-time:
+      - '120'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/tweets/search/recent?query=Tweepy
+version: 1
diff --git a/cassettes/test_asyncclient_search_spaces.yaml b/cassettes/test_asyncclient_search_spaces.yaml
new file mode 100644 (file)
index 0000000..eb26b9f
--- /dev/null
@@ -0,0 +1,62 @@
+interactions:
+- request:
+    body: null
+    headers:
+      User-Agent:
+      - Python/3.10.0 aiohttp/3.7.4.post0 Tweepy/4.9.0
+    method: GET
+    uri: https://api.twitter.com/2/spaces/search?query=Twitter
+  response:
+    body:
+      string: '{"data":[{"id":"1mrxmanYEAdxy","state":"live"},{"id":"1BdGYwoOmYZxX","state":"live"},{"id":"1OwxWzWWVkZJQ","state":"live"},{"id":"1mrGmanRNNkGy","state":"scheduled"},{"id":"1RDxlgWODbRJL","state":"scheduled"},{"id":"1jMJgeEPBzMKL","state":"scheduled"},{"id":"1LyxBoQrPyrKN","state":"scheduled"},{"id":"1vAxRkEegOZKl","state":"scheduled"},{"id":"1zqJVBLABbXJB","state":"scheduled"},{"id":"1DXGyDYaXWgKM","state":"scheduled"},{"id":"1yNGaYXkDkdGj","state":"scheduled"},{"id":"1ZkJzbNpAzRJv","state":"scheduled"},{"id":"1YqKDqQOblLGV","state":"scheduled"},{"id":"1vOGwyVAmBMxB","state":"scheduled"},{"id":"1ypJdEYmMEYxW","state":"scheduled"},{"id":"1mrGmandXoNGy","state":"scheduled"},{"id":"1mnGedoEDvRKX","state":"scheduled"},{"id":"1OwxWzWOoOmJQ","state":"scheduled"},{"id":"1YpKkZLVeaXxj","state":"scheduled"},{"id":"1LyxBoQMZVEKN","state":"scheduled"},{"id":"1djxXPnEmPzxZ","state":"scheduled"},{"id":"1OyKADQBzVMxb","state":"scheduled"},{"id":"1RDGlgWqlkdKL","state":"scheduled"},{"id":"1mnxedoYQDQJX","state":"scheduled"},{"id":"1YqGopgkavaJv","state":"scheduled"},{"id":"1yoKMWVVYwNJQ","state":"scheduled"},{"id":"1lPKqmkklNbKb","state":"scheduled"},{"id":"1ypJdEYYWdyxW","state":"scheduled"},{"id":"1nAKEYRgeDXKL","state":"scheduled"},{"id":"1vOGwyVWWpbxB","state":"scheduled"},{"id":"1LyGBoQydnzJN","state":"scheduled"},{"id":"1vOxwyVwDjqGB","state":"scheduled"},{"id":"1djGXPnLVeyGZ","state":"scheduled"},{"id":"1BRJjneXLljJw","state":"scheduled"}],"meta":{"result_count":34}}'
+    headers:
+      api-version:
+      - '2.42'
+      cache-control:
+      - no-cache, no-store, max-age=0
+      content-disposition:
+      - attachment; filename=json.json
+      content-encoding:
+      - gzip
+      content-length:
+      - '454'
+      content-type:
+      - application/json; charset=utf-8
+      date:
+      - Sat, 07 May 2022 12:56:32 UTC
+      server:
+      - tsa_b
+      set-cookie:
+      - guest_id_marketing=v1%3A165192819217825125; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:32 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id_ads=v1%3A165192819217825125; Max-Age=63072000; Expires=Mon, 06 May
+        2024 12:56:32 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - personalization_id="v1_g6r1bsoFFTqoVoJPqg4qbQ=="; Max-Age=63072000; Expires=Mon,
+        06 May 2024 12:56:32 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      - guest_id=v1%3A165192819217825125; Max-Age=63072000; Expires=Mon, 06 May 2024
+        12:56:32 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+      strict-transport-security:
+      - max-age=631138519
+      x-access-level:
+      - read
+      x-connection-hash:
+      - b46582c764b58eaba8a2c369b69ca6cbc2c93013b4ae3520552b8075f344893d
+      x-content-type-options:
+      - nosniff
+      x-frame-options:
+      - SAMEORIGIN
+      x-rate-limit-limit:
+      - '300'
+      x-rate-limit-remaining:
+      - '298'
+      x-rate-limit-reset:
+      - '1651928741'
+      x-response-time:
+      - '399'
+      x-xss-protection:
+      - '0'
+    status:
+      code: 200
+      message: OK
+    url: https://api.twitter.com/2/spaces/search?query=Twitter
+version: 1
diff --git a/docs/asyncclient.rst b/docs/asyncclient.rst
new file mode 100644 (file)
index 0000000..efd139c
--- /dev/null
@@ -0,0 +1,493 @@
+.. _asyncclient_reference:
+
+.. currentmodule:: tweepy.asynchronous
+
+********************
+:class:`AsyncClient`
+********************
+
+.. autoclass:: AsyncClient
+
+.. table::
+    :align: center
+
+    +--------------------------------------------------------------+---------------------------------------------+
+    | Twitter API v2 Endpoint                                      | :class:`AsyncClient` Method                 |
+    +==============================================================+=============================================+
+    | .. centered:: :ref:`Tweets`                                                                                |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Bookmarks|_                                                                                 |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `DELETE /2/users/:id/bookmarks/:tweet_id`_                   | :meth:`AsyncClient.remove_bookmark`         |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/:id/bookmarks`_                                | :meth:`AsyncClient.get_bookmarks`           |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `POST /2/users/:id/bookmarks`_                               | :meth:`AsyncClient.bookmark`                |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Hide replies|_                                                                              |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `PUT /2/tweets/:id/hidden`_                                  | :meth:`AsyncClient.hide_reply`              |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `PUT /2/tweets/:id/hidden`_                                  | :meth:`AsyncClient.unhide_reply`            |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Likes|_                                                                                     |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `DELETE /2/users/:id/likes/:tweet_id`_                       | :meth:`AsyncClient.unlike`                  |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/tweets/:id/liking_users`_                            | :meth:`AsyncClient.get_liking_users`        |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/:id/liked_tweets`_                             | :meth:`AsyncClient.get_liked_tweets`        |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `POST /2/users/:id/likes`_                                   | :meth:`AsyncClient.like`                    |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Manage Tweets|_                                                                             |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `DELETE /2/tweets/:id`_                                      | :meth:`AsyncClient.delete_tweet`            |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `POST /2/tweets`_                                            | :meth:`AsyncClient.create_tweet`            |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Quote Tweets|_                                                                              |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/tweets/:id/quote_tweets`_                            | :meth:`AsyncClient.get_quote_tweets`        |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Retweets|_                                                                                  |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `DELETE /2/users/:id/retweets/:source_tweet_id`_             | :meth:`AsyncClient.unretweet`               |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/tweets/:id/retweeted_by`_                            | :meth:`AsyncClient.get_retweeters`          |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `POST /2/users/:id/retweets`_                                | :meth:`AsyncClient.retweet`                 |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Search Tweets|_                                                                             |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/tweets/search/all`_                                  | :meth:`AsyncClient.search_all_tweets`       |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/tweets/search/recent`_                               | :meth:`AsyncClient.search_recent_tweets`    |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Timelines|_                                                                                 |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/:id/mentions`_                                 | :meth:`AsyncClient.get_users_mentions`      |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/:id/tweets`_                                   | :meth:`AsyncClient.get_users_tweets`        |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Tweet counts|_                                                                              |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/tweets/counts/all`_                                  | :meth:`AsyncClient.get_all_tweets_count`    |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/tweets/counts/recent`_                               | :meth:`AsyncClient.get_recent_tweets_count` |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Tweet lookup|_                                                                              |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/tweets/:id`_                                         | :meth:`AsyncClient.get_tweet`               |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/tweets`_                                             | :meth:`AsyncClient.get_tweets`              |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: :ref:`Users`                                                                                 |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Blocks|_                                                                                    |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `DELETE /2/users/:source_user_id/blocking/:target_user_id`_  | :meth:`AsyncClient.unblock`                 |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/:id/blocking`_                                 | :meth:`AsyncClient.get_blocked`             |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `POST /2/users/:id/blocking`_                                | :meth:`AsyncClient.block`                   |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Follows|_                                                                                   |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `DELETE /2/users/:source_user_id/following/:target_user_id`_ | :meth:`AsyncClient.unfollow_user`           |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/:id/followers`_                                | :meth:`AsyncClient.get_users_followers`     |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/:id/following`_                                | :meth:`AsyncClient.get_users_following`     |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `POST /2/users/:id/following`_                               | :meth:`AsyncClient.follow_user`             |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Mutes|_                                                                                     |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `DELETE /2/users/:source_user_id/muting/:target_user_id`_    | :meth:`AsyncClient.unmute`                  |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/:id/muting`_                                   | :meth:`AsyncClient.get_muted`               |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `POST /2/users/:id/muting`_                                  | :meth:`AsyncClient.mute`                    |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |User lookup|_                                                                               |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/:id`_                                          | :meth:`AsyncClient.get_user`                |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/by/username/:username`_                        | :meth:`AsyncClient.get_user`                |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users`_                                              | :meth:`AsyncClient.get_users`               |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/by`_                                           | :meth:`AsyncClient.get_users`               |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/me`_                                           | :meth:`AsyncClient.get_me`                  |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: :ref:`Spaces`                                                                                |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Search Spaces|_                                                                             |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/spaces/search`_                                      | :meth:`AsyncClient.search_spaces`           |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Spaces lookup|_                                                                             |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/spaces`_                                             | :meth:`AsyncClient.get_spaces`              |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/spaces/:id`_                                         | :meth:`AsyncClient.get_space`               |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/spaces/:id/buyers`_                                  | :meth:`AsyncClient.get_space_buyers`        |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/spaces/:id/tweets`_                                  | :meth:`AsyncClient.get_space_tweets`        |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/spaces/by/creator_ids`_                              | :meth:`AsyncClient.get_spaces`              |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: :ref:`Lists`                                                                                 |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |List Tweets lookup|_                                                                        |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/lists/:id/tweets`_                                   | :meth:`AsyncClient.get_list_tweets`         |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |List follows|_                                                                              |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `DELETE /2/users/:id/followed_lists/:list_id`_               | :meth:`AsyncClient.unfollow_list`           |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/lists/:id/followers`_                                | :meth:`AsyncClient.get_list_followers`      |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/:id/followed_lists`_                           | :meth:`AsyncClient.get_followed_lists`      |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `POST /2/users/:id/followed_lists`_                          | :meth:`AsyncClient.follow_list`             |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |List lookup|_                                                                               |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/lists/:id`_                                          | :meth:`AsyncClient.get_list`                |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/:id/owned_lists`_                              | :meth:`AsyncClient.get_owned_lists`         |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |List members|_                                                                              |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `DELETE /2/lists/:id/members/:user_id`_                      | :meth:`AsyncClient.remove_list_member`      |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/lists/:id/members`_                                  | :meth:`AsyncClient.get_list_members`        |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/:id/list_memberships`_                         | :meth:`AsyncClient.get_list_memberships`    |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `POST /2/lists/:id/members`_                                 | :meth:`AsyncClient.add_list_member`         |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Manage Lists|_                                                                              |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `DELETE /2/lists/:id`_                                       | :meth:`AsyncClient.delete_list`             |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `PUT /2/lists/:id`_                                          | :meth:`AsyncClient.update_list`             |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `POST /2/lists`_                                             | :meth:`AsyncClient.create_list`             |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Pinned Lists|_                                                                              |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `DELETE /2/users/:id/pinned_lists/:list_id`_                 | :meth:`AsyncClient.unpin_list`              |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/users/:id/pinned_lists`_                             | :meth:`AsyncClient.get_pinned_lists`        |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `POST /2/users/:id/pinned_lists`_                            | :meth:`AsyncClient.pin_list`                |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: :ref:`Compliance`                                                                            |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | .. centered:: |Batch Compliance|_                                                                          |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/compliance/jobs`_                                    | :meth:`AsyncClient.get_compliance_jobs`     |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `GET /2/compliance/jobs/:id`_                                | :meth:`AsyncClient.get_compliance_job`      |
+    +--------------------------------------------------------------+---------------------------------------------+
+    | `POST /2/compliance/jobs`_                                   | :meth:`AsyncClient.create_compliance_job`   |
+    +--------------------------------------------------------------+---------------------------------------------+
+
+.. |Bookmarks| replace:: *Bookmarks*
+.. _DELETE /2/users/:id/bookmarks/:tweet_id: https://developer.twitter.com/en/docs/twitter-api/tweets/bookmarks/api-reference/delete-users-id-bookmarks-tweet_id
+.. _GET /2/users/:id/bookmarks: https://developer.twitter.com/en/docs/twitter-api/tweets/bookmarks/api-reference/get-users-id-bookmarks
+.. _POST /2/users/:id/bookmarks: https://developer.twitter.com/en/docs/twitter-api/tweets/bookmarks/api-reference/post-users-id-bookmarks
+.. |Hide replies| replace:: *Hide replies*
+.. _PUT /2/tweets/:id/hidden: https://developer.twitter.com/en/docs/twitter-api/tweets/hide-replies/api-reference/put-tweets-id-hidden
+.. |Likes| replace:: *Likes*
+.. _DELETE /2/users/:id/likes/:tweet_id: https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/delete-users-id-likes-tweet_id
+.. _GET /2/tweets/:id/liking_users: https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/get-tweets-id-liking_users
+.. _GET /2/users/:id/liked_tweets: https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/get-users-id-liked_tweets
+.. _POST /2/users/:id/likes: https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/post-users-id-likes
+.. |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
+.. _POST /2/users/:id/retweets: https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/post-users-id-retweets
+.. |Search Tweets| replace:: *Search Tweets*
+.. _GET /2/tweets/search/all: https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-all
+.. _GET /2/tweets/search/recent: https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent
+.. |Timelines| replace:: *Timelines*
+.. _GET /2/users/:id/mentions: https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-mentions
+.. _GET /2/users/:id/tweets: https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets
+.. |Tweet counts| replace:: *Tweet counts*
+.. _GET /2/tweets/counts/all: https://developer.twitter.com/en/docs/twitter-api/tweets/counts/api-reference/get-tweets-counts-all
+.. _GET /2/tweets/counts/recent: https://developer.twitter.com/en/docs/twitter-api/tweets/counts/api-reference/get-tweets-counts-recent
+.. |Tweet lookup| replace:: *Tweet lookup*
+.. _GET /2/tweets/:id: https://developer.twitter.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets-id
+.. _GET /2/tweets: https://developer.twitter.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets
+.. |Blocks| replace:: *Blocks*
+.. _DELETE /2/users/:source_user_id/blocking/:target_user_id: https://developer.twitter.com/en/docs/twitter-api/users/blocks/api-reference/delete-users-user_id-blocking
+.. _GET /2/users/:id/blocking: https://developer.twitter.com/en/docs/twitter-api/users/blocks/api-reference/get-users-blocking
+.. _POST /2/users/:id/blocking: https://developer.twitter.com/en/docs/twitter-api/users/blocks/api-reference/post-users-user_id-blocking
+.. |Follows| replace:: *Follows*
+.. _DELETE /2/users/:source_user_id/following/:target_user_id: https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/delete-users-source_id-following
+.. _GET /2/users/:id/followers: https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-followers
+.. _GET /2/users/:id/following: https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-following
+.. _POST /2/users/:id/following: https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/post-users-source_user_id-following
+.. |Mutes| replace:: *Mutes*
+.. _DELETE /2/users/:source_user_id/muting/:target_user_id: https://developer.twitter.com/en/docs/twitter-api/users/mutes/api-reference/delete-users-user_id-muting
+.. _GET /2/users/:id/muting: https://developer.twitter.com/en/docs/twitter-api/users/mutes/api-reference/get-users-muting
+.. _POST /2/users/:id/muting: https://developer.twitter.com/en/docs/twitter-api/users/mutes/api-reference/post-users-user_id-muting
+.. |User lookup| replace:: *User lookup*
+.. _GET /2/users/:id: https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-id
+.. _GET /2/users/by/username/:username: https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by-username-username
+.. _GET /2/users: https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users
+.. _GET /2/users/by: https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by
+.. _GET /2/users/me: https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-me
+.. |Search Spaces| replace:: *Search Spaces*
+.. _GET /2/spaces/search: https://developer.twitter.com/en/docs/twitter-api/spaces/search/api-reference/get-spaces-search
+.. |Spaces lookup| replace:: *Spaces lookup*
+.. _GET /2/spaces: https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces
+.. _GET /2/spaces/:id: https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-id
+.. _GET /2/spaces/:id/buyers: https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-id-buyers
+.. _GET /2/spaces/:id/tweets: https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-id-tweets
+.. _GET /2/spaces/by/creator_ids: https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-by-creator-ids
+.. |List Tweets lookup| replace:: *List Tweets lookup*
+.. _GET /2/lists/:id/tweets: https://developer.twitter.com/en/docs/twitter-api/lists/list-tweets/api-reference/get-lists-id-tweets
+.. |List follows| replace:: *List follows*
+.. _DELETE /2/users/:id/followed_lists/:list_id: https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/delete-users-id-followed-lists-list_id
+.. _GET /2/lists/:id/followers: https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/get-lists-id-followers
+.. _GET /2/users/:id/followed_lists: https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/get-users-id-followed_lists
+.. _POST /2/users/:id/followed_lists: https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/post-users-id-followed-lists
+.. |List lookup| replace:: *List lookup*
+.. _GET /2/lists/:id: https://developer.twitter.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-lists-id
+.. _GET /2/users/:id/owned_lists: https://developer.twitter.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-users-id-owned_lists
+.. |List members| replace:: *List members*
+.. _DELETE /2/lists/:id/members/:user_id: https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/delete-lists-id-members-user_id
+.. _GET /2/lists/:id/members: https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/get-lists-id-members
+.. _GET /2/users/:id/list_memberships: https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/get-users-id-list_memberships
+.. _POST /2/lists/:id/members: https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/post-lists-id-members
+.. |Manage Lists| replace:: *Manage Lists*
+.. _DELETE /2/lists/:id: https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-lists-id
+.. _PUT /2/lists/:id: https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/put-lists-id
+.. _POST /2/lists: https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-lists
+.. |Pinned Lists| replace:: *Pinned Lists*
+.. _DELETE /2/users/:id/pinned_lists/:list_id: https://developer.twitter.com/en/docs/twitter-api/lists/pinned-lists/api-reference/delete-users-id-pinned-lists-list_id
+.. _GET /2/users/:id/pinned_lists: https://developer.twitter.com/en/docs/twitter-api/lists/pinned-lists/api-reference/get-users-id-pinned_lists
+.. _POST /2/users/:id/pinned_lists: https://developer.twitter.com/en/docs/twitter-api/lists/pinned-lists/api-reference/post-users-id-pinned-lists
+.. |Batch Compliance| replace:: *Batch Compliance*
+.. _GET /2/compliance/jobs: https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs
+.. _GET /2/compliance/jobs/:id: https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs-id
+.. _POST /2/compliance/jobs: https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/post-compliance-jobs
+
+Tweets
+======
+
+Bookmarks
+---------
+
+.. automethod:: AsyncClient.remove_bookmark
+
+.. automethod:: AsyncClient.get_bookmarks
+
+.. automethod:: AsyncClient.bookmark
+
+Hide replies
+------------
+
+.. automethod:: AsyncClient.hide_reply
+
+.. automethod:: AsyncClient.unhide_reply
+
+Likes
+-----
+
+.. automethod:: AsyncClient.unlike
+
+.. automethod:: AsyncClient.get_liking_users
+
+.. automethod:: AsyncClient.get_liked_tweets
+
+.. automethod:: AsyncClient.like
+
+Manage Tweets
+-------------
+
+.. automethod:: AsyncClient.delete_tweet
+
+.. automethod:: AsyncClient.create_tweet
+
+Quote Tweets
+------------
+
+.. automethod:: AsyncClient.get_quote_tweets
+
+Retweets
+--------
+
+.. automethod:: AsyncClient.unretweet
+
+.. automethod:: AsyncClient.get_retweeters
+
+.. automethod:: AsyncClient.retweet
+
+Search Tweets
+-------------
+
+.. automethod:: AsyncClient.search_all_tweets
+
+.. automethod:: AsyncClient.search_recent_tweets
+
+Timelines
+---------
+
+.. automethod:: AsyncClient.get_users_mentions
+
+.. automethod:: AsyncClient.get_users_tweets
+
+Tweet counts
+------------
+
+.. automethod:: AsyncClient.get_all_tweets_count
+
+.. automethod:: AsyncClient.get_recent_tweets_count
+
+Tweet lookup
+------------
+
+.. automethod:: AsyncClient.get_tweet
+
+.. automethod:: AsyncClient.get_tweets
+
+Users
+=====
+
+Blocks
+------
+
+.. automethod:: AsyncClient.unblock
+
+.. automethod:: AsyncClient.get_blocked
+
+.. automethod:: AsyncClient.block
+
+Follows
+-------
+
+.. automethod:: AsyncClient.unfollow_user
+
+.. automethod:: AsyncClient.get_users_followers
+
+.. automethod:: AsyncClient.get_users_following
+
+.. automethod:: AsyncClient.follow_user
+
+Mutes
+-----
+
+.. automethod:: AsyncClient.unmute
+
+.. automethod:: AsyncClient.get_muted
+
+.. automethod:: AsyncClient.mute
+
+User lookup
+-----------
+
+.. automethod:: AsyncClient.get_user
+
+.. automethod:: AsyncClient.get_users
+
+.. automethod:: AsyncClient.get_me
+
+Spaces
+======
+
+Search Spaces
+-------------
+
+.. automethod:: AsyncClient.search_spaces
+
+Spaces lookup
+-------------
+
+.. automethod:: AsyncClient.get_spaces
+
+.. automethod:: AsyncClient.get_space
+
+.. automethod:: AsyncClient.get_space_buyers
+
+.. automethod:: AsyncClient.get_space_tweets
+
+Lists
+=====
+
+List Tweets lookup
+------------------
+
+.. automethod:: AsyncClient.get_list_tweets
+
+List follows
+------------
+
+.. automethod:: AsyncClient.unfollow_list
+
+.. automethod:: AsyncClient.get_list_followers
+
+.. automethod:: AsyncClient.get_followed_lists
+
+.. automethod:: AsyncClient.follow_list
+
+List lookup
+-----------
+
+.. automethod:: AsyncClient.get_list
+
+.. automethod:: AsyncClient.get_owned_lists
+
+List members
+------------
+
+.. automethod:: AsyncClient.remove_list_member
+
+.. automethod:: AsyncClient.get_list_members
+
+.. automethod:: AsyncClient.get_list_memberships
+
+.. automethod:: AsyncClient.add_list_member
+
+Manage Lists
+------------
+
+.. automethod:: AsyncClient.delete_list
+
+.. automethod:: AsyncClient.update_list
+
+.. automethod:: AsyncClient.create_list
+
+Pinned Lists
+------------
+
+.. automethod:: AsyncClient.unpin_list
+
+.. automethod:: AsyncClient.get_pinned_lists
+
+.. automethod:: AsyncClient.pin_list
+
+Compliance
+==========
+
+Batch compliance
+----------------
+
+.. automethod:: AsyncClient.get_compliance_jobs
+
+.. automethod:: AsyncClient.get_compliance_job
+
+.. automethod:: AsyncClient.create_compliance_job
index 63cbba4abb4ba1c7e5330fe9254107c6bb748047..41465f98ff9f87fe82b56c8f04e704a507ae99d5 100644 (file)
@@ -38,6 +38,7 @@ Contents:
    client.rst
    response.rst
    streamingclient.rst
+   asyncclient.rst
    exceptions.rst
    expansions_and_fields.rst
    v2_models.rst
index 97a9b8731c05f5228de1211b87e8ff321bc03e41..13f6ab3ea1ecbb73340887271f9defe9b3398f74 100644 (file)
--- a/setup.cfg
+++ b/setup.cfg
@@ -11,4 +11,4 @@ envlist = py37, py38, py39, py310
 
 [testenv]
 commands = python -m unittest discover tests
-extras = test
+extras = async, test
index dbf324c7c56d64aea6725230be322bc10124dd41..4d7c871cd3209783f9ec1d37f776fbf36b3093ff 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -39,7 +39,10 @@ setup(
         "requests-oauthlib>=1.2.0,<2",
     ],
     extras_require={
-        "async": ["aiohttp>=3.7.3,<4"],
+        "async": [
+            "aiohttp>=3.7.3,<4",
+            "async-lru>=1.0.3,<2"
+        ],
         "dev": [
             "coverage>=4.4.2",
             "coveralls>=2.1.0",
diff --git a/tests/test_asyncclient.py b/tests/test_asyncclient.py
new file mode 100644 (file)
index 0000000..f51d695
--- /dev/null
@@ -0,0 +1,247 @@
+try:
+    from unittest import IsolatedAsyncioTestCase
+except ImportError:
+    from unittest import SkipTest
+    raise SkipTest("Skipping AsyncClient tests for Python 3.7")
+
+from config import (
+    access_token, access_token_secret, bearer_token, consumer_key,
+    consumer_secret, tape, user_id
+)
+from tweepy.asynchronous import AsyncClient
+
+
+class TweepyAsyncClientTests(IsolatedAsyncioTestCase):
+
+    def setUp(self):
+        self.client = AsyncClient(
+            bearer_token, consumer_key, consumer_secret,
+            access_token or user_id, access_token_secret
+        )
+
+    @tape.use_cassette("test_asyncclient_bookmarks.yaml")
+    async def test_bookmarks(self):
+        tweet_id = 1507070437557096461
+        # @TwitterDev Tweet announcing API v2 Bookmarks endpoints
+        await self.client.bookmark(tweet_id)
+        await self.client.get_bookmarks()
+        await self.client.remove_bookmark(tweet_id)
+
+    @tape.use_cassette("test_asyncclient_hide_and_unhide_reply.yaml")
+    async def test_hide_and_unhide_reply(self):
+        reply_id = 1344794616005066752  # Test Tweet for reply hide/unhide
+        await self.client.hide_reply(reply_id)
+        await self.client.unhide_reply(reply_id)
+
+    @tape.use_cassette("test_asyncclient_like_and_unlike.yaml")
+    async def test_like_and_unlike(self):
+        tweet_id = 1293593516040269825  # @TwitterDev Tweet announcing API v2
+        await self.client.like(tweet_id)
+        await self.client.unlike(tweet_id)
+
+    @tape.use_cassette("test_asyncclient_get_liking_users.yaml")
+    async def test_get_liking_users(self):
+        tweet_id = 1293593516040269825  # @TwitterDev Tweet announcing API v2
+        await self.client.get_liking_users(tweet_id)
+
+    @tape.use_cassette("test_asyncclient_get_liked_tweets.yaml")
+    async def test_get_liked_tweets(self):
+        user_id = 783214  # User ID for @Twitter
+        await self.client.get_liked_tweets(user_id)
+
+    @tape.use_cassette("test_asyncclient_create_and_delete_tweet.yaml")
+    async def test_create_and_delete_tweet(self):
+        response = await self.client.create_tweet(text="Test Tweet")
+        tweet_id = response.data["id"]
+        await self.client.delete_tweet(tweet_id)
+
+    @tape.use_cassette("test_asyncclient_get_quote_tweets.yaml")
+    async def test_get_quote_tweets(self):
+        tweet_id = 1293593516040269825  # @TwitterDev Tweet announcing API v2
+        await self.client.get_quote_tweets(tweet_id)
+
+    @tape.use_cassette("test_asyncclient_retweet_and_unretweet.yaml")
+    async def test_retweet_and_unretweet(self):
+        tweet_id = 1415348607813832708
+        # @TwitterDev Tweet announcing API v2 Retweet endpoints
+        await self.client.retweet(tweet_id)
+        await self.client.unretweet(tweet_id)
+
+    @tape.use_cassette("test_asyncclient_get_retweeters.yaml")
+    async def test_get_retweeters(self):
+        tweet_id = 1415348607813832708
+        # @TwitterDev Tweet announcing API v2 Retweet endpoints
+        await self.client.get_retweeters(tweet_id)
+
+    @tape.use_cassette("test_asyncclient_search_all_tweets.yaml")
+    async def test_search_all_tweets(self):
+        await self.client.search_all_tweets("Tweepy")
+
+    @tape.use_cassette("test_asyncclient_search_recent_tweets.yaml")
+    async def test_search_recent_tweets(self):
+        await self.client.search_recent_tweets("Tweepy")
+
+    @tape.use_cassette("test_asyncclient_get_users_mentions.yaml")
+    async def test_get_users_mentions(self):
+        user_id = 783214  # User ID for @Twitter
+        await self.client.get_users_mentions(user_id)
+
+    @tape.use_cassette("test_asyncclient_get_users_tweets.yaml")
+    async def test_get_users_tweets(self):
+        user_id = 783214  # User ID for @Twitter
+        await self.client.get_users_tweets(user_id)
+
+    @tape.use_cassette("test_asyncclient_get_all_tweets_count.yaml")
+    async def test_get_all_tweets_count(self):
+        await self.client.get_all_tweets_count("Tweepy")
+
+    @tape.use_cassette("test_asyncclient_get_recent_tweets_count.yaml")
+    async def test_get_recent_tweets_count(self):
+        await self.client.get_recent_tweets_count("Tweepy")
+
+    @tape.use_cassette("test_asyncclient_get_tweet.yaml")
+    async def test_get_tweet(self):
+        tweet_id = 1293593516040269825  # @TwitterDev Tweet announcing API v2
+        await self.client.get_tweet(tweet_id)
+
+    @tape.use_cassette("test_asyncclient_get_tweets.yaml")
+    async def test_get_tweets(self):
+        tweet_ids = [1293593516040269825, 1293595870563381249]
+        # @TwitterDev and @TwitterAPI Tweets announcing API v2
+        await self.client.get_tweets(tweet_ids)
+
+    @tape.use_cassette(
+        "test_asyncclient_block_and_get_blocked_and unblock.yaml"
+    )
+    async def test_block_and_get_blocked_and_unblock(self):
+        user_id = 17874544  # User ID for @TwitterSupport
+        await self.client.block(user_id)
+        await self.client.get_blocked()
+        await self.client.unblock(user_id)
+
+    @tape.use_cassette("test_asyncclient_follow_and_unfollow_user.yaml")
+    async def test_follow_and_unfollow_user(self):
+        user_id = 17874544  # User ID for @TwitterSupport
+        await self.client.follow_user(user_id)
+        await self.client.unfollow_user(user_id)
+
+    @tape.use_cassette("test_asyncclient_get_users_followers.yaml")
+    async def test_get_users_followers(self):
+        user_id = 783214  # User ID for @Twitter
+        await self.client.get_users_followers(user_id)
+
+    @tape.use_cassette("test_asyncclient_get_users_following.yaml")
+    async def test_get_users_following(self):
+        user_id = 2244994945  # User ID for @TwitterDev
+        await self.client.get_users_following(user_id)
+
+    @tape.use_cassette("test_asyncclient_mute_get_muted_and_unmute.yaml")
+    async def test_mute_get_muted_and_unmute(self):
+        user_id = 17874544  # User ID for @TwitterSupport
+        await self.client.mute(user_id)
+        await self.client.get_muted()
+        await self.client.unmute(user_id)
+
+    @tape.use_cassette("test_asyncclient_get_user.yaml")
+    async def test_get_user(self):
+        await self.client.get_user(username="Twitter")
+
+    @tape.use_cassette("test_asyncclient_get_users.yaml")
+    async def test_get_users(self):
+        await self.client.get_users(usernames=["Twitter", "TwitterDev"])
+
+    @tape.use_cassette("test_asyncclient_get_me.yaml")
+    async def test_get_me(self):
+        await self.client.get_me()
+
+    @tape.use_cassette("test_asyncclient_search_spaces.yaml")
+    async def test_search_spaces(self):
+        await self.client.search_spaces("Twitter")
+
+    @tape.use_cassette("test_asyncclient_get_spaces.yaml")
+    async def test_get_spaces(self):
+        space_ids = ["1ynKOZVRyOwxR", "1mrGmanRNNkGy"]
+        # Space ID for @TwitterSpaces Spaces community gathering + Q&A
+        # https://twitter.com/TwitterSpaces/status/1512506527025926150
+        # Space ID for @TwitterMktg Twitter Trends â€˜22: Finance Goes Social
+        # https://twitter.com/TwitterMktg/status/1522634733867487234
+        user_ids = [357750891, 1517225601463205888]
+        # User IDs for @TwitterMktg and @TwitterVoices
+        await self.client.get_spaces(ids=space_ids)
+        await self.client.get_spaces(user_ids=user_ids)
+
+    @tape.use_cassette("test_asyncclient_get_space.yaml")
+    async def test_get_space(self):
+        space_id = "1ynKOZVRyOwxR"
+        # Space ID for @TwitterSpaces Spaces community gathering + Q&A
+        # https://twitter.com/TwitterSpaces/status/1512506527025926150
+        await self.client.get_space(space_id)
+
+    # TODO: Test AsyncClient.get_space_buyers
+
+    # TODO: Test AsyncClient.get_space_tweets
+
+    @tape.use_cassette("test_asyncclient_get_list_tweets.yaml")
+    async def test_get_list_tweets(self):
+        list_id = 84839422  # List ID for Official Twitter Accounts (@Twitter)
+        await self.client.get_list_tweets(list_id)
+
+    @tape.use_cassette("test_asyncclient_follow_and_unfollow_list.yaml")
+    async def test_follow_and_unfollow_list(self):
+        list_id = 84839422  # List ID for Official Twitter Accounts (@Twitter)
+        await self.client.follow_list(list_id)
+        await self.client.unfollow_list(list_id)
+
+    @tape.use_cassette("test_asyncclient_get_list_followers.yaml")
+    async def test_get_list_followers(self):
+        list_id = 84839422  # List ID for Official Twitter Accounts (@Twitter)
+        await self.client.get_list_followers(list_id)
+
+    @tape.use_cassette("test_asyncclient_get_followed_lists.yaml")
+    async def test_get_followed_lists(self):
+        user_id = 3015271772  # User ID for @TwitterFood
+        await self.client.get_followed_lists(user_id)
+
+    @tape.use_cassette("test_asyncclient_get_list.yaml")
+    async def test_get_list(self):
+        list_id = 84839422  # List ID for Official Twitter Accounts (@Twitter)
+        await self.client.get_list(list_id)
+
+    @tape.use_cassette("test_asyncclient_get_owned_lists.yaml")
+    async def test_get_owned_lists(self):
+        user_id = 783214  # User ID for @Twitter
+        await self.client.get_owned_lists(user_id)
+
+    @tape.use_cassette("test_asyncclient_get_list_members.yaml")
+    async def test_get_list_members(self):
+        list_id = 84839422  # List ID for Official Twitter Accounts (@Twitter)
+        await self.client.get_list_members(list_id)
+
+    @tape.use_cassette("test_asyncclient_get_list_memberships.yaml")
+    async def test_get_list_memberships(self):
+        user_id = 783214  # User ID for @Twitter
+        await self.client.get_list_memberships(user_id)
+
+    @tape.use_cassette("test_asyncclient_manage_and_get_pinned_lists.yaml")
+    async def test_manage_and_get_pinned_lists(self):
+        response = await self.client.create_list("Test List", private=True)
+        list_id = response.data["id"]
+        user_id = 783214  # User ID for @Twitter
+        await self.client.add_list_member(list_id, user_id)
+        await self.client.pin_list(list_id)
+        await self.client.get_pinned_lists()
+        await self.client.remove_list_member(list_id, user_id)
+        await self.client.unpin_list(list_id)
+        await self.client.update_list(
+            list_id, description="Test List Description"
+        )
+        await self.client.delete_list(list_id)
+
+    @tape.use_cassette(
+        "test_asyncclient_create_and_get_compliance_job_and_jobs.yaml"
+    )
+    async def test_create_and_get_compliance_job_and_jobs(self):
+        response = await self.client.create_compliance_job("tweets")
+        job_id = response.data["id"]
+        await self.client.get_compliance_job(job_id)
+        await self.client.get_compliance_jobs("tweets")
index 8db8ec75080d670d32b8a40d9c44267459184beb..22c79b162d66339b36a259832baf69a28ca2ca75 100644 (file)
@@ -18,3 +18,4 @@ except ModuleNotFoundError:
     )
 
 from tweepy.asynchronous.streaming import AsyncStream
+from tweepy.asynchronous.client import AsyncClient
diff --git a/tweepy/asynchronous/client.py b/tweepy/asynchronous/client.py
new file mode 100644 (file)
index 0000000..f03883a
--- /dev/null
@@ -0,0 +1,3203 @@
+# Tweepy
+# Copyright 2009-2022 Joshua Roesslein
+# See LICENSE for details.
+
+try:
+    from functools import cache
+except ImportError:  # Remove when support for Python 3.8 is dropped
+    from functools import lru_cache
+    cache = lru_cache(maxsize=None)
+
+import asyncio
+import logging
+from platform import python_version
+import time
+
+import aiohttp
+from async_lru import alru_cache
+from oauthlib.oauth1 import Client as OAuthClient
+from yarl import URL
+
+import tweepy
+from tweepy.client import BaseClient, Response
+from tweepy.errors import (
+    BadRequest, Forbidden, HTTPException, NotFound, TooManyRequests,
+    TwitterServerError, Unauthorized
+)
+from tweepy.list import List
+from tweepy.space import Space
+from tweepy.tweet import Tweet
+from tweepy.user import User
+
+async_cache = alru_cache(maxsize=None)
+
+log = logging.getLogger(__name__)
+
+
+class AsyncBaseClient(BaseClient):
+
+    def __init__(
+        self, bearer_token=None, consumer_key=None, consumer_secret=None,
+        access_token=None, access_token_secret=None, *, return_type=Response,
+        wait_on_rate_limit=False
+    ):
+        self.bearer_token = bearer_token
+        self.consumer_key = consumer_key
+        self.consumer_secret = consumer_secret
+        self.access_token = access_token
+        self.access_token_secret = access_token_secret
+
+        self.return_type = return_type
+        self.wait_on_rate_limit = wait_on_rate_limit
+
+        self.session = None
+        self.user_agent = (
+            f"Python/{python_version()} "
+            f"aiohttp/{aiohttp.__version__} "
+            f"Tweepy/{tweepy.__version__}"
+        )
+
+    async def request(
+        self, method, route, params=None, json=None, user_auth=False
+    ):
+        session = self.session or aiohttp.ClientSession()
+        url = "https://api.twitter.com" + route
+        headers = {"User-Agent": self.user_agent}
+        if json is not None:
+            headers["Content-Type"] = "application/json"
+
+        if user_auth:
+            oauth_client = OAuthClient(
+                self.consumer_key, self.consumer_secret,
+                self.access_token, self.access_token_secret
+            )
+            url = str(URL(url).with_query(sorted(params.items())))
+            url, headers, body = oauth_client.sign(
+                url, method, headers=headers
+            )
+            params = None
+        else:
+            headers["Authorization"] = f"Bearer {self.bearer_token}"
+
+        log.debug(
+            f"Making API request: {method} {url}\n"
+            f"Parameters: {params}\n"
+            f"Headers: {headers}\n"
+            f"JSON: {json}"
+        )
+
+        async with session.request(
+            method, url, params=params, json=json, headers=headers
+        ) as response:
+            await response.read()
+
+        log.debug(
+            f"Received API response: {response.status} {response.reason}\n"
+            f"Headers: {response.headers}"
+        )
+
+        if self.session is None:
+            await session.close()
+
+        if not 200 <= response.status < 300:
+            response_json = await response.json()
+        if response.status == 400:
+            raise BadRequest(response, response_json=response_json)
+        if response.status == 401:
+            raise Unauthorized(response, response_json=response_json)
+        if response.status == 403:
+            raise Forbidden(response, response_json=response_json)
+        if response.status == 404:
+            raise NotFound(response, response_json=response_json)
+        if response.status == 429:
+            if self.wait_on_rate_limit:
+                reset_time = int(response.headers["x-rate-limit-reset"])
+                sleep_time = reset_time - int(time.time()) + 1
+                if sleep_time > 0:
+                    log.warning(
+                        "Rate limit exceeded. "
+                        f"Sleeping for {sleep_time} seconds."
+                    )
+                    await asyncio.sleep(sleep_time)
+                return self.request(method, route, params, json, user_auth)
+            else:
+                raise TooManyRequests(response, response_json=response_json)
+        if response.status >= 500:
+            raise TwitterServerError(response, response_json=response_json)
+        if not 200 <= response.status < 300:
+            raise HTTPException(response, response_json=response_json)
+
+        return response
+
+    async def _make_request(
+        self, method, route, params={}, endpoint_parameters=None, json=None,
+        data_type=None, user_auth=False
+    ):
+        request_params = self._process_params(params, endpoint_parameters)
+
+        response = await self.request(method, route, params=request_params,
+                                      json=json, user_auth=user_auth)
+
+        if self.return_type is aiohttp.ClientResponse:
+            return response
+
+        response = await response.json()
+
+        if self.return_type is dict:
+            return response
+
+        data = response.get("data")
+        data = self._process_data(data, data_type=data_type)
+
+        includes = response.get("includes", {})
+        includes = self._process_includes(includes)
+
+        errors = response.get("errors", [])
+        meta = response.get("meta", {})
+
+        return Response(data, includes, errors, meta)
+
+
+class AsyncClient(AsyncBaseClient):
+    """AsyncClient( \
+        bearer_token=None, consumer_key=None, consumer_secret=None, \
+        access_token=None, access_token_secret=None, *, return_type=Response, \
+        wait_on_rate_limit=False \
+    )
+
+    Asynchronous Twitter API v2 Client
+
+    .. versionadded:: 4.10
+
+    Parameters
+    ----------
+    bearer_token : str | None
+        Twitter API OAuth 2.0 Bearer Token / Access Token
+    consumer_key : str | None
+        Twitter API OAuth 1.0a Consumer Key
+    consumer_secret : str | None
+        Twitter API OAuth 1.0a Consumer Secret
+    access_token : str | None
+        Twitter API OAuth 1.0a Access Token
+    access_token_secret : str | None
+        Twitter API OAuth 1.0a Access Token Secret
+    return_type : type[dict | aiohttp.ClientResponse | Response]
+        Type to return from requests to the API
+    wait_on_rate_limit : bool
+        Whether to wait when rate limit is reached
+
+    Attributes
+    ----------
+    session : aiohttp.ClientSession
+        Aiohttp client session used to make requests to the API
+    user_agent : str
+        User agent used when making requests to the API
+    """
+
+    async def _get_authenticating_user_id(self, *, oauth_1=False):
+        if oauth_1:
+            if self.access_token is None:
+                raise TypeError(
+                    "Access Token must be provided for OAuth 1.0a User Context"
+                )
+            else:
+                return self._get_oauth_1_authenticating_user_id(
+                    self.access_token
+                )
+        else:
+            if self.bearer_token is None:
+                raise TypeError(
+                    "Access Token must be provided for "
+                    "OAuth 2.0 Authorization Code Flow with PKCE"
+                )
+            else:
+                return await self._get_oauth_2_authenticating_user_id(
+                    self.bearer_token
+                )
+
+    @cache
+    def _get_oauth_1_authenticating_user_id(self, access_token):
+        return access_token.partition('-')[0]
+
+    @async_cache
+    async def _get_oauth_2_authenticating_user_id(self, access_token):
+        original_access_token = self.bearer_token
+        original_return_type = self.return_type
+
+        self.bearer_token = access_token
+        self.return_type = dict
+        user_id = (await self.get_me(user_auth=False))["data"]["id"]
+
+        self.bearer_token = original_access_token
+        self.return_type = original_return_type
+
+        return user_id
+
+    # Bookmarks
+
+    async def remove_bookmark(self, tweet_id):
+        """Allows a user or authenticated user ID to remove a Bookmark of a
+        Tweet.
+
+        .. note::
+
+            A request is made beforehand to Twitter's API to determine the
+            authenticating user's ID. This is cached and only done once per
+            :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        tweet_id : int | str
+            The ID of the Tweet that you would like the ``id`` to remove a
+            Bookmark of.
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/bookmarks/api-reference/delete-users-id-bookmarks-tweet_id
+        """
+        id = await self._get_authenticating_user_id()
+        route = f"/2/users/{id}/bookmarks/{tweet_id}"
+
+        return await self._make_request(
+            "DELETE", route
+        )
+
+    async def get_bookmarks(self, **params):
+        """get_bookmarks( \
+            *, expansions=None, max_results=None, media_fields=None, \
+            pagination_token=None, place_fields=None, poll_fields=None, \
+            tweet_fields=None, user_fields=None \
+        )
+
+        Allows you to get an authenticated user's 800 most recent bookmarked
+        Tweets.
+
+        .. note::
+
+            A request is made beforehand to Twitter's API to determine the
+            authenticating user's ID. This is cached and only done once per
+            :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        max_results : int | None
+            The maximum number of results to be returned per page. This can be
+            a number between 1 and 100. By default, each page will return 100
+            results.
+        media_fields : list[str] | str | None
+            :ref:`media_fields_parameter`
+        pagination_token : str | None
+            Used to request the next page of results if all results weren't
+            returned with the latest request, or to go back to the previous
+            page of results. To return the next page, pass the ``next_token``
+            returned in your previous response. To go back one page, pass the
+            ``previous_token`` returned in your previous response.
+        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`
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/bookmarks/api-reference/get-users-id-bookmarks
+        """
+        id = await self._get_authenticating_user_id()
+        route = f"/2/users/{id}/bookmarks"
+
+        return await self._make_request(
+            "GET", route, params=params,
+            endpoint_parameters=(
+                "expansions", "max_results", "media.fields",
+                "pagination_token", "place.fields", "poll.fields",
+                "tweet.fields", "user.fields"
+            ), data_type=Tweet
+        )
+
+    async def bookmark(self, tweet_id):
+        """Causes the authenticating user to Bookmark the target Tweet provided
+        in the request body.
+
+        .. note::
+
+            A request is made beforehand to Twitter's API to determine the
+            authenticating user's ID. This is cached and only done once per
+            :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        tweet_id : int | str
+            The ID of the Tweet that you would like the user ``id`` to
+            Bookmark.
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/bookmarks/api-reference/post-users-id-bookmarks
+        """
+        id = await self._get_authenticating_user_id()
+        route = f"/2/users/{id}/bookmarks"
+
+        return await self._make_request(
+            "POST", route, json={"tweet_id": str(tweet_id)}
+        )
+
+    # Hide replies
+
+    async def hide_reply(self, id, *, user_auth=True):
+        """Hides a reply to a Tweet.
+
+        Parameters
+        ----------
+        id : int | str
+            Unique identifier of the Tweet to hide. The Tweet must belong to a
+            conversation initiated by the authenticating user.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/hide-replies/api-reference/put-tweets-id-hidden
+        """
+        return await self._make_request(
+            "PUT", f"/2/tweets/{id}/hidden", json={"hidden": True},
+            user_auth=user_auth
+        )
+
+    async def unhide_reply(self, id, *, user_auth=True):
+        """Unhides a reply to a Tweet.
+
+        Parameters
+        ----------
+        id : int | str
+            Unique identifier of the Tweet to unhide. The Tweet must belong to
+            a conversation initiated by the authenticating user.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/hide-replies/api-reference/put-tweets-id-hidden
+        """
+        return await self._make_request(
+            "PUT", f"/2/tweets/{id}/hidden", json={"hidden": False},
+            user_auth=user_auth
+        )
+
+    # Likes
+
+    async def unlike(self, tweet_id, *, user_auth=True):
+        """Unlike a Tweet.
+
+        The request succeeds with no action when the user sends a request to a
+        user they're not liking the Tweet or have already unliked the Tweet.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        tweet_id : int | str
+            The ID of the Tweet that you would like to unlike.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/delete-users-id-likes-tweet_id
+        """
+        id = await self._get_authenticating_user_id(oauth_1=user_auth)
+        route = f"/2/users/{id}/likes/{tweet_id}"
+
+        return await self._make_request(
+            "DELETE", route, user_auth=user_auth
+        )
+
+    async def get_liking_users(self, id, *, user_auth=False, **params):
+        """get_liking_users( \
+            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 \
+        )
+
+        Allows you to get information about a Tweet’s liking users.
+
+        Parameters
+        ----------
+        id : int | str
+            Tweet ID of the Tweet to request liking users of.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        max_results : int | None
+            The maximum number of results to be returned per page. This can be
+            a number between 1 and 100. By default, each page will return 100
+            results.
+        media_fields : list[str] | str | None
+            :ref:`media_fields_parameter`
+        pagination_token : str | None
+            Used to request the next page of results if all results weren't
+            returned with the latest request, or to go back to the previous
+            page of results. To return the next page, pass the ``next_token``
+            returned in your previous response. To go back one page, pass the
+            ``previous_token`` returned in your previous response.
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/get-tweets-id-liking_users
+        """
+        return await self._make_request(
+            "GET", f"/2/tweets/{id}/liking_users", params=params,
+            endpoint_parameters=(
+                "expansions", "max_results", "media.fields",
+                "pagination_token", "place.fields", "poll.fields",
+                "tweet.fields", "user.fields"
+            ), data_type=User, user_auth=user_auth
+        )
+
+    async def get_liked_tweets(self, id, *, user_auth=False, **params):
+        """get_liked_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 \
+        )
+
+        Allows you to get information about a user’s liked Tweets.
+
+        The Tweets returned by this endpoint count towards the Project-level
+        `Tweet cap`_.
+
+        Parameters
+        ----------
+        id : int | str
+            User ID of the user to request liked Tweets for.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        max_results : int | None
+            The maximum number of results to be returned per page. This can be
+            a number between 5 and 100. By default, each page will return 100
+            results.
+        media_fields : list[str] | str | None
+            :ref:`media_fields_parameter`
+        pagination_token : str | None
+            Used to request the next page of results if all results weren't
+            returned with the latest request, or to go back to the previous
+            page of results. To return the next page, pass the ``next_token``
+            returned in your previous response. To go back one page, pass the
+            ``previous_token`` returned in your previous response.
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/get-users-id-liked_tweets
+
+        .. _Tweet cap: https://developer.twitter.com/en/docs/projects/overview#tweet-cap
+        """
+        return await self._make_request(
+            "GET", f"/2/users/{id}/liked_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
+        )
+
+    async def like(self, tweet_id, *, user_auth=True):
+        """Like a Tweet.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        tweet_id : int | str
+            The ID of the Tweet that you would like to Like.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/post-users-id-likes
+        """
+        id = await self._get_authenticating_user_id(oauth_1=user_auth)
+        route = f"/2/users/{id}/likes"
+
+        return await self._make_request(
+            "POST", route, json={"tweet_id": str(tweet_id)},
+            user_auth=user_auth
+        )
+
+    # Manage Tweets
+
+    async def delete_tweet(self, id, *, user_auth=True):
+        """Allows an authenticated user ID to delete a Tweet.
+
+        Parameters
+        ----------
+        id : int | str
+            The Tweet ID you are deleting.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/delete-tweets-id
+        """
+        return await self._make_request(
+            "DELETE", f"/2/tweets/{id}", user_auth=user_auth
+        )
+
+    async def create_tweet(
+        self, *, direct_message_deep_link=None, for_super_followers_only=None,
+        place_id=None, media_ids=None, media_tagged_user_ids=None,
+        poll_duration_minutes=None, poll_options=None, quote_tweet_id=None,
+        exclude_reply_user_ids=None, in_reply_to_tweet_id=None,
+        reply_settings=None, text=None, user_auth=True
+    ):
+        """Creates a Tweet on behalf of an authenticated user.
+
+        Parameters
+        ----------
+        direct_message_deep_link : str | None
+            `Tweets a link directly to a Direct Message conversation`_ with an
+            account.
+        for_super_followers_only : bool | None
+            Allows you to Tweet exclusively for `Super Followers`_.
+        place_id : str | None
+            Place ID being attached to the Tweet for geo location.
+        media_ids : list[int | str] | None
+            A list of Media IDs being attached to the Tweet. This is only
+            required if the request includes the ``tagged_user_ids``.
+        media_tagged_user_ids : list[int | str] | None
+            A list of User IDs being tagged in the Tweet with Media. If the
+            user you're tagging doesn't have photo-tagging enabled, their names
+            won't show up in the list of tagged users even though the Tweet is
+            successfully created.
+        poll_duration_minutes : int | None
+            Duration of the poll in minutes for a Tweet with a poll. This is
+            only required if the request includes ``poll.options``.
+        poll_options : list[str] | None
+            A list of poll options for a Tweet with a poll.
+        quote_tweet_id : int | str | None
+            Link to the Tweet being quoted.
+        exclude_reply_user_ids : list[int | str] | None
+            A list of User IDs to be excluded from the reply Tweet thus
+            removing a user from a thread.
+        in_reply_to_tweet_id : int | str | None
+            Tweet ID of the Tweet being replied to. Please note that
+            ``in_reply_to_tweet_id`` needs to be in the request if
+            ``exclude_reply_user_ids`` is present.
+        reply_settings : str | None
+            `Settings`_ to indicate who can reply to the Tweet. Limited to
+            "mentionedUsers" and "following". If the field isn’t specified, it
+            will default to everyone.
+        text : str | None
+            Text of the Tweet being created. This field is required if
+            ``media.media_ids`` is not present.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets
+
+        .. _Tweets a link directly to a Direct Message conversation: https://business.twitter.com/en/help/campaign-editing-and-optimization/public-to-private-conversation.html
+        .. _Super Followers: https://help.twitter.com/en/using-twitter/super-follows
+        .. _Settings: https://blog.twitter.com/en_us/topics/product/2020/new-conversation-settings-coming-to-a-tweet-near-you
+        """
+        json = {}
+
+        if direct_message_deep_link is not None:
+            json["direct_message_deep_link"] = direct_message_deep_link
+
+        if for_super_followers_only is not None:
+            json["for_super_followers_only"] = for_super_followers_only
+
+        if place_id is not None:
+            json["geo"] = {"place_id": place_id}
+
+        if media_ids is not None:
+            json["media"] = {
+                "media_ids": [str(media_id) for media_id in media_ids]
+            }
+            if media_tagged_user_ids is not None:
+                json["media"]["tagged_user_ids"] = [
+                    str(media_tagged_user_id)
+                    for media_tagged_user_id in media_tagged_user_ids
+                ]
+
+        if poll_options is not None:
+            json["poll"] = {"options": poll_options}
+            if poll_duration_minutes is not None:
+                json["poll"]["duration_minutes"] = poll_duration_minutes
+
+        if quote_tweet_id is not None:
+            json["quote_tweet_id"] = str(quote_tweet_id)
+
+        if in_reply_to_tweet_id is not None:
+            json["reply"] = {"in_reply_to_tweet_id": str(in_reply_to_tweet_id)}
+            if exclude_reply_user_ids is not None:
+                json["reply"]["exclude_reply_user_ids"] = [
+                    str(exclude_reply_user_id)
+                    for exclude_reply_user_id in exclude_reply_user_ids
+                ]
+
+        if reply_settings is not None:
+            json["reply_settings"] = reply_settings
+
+        if text is not None:
+            json["text"] = text
+
+        return await self._make_request(
+            "POST", f"/2/tweets", json=json, user_auth=user_auth
+        )
+
+    # Quote Tweets
+
+    async 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`_.
+
+        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 | aiohttp.ClientResponse | 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 await 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
+
+    async def unretweet(self, source_tweet_id, *, user_auth=True):
+        """Allows an authenticated user ID to remove the Retweet of a Tweet.
+
+        The request succeeds with no action when the user sends a request to a
+        user they're not Retweeting the Tweet or have already removed the
+        Retweet of.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        source_tweet_id : int | str
+            The ID of the Tweet that you would like to remove the Retweet of.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/delete-users-id-retweets-tweet_id
+        """
+        id = await self._get_authenticating_user_id(oauth_1=user_auth)
+        route = f"/2/users/{id}/retweets/{source_tweet_id}"
+
+        return await self._make_request(
+            "DELETE", route, user_auth=user_auth
+        )
+
+    async def get_retweeters(self, id, *, user_auth=False, **params):
+        """get_retweeters( \
+            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 \
+        )
+
+        Allows you to get information about who has Retweeted a Tweet.
+
+        Parameters
+        ----------
+        id : int | str
+            Tweet ID of the Tweet to request Retweeting users of.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        max_results : int | None
+            The maximum number of results to be returned per page. This can be
+            a number between 1 and 100. By default, each page will return 100
+            results.
+        media_fields : list[str] | str | None
+            :ref:`media_fields_parameter`
+        pagination_token : str | None
+            Used to request the next page of results if all results weren't
+            returned with the latest request, or to go back to the previous
+            page of results. To return the next page, pass the ``next_token``
+            returned in your previous response. To go back one page, pass the
+            ``previous_token`` returned in your previous response.
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/get-tweets-id-retweeted_by
+        """
+        return await self._make_request(
+            "GET", f"/2/tweets/{id}/retweeted_by", params=params,
+            endpoint_parameters=(
+                "expansions", "max_results", "media.fields",
+                "pagination_token", "place.fields", "poll.fields",
+                "tweet.fields", "user.fields"
+            ), data_type=User, user_auth=user_auth
+        )
+
+    async def retweet(self, tweet_id, *, user_auth=True):
+        """Causes the user ID to Retweet the target Tweet.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        tweet_id : int | str
+            The ID of the Tweet that you would like to Retweet.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/post-users-id-retweets
+        """
+        id = await self._get_authenticating_user_id(oauth_1=user_auth)
+        route = f"/2/users/{id}/retweets"
+
+        return await self._make_request(
+            "POST", route, json={"tweet_id": str(tweet_id)},
+            user_auth=user_auth
+        )
+
+    # Search Tweets
+
+    async def search_all_tweets(self, query, **params):
+        """search_all_tweets( \
+            query, *, end_time=None, expansions=None, max_results=None, \
+            media_fields=None, next_token=None, place_fields=None, \
+            poll_fields=None, since_id=None, sort_order=None, \
+            start_time=None, tweet_fields=None, until_id=None, \
+            user_fields=None \
+        )
+
+        This endpoint is only available to those users who have been approved
+        for the `Academic Research product track`_.
+
+        The full-archive search endpoint returns the complete history of public
+        Tweets matching a search query; since the first Tweet was created March
+        26, 2006.
+
+        The Tweets returned by this endpoint count towards the Project-level
+        `Tweet cap`_.
+
+        .. note::
+
+            By default, a request will return Tweets from up to 30 days ago if
+            the ``start_time`` parameter is not provided.
+
+        Parameters
+        ----------
+        query : str
+            One query for matching Tweets. Up to 1024 characters.
+        end_time : datetime.datetime | str | None
+            YYYY-MM-DDTHH:mm:ssZ (ISO 8601/RFC 3339). Used with ``start_time``.
+            The newest, most recent UTC timestamp to which the Tweets will be
+            provided. Timestamp is in second granularity and is exclusive (for
+            example, 12:00:01 excludes the first second of the minute). If used
+            without ``start_time``, Tweets from 30 days before ``end_time``
+            will be returned by default. If not specified, ``end_time`` will
+            default to [now - 30 seconds].
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        max_results : int | None
+            The maximum number of search results to be returned by a request. A
+            number between 10 and the system limit (currently 500). By default,
+            a request response will return 10 results.
+        media_fields : list[str] | str | None
+            :ref:`media_fields_parameter`
+        next_token : str | None
+            This parameter is used to get the next 'page' of results. The value
+            used with the parameter is pulled directly from the response
+            provided by the API, and should not be modified. You can learn more
+            by visiting our page on `pagination`_.
+        place_fields : list[str] | str | None
+            :ref:`place_fields_parameter`
+        poll_fields : list[str] | str | None
+            :ref:`poll_fields_parameter`
+        since_id : int | str | None
+            Returns results with a Tweet ID greater than (for example, more
+            recent than) the specified ID. The ID specified is exclusive and
+            responses will not include it. If included with the same request as
+            a ``start_time`` parameter, only ``since_id`` will be used.
+        sort_order : str | None
+            This parameter is used to specify the order in which you want the
+            Tweets returned. By default, a request will return the most recent
+            Tweets first (sorted by recency).
+        start_time : datetime.datetime | str | None
+            YYYY-MM-DDTHH:mm:ssZ (ISO 8601/RFC 3339). The oldest UTC timestamp
+            from which the Tweets will be provided. Timestamp is in second
+            granularity and is inclusive (for example, 12:00:01 includes the
+            first second of the minute). By default, a request will return
+            Tweets from up to 30 days ago if you do not include this parameter.
+        tweet_fields : list[str] | str | None
+            :ref:`tweet_fields_parameter`
+        until_id : int | str | None
+            Returns results with a Tweet ID less than (that is, older than) the
+            specified ID. Used with ``since_id``. The ID specified is exclusive
+            and responses will not include it.
+        user_fields : list[str] | str | None
+            :ref:`user_fields_parameter`
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-all
+
+        .. _Academic Research product track: https://developer.twitter.com/en/docs/projects/overview#product-track
+        .. _Tweet cap: https://developer.twitter.com/en/docs/projects/overview#tweet-cap
+        .. _pagination: https://developer.twitter.com/en/docs/twitter-api/tweets/search/integrate/paginate
+        """
+        params["query"] = query
+        return await self._make_request(
+            "GET", "/2/tweets/search/all", params=params,
+            endpoint_parameters=(
+                "end_time", "expansions", "max_results", "media.fields",
+                "next_token", "place.fields", "poll.fields", "query",
+                "since_id", "sort_order", "start_time", "tweet.fields",
+                "until_id", "user.fields"
+            ), data_type=Tweet
+        )
+
+    async def search_recent_tweets(self, query, *, user_auth=False, **params):
+        """search_recent_tweets( \
+            query, *, end_time=None, expansions=None, max_results=None, \
+            media_fields=None, next_token=None, place_fields=None, \
+            poll_fields=None, since_id=None, sort_order=None, \
+            start_time=None, tweet_fields=None, until_id=None, \
+            user_fields=None, user_auth=False \
+        )
+
+        The recent search endpoint returns Tweets from the last seven days that
+        match a search query.
+
+        The Tweets returned by this endpoint count towards the Project-level
+        `Tweet cap`_.
+
+        Parameters
+        ----------
+        query : str
+            One rule for matching Tweets. If you are using a
+            `Standard Project`_ at the Basic `access level`_, you can use the
+            basic set of `operators`_ and can make queries up to 512 characters
+            long. If you are using an `Academic Research Project`_ at the Basic
+            access level, you can use all available operators and can make
+            queries up to 1,024 characters long.
+        end_time : datetime.datetime | str | None
+            YYYY-MM-DDTHH:mm:ssZ (ISO 8601/RFC 3339). The newest, most recent
+            UTC timestamp to which the Tweets will be provided. Timestamp is in
+            second granularity and is exclusive (for example, 12:00:01 excludes
+            the first second of the minute). By default, a request will return
+            Tweets from as recent as 30 seconds ago if you do not include this
+            parameter.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        max_results : int | None
+            The maximum number of search results to be returned by a request. A
+            number between 10 and 100. By default, a request response will
+            return 10 results.
+        media_fields : list[str] | str | None
+            :ref:`media_fields_parameter`
+        next_token : str | None
+            This parameter is used to get the next 'page' of results. 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`
+        since_id : int | str | None
+            Returns results with a Tweet ID greater than (that is, more recent
+            than) the specified ID. The ID specified is exclusive and responses
+            will not include it. If included with the same request as a
+            ``start_time`` parameter, only ``since_id`` will be used.
+        sort_order : str | None
+            This parameter is used to specify the order in which you want the
+            Tweets returned. By default, a request will return the most recent
+            Tweets first (sorted by recency).
+        start_time : datetime.datetime | str | None
+            YYYY-MM-DDTHH:mm:ssZ (ISO 8601/RFC 3339). The oldest UTC timestamp
+            (from most recent seven days) from which the Tweets will be
+            provided. Timestamp is in second granularity and is inclusive (for
+            example, 12:00:01 includes the first second of the minute). If
+            included with the same request as a ``since_id`` parameter, only
+            ``since_id`` will be used. By default, a request will return Tweets
+            from up to seven days ago if you do not include this parameter.
+        tweet_fields : list[str] | str | None
+            :ref:`tweet_fields_parameter`
+        until_id : int | str | None
+            Returns results with a Tweet ID less than (that is, older than) the
+            specified ID. The ID specified is exclusive and responses will not
+            include it.
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent
+
+        .. _Tweet cap: https://developer.twitter.com/en/docs/projects/overview#tweet-cap
+        .. _Standard Project: https://developer.twitter.com/en/docs/projects
+        .. _access level: https://developer.twitter.com/en/products/twitter-api/early-access/guide.html#na_1
+        .. _operators: https://developer.twitter.com/en/docs/twitter-api/tweets/search/integrate/build-a-query
+        .. _Academic Research Project: https://developer.twitter.com/en/docs/projects
+        """
+        params["query"] = query
+        return await self._make_request(
+            "GET", "/2/tweets/search/recent", params=params,
+            endpoint_parameters=(
+                "end_time", "expansions", "max_results", "media.fields",
+                "next_token", "place.fields", "poll.fields", "query",
+                "since_id", "sort_order", "start_time", "tweet.fields",
+                "until_id", "user.fields"
+            ), data_type=Tweet, user_auth=user_auth
+        )
+
+    # Timelines
+
+    async def get_users_mentions(self, id, *, user_auth=False, **params):
+        """get_users_mentions( \
+            id, *, end_time=None, expansions=None, max_results=None, \
+            media_fields=None, pagination_token=None, place_fields=None, \
+            poll_fields=None, since_id=None, start_time=None, \
+            tweet_fields=None, until_id=None, user_fields=None, \
+            user_auth=False \
+        )
+
+        Returns Tweets mentioning a single user specified by the requested user
+        ID. By default, the most recent ten Tweets are returned per request.
+        Using pagination, up to the most recent 800 Tweets can be retrieved.
+
+        The Tweets returned by this endpoint count towards the Project-level
+        `Tweet cap`_.
+
+        Parameters
+        ----------
+        id : int | str
+            Unique identifier of the user for whom to return Tweets mentioning
+            the user. User ID can be referenced using the `user/lookup`_
+            endpoint. More information on Twitter IDs is `here`_.
+        end_time : datetime.datetime | str | None
+            YYYY-MM-DDTHH:mm:ssZ (ISO 8601/RFC 3339). The new UTC timestamp
+            from which the Tweets will be provided. Timestamp is in second
+            granularity and is inclusive (for example, 12:00:01 includes the
+            first second of the minute).
+
+            Please note that this parameter does not support a millisecond
+            value.
+        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 5.
+            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 or backwards through
+            'pages' of results, based on the value of the ``next_token`` or
+            ``previous_token`` in the response. 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`
+        since_id : int | str | None
+            Returns results with a Tweet ID greater than (that is, more recent
+            than) the specified 'since' Tweet ID. There are limits to the
+            number of Tweets that can be accessed through the API. If the limit
+            of Tweets has occurred since the ``since_id``, the ``since_id``
+            will be forced to the oldest ID available. More information on
+            Twitter IDs is `here`_.
+        start_time : datetime.datetime | str | None
+            YYYY-MM-DDTHH:mm:ssZ (ISO 8601/RFC 3339). The oldest UTC timestamp
+            from which the Tweets will be provided. Timestamp is in second
+            granularity and is inclusive (for example, 12:00:01 includes the
+            first second of the minute).
+
+            Please note that this parameter does not support a millisecond
+            value.
+        tweet_fields : list[str] | str | None
+            :ref:`tweet_fields_parameter`
+        until_id : int | str | None
+            Returns results with a Tweet ID less less than (that is, older
+            than) the specified 'until' Tweet ID. There are limits to the
+            number of Tweets that can be accessed through the API. If the limit
+            of Tweets has occurred since the ``until_id``, the ``until_id``
+            will be forced to the most recent ID available. More information on
+            Twitter IDs is `here`_.
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-mentions
+
+        .. _Tweet cap: https://developer.twitter.com/en/docs/projects/overview#tweet-cap
+        .. _user/lookup: https://developer.twitter.com/en/docs/twitter-api/users/lookup/introduction
+        .. _here: https://developer.twitter.com/en/docs/twitter-ids
+        """
+        return await self._make_request(
+            "GET", f"/2/users/{id}/mentions", params=params,
+            endpoint_parameters=(
+                "end_time", "expansions", "max_results", "media.fields",
+                "pagination_token", "place.fields", "poll.fields", "since_id",
+                "start_time", "tweet.fields", "until_id", "user.fields"
+            ), data_type=Tweet, user_auth=user_auth
+        )
+
+    async def get_users_tweets(self, id, *, user_auth=False, **params):
+        """get_users_tweets( \
+            id, *, end_time=None, exclude=None, expansions=None, \
+            max_results=None, media_fields=None, pagination_token=None, \
+            place_fields=None, poll_fields=None, since_id=None, \
+            start_time=None, tweet_fields=None, until_id=None, \
+            user_fields=None, user_auth=False \
+        )
+
+        Returns Tweets composed by a single user, specified by the requested
+        user ID. By default, the most recent ten Tweets are returned per
+        request. Using pagination, the most recent 3,200 Tweets can be
+        retrieved.
+
+        The Tweets returned by this endpoint count towards the Project-level
+        `Tweet cap`_.
+
+        Parameters
+        ----------
+        id : int | str
+            Unique identifier of the Twitter account (user ID) for whom to
+            return results. User ID can be referenced using the `user/lookup`_
+            endpoint. More information on Twitter IDs is `here`_.
+        end_time : datetime.datetime | str | None
+            YYYY-MM-DDTHH:mm:ssZ (ISO 8601/RFC 3339). The newest or most recent
+            UTC timestamp from which the Tweets will be provided. Only the 3200
+            most recent Tweets are available. Timestamp is in second
+            granularity and is inclusive (for example, 12:00:01 includes the
+            first second of the minute). Minimum allowable time is
+            2010-11-06T00:00:01Z
+
+            Please note that this parameter does not support a millisecond
+            value.
+        exclude : list[str] | str | None
+            Comma-separated list of the types of Tweets to exclude from the
+            response. When ``exclude=retweets`` is used, the maximum historical
+            Tweets returned is still 3200. When the ``exclude=replies``
+            parameter is used for any value, only the most recent 800 Tweets
+            are available.
+        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 5.
+            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 or backwards through
+            'pages' of results, based on the value of the ``next_token`` or
+            ``previous_token`` in the response. 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`
+        since_id : int | str | None
+            Returns results with a Tweet ID greater than (that is, more recent
+            than) the specified 'since' Tweet ID. Only the 3200 most recent
+            Tweets are available. The result will exclude the ``since_id``. If
+            the limit of Tweets has occurred since the ``since_id``, the
+            ``since_id`` will be forced to the oldest ID available.
+        start_time : datetime.datetime | str | None
+            YYYY-MM-DDTHH:mm:ssZ (ISO 8601/RFC 3339). The oldest or earliest
+            UTC timestamp from which the Tweets will be provided. Only the 3200
+            most recent Tweets are available. Timestamp is in second
+            granularity and is inclusive (for example, 12:00:01 includes the
+            first second of the minute). Minimum allowable time is
+            2010-11-06T00:00:00Z
+
+            Please note that this parameter does not support a millisecond
+            value.
+        tweet_fields : list[str] | str | None
+            :ref:`tweet_fields_parameter`
+        until_id : int | str | None
+            Returns results with a Tweet ID less less than (that is, older
+            than) the specified 'until' Tweet ID. Only the 3200 most recent
+            Tweets are available. The result will exclude the ``until_id``. If
+            the limit of Tweets has occurred since the ``until_id``, the
+            ``until_id`` will be forced to the most recent ID available.
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets
+
+        .. _Tweet cap: https://developer.twitter.com/en/docs/projects/overview#tweet-cap
+        .. _user/lookup: https://developer.twitter.com/en/docs/twitter-api/users/lookup/introduction
+        .. _here: https://developer.twitter.com/en/docs/twitter-ids
+        """
+        return await self._make_request(
+            "GET", f"/2/users/{id}/tweets", params=params,
+            endpoint_parameters=(
+                "end_time", "exclude", "expansions", "max_results",
+                "media.fields", "pagination_token", "place.fields",
+                "poll.fields", "since_id", "start_time", "tweet.fields",
+                "until_id", "user.fields"
+            ), data_type=Tweet, user_auth=user_auth
+        )
+
+    # Tweet counts
+
+    async def get_all_tweets_count(self, query, **params):
+        """get_all_tweets_count( \
+            query, *, end_time=None, granularity=None, next_token=None, \
+            since_id=None, start_time=None, until_id=None \
+        )
+
+        This endpoint is only available to those users who have been approved
+        for the `Academic Research product track`_.
+
+        The full-archive search endpoint returns the complete history of public
+        Tweets matching a search query; since the first Tweet was created March
+        26, 2006.
+
+        Parameters
+        ----------
+        query : str
+            One query for matching Tweets. Up to 1024 characters.
+        end_time : datetime.datetime | str | None
+            YYYY-MM-DDTHH:mm:ssZ (ISO 8601/RFC 3339). Used with ``start_time``.
+            The newest, most recent UTC timestamp to which the Tweets will be
+            provided. Timestamp is in second granularity and is exclusive (for
+            example, 12:00:01 excludes the first second of the minute). If used
+            without ``start_time``, Tweets from 30 days before ``end_time``
+            will be returned by default. If not specified, ``end_time`` will
+            default to [now - 30 seconds].
+        granularity : str | None
+            This is the granularity that you want the timeseries count data to
+            be grouped by. You can request ``minute``, ``hour``, or ``day``
+            granularity. The default granularity, if not specified is ``hour``.
+        next_token : str | None
+            This parameter is used to get the next 'page' of results. The value
+            used with the parameter is pulled directly from the response
+            provided by the API, and should not be modified. You can learn more
+            by visiting our page on `pagination`_.
+        since_id : int | str | None
+            Returns results with a Tweet ID greater than (for example, more
+            recent than) the specified ID. The ID specified is exclusive and
+            responses will not include it. If included with the same request as
+            a ``start_time`` parameter, only ``since_id`` will be used.
+        start_time : datetime.datetime | str | None
+            YYYY-MM-DDTHH:mm:ssZ (ISO 8601/RFC 3339). The oldest UTC timestamp
+            from which the Tweets will be provided. Timestamp is in second
+            granularity and is inclusive (for example, 12:00:01 includes the
+            first second of the minute). By default, a request will return
+            Tweets from up to 30 days ago if you do not include this parameter.
+        until_id : int | str | None
+            Returns results with a Tweet ID less than (that is, older than) the
+            specified ID. Used with ``since_id``. The ID specified is exclusive
+            and responses will not include it.
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/counts/api-reference/get-tweets-counts-all
+
+        .. _Academic Research product track: https://developer.twitter.com/en/docs/projects/overview#product-track
+        .. _pagination: https://developer.twitter.com/en/docs/twitter-api/tweets/search/integrate/paginate
+        """
+        params["query"] = query
+        return await self._make_request(
+            "GET", "/2/tweets/counts/all", params=params,
+            endpoint_parameters=(
+                "end_time", "granularity", "next_token", "query", "since_id",
+                "start_time", "until_id"
+            )
+        )
+
+    async def get_recent_tweets_count(self, query, **params):
+        """get_recent_tweets_count( \
+            query, *, end_time=None, granularity=None, since_id=None, \
+            start_time=None, until_id=None \
+        )
+
+        The recent Tweet counts endpoint returns count of Tweets from the last
+        seven days that match a search query.
+
+        Parameters
+        ----------
+        query : str
+            One rule for matching Tweets. If you are using a
+            `Standard Project`_ at the Basic `access level`_, you can use the
+            basic set of `operators`_ and can make queries up to 512 characters
+            long. If you are using an `Academic Research Project`_ at the Basic
+            access level, you can use all available operators and can make
+            queries up to 1,024 characters long.
+        end_time : datetime.datetime | str | None
+            YYYY-MM-DDTHH:mm:ssZ (ISO 8601/RFC 3339). The newest, most recent
+            UTC timestamp to which the Tweets will be provided. Timestamp is in
+            second granularity and is exclusive (for example, 12:00:01 excludes
+            the first second of the minute). By default, a request will return
+            Tweets from as recent as 30 seconds ago if you do not include this
+            parameter.
+        granularity : str | None
+            This is the granularity that you want the timeseries count data to
+            be grouped by. You can request ``minute``, ``hour``, or ``day``
+            granularity. The default granularity, if not specified is ``hour``.
+        since_id : int | str | None
+            Returns results with a Tweet ID greater than (that is, more recent
+            than) the specified ID. The ID specified is exclusive and responses
+            will not include it. If included with the same request as a
+            ``start_time`` parameter, only ``since_id`` will be used.
+        start_time : datetime.datetime | str | None
+            YYYY-MM-DDTHH:mm:ssZ (ISO 8601/RFC 3339). The oldest UTC timestamp
+            (from most recent seven days) from which the Tweets will be
+            provided. Timestamp is in second granularity and is inclusive (for
+            example, 12:00:01 includes the first second of the minute). If
+            included with the same request as a ``since_id`` parameter, only
+            ``since_id`` will be used. By default, a request will return Tweets
+            from up to seven days ago if you do not include this parameter.
+        until_id : int | str | None
+            Returns results with a Tweet ID less than (that is, older than) the
+            specified ID. The ID specified is exclusive and responses will not
+            include it.
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/counts/api-reference/get-tweets-counts-recent
+
+        .. _Standard Project: https://developer.twitter.com/en/docs/projects
+        .. _access level: https://developer.twitter.com/en/products/twitter-api/early-access/guide.html#na_1
+        .. _operators: https://developer.twitter.com/en/docs/twitter-api/tweets/search/integrate/build-a-query
+        .. _Academic Research Project: https://developer.twitter.com/en/docs/projects
+        """
+        params["query"] = query
+        return await self._make_request(
+            "GET", "/2/tweets/counts/recent", params=params,
+            endpoint_parameters=(
+                "end_time", "granularity", "query", "since_id", "start_time",
+                "until_id"
+            )
+        )
+
+    # Tweet lookup
+
+    async def get_tweet(self, id, *, user_auth=False, **params):
+        """get_tweet( \
+            id, *, expansions=None, media_fields=None, place_fields=None, \
+            poll_fields=None, tweet_fields=None, user_fields=None, \
+            user_auth=False \
+        )
+
+        Returns a variety of information about a single Tweet specified by
+        the requested ID.
+
+        Parameters
+        ----------
+        id : int | str
+            Unique identifier of the Tweet to request
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        media_fields : list[str] | str | None
+            :ref:`media_fields_parameter`
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets-id
+        """
+        return await self._make_request(
+            "GET", f"/2/tweets/{id}", params=params,
+            endpoint_parameters=(
+                "expansions", "media.fields", "place.fields", "poll.fields",
+                "tweet.fields", "user.fields"
+            ), data_type=Tweet, user_auth=user_auth
+        )
+
+    async def get_tweets(self, ids, *, user_auth=False, **params):
+        """get_tweets( \
+            ids, *, expansions=None, media_fields=None, place_fields=None, \
+            poll_fields=None, tweet_fields=None, user_fields=None, \
+            user_auth=False \
+        )
+
+        Returns a variety of information about the Tweet specified by the
+        requested ID or list of IDs.
+
+        Parameters
+        ----------
+        ids : list[int | str] | str
+            A comma separated list of Tweet IDs. Up to 100 are allowed in a
+            single request. Make sure to not include a space between commas and
+            fields.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        media_fields : list[str] | str | None
+            :ref:`media_fields_parameter`
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets
+        """
+        params["ids"] = ids
+        return await self._make_request(
+            "GET", "/2/tweets", params=params,
+            endpoint_parameters=(
+                "ids", "expansions", "media.fields", "place.fields",
+                "poll.fields", "tweet.fields", "user.fields"
+            ), data_type=Tweet, user_auth=user_auth
+        )
+
+    # Blocks
+
+    async def unblock(self, target_user_id, *, user_auth=True):
+        """Unblock another user.
+
+        The request succeeds with no action when the user sends a request to a
+        user they're not blocking or have already unblocked.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        target_user_id : int | str
+            The user ID of the user that you would like to unblock.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/users/blocks/api-reference/delete-users-user_id-blocking
+        """
+        source_user_id = await self._get_authenticating_user_id(
+            oauth_1=user_auth
+        )
+        route = f"/2/users/{source_user_id}/blocking/{target_user_id}"
+
+        return await self._make_request(
+            "DELETE", route, user_auth=user_auth
+        )
+
+    async def get_blocked(self, *, user_auth=True, **params):
+        """get_blocked( \
+            *, expansions=None, max_results=None, pagination_token=None, \
+            tweet_fields=None, user_fields=None, user_auth=True \
+        )
+
+        Returns a list of users who are blocked by the authenticating user.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        max_results : int | None
+            The maximum number of results to be returned per page. This can be
+            a number between 1 and 1000. By default, each page will return 100
+            results.
+        pagination_token : str | None
+            Used to request the next page of results if all results weren't
+            returned with the latest request, or to go back to the previous
+            page of results.
+        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
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/users/blocks/api-reference/get-users-blocking
+        """
+        id = await self._get_authenticating_user_id(oauth_1=user_auth)
+        route = f"/2/users/{id}/blocking"
+
+        return await self._make_request(
+            "GET", route, params=params,
+            endpoint_parameters=(
+                "expansions", "max_results", "pagination_token",
+                "tweet.fields", "user.fields"
+            ), data_type=User, user_auth=user_auth
+        )
+
+    async def block(self, target_user_id, *, user_auth=True):
+        """Block another user.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        target_user_id : int | str
+            The user ID of the user that you would like to block.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/users/blocks/api-reference/post-users-user_id-blocking
+        """
+        id = await self._get_authenticating_user_id(oauth_1=user_auth)
+        route = f"/2/users/{id}/blocking"
+
+        return await self._make_request(
+            "POST", route, json={"target_user_id": str(target_user_id)},
+            user_auth=user_auth
+        )
+
+    # Follows
+
+    async def unfollow_user(self, target_user_id, *, user_auth=True):
+        """Allows a user ID to unfollow another user.
+
+        The request succeeds with no action when the authenticated user sends a
+        request to a user they're not following or have already unfollowed.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        target_user_id : int | str
+            The user ID of the user that you would like to unfollow.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/delete-users-source_id-following
+        """
+        source_user_id = await self._get_authenticating_user_id(
+            oauth_1=user_auth
+        )
+        route = f"/2/users/{source_user_id}/following/{target_user_id}"
+
+        return await self._make_request(
+            "DELETE", route, user_auth=user_auth
+        )
+
+    async def get_users_followers(self, id, *, user_auth=False, **params):
+        """get_users_followers( \
+            id, *, expansions=None, max_results=None, pagination_token=None, \
+            tweet_fields=None, user_fields=None, user_auth=False \
+        )
+
+        Returns a list of users who are followers of the specified user ID.
+
+        Parameters
+        ----------
+        id : int | str
+            The user ID whose followers you would like to retrieve.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        max_results : int | None
+            The maximum number of results to be returned per page. This can be
+            a number between 1 and the 1000. By default, each page will return
+            100 results.
+        pagination_token : str | None
+            Used to request the next page of results if all results weren't
+            returned with the latest request, or to go back to the previous
+            page of results. To return the next page, pass the ``next_token``
+            returned in your previous response. To go back one page, pass the
+            ``previous_token`` returned in your previous response.
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-followers
+        """
+        return await self._make_request(
+            "GET", f"/2/users/{id}/followers", params=params,
+            endpoint_parameters=(
+                "expansions", "max_results", "pagination_token",
+                "tweet.fields", "user.fields"
+            ),
+            data_type=User, user_auth=user_auth
+        )
+
+    async def get_users_following(self, id, *, user_auth=False, **params):
+        """get_users_following( \
+            id, *, expansions=None, max_results=None, pagination_token=None, \
+            tweet_fields=None, user_fields=None, user_auth=False \
+        )
+
+        Returns a list of users the specified user ID is following.
+
+        Parameters
+        ----------
+        id : int | str
+            The user ID whose following you would like to retrieve.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        max_results : int | None
+            The maximum number of results to be returned per page. This can be
+            a number between 1 and the 1000. By default, each page will return
+            100 results.
+        pagination_token : str | None
+            Used to request the next page of results if all results weren't
+            returned with the latest request, or to go back to the previous
+            page of results. To return the next page, pass the ``next_token``
+            returned in your previous response. To go back one page, pass the
+            ``previous_token`` returned in your previous response.
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-following
+        """
+        return await self._make_request(
+            "GET", f"/2/users/{id}/following", params=params,
+            endpoint_parameters=(
+                "expansions", "max_results", "pagination_token",
+                "tweet.fields", "user.fields"
+            ), data_type=User, user_auth=user_auth
+        )
+
+    async def follow_user(self, target_user_id, *, user_auth=True):
+        """Allows a user ID to follow another user.
+
+        If the target user does not have public Tweets, this endpoint will send
+        a follow request.
+
+        The request succeeds with no action when the authenticated user sends a
+        request to a user they're already following, or if they're sending a
+        follower request to a user that does not have public Tweets.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        target_user_id : int | str
+            The user ID of the user that you would like to follow.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/post-users-source_user_id-following
+        """
+        source_user_id = await self._get_authenticating_user_id(
+            oauth_1=user_auth
+        )
+        route = f"/2/users/{source_user_id}/following"
+
+        return await self._make_request(
+            "POST", route, json={"target_user_id": str(target_user_id)},
+            user_auth=user_auth
+        )
+
+    # Mutes
+
+    async def unmute(self, target_user_id, *, user_auth=True):
+        """Allows an authenticated user ID to unmute the target user.
+
+        The request succeeds with no action when the user sends a request to a
+        user they're not muting or have already unmuted.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        target_user_id : int | str
+            The user ID of the user that you would like to unmute.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/users/mutes/api-reference/delete-users-user_id-muting
+        """
+        source_user_id = await self._get_authenticating_user_id(
+            oauth_1=user_auth
+        )
+        route = f"/2/users/{source_user_id}/muting/{target_user_id}"
+
+        return await self._make_request(
+            "DELETE", route, user_auth=user_auth
+        )
+
+    async def get_muted(self, *, user_auth=True, **params):
+        """get_muted( \
+            *, expansions=None, max_results=None, pagination_token=None, \
+            tweet_fields=None, user_fields=None, user_auth=True \
+        )
+
+        Returns a list of users who are muted by the authenticating user.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        max_results : int | None
+            The maximum number of results to be returned per page. This can be
+            a number between 1 and 1000. By default, each page will return 100
+            results.
+        pagination_token : str | None
+            Used to request the next page of results if all results weren't
+            returned with the latest request, or to go back to the previous
+            page of results.
+        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
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/users/mutes/api-reference/get-users-muting
+        """
+        id = await self._get_authenticating_user_id(oauth_1=user_auth)
+        route = f"/2/users/{id}/muting"
+
+        return await self._make_request(
+            "GET", route, params=params,
+            endpoint_parameters=(
+                "expansions", "max_results", "pagination_token",
+                "tweet.fields", "user.fields"
+            ), data_type=User, user_auth=user_auth
+        )
+
+    async def mute(self, target_user_id, *, user_auth=True):
+        """Allows an authenticated user ID to mute the target user.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        target_user_id : int | str
+            The user ID of the user that you would like to mute.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/users/mutes/api-reference/post-users-user_id-muting
+        """
+        id = await self._get_authenticating_user_id(oauth_1=user_auth)
+        route = f"/2/users/{id}/muting"
+
+        return await self._make_request(
+            "POST", route, json={"target_user_id": str(target_user_id)},
+            user_auth=user_auth
+        )
+
+    # User lookup
+
+    async def get_user(
+        self, *, id=None, username=None, user_auth=False, **params
+    ):
+        """get_user(*, id=None, username=None, expansions=None, \
+                    tweet_fields=None, user_fields=None, user_auth=False)
+
+        Returns a variety of information about a single user specified by the
+        requested ID or username.
+
+        Parameters
+        ----------
+        id : int | str | None
+            The ID of the user to lookup.
+        username : str | None
+            The Twitter username (handle) of the user.
+        expansions : list[str] | str | None
+            :ref:`expansions_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
+
+        Raises
+        ------
+        TypeError
+            If ID and username are not passed or both are passed
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-id
+        https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by-username-username
+        """
+        if id is not None and username is not None:
+            raise TypeError("Expected ID or username, not both")
+
+        route = "/2/users"
+
+        if id is not None:
+            route += f"/{id}"
+        elif username is not None:
+            route += f"/by/username/{username}"
+        else:
+            raise TypeError("ID or username is required")
+
+        return await self._make_request(
+            "GET", route, params=params,
+            endpoint_parameters=("expansions", "tweet.fields", "user.fields"),
+            data_type=User, user_auth=user_auth
+        )
+
+    async def get_users(self, *, ids=None, usernames=None, user_auth=False,
+                        **params):
+        """get_users(*, ids=None, usernames=None, expansions=None, \
+                     tweet_fields=None, user_fields=None, user_auth=False)
+
+        Returns a variety of information about one or more users specified by
+        the requested IDs or usernames.
+
+        Parameters
+        ----------
+        ids : list[int | str] | str | None
+            A comma separated list of user IDs. Up to 100 are allowed in a
+            single request. Make sure to not include a space between commas and
+            fields.
+        usernames : list[str] | str | None
+            A comma separated list of Twitter usernames (handles). Up to 100
+            are allowed in a single request. Make sure to not include a space
+            between commas and fields.
+        expansions : list[str] | str | None
+            :ref:`expansions_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
+
+        Raises
+        ------
+        TypeError
+            If IDs and usernames are not passed or both are passed
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users
+        https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by
+        """
+        if ids is not None and usernames is not None:
+            raise TypeError("Expected IDs or usernames, not both")
+
+        route = "/2/users"
+
+        if ids is not None:
+            params["ids"] = ids
+        elif usernames is not None:
+            route += "/by"
+            params["usernames"] = usernames
+        else:
+            raise TypeError("IDs or usernames are required")
+
+        return await self._make_request(
+            "GET", route, params=params,
+            endpoint_parameters=(
+                "ids", "usernames", "expansions", "tweet.fields", "user.fields"
+            ), data_type=User, user_auth=user_auth
+        )
+
+    async def get_me(self, *, user_auth=True, **params):
+        """get_me(*, expansions=None, tweet_fields=None, user_fields=None, \
+                  user_auth=True)
+
+        Returns information about an authorized user.
+
+        Parameters
+        ----------
+        expansions : list[str] | str | None
+            :ref:`expansions_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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-me
+        """
+        return await self._make_request(
+            "GET", f"/2/users/me", params=params,
+            endpoint_parameters=("expansions", "tweet.fields", "user.fields"),
+            data_type=User, user_auth=user_auth
+        )
+
+    # Search Spaces
+
+    async def search_spaces(self, query, **params):
+        """search_spaces(query, *, expansions=None, max_results=None, \
+                         space_fields=None, state=None, user_fields=None)
+
+        Return live or scheduled Spaces matching your specified search terms
+
+        Parameters
+        ----------
+        query : str
+            Your search term. This can be any text (including mentions and
+            Hashtags) present in the title of the Space.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        max_results : int | None
+            The maximum number of results to return in this request. Specify a
+            value between 1 and 100.
+        space_fields : list[str] | str | None
+            :ref:`space_fields_parameter`
+        state : str | None
+            Determines the type of results to return. This endpoint returns all
+            Spaces by default. Use ``live`` to only return live Spaces or
+            ``scheduled`` to only return upcoming Spaces.
+        user_fields : list[str] | str | None
+            :ref:`user_fields_parameter`
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/spaces/search/api-reference/get-spaces-search
+        """
+        params["query"] = query
+        return await self._make_request(
+            "GET", "/2/spaces/search", params=params,
+            endpoint_parameters=(
+                "query", "expansions", "max_results", "space.fields", "state",
+                "user.fields"
+            ), data_type=Space
+        )
+
+    # Spaces lookup
+
+    async def get_spaces(self, *, ids=None, user_ids=None, **params):
+        """get_spaces(*, ids=None, user_ids=None, expansions=None, \
+                      space_fields=None, user_fields=None)
+
+        Returns details about multiple live or scheduled Spaces (created by the
+        specified user IDs if specified). Up to 100 comma-separated Space or
+        user IDs can be looked up using this endpoint.
+
+        Parameters
+        ----------
+        ids : list[str] | str | None
+            A comma separated list of Spaces (up to 100).
+        user_ids : list[int | str] | str | None
+            A comma separated list of user IDs (up to 100).
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        space_fields : list[str] | str | None
+            :ref:`space_fields_parameter`
+        user_fields : list[str] | str | None
+            :ref:`user_fields_parameter`
+
+        Raises
+        ------
+        TypeError
+            If IDs and user IDs are not passed or both are passed
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces
+        https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-by-creator-ids
+        """
+        if ids is not None and user_ids is not None:
+            raise TypeError("Expected IDs or user IDs, not both")
+
+        route = "/2/spaces"
+
+        if ids is not None:
+            params["ids"] = ids
+        elif user_ids is not None:
+            route += "/by/creator_ids"
+            params["user_ids"] = user_ids
+        else:
+            raise TypeError("IDs or user IDs are required")
+
+        return await self._make_request(
+            "GET", route, params=params,
+            endpoint_parameters=(
+                "ids", "user_ids", "expansions", "space.fields", "user.fields"
+            ), data_type=Space
+        )
+
+    async def get_space(self, id, **params):
+        """get_space(id, *, expansions=None, space_fields=None, \
+                     user_fields=None)
+
+        Returns a variety of information about a single Space specified by the
+        requested ID.
+
+        Parameters
+        ----------
+        id : list[str] | str
+            Unique identifier of the Space to request.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        space_fields : list[str] | str | None
+            :ref:`space_fields_parameter`
+        user_fields : list[str] | str | None
+            :ref:`user_fields_parameter`
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-id
+        """
+        return await self._make_request(
+            "GET", f"/2/spaces/{id}", params=params,
+            endpoint_parameters=(
+                "expansions", "space.fields", "user.fields"
+            ), data_type=Space
+        )
+
+    async def get_space_buyers(self, id, **params):
+        """get_space_buyers( \
+            id, *, expansions=None, media_fields=None, place_fields=None, \
+            poll_fields=None, tweet_fields=None, user_fields=None \
+        )
+
+        Returns a list of user who purchased a ticket to the requested Space.
+        You must authenticate the request using the Access Token of the creator
+        of the requested Space.
+
+        Parameters
+        ----------
+        id : str
+            Unique identifier of the Space for which you want to request
+            Tweets.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        media_fields : list[str] | str | None
+            :ref:`media_fields_parameter`
+        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`
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-id-buyers
+        """
+        return await self._make_request(
+            "GET", f"/2/spaces/{id}/buyers", params=params,
+            endpoint_parameters=(
+                "expansions", "media.fields", "place.fields", "poll.fields",
+                "tweet.fields", "user.fields"
+            ), data_type=User
+        )
+
+    async def get_space_tweets(self, id, **params):
+        """get_space_tweets( \
+            id, *, expansions=None, media_fields=None, place_fields=None, \
+            poll_fields=None, tweet_fields=None, user_fields=None \
+        )
+
+        Returns Tweets shared in the requested Spaces.
+
+        Parameters
+        ----------
+        id : str
+            Unique identifier of the Space containing the Tweets you'd like to
+            access.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        media_fields : list[str] | str | None
+            :ref:`media_fields_parameter`
+        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`
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-id-tweets
+        """
+        return await self._make_request(
+            "GET", f"/2/spaces/{id}/tweets", params=params,
+            endpoint_parameters=(
+                "expansions", "media.fields", "place.fields", "poll.fields",
+                "tweet.fields", "user.fields"
+            ), data_type=Tweet
+        )
+
+    # List Tweets lookup
+
+    async def get_list_tweets(self, id, *, user_auth=False, **params):
+        """get_list_tweets( \
+            id, *, expansions=None, max_results=None, pagination_token=None, \
+            tweet_fields=None, user_fields=None, user_auth=False \
+        )
+
+        Returns a list of Tweets from the specified List.
+
+        Parameters
+        ----------
+        id : list[str] | str
+            The ID of the List whose Tweets you would like to retrieve.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        max_results : int | None
+            The maximum number of results to be returned per page. This can be
+            a number between 1 and 100. By default, each page will return 100
+            results.
+        pagination_token : str | None
+            Used to request the next page of results if all results weren't
+            returned with the latest request, or to go back to the previous
+            page of results. To return the next page, pass the next_token
+            returned in your previous response. To go back one page, pass the
+            previous_token returned in your previous response.
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/list-tweets/api-reference/get-lists-id-tweets
+        """
+        return await self._make_request(
+            "GET", f"/2/lists/{id}/tweets", params=params,
+            endpoint_parameters=(
+                "expansions", "max_results", "pagination_token",
+                "tweet.fields", "user.fields"
+            ), data_type=Tweet, user_auth=user_auth
+        )
+
+    # List follows
+
+    async def unfollow_list(self, list_id, *, user_auth=True):
+        """Enables the authenticated user to unfollow a List.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        list_id : int | str
+            The ID of the List that you would like the user to unfollow.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/delete-users-id-followed-lists-list_id
+        """
+        id = await self._get_authenticating_user_id(oauth_1=user_auth)
+        route = f"/2/users/{id}/followed_lists/{list_id}"
+
+        return await self._make_request(
+            "DELETE", route, user_auth=user_auth
+        )
+
+    async def get_list_followers(self, id, *, user_auth=False, **params):
+        """get_list_followers( \
+            id, *, expansions=None, max_results=None, pagination_token=None, \
+            tweet_fields=None, user_fields=None, user_auth=False \
+        )
+
+        Returns a list of users who are followers of the specified List.
+
+        Parameters
+        ----------
+        id : list[str] | str
+            The ID of the List whose followers you would like to retrieve.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        max_results : int | None
+            The maximum number of results to be returned per page. This can be
+            a number between 1 and 100. By default, each page will return 100
+            results.
+        pagination_token : str | None
+            Used to request the next page of results if all results weren't
+            returned with the latest request, or to go back to the previous
+            page of results. To return the next page, pass the next_token
+            returned in your previous response. To go back one page, pass the
+            previous_token returned in your previous response.
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/get-lists-id-followers
+        """
+        return await self._make_request(
+            "GET", f"/2/lists/{id}/followers", params=params,
+            endpoint_parameters=(
+                "expansions", "max_results", "pagination_token",
+                "tweet.fields", "user.fields"
+            ), data_type=User, user_auth=user_auth
+        )
+
+    async def get_followed_lists(self, id, *, user_auth=False, **params):
+        """get_followed_lists( \
+            id, *, expansions=None, list_fields=None, max_results=None, \
+            pagination_token=None, user_fields=None, user_auth=False \
+        )
+
+        Returns all Lists a specified user follows.
+
+        Parameters
+        ----------
+        id : list[str] | str
+            The user ID whose followed Lists you would like to retrieve.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        list_fields : list[str] | str | None
+            :ref:`list_fields_parameter`
+        max_results : int | None
+            The maximum number of results to be returned per page. This can be
+            a number between 1 and 100. By default, each page will return 100
+            results.
+        pagination_token : str | None
+            Used to request the next page of results if all results weren't
+            returned with the latest request, or to go back to the previous
+            page of results. To return the next page, pass the next_token
+            returned in your previous response. To go back one page, pass the
+            previous_token returned in your previous response.
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/get-users-id-followed_lists
+        """
+        return await self._make_request(
+            "GET", f"/2/users/{id}/followed_lists", params=params,
+            endpoint_parameters=(
+                "expansions", "list.fields", "max_results", "pagination_token",
+                "user.fields"
+            ), data_type=List, user_auth=user_auth
+        )
+
+    async def follow_list(self, list_id, *, user_auth=True):
+        """Enables the authenticated user to follow a List.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        list_id : int | str
+            The ID of the List that you would like the user to follow.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/post-users-id-followed-lists
+        """
+        id = await self._get_authenticating_user_id(oauth_1=user_auth)
+        route = f"/2/users/{id}/followed_lists"
+
+        return await self._make_request(
+            "POST", route, json={"list_id": str(list_id)}, user_auth=user_auth
+        )
+
+    # List lookup
+
+    async def get_list(self, id, *, user_auth=False, **params):
+        """get_list(id, *, expansions=None, list_fields=None, \
+                    user_fields=None, user_auth=False)
+
+        Returns the details of a specified List.
+
+        Parameters
+        ----------
+        id : list[str] | str
+            The ID of the List to lookup.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        list_fields : list[str] | str | None
+            :ref:`list_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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-lists-id
+        """
+        return await self._make_request(
+            "GET", f"/2/lists/{id}", params=params,
+            endpoint_parameters=(
+                "expansions", "list.fields", "user.fields"
+            ), data_type=List, user_auth=user_auth
+        )
+
+    async def get_owned_lists(self, id, *, user_auth=False, **params):
+        """get_owned_lists( \
+            id, *, expansions=None, list_fields=None, max_results=None, \
+            pagination_token=None, user_fields=None, user_auth=False \
+        )
+
+        Returns all Lists owned by the specified user.
+
+        Parameters
+        ----------
+        id : list[str] | str
+            The user ID whose owned Lists you would like to retrieve.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        list_fields : list[str] | str | None
+            :ref:`list_fields_parameter`
+        max_results : int | None
+            The maximum number of results to be returned per page. This can be
+            a number between 1 and 100. By default, each page will return 100
+            results.
+        pagination_token : str | None
+            Used to request the next page of results if all results weren't
+            returned with the latest request, or to go back to the previous
+            page of results. To return the next page, pass the next_token
+            returned in your previous response. To go back one page, pass the
+            previous_token returned in your previous response.
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-users-id-owned_lists
+        """
+        return await self._make_request(
+            "GET", f"/2/users/{id}/owned_lists", params=params,
+            endpoint_parameters=(
+                "expansions", "list.fields", "max_results", "pagination_token",
+                "user.fields"
+            ), data_type=List, user_auth=user_auth
+        )
+
+    # List members
+
+    async def remove_list_member(self, id, user_id, *, user_auth=True):
+        """Enables the authenticated user to remove a member from a List they
+        own.
+
+        Parameters
+        ----------
+        id : int | str
+            The ID of the List you are removing a member from.
+        user_id : int | str
+            The ID of the user you wish to remove as a member of the List.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/delete-lists-id-members-user_id
+        """
+
+        return await self._make_request(
+            "DELETE", f"/2/lists/{id}/members/{user_id}", user_auth=user_auth
+        )
+
+    async def get_list_members(self, id, *, user_auth=False, **params):
+        """get_list_members( \
+            id, *, expansions=None, max_results=None, pagination_token=None, \
+            tweet_fields=None, user_fields=None, user_auth=False \
+        )
+
+        Returns a list of users who are members of the specified List.
+
+        Parameters
+        ----------
+        id : list[str] | str
+            The ID of the List whose members you would like to retrieve.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        max_results : int | None
+            The maximum number of results to be returned per page. This can be
+            a number between 1 and 100. By default, each page will return 100
+            results.
+        pagination_token : str | None
+            Used to request the next page of results if all results weren't
+            returned with the latest request, or to go back to the previous
+            page of results. To return the next page, pass the next_token
+            returned in your previous response. To go back one page, pass the
+            previous_token returned in your previous response.
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/get-lists-id-members
+        """
+        return await self._make_request(
+            "GET", f"/2/lists/{id}/members", params=params,
+            endpoint_parameters=(
+                "expansions", "max_results", "pagination_token",
+                "tweet.fields", "user.fields"
+            ), data_type=User, user_auth=user_auth
+        )
+
+    async def get_list_memberships(self, id, *, user_auth=False, **params):
+        """get_list_memberships( \
+            id, *, expansions=None, list_fields=None, max_results=None, \
+            pagination_token=None, user_fields=None, user_auth=False \
+        )
+
+        Returns all Lists a specified user is a member of.
+
+        Parameters
+        ----------
+        id : list[str] | str
+            The user ID whose List memberships you would like to retrieve.
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        list_fields : list[str] | str | None
+            :ref:`list_fields_parameter`
+        max_results : int | None
+            The maximum number of results to be returned per page. This can be
+            a number between 1 and 100. By default, each page will return 100
+            results.
+        pagination_token : str | None
+            Used to request the next page of results if all results weren't
+            returned with the latest request, or to go back to the previous
+            page of results. To return the next page, pass the next_token
+            returned in your previous response. To go back one page, pass the
+            previous_token returned in your previous response.
+        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 | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/get-users-id-list_memberships
+        """
+        return await self._make_request(
+            "GET", f"/2/users/{id}/list_memberships", params=params,
+            endpoint_parameters=(
+                "expansions", "list.fields", "max_results", "pagination_token",
+                "user.fields"
+            ), data_type=List, user_auth=user_auth
+        )
+
+    async def add_list_member(self, id, user_id, *, user_auth=True):
+        """Enables the authenticated user to add a member to a List they own.
+
+        Parameters
+        ----------
+        id : int | str
+            The ID of the List you are adding a member to.
+        user_id : int | str
+            The ID of the user you wish to add as a member of the List.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/post-lists-id-members
+        """
+        return await self._make_request(
+            "POST", f"/2/lists/{id}/members", json={"user_id": str(user_id)},
+            user_auth=user_auth
+        )
+
+    # Manage Lists
+
+    async def delete_list(self, id, *, user_auth=True):
+        """Enables the authenticated user to delete a List that they own.
+
+        Parameters
+        ----------
+        id : int | str
+            The ID of the List to be deleted.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-lists-id
+        """
+
+        return await self._make_request(
+            "DELETE", f"/2/lists/{id}", user_auth=user_auth
+        )
+
+    async def update_list(self, id, *, description=None, name=None,
+                          private=None, user_auth=True):
+        """Enables the authenticated user to update the meta data of a
+        specified List that they own.
+
+        Parameters
+        ----------
+        id : int | str
+            The ID of the List to be updated.
+        description : str | None
+            Updates the description of the List.
+        name : str | None
+            Updates the name of the List.
+        private : bool | None
+            Determines whether the List should be private.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/put-lists-id
+        """
+        json = {}
+
+        if description is not None:
+            json["description"] = description
+
+        if name is not None:
+            json["name"] = name
+
+        if private is not None:
+            json["private"] = private
+
+        return await self._make_request(
+            "PUT", f"/2/lists/{id}", json=json, user_auth=user_auth
+        )
+
+    async def create_list(self, name, *, description=None, private=None,
+                          user_auth=True):
+        """Enables the authenticated user to create a List.
+
+        Parameters
+        ----------
+        name : str
+            The name of the List you wish to create.
+        description : str | None
+            Description of the List.
+        private : bool | None
+            Determine whether the List should be private.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-lists
+        """
+        json = {"name": name}
+
+        if description is not None:
+            json["description"] = description
+
+        if private is not None:
+            json["private"] = private
+
+        return await self._make_request(
+            "POST", f"/2/lists", json=json, user_auth=user_auth
+        )
+
+    # Pinned Lists
+
+    async def unpin_list(self, list_id, *, user_auth=True):
+        """Enables the authenticated user to unpin a List.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        list_id : int | str
+            The ID of the List that you would like the user to unpin.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/pinned-lists/api-reference/delete-users-id-pinned-lists-list_id
+        """
+        id = await self._get_authenticating_user_id(oauth_1=user_auth)
+        route = f"/2/users/{id}/pinned_lists/{list_id}"
+
+        return await self._make_request(
+            "DELETE", route, user_auth=user_auth
+        )
+
+    async def get_pinned_lists(self, *, user_auth=True, **params):
+        """get_pinned_lists(*, expansions=None, list_fields=None, \
+                            user_fields=None, user_auth=True)
+
+        Returns the Lists pinned by a specified user.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        expansions : list[str] | str | None
+            :ref:`expansions_parameter`
+        list_fields : list[str] | str | None
+            :ref:`list_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
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/pinned-lists/api-reference/get-users-id-pinned_lists
+        """
+        id = await self._get_authenticating_user_id(oauth_1=user_auth)
+        route = f"/2/users/{id}/pinned_lists"
+
+        return await self._make_request(
+            "GET", route, params=params,
+            endpoint_parameters=(
+                "expansions", "list.fields", "user.fields"
+            ), data_type=List, user_auth=user_auth
+        )
+
+    async def pin_list(self, list_id, *, user_auth=True):
+        """Enables the authenticated user to pin a List.
+
+        .. note::
+
+            When using OAuth 2.0 Authorization Code Flow with PKCE with
+            ``user_auth=False``, a request is made beforehand to Twitter's API
+            to determine the authenticating user's ID. This is cached and only
+            done once per :class:`Client` instance for each access token used.
+
+        Parameters
+        ----------
+        list_id : int | str
+            The ID of the List that you would like the user to pin.
+        user_auth : bool
+            Whether or not to use OAuth 1.0a User Context to authenticate
+
+        Raises
+        ------
+        TypeError
+            If the access token isn't set
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/lists/pinned-lists/api-reference/post-users-id-pinned-lists
+        """
+        id = await self._get_authenticating_user_id(oauth_1=user_auth)
+        route = f"/2/users/{id}/pinned_lists"
+
+        return await self._make_request(
+            "POST", route, json={"list_id": str(list_id)}, user_auth=user_auth
+        )
+
+    # Batch Compliance
+
+    async def get_compliance_jobs(self, type, **params):
+        """get_compliance_jobs(type, *, status=None)
+
+        Returns a list of recent compliance jobs.
+
+        Parameters
+        ----------
+        type : str
+            Allows to filter by job type - either by tweets or user ID. Only
+            one filter (tweets or users) can be specified per request.
+        status : str | None
+            Allows to filter by job status. Only one filter can be specified
+            per request.
+            Default: ``all``
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs
+        """
+        params["type"] = type
+        return await self._make_request(
+            "GET", "/2/compliance/jobs", params=params,
+            endpoint_parameters=("type", "status")
+        )
+
+    async def get_compliance_job(self, id):
+        """Get a single compliance job with the specified ID.
+
+        Parameters
+        ----------
+        id : int | str
+            The unique identifier for the compliance job you want to retrieve.
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs-id
+        """
+        return await self._make_request(
+            "GET", f"/2/compliance/jobs/{id}"
+        )
+
+    async def create_compliance_job(self, type, *, name=None, resumable=None):
+        """Creates a new compliance job for Tweet IDs or user IDs.
+
+        A compliance job will contain an ID and a destination URL. The
+        destination URL represents the location that contains the list of IDs
+        consumed by your app.
+
+        You can run one batch job at a time.
+
+        Parameters
+        ----------
+        type : str
+            Specify whether you will be uploading tweet or user IDs. You can
+            either specify tweets or users.
+        name : str | None
+            A name for this job, useful to identify multiple jobs using a label
+            you define.
+        resumable : bool | None
+            Specifies whether to enable the upload URL with support for
+            resumable uploads. If true, this endpoint will return a pre-signed
+            URL with resumable uploads enabled.
+
+        Returns
+        -------
+        dict | aiohttp.ClientResponse | Response
+
+        References
+        ----------
+        https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/post-compliance-jobs
+        """
+        json = {"type": type}
+
+        if name is not None:
+            json["name"] = name
+
+        if resumable is not None:
+            json["resumable"] = resumable
+
+        return await self._make_request(
+            "POST", "/2/compliance/jobs", json=json
+        )
index cea3efe799194da8b83124f5f823ee4a9d1c79d7..673a1458218b01c7398fefc8f718dd4ee17b8dba 100644 (file)
@@ -20,9 +20,13 @@ class HTTPException(TweepyException):
 
     .. versionadded:: 4.0
 
+    .. versionchanged:: 4.10
+        ``response`` attribute can be an instance of
+        :class:`aiohttp.ClientResponse`
+
     Attributes
     ----------
-    response : requests.Response
+    response : requests.Response | aiohttp.ClientResponse
         Requests Response from the Twitter API
     api_errors : list[dict[str, int | str]]
         The errors the Twitter API responded with, if any
@@ -32,7 +36,7 @@ class HTTPException(TweepyException):
         The error messages the Twitter API responded with, if any
     """
 
-    def __init__(self, response):
+    def __init__(self, response, *, response_json=None):
         self.response = response
 
         self.api_errors = []
@@ -40,44 +44,52 @@ class HTTPException(TweepyException):
         self.api_messages = []
 
         try:
-            response_json = response.json()
-        except requests.JSONDecodeError:
-            super().__init__(f"{response.status_code} {response.reason}")
-        else:
-            errors = response_json.get("errors", [])
-
-            # Use := when support for Python 3.7 is dropped
-            if "error" in response_json:
-                errors.append(response_json["error"])
-
-            error_text = ""
-
-            for error in errors:
-                self.api_errors.append(error)
-
-                if isinstance(error, str):
-                    self.api_messages.append(error)
-                    error_text += '\n' + error
-                    continue
-
-                if "code" in error:
-                    self.api_codes.append(error["code"])
-                if "message" in error:
-                    self.api_messages.append(error["message"])
-
-                if "code" in error and "message" in error:
-                    error_text += f"\n{error['code']} - {error['message']}"
-                elif "message" in error:
-                    error_text += '\n' + error["message"]
-
-            # Use := when support for Python 3.7 is dropped
-            if not error_text and "detail" in response_json:
-                self.api_messages.append(response_json["detail"])
-                error_text = '\n' + response_json["detail"]
-
-            super().__init__(
-                f"{response.status_code} {response.reason}{error_text}"
-            )
+            status_code = response.status_code
+        except AttributeError:
+            # response is an instance of aiohttp.ClientResponse
+            status_code = response.status
+
+        if response_json is None:
+            try:
+                response_json = response.json()
+            except requests.JSONDecodeError:
+                super().__init__(f"{status_code} {response.reason}")
+                return
+
+        errors = response_json.get("errors", [])
+
+        # Use := when support for Python 3.7 is dropped
+        if "error" in response_json:
+            errors.append(response_json["error"])
+
+        error_text = ""
+
+        for error in errors:
+            self.api_errors.append(error)
+
+            if isinstance(error, str):
+                self.api_messages.append(error)
+                error_text += '\n' + error
+                continue
+
+            if "code" in error:
+                self.api_codes.append(error["code"])
+            if "message" in error:
+                self.api_messages.append(error["message"])
+
+            if "code" in error and "message" in error:
+                error_text += f"\n{error['code']} - {error['message']}"
+            elif "message" in error:
+                error_text += '\n' + error["message"]
+
+        # Use := when support for Python 3.7 is dropped
+        if not error_text and "detail" in response_json:
+            self.api_messages.append(response_json["detail"])
+            error_text = '\n' + response_json["detail"]
+
+        super().__init__(
+            f"{status_code} {response.reason}{error_text}"
+        )
 
 
 class BadRequest(HTTPException):