From 6001ecbc6504d11d83fbebe0a3cffd83713e71bd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 21:01:29 +0000 Subject: [PATCH 1/3] feat(api): api update --- .stats.yml | 8 +- README.md | 9 +- api.md | 23 +- src/x_twitter_scraper/resources/draws.py | 20 +- src/x_twitter_scraper/resources/events.py | 16 +- .../resources/extractions.py | 1286 +++++++++++- .../resources/support/__init__.py | 14 + .../resources/support/attachments.py | 185 ++ .../resources/support/support.py | 38 + .../resources/x/communities/communities.py | 234 ++- src/x_twitter_scraper/resources/x/lists.py | 238 ++- .../resources/x/tweets/tweets.py | 1079 ++++++++-- .../resources/x/users/users.py | 1747 +++++++++++++++-- .../types/draw_export_params.py | 6 +- .../types/draw_list_params.py | 2 +- .../types/event_list_params.py | 7 +- .../types/extraction_estimate_cost_params.py | 296 ++- .../extraction_estimate_cost_response.py | 1 + .../types/extraction_export_results_params.py | 60 +- .../types/extraction_list_params.py | 2 +- .../types/extraction_retrieve_params.py | 18 +- .../types/extraction_run_params.py | 219 ++- .../types/extraction_run_response.py | 43 +- src/x_twitter_scraper/types/monitor.py | 9 +- src/x_twitter_scraper/types/shared/error.py | 8 + .../types/shared/paginated_tweets.py | 5 +- .../types/shared/paginated_users.py | 2 +- src/x_twitter_scraper/types/x/__init__.py | 6 + .../x/community_retrieve_members_params.py | 42 + .../x/community_retrieve_moderators_params.py | 46 +- .../types/x/list_retrieve_followers_params.py | 47 +- .../types/x/list_retrieve_members_params.py | 42 + .../types/x/tweet_get_favoriters_params.py | 47 +- .../types/x/tweet_get_quotes_params.py | 57 + .../types/x/tweet_get_replies_params.py | 104 +- .../types/x/tweet_get_replies_response.py | 4 +- .../types/x/tweet_get_retweeters_params.py | 47 +- .../types/x/tweet_search_params.py | 84 +- .../types/x/tweet_search_response.py | 102 + .../types/x/user_retrieve_followers_params.py | 68 +- .../x/user_retrieve_followers_response.py | 81 + ...user_retrieve_followers_you_know_params.py | 47 +- .../types/x/user_retrieve_following_params.py | 68 +- .../x/user_retrieve_following_response.py | 81 + .../types/x/user_retrieve_likes_params.py | 57 + .../types/x/user_retrieve_media_params.py | 57 + .../types/x/user_retrieve_mentions_params.py | 57 + .../types/x/user_retrieve_replies_params.py | 69 +- .../types/x/user_retrieve_search_params.py | 46 +- .../types/x/user_retrieve_tweets_params.py | 69 +- ...user_retrieve_verified_followers_params.py | 72 +- ...er_retrieve_verified_followers_response.py | 81 + src/x_twitter_scraper/types/x/x_account.py | 10 +- .../api_resources/support/test_attachments.py | 176 ++ tests/api_resources/test_events.py | 2 + tests/api_resources/test_extractions.py | 324 ++- tests/api_resources/x/test_communities.py | 56 + tests/api_resources/x/test_lists.py | 56 + tests/api_resources/x/test_tweets.py | 209 +- tests/api_resources/x/test_users.py | 399 +++- 60 files changed, 7620 insertions(+), 668 deletions(-) create mode 100644 src/x_twitter_scraper/resources/support/attachments.py create mode 100644 src/x_twitter_scraper/types/x/tweet_search_response.py create mode 100644 src/x_twitter_scraper/types/x/user_retrieve_followers_response.py create mode 100644 src/x_twitter_scraper/types/x/user_retrieve_following_response.py create mode 100644 src/x_twitter_scraper/types/x/user_retrieve_verified_followers_response.py create mode 100644 tests/api_resources/support/test_attachments.py diff --git a/.stats.yml b/.stats.yml index ec9dedf..f192b6e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 123 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/xquik/x-twitter-scraper-5f26f3694399b4ac5a4431c66f7d27c4024f9d0dcd899702de5fde1150e28330.yml -openapi_spec_hash: 362e24e622f9a74ded8b38018e50460c -config_hash: dab26921eb273c16e5570c0485c9ac2c +configured_endpoints: 124 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/xquik/x-twitter-scraper-7bcac1557175956021a62532c55ce29b8822b5a41d0d59ae67787a6326c0ef8a.yml +openapi_spec_hash: 04e28f19097d9b59119101492100c4ab +config_hash: 217d68ca6999ad03cfc4922e9658297e diff --git a/README.md b/README.md index d54f1ce..f84f867 100644 --- a/README.md +++ b/README.md @@ -123,11 +123,10 @@ client = XTwitterScraper( api_key=os.environ.get("X_TWITTER_SCRAPER_API_KEY"), # This is the default and can be omitted ) -paginated_tweets = client.x.tweets.search( +response = client.x.tweets.search( q="from:elonmusk", limit=10, ) -print(paginated_tweets.has_next_page) ``` While you can provide an `api_key` keyword argument, @@ -150,11 +149,10 @@ client = AsyncXTwitterScraper( async def main() -> None: - paginated_tweets = await client.x.tweets.search( + response = await client.x.tweets.search( q="from:elonmusk", limit=10, ) - print(paginated_tweets.has_next_page) asyncio.run(main()) @@ -189,11 +187,10 @@ async def main() -> None: ), # This is the default and can be omitted http_client=DefaultAioHttpClient(), ) as client: - paginated_tweets = await client.x.tweets.search( + response = await client.x.tweets.search( q="from:elonmusk", limit=10, ) - print(paginated_tweets.has_next_page) asyncio.run(main()) diff --git a/api.md b/api.md index b652b9b..ff10877 100644 --- a/api.md +++ b/api.md @@ -277,6 +277,7 @@ from x_twitter_scraper.types.x import ( TweetRetrieveResponse, TweetDeleteResponse, TweetGetRepliesResponse, + TweetSearchResponse, ) ``` @@ -291,7 +292,7 @@ Methods: - client.x.tweets.get_replies(id, \*\*params) -> TweetGetRepliesResponse - client.x.tweets.get_retweeters(id, \*\*params) -> PaginatedUsers - client.x.tweets.get_thread(id, \*\*params) -> PaginatedTweets -- client.x.tweets.search(\*\*params) -> PaginatedTweets +- client.x.tweets.search(\*\*params) -> TweetSearchResponse ### Like @@ -324,7 +325,13 @@ Methods: Types: ```python -from x_twitter_scraper.types.x import UserRemoveFollowerResponse, UserRetrieveBatchResponse +from x_twitter_scraper.types.x import ( + UserRemoveFollowerResponse, + UserRetrieveBatchResponse, + UserRetrieveFollowersResponse, + UserRetrieveFollowingResponse, + UserRetrieveVerifiedFollowersResponse, +) ``` Methods: @@ -332,16 +339,16 @@ Methods: - client.x.users.retrieve(id) -> UserProfile - client.x.users.remove_follower(id, \*\*params) -> UserRemoveFollowerResponse - client.x.users.retrieve_batch(\*\*params) -> UserRetrieveBatchResponse -- client.x.users.retrieve_followers(id, \*\*params) -> PaginatedUsers +- client.x.users.retrieve_followers(id, \*\*params) -> UserRetrieveFollowersResponse - client.x.users.retrieve_followers_you_know(id, \*\*params) -> PaginatedUsers -- client.x.users.retrieve_following(id, \*\*params) -> PaginatedUsers +- client.x.users.retrieve_following(id, \*\*params) -> UserRetrieveFollowingResponse - client.x.users.retrieve_likes(id, \*\*params) -> PaginatedTweets - client.x.users.retrieve_media(id, \*\*params) -> PaginatedTweets - client.x.users.retrieve_mentions(id, \*\*params) -> PaginatedTweets - client.x.users.retrieve_replies(id, \*\*params) -> PaginatedTweets - client.x.users.retrieve_search(\*\*params) -> PaginatedUsers - client.x.users.retrieve_tweets(id, \*\*params) -> PaginatedTweets -- client.x.users.retrieve_verified_followers(id, \*\*params) -> PaginatedUsers +- client.x.users.retrieve_verified_followers(id, \*\*params) -> UserRetrieveVerifiedFollowersResponse ### Follow @@ -537,6 +544,12 @@ Methods: # Support +## Attachments + +Methods: + +- client.support.attachments.download(id) -> BinaryAPIResponse + ## Tickets Types: diff --git a/src/x_twitter_scraper/resources/draws.py b/src/x_twitter_scraper/resources/draws.py index cad659f..42bc4a7 100644 --- a/src/x_twitter_scraper/resources/draws.py +++ b/src/x_twitter_scraper/resources/draws.py @@ -108,7 +108,7 @@ def list( List draws Args: - cursor: Cursor for keyset pagination from prior response next_cursor + cursor: Previous nextCursor. limit: Maximum number of items to return (1-100, default 50). For paid per-result endpoints, the returned count may be lower when remaining credits cannot cover @@ -154,11 +154,13 @@ def export( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BinaryAPIResponse: - """ - Export draw data + """Export draw data Args: - format: Export output format + format: Export output format. + + PDF entry exports include up to 10,000 rows. Other entry + formats include up to 100,000 rows. type: Export winners or all entries @@ -326,7 +328,7 @@ async def list( List draws Args: - cursor: Cursor for keyset pagination from prior response next_cursor + cursor: Previous nextCursor. limit: Maximum number of items to return (1-100, default 50). For paid per-result endpoints, the returned count may be lower when remaining credits cannot cover @@ -372,11 +374,13 @@ async def export( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncBinaryAPIResponse: - """ - Export draw data + """Export draw data Args: - format: Export output format + format: Export output format. + + PDF entry exports include up to 10,000 rows. Other entry + formats include up to 100,000 rows. type: Export winners or all entries diff --git a/src/x_twitter_scraper/resources/events.py b/src/x_twitter_scraper/resources/events.py index 3b1ff17..3d7ae5a 100644 --- a/src/x_twitter_scraper/resources/events.py +++ b/src/x_twitter_scraper/resources/events.py @@ -87,6 +87,7 @@ def list( *, cursor: str | Omit = omit, event_type: EventType | Omit = omit, + keyword_monitor_id: str | Omit = omit, limit: int | Omit = omit, monitor_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -100,16 +101,18 @@ def list( List events Args: - cursor: Cursor for keyset pagination from prior response next_cursor + cursor: Previous nextCursor. event_type: Filter events by type + keyword_monitor_id: Keyword monitor ID. + limit: Maximum number of items to return (1-100, default 50). For paid per-result endpoints, the returned count may be lower when remaining credits cannot cover the requested page. If zero paid results are affordable, the endpoint returns 402 insufficient_credits. - monitor_id: Filter events by monitor ID + monitor_id: Account monitor ID. extra_headers: Send extra headers @@ -130,6 +133,7 @@ def list( { "cursor": cursor, "event_type": event_type, + "keyword_monitor_id": keyword_monitor_id, "limit": limit, "monitor_id": monitor_id, }, @@ -200,6 +204,7 @@ async def list( *, cursor: str | Omit = omit, event_type: EventType | Omit = omit, + keyword_monitor_id: str | Omit = omit, limit: int | Omit = omit, monitor_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -213,16 +218,18 @@ async def list( List events Args: - cursor: Cursor for keyset pagination from prior response next_cursor + cursor: Previous nextCursor. event_type: Filter events by type + keyword_monitor_id: Keyword monitor ID. + limit: Maximum number of items to return (1-100, default 50). For paid per-result endpoints, the returned count may be lower when remaining credits cannot cover the requested page. If zero paid results are affordable, the endpoint returns 402 insufficient_credits. - monitor_id: Filter events by monitor ID + monitor_id: Account monitor ID. extra_headers: Send extra headers @@ -243,6 +250,7 @@ async def list( { "cursor": cursor, "event_type": event_type, + "keyword_monitor_id": keyword_monitor_id, "limit": limit, "monitor_id": monitor_id, }, diff --git a/src/x_twitter_scraper/resources/extractions.py b/src/x_twitter_scraper/resources/extractions.py index 324bcf0..d7481b0 100644 --- a/src/x_twitter_scraper/resources/extractions.py +++ b/src/x_twitter_scraper/resources/extractions.py @@ -6,8 +6,8 @@ from __future__ import annotations -from typing import Union -from datetime import date +from typing import Union, Iterable +from datetime import date, datetime from typing_extensions import Literal import httpx @@ -19,7 +19,7 @@ extraction_estimate_cost_params, extraction_export_results_params, ) -from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -73,7 +73,11 @@ def retrieve( id: str, *, cursor: str | Omit = omit, + field_style: Literal["source", "camelCase", "snake_case"] | Omit = omit, + include_raw: bool | Omit = omit, limit: int | Omit = omit, + output_mode: Literal["compact", "full", "raw"] | Omit = omit, + output_preset: Literal["nested", "flat"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -85,10 +89,18 @@ def retrieve( Get extraction results Args: - cursor: Cursor for keyset pagination from prior response next_cursor + cursor: Previous nextCursor. + + field_style: Preserve source keys or convert result field names. + + include_raw: Use outputMode=raw instead. limit: Maximum number of results to return (1-1000, default 100) + output_mode: Select compact, full, or raw-compatible result fields. + + output_preset: Keep enrichment nested or merge it into each result. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -109,7 +121,11 @@ def retrieve( query=maybe_transform( { "cursor": cursor, + "field_style": field_style, + "include_raw": include_raw, "limit": limit, + "output_mode": output_mode, + "output_preset": output_preset, }, extraction_retrieve_params.ExtractionRetrieveParams, ), @@ -160,7 +176,7 @@ def list( List extraction jobs Args: - cursor: Cursor for keyset pagination from prior response next_cursor + cursor: Previous nextCursor. limit: Maximum number of items to return (1-100, default 50). For paid per-result endpoints, the returned count may be lower when remaining credits cannot cover @@ -229,42 +245,99 @@ def estimate_cost( ], advanced_query: str | Omit = omit, any_words: str | Omit = omit, + bio_contains: str | Omit = omit, + blue_verified_only: bool | Omit = omit, bounding_box: str | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, + collection_strategy: Literal["auto", "complete", "direct", "search", "thread"] | Omit = omit, conversation_id: str | Omit = omit, + dedupe_across_targets: bool | Omit = omit, + dedupe_mode: Literal["none", "first", "merge"] | Omit = omit, exact_phrase: str | Omit = omit, + exclude_original_author: bool | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, + has_location: bool | Omit = omit, + has_media_only: bool | Omit = omit, + has_website: bool | Omit = omit, + include_original_post: bool | Omit = omit, + include_search_terms: bool | Omit = omit, + include_target_metadata: bool | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, list_id: str | Omit = omit, + location_contains: str | Omit = omit, + max_depth: int | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_id: str | Omit = omit, + max_items_per_target: int | Omit = omit, + max_likes: int | Omit = omit, + max_pages_per_target: int | Omit = omit, + max_posts: int | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_account_age_days: int | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_posts: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, + overlap_mode: bool | Omit = omit, place: str | Omit = omit, place_country: str | Omit = omit, point_radius: str | Omit = omit, + query_type: Literal["Latest", "Top", "Both"] | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, + relation_targets: Iterable[extraction_estimate_cost_params.RelationTarget] | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, results_limit: int | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, + scope: Literal["all", "direct", "nested"] | Omit = omit, + search_queries: SequenceNotStr[str] | Omit = omit, search_query: str | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, + since_time: Union[Union[str, datetime], int] | Omit = omit, + sort: Literal["relevance", "latest", "oldest", "likes"] | Omit = omit, + source: str | Omit = omit, + start_cursor: str | Omit = omit, target_community_id: str | Omit = omit, + target_community_ids: SequenceNotStr[str] | Omit = omit, target_list_id: str | Omit = omit, + target_list_ids: SequenceNotStr[str] | Omit = omit, + targets: SequenceNotStr[extraction_estimate_cost_params.Target] | Omit = omit, target_space_id: str | Omit = omit, target_tweet_id: str | Omit = omit, + target_tweet_ids: SequenceNotStr[str] | Omit = omit, target_username: str | Omit = omit, + target_usernames: SequenceNotStr[str] | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, + until_time: Union[Union[str, datetime], int] | Omit = omit, url: str | Omit = omit, + username_contains: str | Omit = omit, verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -278,83 +351,195 @@ def estimate_cost( Args: tool_type: Identifier for the extraction tool used to run a job. - advanced_query: Raw advanced query string appended to the estimate (tweet_search_extractor) + advanced_query: Raw advanced search query appended as-is (tweet_search_extractor) + + any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, + or lines. (tweet_search_extractor) + + bio_contains: Bio terms separated by commas or lines. + + blue_verified_only: Return only Blue-verified Tweet authors. + + bounding_box: Geo bounding box, e.g. -74.1 40.6 -73.9 40.8 (tweet_search_extractor) + + card_name: Match the Tweet card name. + + cashtags: Cashtags separated by spaces, commas, or lines. (tweet_search_extractor) + + collection_strategy: Reply collection strategy. + + conversation_id: Conversation ID filter (tweet_search_extractor) + + dedupe_across_targets: Merge duplicate results across collection targets. + + dedupe_mode: Keep target duplicates, first rows, or merged overlap. + + exact_phrase: Exact phrase to match (tweet_search_extractor) + + exclude_original_author: Exclude replies from the source author. - any_words: Alternative words or quoted phrases for estimated results. Separate with spaces, - commas, or lines. + exclude_source: Exclude a source application. - bounding_box: Geo bounding box used for estimation, e.g. -74.1 40.6 -73.9 40.8 + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. (tweet_search_extractor) - cashtags: Cashtags applied to the estimate, separated by spaces, commas, or lines. + from_user: Filter by author username (tweet_search_extractor) - conversation_id: Conversation ID filter used for estimation (tweet_search_extractor) + geocode: Match latitude, longitude, and radius. - exact_phrase: Exact phrase filter for search estimation + hashtags: Hashtags separated by spaces, commas, or lines. (tweet_search_extractor) - exclude_words: Words or quoted phrases excluded from estimated results. Separate with spaces, - commas, or lines. + has_location: Require a profile location. - from_user: Estimate only tweets from this author username (tweet_search_extractor) + has_media_only: Return only replies with media. - hashtags: Hashtags applied to the estimate, separated by spaces, commas, or lines. + has_website: Require a profile website. - in_reply_to_tweet_id: Estimate only replies to this tweet ID (tweet_search_extractor) + include_original_post: Include the source post in reply results. - language: Language code used for estimate filtering (tweet_search_extractor) + include_search_terms: Add matching search terms to collection metadata. - list_id: Estimate search results within this list ID (tweet_search_extractor) + include_target_metadata: Add source target metadata to each result. - media_type: Media type used for estimate filtering (tweet_search_extractor) + in_reply_to_tweet_id: Only replies to this tweet ID (tweet_search_extractor) - mentioning: Estimate tweets mentioning this username (tweet_search_extractor) + language: Language code filter (tweet_search_extractor) - min_faves: Minimum likes threshold for estimated results (tweet_search_extractor) + list_id: Search within a list ID (tweet_search_extractor) - min_quotes: Minimum quote count threshold for estimated results (tweet_search_extractor) + location_contains: Required profile location text. - min_replies: Minimum replies threshold for estimated results (tweet_search_extractor) + max_depth: Maximum nested reply depth. - min_retweets: Minimum retweets threshold for estimated results (tweet_search_extractor) + max_followers: Maximum follower count for profile results. - place: Estimate search results within this place ID (tweet_search_extractor) + max_following: Maximum following count for profile results. - place_country: Estimate search results within this country code (tweet_search_extractor) + max_id: Return Tweets older than this Tweet ID. - point_radius: Geo point radius used for estimation, e.g. -73.99 40.73 25mi - (tweet_search_extractor) + max_items_per_target: Maximum results collected for each target. + + max_likes: Maximum Tweet like count. + + max_pages_per_target: Reply pages collected for each target. + + max_posts: Maximum post count for profile results. + + max_quotes: Maximum Tweet quote count. + + max_replies: Maximum Tweet reply count. + + max_retweets: Maximum Tweet repost count. + + media_type: Media type filter (tweet_search_extractor) + + mentioning: Filter tweets mentioning a username (tweet_search_extractor) + + min_account_age_days: Minimum profile age in days. + + min_bookmarks: Minimum Tweet bookmark count. + + min_faves: Minimum likes threshold (tweet_search_extractor) + + min_followers: Minimum follower count for profile results. + + min_following: Minimum following count for profile results. + + min_posts: Minimum post count for profile results. - quotes: Quote mode used for estimation (tweet_search_extractor) + min_quotes: Minimum quote count threshold (tweet_search_extractor) + + min_replies: Minimum replies threshold (tweet_search_extractor) + + min_retweets: Minimum retweets threshold (tweet_search_extractor) + + min_views: Minimum Tweet view count. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + + overlap_mode: Shortcut for dedupeMode=merge. + + place: Search within a place ID (tweet_search_extractor) - quotes_of_tweet_id: Estimate only quotes of this tweet ID (tweet_search_extractor) + place_country: Search within a country code (tweet_search_extractor) + + point_radius: Geo point radius, e.g. -73.99 40.73 25mi (tweet_search_extractor) + + query_type: Search ranking applied to every query. + + quotes: Quote mode (tweet_search_extractor) - replies: Reply mode used for estimation (tweet_search_extractor) + quotes_of_tweet_id: Only quotes of this tweet ID (tweet_search_extractor) - results_limit: Maximum number of results to estimate. When set, the estimate caps projected - results to this value. + relation_targets: Profile relations processed within one job. - retweets: Retweet mode used for estimation (tweet_search_extractor) + replies: Reply mode (tweet_search_extractor) - retweets_of_tweet_id: Estimate only retweets of this tweet ID (tweet_search_extractor) + results_limit: Maximum number of results to extract. When set, the extraction stops after + reaching this limit. - search_query: Query used to price tweet_search_extractor or community_search. + retweets: Retweet mode (tweet_search_extractor) - since_date: Estimate start date in YYYY-MM-DD format (tweet_search_extractor) + retweets_of_tweet_id: Only retweets of this tweet ID (tweet_search_extractor) - target_community_id: Community ID used to price community_post_extractor or community_search. + safe: Enable the safe-search filter. - target_list_id: List ID used to price list_follower_explorer, list_member_extractor, or + scope: Reply depth scope. + + search_queries: Search queries processed as one collection job. + + search_query: Required for tweet_search_extractor & community_search. + + since_date: Start date YYYY-MM-DD (tweet_search_extractor) + + since_id: Return Tweets newer than this Tweet ID. + + since_time: Reply start time as ISO 8601 or Unix seconds. + + sort: Reply result order. + + source: Match the source application. + + start_cursor: Resume one reply target from this cursor. + + target_community_id: Required for community_post_extractor & community_search. + + target_community_ids: Community IDs processed as one collection job. + + target_list_id: Required for list_follower_explorer, list_member_extractor & list_post_extractor. - target_space_id: Space ID used to price space_explorer. + target_list_ids: List IDs processed as one collection job. - to_user: Estimate replies sent to this username (tweet_search_extractor) + targets: Mixed targets auto-routed within one job. - until_date: Estimate end date in YYYY-MM-DD format (tweet_search_extractor) + target_space_id: Required for space_explorer. + + target_tweet_ids: Tweet IDs processed as one collection job. - url: URL substring or domain filter used for estimation (tweet_search_extractor) + target_usernames: Usernames processed as one collection job. - verified_only: Estimate only verified authors (tweet_search_extractor) + to_user: Filter replies sent to a username (tweet_search_extractor) + + until_date: End date YYYY-MM-DD (tweet_search_extractor) + + until_time: Reply end time as ISO 8601 or Unix seconds. + + url: URL substring or domain filter (tweet_search_extractor) + + username_contains: Required username text. + + verified_only: Only verified authors (tweet_search_extractor) + + verified_type: Exact profile verification type. + + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. extra_headers: Send extra headers @@ -371,42 +556,99 @@ def estimate_cost( "tool_type": tool_type, "advanced_query": advanced_query, "any_words": any_words, + "bio_contains": bio_contains, + "blue_verified_only": blue_verified_only, "bounding_box": bounding_box, + "card_name": card_name, "cashtags": cashtags, + "collection_strategy": collection_strategy, "conversation_id": conversation_id, + "dedupe_across_targets": dedupe_across_targets, + "dedupe_mode": dedupe_mode, "exact_phrase": exact_phrase, + "exclude_original_author": exclude_original_author, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, + "has_location": has_location, + "has_media_only": has_media_only, + "has_website": has_website, + "include_original_post": include_original_post, + "include_search_terms": include_search_terms, + "include_target_metadata": include_target_metadata, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, "list_id": list_id, + "location_contains": location_contains, + "max_depth": max_depth, + "max_followers": max_followers, + "max_following": max_following, + "max_id": max_id, + "max_items_per_target": max_items_per_target, + "max_likes": max_likes, + "max_pages_per_target": max_pages_per_target, + "max_posts": max_posts, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_account_age_days": min_account_age_days, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, + "min_followers": min_followers, + "min_following": min_following, + "min_posts": min_posts, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, + "overlap_mode": overlap_mode, "place": place, "place_country": place_country, "point_radius": point_radius, + "query_type": query_type, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, + "relation_targets": relation_targets, "replies": replies, "results_limit": results_limit, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, + "scope": scope, + "search_queries": search_queries, "search_query": search_query, "since_date": since_date, + "since_id": since_id, + "since_time": since_time, + "sort": sort, + "source": source, + "start_cursor": start_cursor, "target_community_id": target_community_id, + "target_community_ids": target_community_ids, "target_list_id": target_list_id, + "target_list_ids": target_list_ids, + "targets": targets, "target_space_id": target_space_id, "target_tweet_id": target_tweet_id, + "target_tweet_ids": target_tweet_ids, "target_username": target_username, + "target_usernames": target_usernames, "to_user": to_user, "until_date": until_date, + "until_time": until_time, "url": url, + "username_contains": username_contains, "verified_only": verified_only, + "verified_type": verified_type, + "within": within, + "within_time": within_time, }, extraction_estimate_cost_params.ExtractionEstimateCostParams, ), @@ -421,6 +663,24 @@ def export_results( id: str, *, format: Literal["csv", "json", "md", "md-document", "pdf", "txt", "xlsx"], + has_description: bool | Omit = omit, + has_location: bool | Omit = omit, + has_media: bool | Omit = omit, + lang: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_posts: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_likes: int | Omit = omit, + min_posts: int | Omit = omit, + min_replies: int | Omit = omit, + min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + search: str | Omit = omit, + since_date: Union[str, date] | Omit = omit, + until_date: Union[str, date] | Omit = omit, + verified: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -434,6 +694,42 @@ def export_results( Args: format: Export file format + has_description: Require a non-empty description. + + has_location: Require a non-empty location. + + has_media: Require media. + + lang: Filter by language code. + + max_followers: Maximum follower count. + + max_following: Maximum following count. + + max_posts: Maximum post count. + + min_followers: Minimum follower count. + + min_following: Minimum following count. + + min_likes: Minimum like count. + + min_posts: Minimum post count. + + min_replies: Minimum reply count. + + min_retweets: Minimum repost count. + + min_views: Minimum view count. + + search: Search exported result text. + + since_date: Include results on or after this date. + + until_date: Include results on or before this date. + + verified: Filter by verified status. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -453,7 +749,28 @@ def export_results( extra_body=extra_body, timeout=timeout, query=maybe_transform( - {"format": format}, extraction_export_results_params.ExtractionExportResultsParams + { + "format": format, + "has_description": has_description, + "has_location": has_location, + "has_media": has_media, + "lang": lang, + "max_followers": max_followers, + "max_following": max_following, + "max_posts": max_posts, + "min_followers": min_followers, + "min_following": min_following, + "min_likes": min_likes, + "min_posts": min_posts, + "min_replies": min_replies, + "min_retweets": min_retweets, + "min_views": min_views, + "search": search, + "since_date": since_date, + "until_date": until_date, + "verified": verified, + }, + extraction_export_results_params.ExtractionExportResultsParams, ), ), cast_to=BinaryAPIResponse, @@ -487,44 +804,102 @@ def run( "user_media", "verified_follower_explorer", ], + dry_run: bool | Omit = omit, advanced_query: str | Omit = omit, any_words: str | Omit = omit, + bio_contains: str | Omit = omit, + blue_verified_only: bool | Omit = omit, bounding_box: str | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, + collection_strategy: Literal["auto", "complete", "direct", "search", "thread"] | Omit = omit, conversation_id: str | Omit = omit, + dedupe_across_targets: bool | Omit = omit, + dedupe_mode: Literal["none", "first", "merge"] | Omit = omit, exact_phrase: str | Omit = omit, + exclude_original_author: bool | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, + has_location: bool | Omit = omit, + has_media_only: bool | Omit = omit, + has_website: bool | Omit = omit, + include_original_post: bool | Omit = omit, + include_search_terms: bool | Omit = omit, + include_target_metadata: bool | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, list_id: str | Omit = omit, + location_contains: str | Omit = omit, + max_depth: int | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_id: str | Omit = omit, + max_items_per_target: int | Omit = omit, + max_likes: int | Omit = omit, + max_pages_per_target: int | Omit = omit, + max_posts: int | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_account_age_days: int | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_posts: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, + overlap_mode: bool | Omit = omit, place: str | Omit = omit, place_country: str | Omit = omit, point_radius: str | Omit = omit, + query_type: Literal["Latest", "Top", "Both"] | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, + relation_targets: Iterable[extraction_run_params.RelationTarget] | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, results_limit: int | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, + scope: Literal["all", "direct", "nested"] | Omit = omit, + search_queries: SequenceNotStr[str] | Omit = omit, search_query: str | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, + since_time: Union[Union[str, datetime], int] | Omit = omit, + sort: Literal["relevance", "latest", "oldest", "likes"] | Omit = omit, + source: str | Omit = omit, + start_cursor: str | Omit = omit, target_community_id: str | Omit = omit, + target_community_ids: SequenceNotStr[str] | Omit = omit, target_list_id: str | Omit = omit, + target_list_ids: SequenceNotStr[str] | Omit = omit, + targets: SequenceNotStr[extraction_run_params.Target] | Omit = omit, target_space_id: str | Omit = omit, target_tweet_id: str | Omit = omit, + target_tweet_ids: SequenceNotStr[str] | Omit = omit, target_username: str | Omit = omit, + target_usernames: SequenceNotStr[str] | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, + until_time: Union[Union[str, datetime], int] | Omit = omit, url: str | Omit = omit, + username_contains: str | Omit = omit, verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -538,54 +913,134 @@ def run( Args: tool_type: Identifier for the extraction tool used to run a job. + dry_run: Estimate cost without creating an extraction. + advanced_query: Raw advanced search query appended as-is (tweet_search_extractor) any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. (tweet_search_extractor) + bio_contains: Bio terms separated by commas or lines. + + blue_verified_only: Return only Blue-verified Tweet authors. + bounding_box: Geo bounding box, e.g. -74.1 40.6 -73.9 40.8 (tweet_search_extractor) + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. (tweet_search_extractor) + collection_strategy: Reply collection strategy. + conversation_id: Conversation ID filter (tweet_search_extractor) + dedupe_across_targets: Merge duplicate results across collection targets. + + dedupe_mode: Keep target duplicates, first rows, or merged overlap. + exact_phrase: Exact phrase to match (tweet_search_extractor) + exclude_original_author: Exclude replies from the source author. + + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. (tweet_search_extractor) from_user: Filter by author username (tweet_search_extractor) + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. (tweet_search_extractor) + has_location: Require a profile location. + + has_media_only: Return only replies with media. + + has_website: Require a profile website. + + include_original_post: Include the source post in reply results. + + include_search_terms: Add matching search terms to collection metadata. + + include_target_metadata: Add source target metadata to each result. + in_reply_to_tweet_id: Only replies to this tweet ID (tweet_search_extractor) language: Language code filter (tweet_search_extractor) list_id: Search within a list ID (tweet_search_extractor) + location_contains: Required profile location text. + + max_depth: Maximum nested reply depth. + + max_followers: Maximum follower count for profile results. + + max_following: Maximum following count for profile results. + + max_id: Return Tweets older than this Tweet ID. + + max_items_per_target: Maximum results collected for each target. + + max_likes: Maximum Tweet like count. + + max_pages_per_target: Reply pages collected for each target. + + max_posts: Maximum post count for profile results. + + max_quotes: Maximum Tweet quote count. + + max_replies: Maximum Tweet reply count. + + max_retweets: Maximum Tweet repost count. + media_type: Media type filter (tweet_search_extractor) mentioning: Filter tweets mentioning a username (tweet_search_extractor) + min_account_age_days: Minimum profile age in days. + + min_bookmarks: Minimum Tweet bookmark count. + min_faves: Minimum likes threshold (tweet_search_extractor) + min_followers: Minimum follower count for profile results. + + min_following: Minimum following count for profile results. + + min_posts: Minimum post count for profile results. + min_quotes: Minimum quote count threshold (tweet_search_extractor) min_replies: Minimum replies threshold (tweet_search_extractor) min_retweets: Minimum retweets threshold (tweet_search_extractor) + min_views: Minimum Tweet view count. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + + overlap_mode: Shortcut for dedupeMode=merge. + place: Search within a place ID (tweet_search_extractor) place_country: Search within a country code (tweet_search_extractor) point_radius: Geo point radius, e.g. -73.99 40.73 25mi (tweet_search_extractor) + query_type: Search ranking applied to every query. + quotes: Quote mode (tweet_search_extractor) quotes_of_tweet_id: Only quotes of this tweet ID (tweet_search_extractor) + relation_targets: Profile relations processed within one job. + replies: Reply mode (tweet_search_extractor) results_limit: Maximum number of results to extract. When set, the extraction stops after @@ -595,25 +1050,61 @@ def run( retweets_of_tweet_id: Only retweets of this tweet ID (tweet_search_extractor) + safe: Enable the safe-search filter. + + scope: Reply depth scope. + + search_queries: Search queries processed as one collection job. + search_query: Required for tweet_search_extractor & community_search. since_date: Start date YYYY-MM-DD (tweet_search_extractor) + since_id: Return Tweets newer than this Tweet ID. + + since_time: Reply start time as ISO 8601 or Unix seconds. + + sort: Reply result order. + + source: Match the source application. + + start_cursor: Resume one reply target from this cursor. + target_community_id: Required for community_post_extractor & community_search. + target_community_ids: Community IDs processed as one collection job. + target_list_id: Required for list_follower_explorer, list_member_extractor & list_post_extractor. + target_list_ids: List IDs processed as one collection job. + + targets: Mixed targets auto-routed within one job. + target_space_id: Required for space_explorer. + target_tweet_ids: Tweet IDs processed as one collection job. + + target_usernames: Usernames processed as one collection job. + to_user: Filter replies sent to a username (tweet_search_extractor) until_date: End date YYYY-MM-DD (tweet_search_extractor) + until_time: Reply end time as ISO 8601 or Unix seconds. + url: URL substring or domain filter (tweet_search_extractor) + username_contains: Required username text. + verified_only: Only verified authors (tweet_search_extractor) + verified_type: Exact profile verification type. + + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -629,47 +1120,108 @@ def run( "tool_type": tool_type, "advanced_query": advanced_query, "any_words": any_words, + "bio_contains": bio_contains, + "blue_verified_only": blue_verified_only, "bounding_box": bounding_box, + "card_name": card_name, "cashtags": cashtags, + "collection_strategy": collection_strategy, "conversation_id": conversation_id, + "dedupe_across_targets": dedupe_across_targets, + "dedupe_mode": dedupe_mode, "exact_phrase": exact_phrase, + "exclude_original_author": exclude_original_author, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, + "has_location": has_location, + "has_media_only": has_media_only, + "has_website": has_website, + "include_original_post": include_original_post, + "include_search_terms": include_search_terms, + "include_target_metadata": include_target_metadata, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, "list_id": list_id, + "location_contains": location_contains, + "max_depth": max_depth, + "max_followers": max_followers, + "max_following": max_following, + "max_id": max_id, + "max_items_per_target": max_items_per_target, + "max_likes": max_likes, + "max_pages_per_target": max_pages_per_target, + "max_posts": max_posts, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_account_age_days": min_account_age_days, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, + "min_followers": min_followers, + "min_following": min_following, + "min_posts": min_posts, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, + "overlap_mode": overlap_mode, "place": place, "place_country": place_country, "point_radius": point_radius, + "query_type": query_type, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, + "relation_targets": relation_targets, "replies": replies, "results_limit": results_limit, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, + "scope": scope, + "search_queries": search_queries, "search_query": search_query, "since_date": since_date, + "since_id": since_id, + "since_time": since_time, + "sort": sort, + "source": source, + "start_cursor": start_cursor, "target_community_id": target_community_id, + "target_community_ids": target_community_ids, "target_list_id": target_list_id, + "target_list_ids": target_list_ids, + "targets": targets, "target_space_id": target_space_id, "target_tweet_id": target_tweet_id, + "target_tweet_ids": target_tweet_ids, "target_username": target_username, + "target_usernames": target_usernames, "to_user": to_user, "until_date": until_date, + "until_time": until_time, "url": url, + "username_contains": username_contains, "verified_only": verified_only, + "verified_type": verified_type, + "within": within, + "within_time": within_time, }, extraction_run_params.ExtractionRunParams, ), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"dry_run": dry_run}, extraction_run_params.ExtractionRunParams), ), cast_to=ExtractionRunResponse, ) @@ -702,7 +1254,11 @@ async def retrieve( id: str, *, cursor: str | Omit = omit, + field_style: Literal["source", "camelCase", "snake_case"] | Omit = omit, + include_raw: bool | Omit = omit, limit: int | Omit = omit, + output_mode: Literal["compact", "full", "raw"] | Omit = omit, + output_preset: Literal["nested", "flat"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -714,10 +1270,18 @@ async def retrieve( Get extraction results Args: - cursor: Cursor for keyset pagination from prior response next_cursor + cursor: Previous nextCursor. + + field_style: Preserve source keys or convert result field names. + + include_raw: Use outputMode=raw instead. limit: Maximum number of results to return (1-1000, default 100) + output_mode: Select compact, full, or raw-compatible result fields. + + output_preset: Keep enrichment nested or merge it into each result. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -738,7 +1302,11 @@ async def retrieve( query=await async_maybe_transform( { "cursor": cursor, + "field_style": field_style, + "include_raw": include_raw, "limit": limit, + "output_mode": output_mode, + "output_preset": output_preset, }, extraction_retrieve_params.ExtractionRetrieveParams, ), @@ -789,7 +1357,7 @@ async def list( List extraction jobs Args: - cursor: Cursor for keyset pagination from prior response next_cursor + cursor: Previous nextCursor. limit: Maximum number of items to return (1-100, default 50). For paid per-result endpoints, the returned count may be lower when remaining credits cannot cover @@ -858,42 +1426,99 @@ async def estimate_cost( ], advanced_query: str | Omit = omit, any_words: str | Omit = omit, + bio_contains: str | Omit = omit, + blue_verified_only: bool | Omit = omit, bounding_box: str | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, + collection_strategy: Literal["auto", "complete", "direct", "search", "thread"] | Omit = omit, conversation_id: str | Omit = omit, + dedupe_across_targets: bool | Omit = omit, + dedupe_mode: Literal["none", "first", "merge"] | Omit = omit, exact_phrase: str | Omit = omit, + exclude_original_author: bool | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, + has_location: bool | Omit = omit, + has_media_only: bool | Omit = omit, + has_website: bool | Omit = omit, + include_original_post: bool | Omit = omit, + include_search_terms: bool | Omit = omit, + include_target_metadata: bool | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, list_id: str | Omit = omit, + location_contains: str | Omit = omit, + max_depth: int | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_id: str | Omit = omit, + max_items_per_target: int | Omit = omit, + max_likes: int | Omit = omit, + max_pages_per_target: int | Omit = omit, + max_posts: int | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_account_age_days: int | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_posts: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, + overlap_mode: bool | Omit = omit, place: str | Omit = omit, place_country: str | Omit = omit, point_radius: str | Omit = omit, + query_type: Literal["Latest", "Top", "Both"] | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, + relation_targets: Iterable[extraction_estimate_cost_params.RelationTarget] | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, results_limit: int | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, + scope: Literal["all", "direct", "nested"] | Omit = omit, + search_queries: SequenceNotStr[str] | Omit = omit, search_query: str | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, + since_time: Union[Union[str, datetime], int] | Omit = omit, + sort: Literal["relevance", "latest", "oldest", "likes"] | Omit = omit, + source: str | Omit = omit, + start_cursor: str | Omit = omit, target_community_id: str | Omit = omit, + target_community_ids: SequenceNotStr[str] | Omit = omit, target_list_id: str | Omit = omit, + target_list_ids: SequenceNotStr[str] | Omit = omit, + targets: SequenceNotStr[extraction_estimate_cost_params.Target] | Omit = omit, target_space_id: str | Omit = omit, target_tweet_id: str | Omit = omit, + target_tweet_ids: SequenceNotStr[str] | Omit = omit, target_username: str | Omit = omit, + target_usernames: SequenceNotStr[str] | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, + until_time: Union[Union[str, datetime], int] | Omit = omit, url: str | Omit = omit, + username_contains: str | Omit = omit, verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -907,83 +1532,195 @@ async def estimate_cost( Args: tool_type: Identifier for the extraction tool used to run a job. - advanced_query: Raw advanced query string appended to the estimate (tweet_search_extractor) + advanced_query: Raw advanced search query appended as-is (tweet_search_extractor) + + any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, + or lines. (tweet_search_extractor) + + bio_contains: Bio terms separated by commas or lines. + + blue_verified_only: Return only Blue-verified Tweet authors. + + bounding_box: Geo bounding box, e.g. -74.1 40.6 -73.9 40.8 (tweet_search_extractor) + + card_name: Match the Tweet card name. + + cashtags: Cashtags separated by spaces, commas, or lines. (tweet_search_extractor) + + collection_strategy: Reply collection strategy. + + conversation_id: Conversation ID filter (tweet_search_extractor) + + dedupe_across_targets: Merge duplicate results across collection targets. + + dedupe_mode: Keep target duplicates, first rows, or merged overlap. + + exact_phrase: Exact phrase to match (tweet_search_extractor) + + exclude_original_author: Exclude replies from the source author. - any_words: Alternative words or quoted phrases for estimated results. Separate with spaces, - commas, or lines. + exclude_source: Exclude a source application. - bounding_box: Geo bounding box used for estimation, e.g. -74.1 40.6 -73.9 40.8 + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. (tweet_search_extractor) - cashtags: Cashtags applied to the estimate, separated by spaces, commas, or lines. + from_user: Filter by author username (tweet_search_extractor) - conversation_id: Conversation ID filter used for estimation (tweet_search_extractor) + geocode: Match latitude, longitude, and radius. - exact_phrase: Exact phrase filter for search estimation + hashtags: Hashtags separated by spaces, commas, or lines. (tweet_search_extractor) - exclude_words: Words or quoted phrases excluded from estimated results. Separate with spaces, - commas, or lines. + has_location: Require a profile location. - from_user: Estimate only tweets from this author username (tweet_search_extractor) + has_media_only: Return only replies with media. - hashtags: Hashtags applied to the estimate, separated by spaces, commas, or lines. + has_website: Require a profile website. - in_reply_to_tweet_id: Estimate only replies to this tweet ID (tweet_search_extractor) + include_original_post: Include the source post in reply results. - language: Language code used for estimate filtering (tweet_search_extractor) + include_search_terms: Add matching search terms to collection metadata. - list_id: Estimate search results within this list ID (tweet_search_extractor) + include_target_metadata: Add source target metadata to each result. - media_type: Media type used for estimate filtering (tweet_search_extractor) + in_reply_to_tweet_id: Only replies to this tweet ID (tweet_search_extractor) - mentioning: Estimate tweets mentioning this username (tweet_search_extractor) + language: Language code filter (tweet_search_extractor) - min_faves: Minimum likes threshold for estimated results (tweet_search_extractor) + list_id: Search within a list ID (tweet_search_extractor) - min_quotes: Minimum quote count threshold for estimated results (tweet_search_extractor) + location_contains: Required profile location text. - min_replies: Minimum replies threshold for estimated results (tweet_search_extractor) + max_depth: Maximum nested reply depth. - min_retweets: Minimum retweets threshold for estimated results (tweet_search_extractor) + max_followers: Maximum follower count for profile results. - place: Estimate search results within this place ID (tweet_search_extractor) + max_following: Maximum following count for profile results. - place_country: Estimate search results within this country code (tweet_search_extractor) + max_id: Return Tweets older than this Tweet ID. - point_radius: Geo point radius used for estimation, e.g. -73.99 40.73 25mi - (tweet_search_extractor) + max_items_per_target: Maximum results collected for each target. + + max_likes: Maximum Tweet like count. + + max_pages_per_target: Reply pages collected for each target. + + max_posts: Maximum post count for profile results. + + max_quotes: Maximum Tweet quote count. + + max_replies: Maximum Tweet reply count. + + max_retweets: Maximum Tweet repost count. + + media_type: Media type filter (tweet_search_extractor) + + mentioning: Filter tweets mentioning a username (tweet_search_extractor) + + min_account_age_days: Minimum profile age in days. + + min_bookmarks: Minimum Tweet bookmark count. + + min_faves: Minimum likes threshold (tweet_search_extractor) + + min_followers: Minimum follower count for profile results. + + min_following: Minimum following count for profile results. + + min_posts: Minimum post count for profile results. - quotes: Quote mode used for estimation (tweet_search_extractor) + min_quotes: Minimum quote count threshold (tweet_search_extractor) + + min_replies: Minimum replies threshold (tweet_search_extractor) + + min_retweets: Minimum retweets threshold (tweet_search_extractor) + + min_views: Minimum Tweet view count. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + + overlap_mode: Shortcut for dedupeMode=merge. + + place: Search within a place ID (tweet_search_extractor) - quotes_of_tweet_id: Estimate only quotes of this tweet ID (tweet_search_extractor) + place_country: Search within a country code (tweet_search_extractor) + + point_radius: Geo point radius, e.g. -73.99 40.73 25mi (tweet_search_extractor) + + query_type: Search ranking applied to every query. + + quotes: Quote mode (tweet_search_extractor) - replies: Reply mode used for estimation (tweet_search_extractor) + quotes_of_tweet_id: Only quotes of this tweet ID (tweet_search_extractor) - results_limit: Maximum number of results to estimate. When set, the estimate caps projected - results to this value. + relation_targets: Profile relations processed within one job. - retweets: Retweet mode used for estimation (tweet_search_extractor) + replies: Reply mode (tweet_search_extractor) - retweets_of_tweet_id: Estimate only retweets of this tweet ID (tweet_search_extractor) + results_limit: Maximum number of results to extract. When set, the extraction stops after + reaching this limit. - search_query: Query used to price tweet_search_extractor or community_search. + retweets: Retweet mode (tweet_search_extractor) - since_date: Estimate start date in YYYY-MM-DD format (tweet_search_extractor) + retweets_of_tweet_id: Only retweets of this tweet ID (tweet_search_extractor) - target_community_id: Community ID used to price community_post_extractor or community_search. + safe: Enable the safe-search filter. - target_list_id: List ID used to price list_follower_explorer, list_member_extractor, or + scope: Reply depth scope. + + search_queries: Search queries processed as one collection job. + + search_query: Required for tweet_search_extractor & community_search. + + since_date: Start date YYYY-MM-DD (tweet_search_extractor) + + since_id: Return Tweets newer than this Tweet ID. + + since_time: Reply start time as ISO 8601 or Unix seconds. + + sort: Reply result order. + + source: Match the source application. + + start_cursor: Resume one reply target from this cursor. + + target_community_id: Required for community_post_extractor & community_search. + + target_community_ids: Community IDs processed as one collection job. + + target_list_id: Required for list_follower_explorer, list_member_extractor & list_post_extractor. - target_space_id: Space ID used to price space_explorer. + target_list_ids: List IDs processed as one collection job. - to_user: Estimate replies sent to this username (tweet_search_extractor) + targets: Mixed targets auto-routed within one job. - until_date: Estimate end date in YYYY-MM-DD format (tweet_search_extractor) + target_space_id: Required for space_explorer. + + target_tweet_ids: Tweet IDs processed as one collection job. - url: URL substring or domain filter used for estimation (tweet_search_extractor) + target_usernames: Usernames processed as one collection job. - verified_only: Estimate only verified authors (tweet_search_extractor) + to_user: Filter replies sent to a username (tweet_search_extractor) + + until_date: End date YYYY-MM-DD (tweet_search_extractor) + + until_time: Reply end time as ISO 8601 or Unix seconds. + + url: URL substring or domain filter (tweet_search_extractor) + + username_contains: Required username text. + + verified_only: Only verified authors (tweet_search_extractor) + + verified_type: Exact profile verification type. + + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. extra_headers: Send extra headers @@ -1000,42 +1737,99 @@ async def estimate_cost( "tool_type": tool_type, "advanced_query": advanced_query, "any_words": any_words, + "bio_contains": bio_contains, + "blue_verified_only": blue_verified_only, "bounding_box": bounding_box, + "card_name": card_name, "cashtags": cashtags, + "collection_strategy": collection_strategy, "conversation_id": conversation_id, + "dedupe_across_targets": dedupe_across_targets, + "dedupe_mode": dedupe_mode, "exact_phrase": exact_phrase, + "exclude_original_author": exclude_original_author, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, + "has_location": has_location, + "has_media_only": has_media_only, + "has_website": has_website, + "include_original_post": include_original_post, + "include_search_terms": include_search_terms, + "include_target_metadata": include_target_metadata, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, "list_id": list_id, + "location_contains": location_contains, + "max_depth": max_depth, + "max_followers": max_followers, + "max_following": max_following, + "max_id": max_id, + "max_items_per_target": max_items_per_target, + "max_likes": max_likes, + "max_pages_per_target": max_pages_per_target, + "max_posts": max_posts, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_account_age_days": min_account_age_days, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, + "min_followers": min_followers, + "min_following": min_following, + "min_posts": min_posts, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, + "overlap_mode": overlap_mode, "place": place, "place_country": place_country, "point_radius": point_radius, + "query_type": query_type, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, + "relation_targets": relation_targets, "replies": replies, "results_limit": results_limit, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, + "scope": scope, + "search_queries": search_queries, "search_query": search_query, "since_date": since_date, + "since_id": since_id, + "since_time": since_time, + "sort": sort, + "source": source, + "start_cursor": start_cursor, "target_community_id": target_community_id, + "target_community_ids": target_community_ids, "target_list_id": target_list_id, + "target_list_ids": target_list_ids, + "targets": targets, "target_space_id": target_space_id, "target_tweet_id": target_tweet_id, + "target_tweet_ids": target_tweet_ids, "target_username": target_username, + "target_usernames": target_usernames, "to_user": to_user, "until_date": until_date, + "until_time": until_time, "url": url, + "username_contains": username_contains, "verified_only": verified_only, + "verified_type": verified_type, + "within": within, + "within_time": within_time, }, extraction_estimate_cost_params.ExtractionEstimateCostParams, ), @@ -1050,6 +1844,24 @@ async def export_results( id: str, *, format: Literal["csv", "json", "md", "md-document", "pdf", "txt", "xlsx"], + has_description: bool | Omit = omit, + has_location: bool | Omit = omit, + has_media: bool | Omit = omit, + lang: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_posts: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_likes: int | Omit = omit, + min_posts: int | Omit = omit, + min_replies: int | Omit = omit, + min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + search: str | Omit = omit, + since_date: Union[str, date] | Omit = omit, + until_date: Union[str, date] | Omit = omit, + verified: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1063,6 +1875,42 @@ async def export_results( Args: format: Export file format + has_description: Require a non-empty description. + + has_location: Require a non-empty location. + + has_media: Require media. + + lang: Filter by language code. + + max_followers: Maximum follower count. + + max_following: Maximum following count. + + max_posts: Maximum post count. + + min_followers: Minimum follower count. + + min_following: Minimum following count. + + min_likes: Minimum like count. + + min_posts: Minimum post count. + + min_replies: Minimum reply count. + + min_retweets: Minimum repost count. + + min_views: Minimum view count. + + search: Search exported result text. + + since_date: Include results on or after this date. + + until_date: Include results on or before this date. + + verified: Filter by verified status. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1082,7 +1930,28 @@ async def export_results( extra_body=extra_body, timeout=timeout, query=await async_maybe_transform( - {"format": format}, extraction_export_results_params.ExtractionExportResultsParams + { + "format": format, + "has_description": has_description, + "has_location": has_location, + "has_media": has_media, + "lang": lang, + "max_followers": max_followers, + "max_following": max_following, + "max_posts": max_posts, + "min_followers": min_followers, + "min_following": min_following, + "min_likes": min_likes, + "min_posts": min_posts, + "min_replies": min_replies, + "min_retweets": min_retweets, + "min_views": min_views, + "search": search, + "since_date": since_date, + "until_date": until_date, + "verified": verified, + }, + extraction_export_results_params.ExtractionExportResultsParams, ), ), cast_to=AsyncBinaryAPIResponse, @@ -1116,44 +1985,102 @@ async def run( "user_media", "verified_follower_explorer", ], + dry_run: bool | Omit = omit, advanced_query: str | Omit = omit, any_words: str | Omit = omit, + bio_contains: str | Omit = omit, + blue_verified_only: bool | Omit = omit, bounding_box: str | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, + collection_strategy: Literal["auto", "complete", "direct", "search", "thread"] | Omit = omit, conversation_id: str | Omit = omit, + dedupe_across_targets: bool | Omit = omit, + dedupe_mode: Literal["none", "first", "merge"] | Omit = omit, exact_phrase: str | Omit = omit, + exclude_original_author: bool | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, + has_location: bool | Omit = omit, + has_media_only: bool | Omit = omit, + has_website: bool | Omit = omit, + include_original_post: bool | Omit = omit, + include_search_terms: bool | Omit = omit, + include_target_metadata: bool | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, list_id: str | Omit = omit, + location_contains: str | Omit = omit, + max_depth: int | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_id: str | Omit = omit, + max_items_per_target: int | Omit = omit, + max_likes: int | Omit = omit, + max_pages_per_target: int | Omit = omit, + max_posts: int | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_account_age_days: int | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_posts: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, + overlap_mode: bool | Omit = omit, place: str | Omit = omit, place_country: str | Omit = omit, point_radius: str | Omit = omit, + query_type: Literal["Latest", "Top", "Both"] | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, + relation_targets: Iterable[extraction_run_params.RelationTarget] | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, results_limit: int | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, + scope: Literal["all", "direct", "nested"] | Omit = omit, + search_queries: SequenceNotStr[str] | Omit = omit, search_query: str | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, + since_time: Union[Union[str, datetime], int] | Omit = omit, + sort: Literal["relevance", "latest", "oldest", "likes"] | Omit = omit, + source: str | Omit = omit, + start_cursor: str | Omit = omit, target_community_id: str | Omit = omit, + target_community_ids: SequenceNotStr[str] | Omit = omit, target_list_id: str | Omit = omit, + target_list_ids: SequenceNotStr[str] | Omit = omit, + targets: SequenceNotStr[extraction_run_params.Target] | Omit = omit, target_space_id: str | Omit = omit, target_tweet_id: str | Omit = omit, + target_tweet_ids: SequenceNotStr[str] | Omit = omit, target_username: str | Omit = omit, + target_usernames: SequenceNotStr[str] | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, + until_time: Union[Union[str, datetime], int] | Omit = omit, url: str | Omit = omit, + username_contains: str | Omit = omit, verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1167,54 +2094,134 @@ async def run( Args: tool_type: Identifier for the extraction tool used to run a job. + dry_run: Estimate cost without creating an extraction. + advanced_query: Raw advanced search query appended as-is (tweet_search_extractor) any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. (tweet_search_extractor) + bio_contains: Bio terms separated by commas or lines. + + blue_verified_only: Return only Blue-verified Tweet authors. + bounding_box: Geo bounding box, e.g. -74.1 40.6 -73.9 40.8 (tweet_search_extractor) + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. (tweet_search_extractor) + collection_strategy: Reply collection strategy. + conversation_id: Conversation ID filter (tweet_search_extractor) + dedupe_across_targets: Merge duplicate results across collection targets. + + dedupe_mode: Keep target duplicates, first rows, or merged overlap. + exact_phrase: Exact phrase to match (tweet_search_extractor) + exclude_original_author: Exclude replies from the source author. + + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. (tweet_search_extractor) from_user: Filter by author username (tweet_search_extractor) + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. (tweet_search_extractor) + has_location: Require a profile location. + + has_media_only: Return only replies with media. + + has_website: Require a profile website. + + include_original_post: Include the source post in reply results. + + include_search_terms: Add matching search terms to collection metadata. + + include_target_metadata: Add source target metadata to each result. + in_reply_to_tweet_id: Only replies to this tweet ID (tweet_search_extractor) language: Language code filter (tweet_search_extractor) list_id: Search within a list ID (tweet_search_extractor) + location_contains: Required profile location text. + + max_depth: Maximum nested reply depth. + + max_followers: Maximum follower count for profile results. + + max_following: Maximum following count for profile results. + + max_id: Return Tweets older than this Tweet ID. + + max_items_per_target: Maximum results collected for each target. + + max_likes: Maximum Tweet like count. + + max_pages_per_target: Reply pages collected for each target. + + max_posts: Maximum post count for profile results. + + max_quotes: Maximum Tweet quote count. + + max_replies: Maximum Tweet reply count. + + max_retweets: Maximum Tweet repost count. + media_type: Media type filter (tweet_search_extractor) mentioning: Filter tweets mentioning a username (tweet_search_extractor) + min_account_age_days: Minimum profile age in days. + + min_bookmarks: Minimum Tweet bookmark count. + min_faves: Minimum likes threshold (tweet_search_extractor) + min_followers: Minimum follower count for profile results. + + min_following: Minimum following count for profile results. + + min_posts: Minimum post count for profile results. + min_quotes: Minimum quote count threshold (tweet_search_extractor) min_replies: Minimum replies threshold (tweet_search_extractor) min_retweets: Minimum retweets threshold (tweet_search_extractor) + min_views: Minimum Tweet view count. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + + overlap_mode: Shortcut for dedupeMode=merge. + place: Search within a place ID (tweet_search_extractor) place_country: Search within a country code (tweet_search_extractor) point_radius: Geo point radius, e.g. -73.99 40.73 25mi (tweet_search_extractor) + query_type: Search ranking applied to every query. + quotes: Quote mode (tweet_search_extractor) quotes_of_tweet_id: Only quotes of this tweet ID (tweet_search_extractor) + relation_targets: Profile relations processed within one job. + replies: Reply mode (tweet_search_extractor) results_limit: Maximum number of results to extract. When set, the extraction stops after @@ -1224,25 +2231,61 @@ async def run( retweets_of_tweet_id: Only retweets of this tweet ID (tweet_search_extractor) + safe: Enable the safe-search filter. + + scope: Reply depth scope. + + search_queries: Search queries processed as one collection job. + search_query: Required for tweet_search_extractor & community_search. since_date: Start date YYYY-MM-DD (tweet_search_extractor) + since_id: Return Tweets newer than this Tweet ID. + + since_time: Reply start time as ISO 8601 or Unix seconds. + + sort: Reply result order. + + source: Match the source application. + + start_cursor: Resume one reply target from this cursor. + target_community_id: Required for community_post_extractor & community_search. + target_community_ids: Community IDs processed as one collection job. + target_list_id: Required for list_follower_explorer, list_member_extractor & list_post_extractor. + target_list_ids: List IDs processed as one collection job. + + targets: Mixed targets auto-routed within one job. + target_space_id: Required for space_explorer. + target_tweet_ids: Tweet IDs processed as one collection job. + + target_usernames: Usernames processed as one collection job. + to_user: Filter replies sent to a username (tweet_search_extractor) until_date: End date YYYY-MM-DD (tweet_search_extractor) + until_time: Reply end time as ISO 8601 or Unix seconds. + url: URL substring or domain filter (tweet_search_extractor) + username_contains: Required username text. + verified_only: Only verified authors (tweet_search_extractor) + verified_type: Exact profile verification type. + + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1258,47 +2301,108 @@ async def run( "tool_type": tool_type, "advanced_query": advanced_query, "any_words": any_words, + "bio_contains": bio_contains, + "blue_verified_only": blue_verified_only, "bounding_box": bounding_box, + "card_name": card_name, "cashtags": cashtags, + "collection_strategy": collection_strategy, "conversation_id": conversation_id, + "dedupe_across_targets": dedupe_across_targets, + "dedupe_mode": dedupe_mode, "exact_phrase": exact_phrase, + "exclude_original_author": exclude_original_author, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, + "has_location": has_location, + "has_media_only": has_media_only, + "has_website": has_website, + "include_original_post": include_original_post, + "include_search_terms": include_search_terms, + "include_target_metadata": include_target_metadata, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, "list_id": list_id, + "location_contains": location_contains, + "max_depth": max_depth, + "max_followers": max_followers, + "max_following": max_following, + "max_id": max_id, + "max_items_per_target": max_items_per_target, + "max_likes": max_likes, + "max_pages_per_target": max_pages_per_target, + "max_posts": max_posts, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_account_age_days": min_account_age_days, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, + "min_followers": min_followers, + "min_following": min_following, + "min_posts": min_posts, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, + "overlap_mode": overlap_mode, "place": place, "place_country": place_country, "point_radius": point_radius, + "query_type": query_type, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, + "relation_targets": relation_targets, "replies": replies, "results_limit": results_limit, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, + "scope": scope, + "search_queries": search_queries, "search_query": search_query, "since_date": since_date, + "since_id": since_id, + "since_time": since_time, + "sort": sort, + "source": source, + "start_cursor": start_cursor, "target_community_id": target_community_id, + "target_community_ids": target_community_ids, "target_list_id": target_list_id, + "target_list_ids": target_list_ids, + "targets": targets, "target_space_id": target_space_id, "target_tweet_id": target_tweet_id, + "target_tweet_ids": target_tweet_ids, "target_username": target_username, + "target_usernames": target_usernames, "to_user": to_user, "until_date": until_date, + "until_time": until_time, "url": url, + "username_contains": username_contains, "verified_only": verified_only, + "verified_type": verified_type, + "within": within, + "within_time": within_time, }, extraction_run_params.ExtractionRunParams, ), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform({"dry_run": dry_run}, extraction_run_params.ExtractionRunParams), ), cast_to=ExtractionRunResponse, ) diff --git a/src/x_twitter_scraper/resources/support/__init__.py b/src/x_twitter_scraper/resources/support/__init__.py index 9846ab2..32241fc 100644 --- a/src/x_twitter_scraper/resources/support/__init__.py +++ b/src/x_twitter_scraper/resources/support/__init__.py @@ -20,8 +20,22 @@ TicketsResourceWithStreamingResponse, AsyncTicketsResourceWithStreamingResponse, ) +from .attachments import ( + AttachmentsResource, + AsyncAttachmentsResource, + AttachmentsResourceWithRawResponse, + AsyncAttachmentsResourceWithRawResponse, + AttachmentsResourceWithStreamingResponse, + AsyncAttachmentsResourceWithStreamingResponse, +) __all__ = [ + "AttachmentsResource", + "AsyncAttachmentsResource", + "AttachmentsResourceWithRawResponse", + "AsyncAttachmentsResourceWithRawResponse", + "AttachmentsResourceWithStreamingResponse", + "AsyncAttachmentsResourceWithStreamingResponse", "TicketsResource", "AsyncTicketsResource", "TicketsResourceWithRawResponse", diff --git a/src/x_twitter_scraper/resources/support/attachments.py b/src/x_twitter_scraper/resources/support/attachments.py new file mode 100644 index 0000000..5289638 --- /dev/null +++ b/src/x_twitter_scraper/resources/support/attachments.py @@ -0,0 +1,185 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import path_template, strip_not_given +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + BinaryAPIResponse, + AsyncBinaryAPIResponse, + StreamedBinaryAPIResponse, + AsyncStreamedBinaryAPIResponse, + to_custom_raw_response_wrapper, + to_custom_streamed_response_wrapper, + async_to_custom_raw_response_wrapper, + async_to_custom_streamed_response_wrapper, +) +from ..._base_client import make_request_options + +__all__ = ["AttachmentsResource", "AsyncAttachmentsResource"] + + +class AttachmentsResource(SyncAPIResource): + """Support ticket management""" + + @cached_property + def with_raw_response(self) -> AttachmentsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/Xquik-dev/x-twitter-scraper-python#accessing-raw-response-data-eg-headers + """ + return AttachmentsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AttachmentsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/Xquik-dev/x-twitter-scraper-python#with_streaming_response + """ + return AttachmentsResourceWithStreamingResponse(self) + + def download( + self, + id: str, + *, + range: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> BinaryAPIResponse: + """Streams an authenticated user's support image or video. + + Video requests support + one standard byte range for seeking and resumable playback. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})} + extra_headers = {**strip_not_given({"Range": range}), **(extra_headers or {})} + return self._get( + path_template("/support/attachments/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BinaryAPIResponse, + ) + + +class AsyncAttachmentsResource(AsyncAPIResource): + """Support ticket management""" + + @cached_property + def with_raw_response(self) -> AsyncAttachmentsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/Xquik-dev/x-twitter-scraper-python#accessing-raw-response-data-eg-headers + """ + return AsyncAttachmentsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAttachmentsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/Xquik-dev/x-twitter-scraper-python#with_streaming_response + """ + return AsyncAttachmentsResourceWithStreamingResponse(self) + + async def download( + self, + id: str, + *, + range: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncBinaryAPIResponse: + """Streams an authenticated user's support image or video. + + Video requests support + one standard byte range for seeking and resumable playback. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})} + extra_headers = {**strip_not_given({"Range": range}), **(extra_headers or {})} + return await self._get( + path_template("/support/attachments/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AsyncBinaryAPIResponse, + ) + + +class AttachmentsResourceWithRawResponse: + def __init__(self, attachments: AttachmentsResource) -> None: + self._attachments = attachments + + self.download = to_custom_raw_response_wrapper( + attachments.download, + BinaryAPIResponse, + ) + + +class AsyncAttachmentsResourceWithRawResponse: + def __init__(self, attachments: AsyncAttachmentsResource) -> None: + self._attachments = attachments + + self.download = async_to_custom_raw_response_wrapper( + attachments.download, + AsyncBinaryAPIResponse, + ) + + +class AttachmentsResourceWithStreamingResponse: + def __init__(self, attachments: AttachmentsResource) -> None: + self._attachments = attachments + + self.download = to_custom_streamed_response_wrapper( + attachments.download, + StreamedBinaryAPIResponse, + ) + + +class AsyncAttachmentsResourceWithStreamingResponse: + def __init__(self, attachments: AsyncAttachmentsResource) -> None: + self._attachments = attachments + + self.download = async_to_custom_streamed_response_wrapper( + attachments.download, + AsyncStreamedBinaryAPIResponse, + ) diff --git a/src/x_twitter_scraper/resources/support/support.py b/src/x_twitter_scraper/resources/support/support.py index c5a3feb..895dac2 100644 --- a/src/x_twitter_scraper/resources/support/support.py +++ b/src/x_twitter_scraper/resources/support/support.py @@ -16,11 +16,24 @@ ) from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource +from .attachments import ( + AttachmentsResource, + AsyncAttachmentsResource, + AttachmentsResourceWithRawResponse, + AsyncAttachmentsResourceWithRawResponse, + AttachmentsResourceWithStreamingResponse, + AsyncAttachmentsResourceWithStreamingResponse, +) __all__ = ["SupportResource", "AsyncSupportResource"] class SupportResource(SyncAPIResource): + @cached_property + def attachments(self) -> AttachmentsResource: + """Support ticket management""" + return AttachmentsResource(self._client) + @cached_property def tickets(self) -> TicketsResource: """Support ticket management""" @@ -47,6 +60,11 @@ def with_streaming_response(self) -> SupportResourceWithStreamingResponse: class AsyncSupportResource(AsyncAPIResource): + @cached_property + def attachments(self) -> AsyncAttachmentsResource: + """Support ticket management""" + return AsyncAttachmentsResource(self._client) + @cached_property def tickets(self) -> AsyncTicketsResource: """Support ticket management""" @@ -76,6 +94,11 @@ class SupportResourceWithRawResponse: def __init__(self, support: SupportResource) -> None: self._support = support + @cached_property + def attachments(self) -> AttachmentsResourceWithRawResponse: + """Support ticket management""" + return AttachmentsResourceWithRawResponse(self._support.attachments) + @cached_property def tickets(self) -> TicketsResourceWithRawResponse: """Support ticket management""" @@ -86,6 +109,11 @@ class AsyncSupportResourceWithRawResponse: def __init__(self, support: AsyncSupportResource) -> None: self._support = support + @cached_property + def attachments(self) -> AsyncAttachmentsResourceWithRawResponse: + """Support ticket management""" + return AsyncAttachmentsResourceWithRawResponse(self._support.attachments) + @cached_property def tickets(self) -> AsyncTicketsResourceWithRawResponse: """Support ticket management""" @@ -96,6 +124,11 @@ class SupportResourceWithStreamingResponse: def __init__(self, support: SupportResource) -> None: self._support = support + @cached_property + def attachments(self) -> AttachmentsResourceWithStreamingResponse: + """Support ticket management""" + return AttachmentsResourceWithStreamingResponse(self._support.attachments) + @cached_property def tickets(self) -> TicketsResourceWithStreamingResponse: """Support ticket management""" @@ -106,6 +139,11 @@ class AsyncSupportResourceWithStreamingResponse: def __init__(self, support: AsyncSupportResource) -> None: self._support = support + @cached_property + def attachments(self) -> AsyncAttachmentsResourceWithStreamingResponse: + """Support ticket management""" + return AsyncAttachmentsResourceWithStreamingResponse(self._support.attachments) + @cached_property def tickets(self) -> AsyncTicketsResourceWithStreamingResponse: """Support ticket management""" diff --git a/src/x_twitter_scraper/resources/x/communities/communities.py b/src/x_twitter_scraper/resources/x/communities/communities.py index 60ee7f8..fd22ae6 100644 --- a/src/x_twitter_scraper/resources/x/communities/communities.py +++ b/src/x_twitter_scraper/resources/x/communities/communities.py @@ -217,8 +217,22 @@ def retrieve_members( self, id: str, *, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -230,12 +244,40 @@ def retrieve_members( List members of a community Args: + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + page_size: Items per page (20-200, default 20). This is an upper bound for paid authenticated calls: remaining credits can reduce the returned page size, and zero affordable results returns 402 insufficient_credits. + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -255,8 +297,22 @@ def retrieve_members( timeout=timeout, query=maybe_transform( { + "bio_contains": bio_contains, "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, }, community_retrieve_members_params.CommunityRetrieveMembersParams, ), @@ -268,7 +324,21 @@ def retrieve_moderators( self, id: str, *, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -280,8 +350,36 @@ def retrieve_moderators( List moderators of a community Args: + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor for community moderators + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -300,7 +398,24 @@ def retrieve_moderators( extra_body=extra_body, timeout=timeout, query=maybe_transform( - {"cursor": cursor}, community_retrieve_moderators_params.CommunityRetrieveModeratorsParams + { + "bio_contains": bio_contains, + "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, + }, + community_retrieve_moderators_params.CommunityRetrieveModeratorsParams, ), ), cast_to=PaginatedUsers, @@ -532,8 +647,22 @@ async def retrieve_members( self, id: str, *, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -545,12 +674,40 @@ async def retrieve_members( List members of a community Args: + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + page_size: Items per page (20-200, default 20). This is an upper bound for paid authenticated calls: remaining credits can reduce the returned page size, and zero affordable results returns 402 insufficient_credits. + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -570,8 +727,22 @@ async def retrieve_members( timeout=timeout, query=await async_maybe_transform( { + "bio_contains": bio_contains, "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, }, community_retrieve_members_params.CommunityRetrieveMembersParams, ), @@ -583,7 +754,21 @@ async def retrieve_moderators( self, id: str, *, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -595,8 +780,36 @@ async def retrieve_moderators( List moderators of a community Args: + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor for community moderators + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -615,7 +828,24 @@ async def retrieve_moderators( extra_body=extra_body, timeout=timeout, query=await async_maybe_transform( - {"cursor": cursor}, community_retrieve_moderators_params.CommunityRetrieveModeratorsParams + { + "bio_contains": bio_contains, + "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, + }, + community_retrieve_moderators_params.CommunityRetrieveModeratorsParams, ), ), cast_to=PaginatedUsers, diff --git a/src/x_twitter_scraper/resources/x/lists.py b/src/x_twitter_scraper/resources/x/lists.py index a3454d3..f2042af 100644 --- a/src/x_twitter_scraper/resources/x/lists.py +++ b/src/x_twitter_scraper/resources/x/lists.py @@ -52,8 +52,22 @@ def retrieve_followers( self, id: str, *, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -65,12 +79,39 @@ def retrieve_followers( List followers of an X List Args: + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor for list followers - page_size: Maximum user profiles requested from this page (20-200, default 200). The - response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + page_size: Maximum user profiles requested from this page (20-200, default 200). Source, + filters, or credits can return fewer profiles. Keep requesting next_cursor while + has_next_page is true. Deprecated aliases remain accepted. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. extra_headers: Send extra headers @@ -91,8 +132,22 @@ def retrieve_followers( timeout=timeout, query=maybe_transform( { + "bio_contains": bio_contains, "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, }, list_retrieve_followers_params.ListRetrieveFollowersParams, ), @@ -104,8 +159,22 @@ def retrieve_members( self, id: str, *, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -117,10 +186,38 @@ def retrieve_members( List members of an X List Args: + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor for list members + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + page_size: Members per page (20-200, default 20) + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -140,8 +237,22 @@ def retrieve_members( timeout=timeout, query=maybe_transform( { + "bio_contains": bio_contains, "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, }, list_retrieve_members_params.ListRetrieveMembersParams, ), @@ -239,8 +350,22 @@ async def retrieve_followers( self, id: str, *, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -252,12 +377,39 @@ async def retrieve_followers( List followers of an X List Args: + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor for list followers - page_size: Maximum user profiles requested from this page (20-200, default 200). The - response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + page_size: Maximum user profiles requested from this page (20-200, default 200). Source, + filters, or credits can return fewer profiles. Keep requesting next_cursor while + has_next_page is true. Deprecated aliases remain accepted. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. extra_headers: Send extra headers @@ -278,8 +430,22 @@ async def retrieve_followers( timeout=timeout, query=await async_maybe_transform( { + "bio_contains": bio_contains, "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, }, list_retrieve_followers_params.ListRetrieveFollowersParams, ), @@ -291,8 +457,22 @@ async def retrieve_members( self, id: str, *, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -304,10 +484,38 @@ async def retrieve_members( List members of an X List Args: + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor for list members + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + page_size: Members per page (20-200, default 20) + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -327,8 +535,22 @@ async def retrieve_members( timeout=timeout, query=await async_maybe_transform( { + "bio_contains": bio_contains, "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, }, list_retrieve_members_params.ListRetrieveMembersParams, ), diff --git a/src/x_twitter_scraper/resources/x/tweets/tweets.py b/src/x_twitter_scraper/resources/x/tweets/tweets.py index 3f4cc10..b0874ee 100644 --- a/src/x_twitter_scraper/resources/x/tweets/tweets.py +++ b/src/x_twitter_scraper/resources/x/tweets/tweets.py @@ -6,7 +6,7 @@ from __future__ import annotations -from typing import Union +from typing import Any, Union, cast from datetime import date from typing_extensions import Literal @@ -54,6 +54,7 @@ from ....types.shared.paginated_tweets import PaginatedTweets from ....types.x.tweet_create_response import TweetCreateResponse from ....types.x.tweet_delete_response import TweetDeleteResponse +from ....types.x.tweet_search_response import TweetSearchResponse from ....types.x.tweet_retrieve_response import TweetRetrieveResponse from ....types.x.tweet_get_replies_response import TweetGetRepliesResponse @@ -260,8 +261,22 @@ def get_favoriters( self, id: str, *, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -276,12 +291,39 @@ def get_favoriters( 424 `favoriters_unavailable` instead of a misleading empty success. Args: + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor for favoriters - page_size: Maximum user profiles requested from this page (20-200, default 200). The - response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + page_size: Maximum user profiles requested from this page (20-200, default 200). Source, + filters, or credits can return fewer profiles. Keep requesting next_cursor while + has_next_page is true. Deprecated aliases remain accepted. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. extra_headers: Send extra headers @@ -302,8 +344,22 @@ def get_favoriters( timeout=timeout, query=maybe_transform( { + "bio_contains": bio_contains, "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, }, tweet_get_favoriters_params.TweetGetFavoritersParams, ), @@ -316,35 +372,54 @@ def get_quotes( id: str, *, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, include_replies: bool | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, page_size: int | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, since_time: str | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, until_time: str | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -359,6 +434,10 @@ def get_quotes( any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. @@ -367,10 +446,14 @@ def get_quotes( exact_phrase: Exact phrase to match. + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. include_replies: Include reply quotes (default false) @@ -379,10 +462,22 @@ def get_quotes( language: Language code filter, e.g. en or tr. + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. + media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -391,6 +486,14 @@ def get_quotes( min_retweets: Minimum retweets threshold. + min_views: Minimum view count threshold. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + page_size: Maximum page items (1-100, default 20). Source, filters, or credits can reduce results. Continue while has_next_page is true. Deprecated limit and count aliases remain accepted. @@ -405,10 +508,16 @@ def get_quotes( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + since_date: Start date in YYYY-MM-DD format. + since_id: Return Tweets newer than this Tweet ID. + since_time: Unix timestamp - return quotes posted after this time + source: Match the source application. + to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. @@ -419,6 +528,10 @@ def get_quotes( verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -439,35 +552,54 @@ def get_quotes( query=maybe_transform( { "any_words": any_words, + "blue_verified_only": blue_verified_only, + "card_name": card_name, "cashtags": cashtags, "conversation_id": conversation_id, "cursor": cursor, "exact_phrase": exact_phrase, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, "include_replies": include_replies, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, "page_size": page_size, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, "replies": replies, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, "since_date": since_date, + "since_id": since_id, "since_time": since_time, + "source": source, "to_user": to_user, "until_date": until_date, "until_time": until_time, "url": url, "verified_only": verified_only, + "within": within, + "within_time": within_time, }, tweet_get_quotes_params.TweetGetQuotesParams, ), @@ -480,36 +612,61 @@ def get_replies( id: str, *, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_original_author: bool | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, + has_media_only: bool | Omit = omit, + include_original_post: bool | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, limit: int | Omit = omit, + max_depth: int | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, - mode: Literal["complete"] | Omit = omit, + min_views: int | Omit = omit, + mode: Literal["standard", "complete"] | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, page_size: int | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, + scope: Literal["all", "direct", "nested"] | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, since_time: str | Omit = omit, + sort: Literal["relevance", "latest", "oldest", "likes"] | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, until_time: str | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -519,41 +676,69 @@ def get_replies( ) -> TweetGetRepliesResponse: """Returns direct replies. - Complete mode merges available timeline views, supported - rankings, every forward cursor module, labeled hidden-content branches, - exact-parent time partitions scaled to the reported reply count, and search. It - separates nested replies and returns 424 below 80% coverage. + Omit mode for automatic maximum coverage with resumable + pagination. Complete mode returns nested replies, diagnostics, and 424 when + direct coverage stays below 80%. Args: any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. - cursor: Pagination cursor for tweet replies + cursor: Cursor from the previous response. Xquik cursors resume automatic coverage. + Existing unprefixed cursors keep legacy standard behavior. exact_phrase: Exact phrase to match. + exclude_original_author: Exclude replies written by the source-post author. + + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. + has_media_only: Only return replies containing media. + + include_original_post: Include the source post and count it toward limit. + in_reply_to_tweet_id: Only replies to this tweet ID. language: Language code filter, e.g. en or tr. - limit: With mode=complete, maximum combined direct and nested reply rows (1-25000). - Without complete mode, this is the deprecated pageSize alias and uses the normal - 1-100 page range. + limit: With mode=complete, maximum combined direct and nested reply rows (1-25000, + default 25000). Automatic pages accept 1-300. Standard pages accept 1-100. + Prefer pageSize outside complete mode. + + max_depth: Maximum reply depth from the source post. + + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -562,12 +747,21 @@ def get_replies( min_retweets: Minimum retweets threshold. - mode: Set complete for maximum-coverage collection. Complete mode accepts only limit. - Remove cursor, pageSize, count, time ranges, and tweet filters. + min_views: Minimum view count threshold. - page_size: Maximum page items (1-100, default 20). Source, filters, or credits can reduce - results. Continue while has_next_page is true. Deprecated limit and count - aliases remain accepted. + mode: Optional advanced override. Omit mode for automatic maximum direct reply + coverage with pagination. Standard keeps legacy pagination. Complete returns + direct and nested replies with diagnostics, scope, depth, sorting, and + original-post controls. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + + page_size: Automatic pages accept 1-300 Tweets. Standard pages keep 1-100. Default 20. + Continue while has_next_page is true. Deprecated aliases remain accepted. quotes: Quote mode. @@ -579,10 +773,20 @@ def get_replies( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + + scope: Select all replies, direct replies, or nested replies. + since_date: Start date in YYYY-MM-DD format. + since_id: Return Tweets newer than this Tweet ID. + since_time: Unix timestamp - return replies posted after this time + sort: Sort the selected replies before applying limit. + + source: Match the source application. + to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. @@ -593,6 +797,10 @@ def get_replies( verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -613,36 +821,61 @@ def get_replies( query=maybe_transform( { "any_words": any_words, + "blue_verified_only": blue_verified_only, + "card_name": card_name, "cashtags": cashtags, "conversation_id": conversation_id, "cursor": cursor, "exact_phrase": exact_phrase, + "exclude_original_author": exclude_original_author, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, + "has_media_only": has_media_only, + "include_original_post": include_original_post, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, "limit": limit, + "max_depth": max_depth, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, "mode": mode, + "native_retweets": native_retweets, + "near": near, + "news": news, "page_size": page_size, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, "replies": replies, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, + "scope": scope, "since_date": since_date, + "since_id": since_id, "since_time": since_time, + "sort": sort, + "source": source, "to_user": to_user, "until_date": until_date, "until_time": until_time, "url": url, "verified_only": verified_only, + "within": within, + "within_time": within_time, }, tweet_get_replies_params.TweetGetRepliesParams, ), @@ -654,8 +887,22 @@ def get_retweeters( self, id: str, *, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -667,12 +914,39 @@ def get_retweeters( List users who retweeted a tweet Args: + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor for retweeters - page_size: Maximum user profiles requested from this page (20-200, default 200). The - response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + page_size: Maximum user profiles requested from this page (20-200, default 200). Source, + filters, or credits can return fewer profiles. Keep requesting next_cursor while + has_next_page is true. Deprecated aliases remain accepted. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. extra_headers: Send extra headers @@ -693,8 +967,22 @@ def get_retweeters( timeout=timeout, query=maybe_transform( { + "bio_contains": bio_contains, "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, }, tweet_get_retweeters_params.TweetGetRetweetersParams, ), @@ -759,24 +1047,39 @@ def search( q: str, advanced_query: str | Omit = omit, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, bounding_box: str | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, limit: int | Omit = omit, list_id: str | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + mode: Literal["standard", "coverage"] | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, place: str | Omit = omit, place_country: str | Omit = omit, point_radius: str | Omit = omit, @@ -786,62 +1089,88 @@ def search( replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, since_time: str | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, until_time: str | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> PaginatedTweets: - """ - Search tweets by query, Tweet ID, X status URL, or account date window + ) -> TweetSearchResponse: + """No-mode search maximizes coverage. Args: - q: Search query (keywords, + q: Query, Tweet ID, or status URL. + + Valid inline bounds apply per page. advanced_query: Raw advanced search query appended as-is. any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + bounding_box: Geo bounding box, e.g. -74.1 40.6 -73.9 40.8. + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. - cursor: Pagination cursor from previous response + cursor: Cursor from the previous response. Xquik cursors resume automatic coverage. + Existing unprefixed cursors keep legacy standard behavior. exact_phrase: Exact phrase to match. + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. in_reply_to_tweet_id: Only replies to this tweet ID. language: Language code filter, e.g. en or tr. - limit: Max tweets to return (server paginates internally). Omit for single page (~20). - This is an upper bound for paid authenticated calls: remaining credits can - reduce the returned page size, and zero affordable results returns 402 - insufficient_credits. + limit: Result upper bound. Omit it for the existing 20-row page size. Explicit coverage + defaults to 2000 and allows 10000. For paid requests, remaining credits can + reduce results. Zero affordable results returns 402. list_id: Search within a list ID. + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. + media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -850,6 +1179,17 @@ def search( min_retweets: Minimum retweets threshold. + min_views: Minimum view count threshold. + + mode: Omit mode for resumable maximum coverage. Standard keeps legacy pagination. + Coverage returns diagnostics once and rejects cursors. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + place: Search within a place ID. place_country: Search within a country code. @@ -868,20 +1208,30 @@ def search( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + since_date: Start date in YYYY-MM-DD format. - since_time: ISO 8601 timestamp - only return tweets after this time + since_id: Return Tweets newer than this Tweet ID. + + since_time: Inclusive ISO bound. + + source: Match the source application. to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. - until_time: ISO 8601 timestamp - only return tweets before this time + until_time: Exclusive ISO bound. url: URL substring or domain filter. verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -890,57 +1240,82 @@ def search( timeout: Override the client-level default timeout for this request, in seconds """ - return self._get( - "/x/tweets/search", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "q": q, - "advanced_query": advanced_query, - "any_words": any_words, - "bounding_box": bounding_box, - "cashtags": cashtags, - "conversation_id": conversation_id, - "cursor": cursor, - "exact_phrase": exact_phrase, - "exclude_words": exclude_words, - "from_user": from_user, - "hashtags": hashtags, - "in_reply_to_tweet_id": in_reply_to_tweet_id, - "language": language, - "limit": limit, - "list_id": list_id, - "media_type": media_type, - "mentioning": mentioning, - "min_faves": min_faves, - "min_quotes": min_quotes, - "min_replies": min_replies, - "min_retweets": min_retweets, - "place": place, - "place_country": place_country, - "point_radius": point_radius, - "query_type": query_type, - "quotes": quotes, - "quotes_of_tweet_id": quotes_of_tweet_id, - "replies": replies, - "retweets": retweets, - "retweets_of_tweet_id": retweets_of_tweet_id, - "since_date": since_date, - "since_time": since_time, - "to_user": to_user, - "until_date": until_date, - "until_time": until_time, - "url": url, - "verified_only": verified_only, - }, - tweet_search_params.TweetSearchParams, + return cast( + TweetSearchResponse, + self._get( + "/x/tweets/search", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "q": q, + "advanced_query": advanced_query, + "any_words": any_words, + "blue_verified_only": blue_verified_only, + "bounding_box": bounding_box, + "card_name": card_name, + "cashtags": cashtags, + "conversation_id": conversation_id, + "cursor": cursor, + "exact_phrase": exact_phrase, + "exclude_source": exclude_source, + "exclude_words": exclude_words, + "from_user": from_user, + "geocode": geocode, + "hashtags": hashtags, + "in_reply_to_tweet_id": in_reply_to_tweet_id, + "language": language, + "limit": limit, + "list_id": list_id, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, + "media_type": media_type, + "mentioning": mentioning, + "min_bookmarks": min_bookmarks, + "min_faves": min_faves, + "min_quotes": min_quotes, + "min_replies": min_replies, + "min_retweets": min_retweets, + "min_views": min_views, + "mode": mode, + "native_retweets": native_retweets, + "near": near, + "news": news, + "place": place, + "place_country": place_country, + "point_radius": point_radius, + "query_type": query_type, + "quotes": quotes, + "quotes_of_tweet_id": quotes_of_tweet_id, + "replies": replies, + "retweets": retweets, + "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, + "since_date": since_date, + "since_id": since_id, + "since_time": since_time, + "source": source, + "to_user": to_user, + "until_date": until_date, + "until_time": until_time, + "url": url, + "verified_only": verified_only, + "within": within, + "within_time": within_time, + }, + tweet_search_params.TweetSearchParams, + ), ), + cast_to=cast( + Any, TweetSearchResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=PaginatedTweets, ) @@ -1144,8 +1519,22 @@ async def get_favoriters( self, id: str, *, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1160,12 +1549,39 @@ async def get_favoriters( 424 `favoriters_unavailable` instead of a misleading empty success. Args: + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor for favoriters - page_size: Maximum user profiles requested from this page (20-200, default 200). The - response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + page_size: Maximum user profiles requested from this page (20-200, default 200). Source, + filters, or credits can return fewer profiles. Keep requesting next_cursor while + has_next_page is true. Deprecated aliases remain accepted. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. extra_headers: Send extra headers @@ -1186,8 +1602,22 @@ async def get_favoriters( timeout=timeout, query=await async_maybe_transform( { + "bio_contains": bio_contains, "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, }, tweet_get_favoriters_params.TweetGetFavoritersParams, ), @@ -1200,35 +1630,54 @@ async def get_quotes( id: str, *, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, include_replies: bool | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, page_size: int | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, since_time: str | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, until_time: str | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1243,6 +1692,10 @@ async def get_quotes( any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. @@ -1251,10 +1704,14 @@ async def get_quotes( exact_phrase: Exact phrase to match. + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. include_replies: Include reply quotes (default false) @@ -1263,10 +1720,22 @@ async def get_quotes( language: Language code filter, e.g. en or tr. + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. + media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -1275,6 +1744,14 @@ async def get_quotes( min_retweets: Minimum retweets threshold. + min_views: Minimum view count threshold. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + page_size: Maximum page items (1-100, default 20). Source, filters, or credits can reduce results. Continue while has_next_page is true. Deprecated limit and count aliases remain accepted. @@ -1289,10 +1766,16 @@ async def get_quotes( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + since_date: Start date in YYYY-MM-DD format. + since_id: Return Tweets newer than this Tweet ID. + since_time: Unix timestamp - return quotes posted after this time + source: Match the source application. + to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. @@ -1303,6 +1786,10 @@ async def get_quotes( verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1323,35 +1810,54 @@ async def get_quotes( query=await async_maybe_transform( { "any_words": any_words, + "blue_verified_only": blue_verified_only, + "card_name": card_name, "cashtags": cashtags, "conversation_id": conversation_id, "cursor": cursor, "exact_phrase": exact_phrase, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, "include_replies": include_replies, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, "page_size": page_size, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, "replies": replies, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, "since_date": since_date, + "since_id": since_id, "since_time": since_time, + "source": source, "to_user": to_user, "until_date": until_date, "until_time": until_time, "url": url, "verified_only": verified_only, + "within": within, + "within_time": within_time, }, tweet_get_quotes_params.TweetGetQuotesParams, ), @@ -1364,36 +1870,61 @@ async def get_replies( id: str, *, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_original_author: bool | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, + has_media_only: bool | Omit = omit, + include_original_post: bool | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, limit: int | Omit = omit, + max_depth: int | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, - mode: Literal["complete"] | Omit = omit, + min_views: int | Omit = omit, + mode: Literal["standard", "complete"] | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, page_size: int | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, + scope: Literal["all", "direct", "nested"] | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, since_time: str | Omit = omit, + sort: Literal["relevance", "latest", "oldest", "likes"] | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, until_time: str | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1403,41 +1934,69 @@ async def get_replies( ) -> TweetGetRepliesResponse: """Returns direct replies. - Complete mode merges available timeline views, supported - rankings, every forward cursor module, labeled hidden-content branches, - exact-parent time partitions scaled to the reported reply count, and search. It - separates nested replies and returns 424 below 80% coverage. + Omit mode for automatic maximum coverage with resumable + pagination. Complete mode returns nested replies, diagnostics, and 424 when + direct coverage stays below 80%. Args: any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. - cursor: Pagination cursor for tweet replies + cursor: Cursor from the previous response. Xquik cursors resume automatic coverage. + Existing unprefixed cursors keep legacy standard behavior. exact_phrase: Exact phrase to match. + exclude_original_author: Exclude replies written by the source-post author. + + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. + has_media_only: Only return replies containing media. + + include_original_post: Include the source post and count it toward limit. + in_reply_to_tweet_id: Only replies to this tweet ID. language: Language code filter, e.g. en or tr. - limit: With mode=complete, maximum combined direct and nested reply rows (1-25000). - Without complete mode, this is the deprecated pageSize alias and uses the normal - 1-100 page range. + limit: With mode=complete, maximum combined direct and nested reply rows (1-25000, + default 25000). Automatic pages accept 1-300. Standard pages accept 1-100. + Prefer pageSize outside complete mode. + + max_depth: Maximum reply depth from the source post. + + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -1446,12 +2005,21 @@ async def get_replies( min_retweets: Minimum retweets threshold. - mode: Set complete for maximum-coverage collection. Complete mode accepts only limit. - Remove cursor, pageSize, count, time ranges, and tweet filters. + min_views: Minimum view count threshold. - page_size: Maximum page items (1-100, default 20). Source, filters, or credits can reduce - results. Continue while has_next_page is true. Deprecated limit and count - aliases remain accepted. + mode: Optional advanced override. Omit mode for automatic maximum direct reply + coverage with pagination. Standard keeps legacy pagination. Complete returns + direct and nested replies with diagnostics, scope, depth, sorting, and + original-post controls. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + + page_size: Automatic pages accept 1-300 Tweets. Standard pages keep 1-100. Default 20. + Continue while has_next_page is true. Deprecated aliases remain accepted. quotes: Quote mode. @@ -1463,10 +2031,20 @@ async def get_replies( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + + scope: Select all replies, direct replies, or nested replies. + since_date: Start date in YYYY-MM-DD format. + since_id: Return Tweets newer than this Tweet ID. + since_time: Unix timestamp - return replies posted after this time + sort: Sort the selected replies before applying limit. + + source: Match the source application. + to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. @@ -1477,6 +2055,10 @@ async def get_replies( verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1497,36 +2079,61 @@ async def get_replies( query=await async_maybe_transform( { "any_words": any_words, + "blue_verified_only": blue_verified_only, + "card_name": card_name, "cashtags": cashtags, "conversation_id": conversation_id, "cursor": cursor, "exact_phrase": exact_phrase, + "exclude_original_author": exclude_original_author, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, + "has_media_only": has_media_only, + "include_original_post": include_original_post, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, "limit": limit, + "max_depth": max_depth, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, "mode": mode, + "native_retweets": native_retweets, + "near": near, + "news": news, "page_size": page_size, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, "replies": replies, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, + "scope": scope, "since_date": since_date, + "since_id": since_id, "since_time": since_time, + "sort": sort, + "source": source, "to_user": to_user, "until_date": until_date, "until_time": until_time, "url": url, "verified_only": verified_only, + "within": within, + "within_time": within_time, }, tweet_get_replies_params.TweetGetRepliesParams, ), @@ -1538,8 +2145,22 @@ async def get_retweeters( self, id: str, *, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1551,12 +2172,39 @@ async def get_retweeters( List users who retweeted a tweet Args: + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor for retweeters - page_size: Maximum user profiles requested from this page (20-200, default 200). The - response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + page_size: Maximum user profiles requested from this page (20-200, default 200). Source, + filters, or credits can return fewer profiles. Keep requesting next_cursor while + has_next_page is true. Deprecated aliases remain accepted. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. extra_headers: Send extra headers @@ -1577,8 +2225,22 @@ async def get_retweeters( timeout=timeout, query=await async_maybe_transform( { + "bio_contains": bio_contains, "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, }, tweet_get_retweeters_params.TweetGetRetweetersParams, ), @@ -1643,24 +2305,39 @@ async def search( q: str, advanced_query: str | Omit = omit, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, bounding_box: str | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, limit: int | Omit = omit, list_id: str | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + mode: Literal["standard", "coverage"] | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, place: str | Omit = omit, place_country: str | Omit = omit, point_radius: str | Omit = omit, @@ -1670,62 +2347,88 @@ async def search( replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, since_time: str | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, until_time: str | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> PaginatedTweets: - """ - Search tweets by query, Tweet ID, X status URL, or account date window + ) -> TweetSearchResponse: + """No-mode search maximizes coverage. Args: - q: Search query (keywords, + q: Query, Tweet ID, or status URL. + + Valid inline bounds apply per page. advanced_query: Raw advanced search query appended as-is. any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + bounding_box: Geo bounding box, e.g. -74.1 40.6 -73.9 40.8. + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. - cursor: Pagination cursor from previous response + cursor: Cursor from the previous response. Xquik cursors resume automatic coverage. + Existing unprefixed cursors keep legacy standard behavior. exact_phrase: Exact phrase to match. + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. in_reply_to_tweet_id: Only replies to this tweet ID. language: Language code filter, e.g. en or tr. - limit: Max tweets to return (server paginates internally). Omit for single page (~20). - This is an upper bound for paid authenticated calls: remaining credits can - reduce the returned page size, and zero affordable results returns 402 - insufficient_credits. + limit: Result upper bound. Omit it for the existing 20-row page size. Explicit coverage + defaults to 2000 and allows 10000. For paid requests, remaining credits can + reduce results. Zero affordable results returns 402. list_id: Search within a list ID. + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. + media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -1734,6 +2437,17 @@ async def search( min_retweets: Minimum retweets threshold. + min_views: Minimum view count threshold. + + mode: Omit mode for resumable maximum coverage. Standard keeps legacy pagination. + Coverage returns diagnostics once and rejects cursors. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + place: Search within a place ID. place_country: Search within a country code. @@ -1752,20 +2466,30 @@ async def search( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + since_date: Start date in YYYY-MM-DD format. - since_time: ISO 8601 timestamp - only return tweets after this time + since_id: Return Tweets newer than this Tweet ID. + + since_time: Inclusive ISO bound. + + source: Match the source application. to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. - until_time: ISO 8601 timestamp - only return tweets before this time + until_time: Exclusive ISO bound. url: URL substring or domain filter. verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1774,57 +2498,82 @@ async def search( timeout: Override the client-level default timeout for this request, in seconds """ - return await self._get( - "/x/tweets/search", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "q": q, - "advanced_query": advanced_query, - "any_words": any_words, - "bounding_box": bounding_box, - "cashtags": cashtags, - "conversation_id": conversation_id, - "cursor": cursor, - "exact_phrase": exact_phrase, - "exclude_words": exclude_words, - "from_user": from_user, - "hashtags": hashtags, - "in_reply_to_tweet_id": in_reply_to_tweet_id, - "language": language, - "limit": limit, - "list_id": list_id, - "media_type": media_type, - "mentioning": mentioning, - "min_faves": min_faves, - "min_quotes": min_quotes, - "min_replies": min_replies, - "min_retweets": min_retweets, - "place": place, - "place_country": place_country, - "point_radius": point_radius, - "query_type": query_type, - "quotes": quotes, - "quotes_of_tweet_id": quotes_of_tweet_id, - "replies": replies, - "retweets": retweets, - "retweets_of_tweet_id": retweets_of_tweet_id, - "since_date": since_date, - "since_time": since_time, - "to_user": to_user, - "until_date": until_date, - "until_time": until_time, - "url": url, - "verified_only": verified_only, - }, - tweet_search_params.TweetSearchParams, + return cast( + TweetSearchResponse, + await self._get( + "/x/tweets/search", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "q": q, + "advanced_query": advanced_query, + "any_words": any_words, + "blue_verified_only": blue_verified_only, + "bounding_box": bounding_box, + "card_name": card_name, + "cashtags": cashtags, + "conversation_id": conversation_id, + "cursor": cursor, + "exact_phrase": exact_phrase, + "exclude_source": exclude_source, + "exclude_words": exclude_words, + "from_user": from_user, + "geocode": geocode, + "hashtags": hashtags, + "in_reply_to_tweet_id": in_reply_to_tweet_id, + "language": language, + "limit": limit, + "list_id": list_id, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, + "media_type": media_type, + "mentioning": mentioning, + "min_bookmarks": min_bookmarks, + "min_faves": min_faves, + "min_quotes": min_quotes, + "min_replies": min_replies, + "min_retweets": min_retweets, + "min_views": min_views, + "mode": mode, + "native_retweets": native_retweets, + "near": near, + "news": news, + "place": place, + "place_country": place_country, + "point_radius": point_radius, + "query_type": query_type, + "quotes": quotes, + "quotes_of_tweet_id": quotes_of_tweet_id, + "replies": replies, + "retweets": retweets, + "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, + "since_date": since_date, + "since_id": since_id, + "since_time": since_time, + "source": source, + "to_user": to_user, + "until_date": until_date, + "until_time": until_time, + "url": url, + "verified_only": verified_only, + "within": within, + "within_time": within_time, + }, + tweet_search_params.TweetSearchParams, + ), ), + cast_to=cast( + Any, TweetSearchResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=PaginatedTweets, ) diff --git a/src/x_twitter_scraper/resources/x/users/users.py b/src/x_twitter_scraper/resources/x/users/users.py index c32eb4c..f80363a 100644 --- a/src/x_twitter_scraper/resources/x/users/users.py +++ b/src/x_twitter_scraper/resources/x/users/users.py @@ -6,7 +6,7 @@ from __future__ import annotations -from typing import Union +from typing import Any, Union, cast from datetime import date from typing_extensions import Literal @@ -50,6 +50,9 @@ from ....types.shared.paginated_tweets import PaginatedTweets from ....types.x.user_retrieve_batch_response import UserRetrieveBatchResponse from ....types.x.user_remove_follower_response import UserRemoveFollowerResponse +from ....types.x.user_retrieve_followers_response import UserRetrieveFollowersResponse +from ....types.x.user_retrieve_following_response import UserRetrieveFollowingResponse +from ....types.x.user_retrieve_verified_followers_response import UserRetrieveVerifiedFollowersResponse __all__ = ["UsersResource", "AsyncUsersResource"] @@ -194,16 +197,31 @@ def retrieve_followers( id: str, *, after: str | Omit = omit, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, limit: int | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, + mode: Literal["standard", "coverage"] | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> PaginatedUsers: + ) -> UserRetrieveFollowersResponse: """List followers of a user Args: @@ -211,14 +229,45 @@ def retrieve_followers( Prefer cursor. - cursor: Pagination cursor for followers list + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + + cursor: Cursor from the previous response. Xquik cursors resume automatic coverage. + Existing unprefixed cursors keep legacy standard behavior. + + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + limit: Legacy page-size alias outside explicit coverage mode. Coverage accepts 1-10000. + Prefer pageSize. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + mode: Omit mode for resumable maximum coverage. Standard keeps legacy pagination. + Coverage returns diagnostics once and rejects cursors. - limit: Legacy integer page size alias for following lists. Prefer pageSize. + page_size: Maximum user profiles: automatic 300; standard 200. Sources return fewer + profiles. Continue with has_next_page. - page_size: Maximum user profiles requested from this page (20-200, default 200). The - response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. extra_headers: Send extra headers @@ -230,32 +279,66 @@ def retrieve_followers( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._get( - path_template("/x/users/{id}/followers", id=id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "after": after, - "cursor": cursor, - "limit": limit, - "page_size": page_size, - }, - user_retrieve_followers_params.UserRetrieveFollowersParams, + return cast( + UserRetrieveFollowersResponse, + self._get( + path_template("/x/users/{id}/followers", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "after": after, + "bio_contains": bio_contains, + "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "limit": limit, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, + "mode": mode, + "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, + }, + user_retrieve_followers_params.UserRetrieveFollowersParams, + ), ), + cast_to=cast( + Any, UserRetrieveFollowersResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=PaginatedUsers, ) def retrieve_followers_you_know( self, id: str, *, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -267,12 +350,39 @@ def retrieve_followers_you_know( List mutual followers between you and a user Args: + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor for followers-you-know - page_size: Maximum user profiles requested from this page (20-200, default 200). The - response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + page_size: Maximum user profiles requested from this page (20-200, default 200). Source, + filters, or credits can return fewer profiles. Keep requesting next_cursor while + has_next_page is true. Deprecated aliases remain accepted. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. extra_headers: Send extra headers @@ -293,8 +403,22 @@ def retrieve_followers_you_know( timeout=timeout, query=maybe_transform( { + "bio_contains": bio_contains, "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, }, user_retrieve_followers_you_know_params.UserRetrieveFollowersYouKnowParams, ), @@ -307,16 +431,31 @@ def retrieve_following( id: str, *, after: str | Omit = omit, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, limit: int | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, + mode: Literal["standard", "coverage"] | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> PaginatedUsers: + ) -> UserRetrieveFollowingResponse: """List accounts a user follows Args: @@ -324,14 +463,45 @@ def retrieve_following( Prefer cursor. - cursor: Pagination cursor for following list + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + + cursor: Cursor from the previous response. Xquik cursors resume automatic coverage. + Existing unprefixed cursors keep legacy standard behavior. + + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + limit: Legacy page-size alias outside explicit coverage mode. Coverage accepts 1-10000. + Prefer pageSize. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. - limit: Legacy page size alias. Prefer pageSize. + min_statuses: Minimum post count. minPosts is also accepted. - page_size: Maximum user profiles requested from this page (20-200, default 200). The - response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + mode: Omit mode for resumable maximum coverage. Standard keeps legacy pagination. + Coverage returns diagnostics once and rejects cursors. + + page_size: Maximum user profiles: automatic 300; standard 200. Sources return fewer + profiles. Continue with has_next_page. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. extra_headers: Send extra headers @@ -343,24 +513,44 @@ def retrieve_following( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._get( - path_template("/x/users/{id}/following", id=id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "after": after, - "cursor": cursor, - "limit": limit, - "page_size": page_size, - }, - user_retrieve_following_params.UserRetrieveFollowingParams, + return cast( + UserRetrieveFollowingResponse, + self._get( + path_template("/x/users/{id}/following", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "after": after, + "bio_contains": bio_contains, + "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "limit": limit, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, + "mode": mode, + "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, + }, + user_retrieve_following_params.UserRetrieveFollowingParams, + ), ), + cast_to=cast( + Any, UserRetrieveFollowingResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=PaginatedUsers, ) def retrieve_likes( @@ -368,32 +558,51 @@ def retrieve_likes( id: str, *, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, page_size: int | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -408,6 +617,10 @@ def retrieve_likes( any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. @@ -416,20 +629,36 @@ def retrieve_likes( exact_phrase: Exact phrase to match. + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. in_reply_to_tweet_id: Only replies to this tweet ID. language: Language code filter, e.g. en or tr. + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. + media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -438,6 +667,14 @@ def retrieve_likes( min_retweets: Minimum retweets threshold. + min_views: Minimum view count threshold. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + page_size: Maximum page items (1-100, default 20). Source, filters, or credits can reduce results. Continue while has_next_page is true. Deprecated limit and count aliases remain accepted. @@ -452,8 +689,14 @@ def retrieve_likes( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + since_date: Start date in YYYY-MM-DD format. + since_id: Return Tweets newer than this Tweet ID. + + source: Match the source application. + to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. @@ -462,6 +705,10 @@ def retrieve_likes( verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -482,32 +729,51 @@ def retrieve_likes( query=maybe_transform( { "any_words": any_words, + "blue_verified_only": blue_verified_only, + "card_name": card_name, "cashtags": cashtags, "conversation_id": conversation_id, "cursor": cursor, "exact_phrase": exact_phrase, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, "page_size": page_size, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, "replies": replies, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, "since_date": since_date, + "since_id": since_id, + "source": source, "to_user": to_user, "until_date": until_date, "url": url, "verified_only": verified_only, + "within": within, + "within_time": within_time, }, user_retrieve_likes_params.UserRetrieveLikesParams, ), @@ -520,32 +786,51 @@ def retrieve_media( id: str, *, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, page_size: int | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -560,6 +845,10 @@ def retrieve_media( any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. @@ -568,20 +857,36 @@ def retrieve_media( exact_phrase: Exact phrase to match. + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. in_reply_to_tweet_id: Only replies to this tweet ID. language: Language code filter, e.g. en or tr. + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. + media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -590,6 +895,14 @@ def retrieve_media( min_retweets: Minimum retweets threshold. + min_views: Minimum view count threshold. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + page_size: Maximum page items (1-100, default 20). Source, filters, or credits can reduce results. Continue while has_next_page is true. Deprecated limit and count aliases remain accepted. @@ -604,8 +917,14 @@ def retrieve_media( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + since_date: Start date in YYYY-MM-DD format. + since_id: Return Tweets newer than this Tweet ID. + + source: Match the source application. + to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. @@ -614,6 +933,10 @@ def retrieve_media( verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -634,32 +957,51 @@ def retrieve_media( query=maybe_transform( { "any_words": any_words, + "blue_verified_only": blue_verified_only, + "card_name": card_name, "cashtags": cashtags, "conversation_id": conversation_id, "cursor": cursor, "exact_phrase": exact_phrase, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, "page_size": page_size, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, "replies": replies, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, "since_date": since_date, + "since_id": since_id, + "source": source, "to_user": to_user, "until_date": until_date, "url": url, "verified_only": verified_only, + "within": within, + "within_time": within_time, }, user_retrieve_media_params.UserRetrieveMediaParams, ), @@ -672,34 +1014,53 @@ def retrieve_mentions( id: str, *, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, page_size: int | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, since_time: str | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, until_time: str | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -714,6 +1075,10 @@ def retrieve_mentions( any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. @@ -722,20 +1087,36 @@ def retrieve_mentions( exact_phrase: Exact phrase to match. + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. in_reply_to_tweet_id: Only replies to this tweet ID. language: Language code filter, e.g. en or tr. + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. + media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -744,6 +1125,14 @@ def retrieve_mentions( min_retweets: Minimum retweets threshold. + min_views: Minimum view count threshold. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + page_size: Maximum page items (1-100, default 20). Source, filters, or credits can reduce results. Continue while has_next_page is true. Deprecated limit and count aliases remain accepted. @@ -758,10 +1147,16 @@ def retrieve_mentions( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + since_date: Start date in YYYY-MM-DD format. + since_id: Return Tweets newer than this Tweet ID. + since_time: Unix timestamp - return mentions after this time + source: Match the source application. + to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. @@ -772,6 +1167,10 @@ def retrieve_mentions( verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -792,34 +1191,53 @@ def retrieve_mentions( query=maybe_transform( { "any_words": any_words, + "blue_verified_only": blue_verified_only, + "card_name": card_name, "cashtags": cashtags, "conversation_id": conversation_id, "cursor": cursor, "exact_phrase": exact_phrase, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, "page_size": page_size, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, "replies": replies, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, "since_date": since_date, + "since_id": since_id, "since_time": since_time, + "source": source, "to_user": to_user, "until_date": until_date, "until_time": until_time, "url": url, "verified_only": verified_only, + "within": within, + "within_time": within_time, }, user_retrieve_mentions_params.UserRetrieveMentionsParams, ), @@ -832,33 +1250,52 @@ def retrieve_replies( id: str, *, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, include_parent_tweet: bool | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, page_size: int | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -866,25 +1303,37 @@ def retrieve_replies( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PaginatedTweets: - """ - Returns the user's timeline with replies included by default. + """Returns target-authored posts and replies. + + Omit mode for automatic maximum + coverage. Pass next_cursor unchanged. Unprefixed cursors stay legacy. Excludes + other-author context. Args: any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. - cursor: Pagination cursor for user replies + cursor: Cursor from the previous response. Xquik cursors resume automatic coverage. + Existing unprefixed cursors keep legacy standard behavior. exact_phrase: Exact phrase to match. + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. include_parent_tweet: Include each reply's parent tweet. @@ -893,10 +1342,22 @@ def retrieve_replies( language: Language code filter, e.g. en or tr. + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. + media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -905,9 +1366,16 @@ def retrieve_replies( min_retweets: Minimum retweets threshold. - page_size: Maximum page items (1-100, default 20). Source, filters, or credits can reduce - results. Continue while has_next_page is true. Deprecated limit and count - aliases remain accepted. + min_views: Minimum view count threshold. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + + page_size: Automatic pages accept 1-300 Tweets. Standard pages keep 1-100. Default 20. + Continue while has_next_page is true. Deprecated aliases remain accepted. quotes: Quote mode. @@ -919,8 +1387,14 @@ def retrieve_replies( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + since_date: Start date in YYYY-MM-DD format. + since_id: Return Tweets newer than this Tweet ID. + + source: Match the source application. + to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. @@ -929,6 +1403,10 @@ def retrieve_replies( verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -949,33 +1427,52 @@ def retrieve_replies( query=maybe_transform( { "any_words": any_words, + "blue_verified_only": blue_verified_only, + "card_name": card_name, "cashtags": cashtags, "conversation_id": conversation_id, "cursor": cursor, "exact_phrase": exact_phrase, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, "include_parent_tweet": include_parent_tweet, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, "page_size": page_size, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, "replies": replies, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, "since_date": since_date, + "since_id": since_id, + "source": source, "to_user": to_user, "until_date": until_date, "url": url, "verified_only": verified_only, + "within": within, + "within_time": within_time, }, user_retrieve_replies_params.UserRetrieveRepliesParams, ), @@ -987,7 +1484,21 @@ def retrieve_search( self, *, q: str, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1001,8 +1512,36 @@ def retrieve_search( Args: q: User search query + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor for user search + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1021,7 +1560,21 @@ def retrieve_search( query=maybe_transform( { "q": q, + "bio_contains": bio_contains, "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, }, user_retrieve_search_params.UserRetrieveSearchParams, ), @@ -1034,34 +1587,53 @@ def retrieve_tweets( id: str, *, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, include_parent_tweet: bool | Omit = omit, include_replies: bool | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, page_size: int | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1069,25 +1641,36 @@ def retrieve_tweets( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PaginatedTweets: - """ - List recent tweets posted by a user + """Omit mode for automatic maximum coverage. + + Pass next_cursor unchanged. Unprefixed + cursors use legacy pagination. Shape and billing stay the same. Args: any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. - cursor: Pagination cursor for user tweets + cursor: Cursor from the previous response. Xquik cursors resume automatic coverage. + Existing unprefixed cursors keep legacy standard behavior. exact_phrase: Exact phrase to match. + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. include_parent_tweet: Include parent tweet for replies @@ -1098,10 +1681,22 @@ def retrieve_tweets( language: Language code filter, e.g. en or tr. + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. + media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -1110,9 +1705,16 @@ def retrieve_tweets( min_retweets: Minimum retweets threshold. - page_size: Maximum page items (1-100, default 20). Source, filters, or credits can reduce - results. Continue while has_next_page is true. Deprecated limit and count - aliases remain accepted. + min_views: Minimum view count threshold. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + + page_size: Automatic pages accept 1-300 Tweets. Standard pages keep 1-100. Default 20. + Continue while has_next_page is true. Deprecated aliases remain accepted. quotes: Quote mode. @@ -1124,8 +1726,14 @@ def retrieve_tweets( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + since_date: Start date in YYYY-MM-DD format. + since_id: Return Tweets newer than this Tweet ID. + + source: Match the source application. + to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. @@ -1134,6 +1742,10 @@ def retrieve_tweets( verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1154,34 +1766,53 @@ def retrieve_tweets( query=maybe_transform( { "any_words": any_words, + "blue_verified_only": blue_verified_only, + "card_name": card_name, "cashtags": cashtags, "conversation_id": conversation_id, "cursor": cursor, "exact_phrase": exact_phrase, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, "include_parent_tweet": include_parent_tweet, "include_replies": include_replies, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, "page_size": page_size, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, "replies": replies, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, "since_date": since_date, + "since_id": since_id, + "source": source, "to_user": to_user, "until_date": until_date, "url": url, "verified_only": verified_only, + "within": within, + "within_time": within_time, }, user_retrieve_tweets_params.UserRetrieveTweetsParams, ), @@ -1193,25 +1824,78 @@ def retrieve_verified_followers( self, id: str, *, + after: str | Omit = omit, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + limit: int | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, + mode: Literal["standard", "coverage"] | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> PaginatedUsers: - """ - List verified followers of a user + ) -> UserRetrieveVerifiedFollowersResponse: + """List verified followers of a user Args: - cursor: Pagination cursor for verified followers + after: Legacy cursor alias. + + Prefer cursor. - page_size: Maximum user profiles requested from this page (20-200, default 200). The - response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + + cursor: Cursor from the previous response. Xquik cursors resume automatic coverage. + Existing unprefixed cursors keep legacy standard behavior. + + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + limit: Legacy page-size alias outside explicit coverage mode. Coverage accepts 1-10000. + Prefer pageSize. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + mode: Omit mode for resumable maximum coverage. Standard keeps legacy pagination. + Coverage returns diagnostics once and rejects cursors. + + page_size: Maximum user profiles: automatic 300; standard 200. Sources return fewer + profiles. Continue with has_next_page. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. extra_headers: Send extra headers @@ -1223,22 +1907,44 @@ def retrieve_verified_followers( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._get( - path_template("/x/users/{id}/verified-followers", id=id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "cursor": cursor, - "page_size": page_size, - }, - user_retrieve_verified_followers_params.UserRetrieveVerifiedFollowersParams, + return cast( + UserRetrieveVerifiedFollowersResponse, + self._get( + path_template("/x/users/{id}/verified-followers", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "after": after, + "bio_contains": bio_contains, + "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "limit": limit, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, + "mode": mode, + "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, + }, + user_retrieve_verified_followers_params.UserRetrieveVerifiedFollowersParams, + ), ), + cast_to=cast( + Any, UserRetrieveVerifiedFollowersResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=PaginatedUsers, ) @@ -1384,16 +2090,31 @@ async def retrieve_followers( id: str, *, after: str | Omit = omit, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, limit: int | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, + mode: Literal["standard", "coverage"] | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> PaginatedUsers: + ) -> UserRetrieveFollowersResponse: """List followers of a user Args: @@ -1401,14 +2122,45 @@ async def retrieve_followers( Prefer cursor. - cursor: Pagination cursor for followers list + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + + cursor: Cursor from the previous response. Xquik cursors resume automatic coverage. + Existing unprefixed cursors keep legacy standard behavior. + + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + limit: Legacy page-size alias outside explicit coverage mode. Coverage accepts 1-10000. + Prefer pageSize. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + mode: Omit mode for resumable maximum coverage. Standard keeps legacy pagination. + Coverage returns diagnostics once and rejects cursors. - limit: Legacy integer page size alias for following lists. Prefer pageSize. + page_size: Maximum user profiles: automatic 300; standard 200. Sources return fewer + profiles. Continue with has_next_page. - page_size: Maximum user profiles requested from this page (20-200, default 200). The - response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. extra_headers: Send extra headers @@ -1420,32 +2172,66 @@ async def retrieve_followers( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._get( - path_template("/x/users/{id}/followers", id=id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "after": after, - "cursor": cursor, - "limit": limit, - "page_size": page_size, - }, - user_retrieve_followers_params.UserRetrieveFollowersParams, + return cast( + UserRetrieveFollowersResponse, + await self._get( + path_template("/x/users/{id}/followers", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "after": after, + "bio_contains": bio_contains, + "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "limit": limit, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, + "mode": mode, + "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, + }, + user_retrieve_followers_params.UserRetrieveFollowersParams, + ), ), + cast_to=cast( + Any, UserRetrieveFollowersResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=PaginatedUsers, ) async def retrieve_followers_you_know( self, id: str, *, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1457,12 +2243,39 @@ async def retrieve_followers_you_know( List mutual followers between you and a user Args: + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor for followers-you-know - page_size: Maximum user profiles requested from this page (20-200, default 200). The - response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + page_size: Maximum user profiles requested from this page (20-200, default 200). Source, + filters, or credits can return fewer profiles. Keep requesting next_cursor while + has_next_page is true. Deprecated aliases remain accepted. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. extra_headers: Send extra headers @@ -1483,8 +2296,22 @@ async def retrieve_followers_you_know( timeout=timeout, query=await async_maybe_transform( { + "bio_contains": bio_contains, "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, }, user_retrieve_followers_you_know_params.UserRetrieveFollowersYouKnowParams, ), @@ -1497,16 +2324,31 @@ async def retrieve_following( id: str, *, after: str | Omit = omit, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, limit: int | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, + mode: Literal["standard", "coverage"] | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> PaginatedUsers: + ) -> UserRetrieveFollowingResponse: """List accounts a user follows Args: @@ -1514,14 +2356,45 @@ async def retrieve_following( Prefer cursor. - cursor: Pagination cursor for following list + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + + cursor: Cursor from the previous response. Xquik cursors resume automatic coverage. + Existing unprefixed cursors keep legacy standard behavior. + + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + limit: Legacy page-size alias outside explicit coverage mode. Coverage accepts 1-10000. + Prefer pageSize. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. - limit: Legacy page size alias. Prefer pageSize. + min_statuses: Minimum post count. minPosts is also accepted. - page_size: Maximum user profiles requested from this page (20-200, default 200). The - response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + mode: Omit mode for resumable maximum coverage. Standard keeps legacy pagination. + Coverage returns diagnostics once and rejects cursors. + + page_size: Maximum user profiles: automatic 300; standard 200. Sources return fewer + profiles. Continue with has_next_page. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. extra_headers: Send extra headers @@ -1533,24 +2406,44 @@ async def retrieve_following( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._get( - path_template("/x/users/{id}/following", id=id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "after": after, - "cursor": cursor, - "limit": limit, - "page_size": page_size, - }, - user_retrieve_following_params.UserRetrieveFollowingParams, + return cast( + UserRetrieveFollowingResponse, + await self._get( + path_template("/x/users/{id}/following", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "after": after, + "bio_contains": bio_contains, + "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "limit": limit, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, + "mode": mode, + "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, + }, + user_retrieve_following_params.UserRetrieveFollowingParams, + ), ), + cast_to=cast( + Any, UserRetrieveFollowingResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=PaginatedUsers, ) async def retrieve_likes( @@ -1558,32 +2451,51 @@ async def retrieve_likes( id: str, *, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, page_size: int | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1598,6 +2510,10 @@ async def retrieve_likes( any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. @@ -1606,20 +2522,36 @@ async def retrieve_likes( exact_phrase: Exact phrase to match. + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. in_reply_to_tweet_id: Only replies to this tweet ID. language: Language code filter, e.g. en or tr. + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. + media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -1628,6 +2560,14 @@ async def retrieve_likes( min_retweets: Minimum retweets threshold. + min_views: Minimum view count threshold. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + page_size: Maximum page items (1-100, default 20). Source, filters, or credits can reduce results. Continue while has_next_page is true. Deprecated limit and count aliases remain accepted. @@ -1642,8 +2582,14 @@ async def retrieve_likes( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + since_date: Start date in YYYY-MM-DD format. + since_id: Return Tweets newer than this Tweet ID. + + source: Match the source application. + to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. @@ -1652,6 +2598,10 @@ async def retrieve_likes( verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1672,32 +2622,51 @@ async def retrieve_likes( query=await async_maybe_transform( { "any_words": any_words, + "blue_verified_only": blue_verified_only, + "card_name": card_name, "cashtags": cashtags, "conversation_id": conversation_id, "cursor": cursor, "exact_phrase": exact_phrase, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, "page_size": page_size, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, "replies": replies, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, "since_date": since_date, + "since_id": since_id, + "source": source, "to_user": to_user, "until_date": until_date, "url": url, "verified_only": verified_only, + "within": within, + "within_time": within_time, }, user_retrieve_likes_params.UserRetrieveLikesParams, ), @@ -1710,32 +2679,51 @@ async def retrieve_media( id: str, *, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, page_size: int | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1750,6 +2738,10 @@ async def retrieve_media( any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. @@ -1758,20 +2750,36 @@ async def retrieve_media( exact_phrase: Exact phrase to match. + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. in_reply_to_tweet_id: Only replies to this tweet ID. language: Language code filter, e.g. en or tr. + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. + media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -1780,6 +2788,14 @@ async def retrieve_media( min_retweets: Minimum retweets threshold. + min_views: Minimum view count threshold. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + page_size: Maximum page items (1-100, default 20). Source, filters, or credits can reduce results. Continue while has_next_page is true. Deprecated limit and count aliases remain accepted. @@ -1794,8 +2810,14 @@ async def retrieve_media( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + since_date: Start date in YYYY-MM-DD format. + since_id: Return Tweets newer than this Tweet ID. + + source: Match the source application. + to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. @@ -1804,6 +2826,10 @@ async def retrieve_media( verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1824,32 +2850,51 @@ async def retrieve_media( query=await async_maybe_transform( { "any_words": any_words, + "blue_verified_only": blue_verified_only, + "card_name": card_name, "cashtags": cashtags, "conversation_id": conversation_id, "cursor": cursor, "exact_phrase": exact_phrase, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, "page_size": page_size, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, "replies": replies, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, "since_date": since_date, + "since_id": since_id, + "source": source, "to_user": to_user, "until_date": until_date, "url": url, "verified_only": verified_only, + "within": within, + "within_time": within_time, }, user_retrieve_media_params.UserRetrieveMediaParams, ), @@ -1862,34 +2907,53 @@ async def retrieve_mentions( id: str, *, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, page_size: int | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, since_time: str | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, until_time: str | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1904,6 +2968,10 @@ async def retrieve_mentions( any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. @@ -1912,20 +2980,36 @@ async def retrieve_mentions( exact_phrase: Exact phrase to match. + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. in_reply_to_tweet_id: Only replies to this tweet ID. language: Language code filter, e.g. en or tr. + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. + media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -1934,6 +3018,14 @@ async def retrieve_mentions( min_retweets: Minimum retweets threshold. + min_views: Minimum view count threshold. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + page_size: Maximum page items (1-100, default 20). Source, filters, or credits can reduce results. Continue while has_next_page is true. Deprecated limit and count aliases remain accepted. @@ -1948,10 +3040,16 @@ async def retrieve_mentions( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + since_date: Start date in YYYY-MM-DD format. + since_id: Return Tweets newer than this Tweet ID. + since_time: Unix timestamp - return mentions after this time + source: Match the source application. + to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. @@ -1962,6 +3060,10 @@ async def retrieve_mentions( verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1982,34 +3084,53 @@ async def retrieve_mentions( query=await async_maybe_transform( { "any_words": any_words, + "blue_verified_only": blue_verified_only, + "card_name": card_name, "cashtags": cashtags, "conversation_id": conversation_id, "cursor": cursor, "exact_phrase": exact_phrase, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, "page_size": page_size, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, "replies": replies, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, "since_date": since_date, + "since_id": since_id, "since_time": since_time, + "source": source, "to_user": to_user, "until_date": until_date, "until_time": until_time, "url": url, "verified_only": verified_only, + "within": within, + "within_time": within_time, }, user_retrieve_mentions_params.UserRetrieveMentionsParams, ), @@ -2022,33 +3143,52 @@ async def retrieve_replies( id: str, *, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, include_parent_tweet: bool | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, page_size: int | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -2056,25 +3196,37 @@ async def retrieve_replies( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PaginatedTweets: - """ - Returns the user's timeline with replies included by default. + """Returns target-authored posts and replies. + + Omit mode for automatic maximum + coverage. Pass next_cursor unchanged. Unprefixed cursors stay legacy. Excludes + other-author context. Args: any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. - cursor: Pagination cursor for user replies + cursor: Cursor from the previous response. Xquik cursors resume automatic coverage. + Existing unprefixed cursors keep legacy standard behavior. exact_phrase: Exact phrase to match. + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. include_parent_tweet: Include each reply's parent tweet. @@ -2083,10 +3235,22 @@ async def retrieve_replies( language: Language code filter, e.g. en or tr. + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. + media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -2095,9 +3259,16 @@ async def retrieve_replies( min_retweets: Minimum retweets threshold. - page_size: Maximum page items (1-100, default 20). Source, filters, or credits can reduce - results. Continue while has_next_page is true. Deprecated limit and count - aliases remain accepted. + min_views: Minimum view count threshold. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + + page_size: Automatic pages accept 1-300 Tweets. Standard pages keep 1-100. Default 20. + Continue while has_next_page is true. Deprecated aliases remain accepted. quotes: Quote mode. @@ -2109,8 +3280,14 @@ async def retrieve_replies( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + since_date: Start date in YYYY-MM-DD format. + since_id: Return Tweets newer than this Tweet ID. + + source: Match the source application. + to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. @@ -2119,6 +3296,10 @@ async def retrieve_replies( verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -2139,33 +3320,52 @@ async def retrieve_replies( query=await async_maybe_transform( { "any_words": any_words, + "blue_verified_only": blue_verified_only, + "card_name": card_name, "cashtags": cashtags, "conversation_id": conversation_id, "cursor": cursor, "exact_phrase": exact_phrase, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, "include_parent_tweet": include_parent_tweet, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, "page_size": page_size, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, "replies": replies, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, "since_date": since_date, + "since_id": since_id, + "source": source, "to_user": to_user, "until_date": until_date, "url": url, "verified_only": verified_only, + "within": within, + "within_time": within_time, }, user_retrieve_replies_params.UserRetrieveRepliesParams, ), @@ -2177,7 +3377,21 @@ async def retrieve_search( self, *, q: str, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -2191,8 +3405,36 @@ async def retrieve_search( Args: q: User search query + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + cursor: Pagination cursor for user search + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -2211,7 +3453,21 @@ async def retrieve_search( query=await async_maybe_transform( { "q": q, + "bio_contains": bio_contains, "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, }, user_retrieve_search_params.UserRetrieveSearchParams, ), @@ -2224,34 +3480,53 @@ async def retrieve_tweets( id: str, *, any_words: str | Omit = omit, + blue_verified_only: bool | Omit = omit, + card_name: str | Omit = omit, cashtags: str | Omit = omit, conversation_id: str | Omit = omit, cursor: str | Omit = omit, exact_phrase: str | Omit = omit, + exclude_source: str | Omit = omit, exclude_words: str | Omit = omit, from_user: str | Omit = omit, + geocode: str | Omit = omit, hashtags: str | Omit = omit, include_parent_tweet: bool | Omit = omit, include_replies: bool | Omit = omit, in_reply_to_tweet_id: str | Omit = omit, language: str | Omit = omit, + max_faves: int | Omit = omit, + max_id: str | Omit = omit, + max_quotes: int | Omit = omit, + max_replies: int | Omit = omit, + max_retweets: int | Omit = omit, media_type: Literal["images", "videos", "gifs", "media", "links", "none"] | Omit = omit, mentioning: str | Omit = omit, + min_bookmarks: int | Omit = omit, min_faves: int | Omit = omit, min_quotes: int | Omit = omit, min_replies: int | Omit = omit, min_retweets: int | Omit = omit, + min_views: int | Omit = omit, + native_retweets: bool | Omit = omit, + near: str | Omit = omit, + news: bool | Omit = omit, page_size: int | Omit = omit, quotes: Literal["include", "exclude", "only"] | Omit = omit, quotes_of_tweet_id: str | Omit = omit, replies: Literal["include", "exclude", "only"] | Omit = omit, retweets: Literal["include", "exclude", "only"] | Omit = omit, retweets_of_tweet_id: str | Omit = omit, + safe: bool | Omit = omit, since_date: Union[str, date] | Omit = omit, + since_id: str | Omit = omit, + source: str | Omit = omit, to_user: str | Omit = omit, until_date: Union[str, date] | Omit = omit, url: str | Omit = omit, verified_only: bool | Omit = omit, + within: str | Omit = omit, + within_time: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -2259,25 +3534,36 @@ async def retrieve_tweets( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> PaginatedTweets: - """ - List recent tweets posted by a user + """Omit mode for automatic maximum coverage. + + Pass next_cursor unchanged. Unprefixed + cursors use legacy pagination. Shape and billing stay the same. Args: any_words: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. + blue_verified_only: Only return tweets from Blue-verified authors. + + card_name: Match the Tweet card name. + cashtags: Cashtags separated by spaces, commas, or lines. conversation_id: Conversation ID filter. - cursor: Pagination cursor for user tweets + cursor: Cursor from the previous response. Xquik cursors resume automatic coverage. + Existing unprefixed cursors keep legacy standard behavior. exact_phrase: Exact phrase to match. + exclude_source: Exclude a source application. + exclude_words: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. from_user: Filter by author username. + geocode: Match latitude, longitude, and radius. + hashtags: Hashtags separated by spaces, commas, or lines. include_parent_tweet: Include parent tweet for replies @@ -2288,10 +3574,22 @@ async def retrieve_tweets( language: Language code filter, e.g. en or tr. + max_faves: Maximum likes threshold. maxLikes is also accepted. + + max_id: Return Tweets older than this Tweet ID. + + max_quotes: Maximum quotes threshold. + + max_replies: Maximum replies threshold. + + max_retweets: Maximum retweets threshold. + media_type: Filter by media type. mentioning: Filter tweets mentioning a username. + min_bookmarks: Minimum bookmark count threshold. + min_faves: Minimum likes threshold. min_quotes: Minimum quote count threshold. @@ -2300,9 +3598,16 @@ async def retrieve_tweets( min_retweets: Minimum retweets threshold. - page_size: Maximum page items (1-100, default 20). Source, filters, or credits can reduce - results. Continue while has_next_page is true. Deprecated limit and count - aliases remain accepted. + min_views: Minimum view count threshold. + + native_retweets: Only return native reposts. + + near: Match a place name. + + news: Only return news results. + + page_size: Automatic pages accept 1-300 Tweets. Standard pages keep 1-100. Default 20. + Continue while has_next_page is true. Deprecated aliases remain accepted. quotes: Quote mode. @@ -2314,8 +3619,14 @@ async def retrieve_tweets( retweets_of_tweet_id: Only retweets of this tweet ID. + safe: Enable the safe-search filter. + since_date: Start date in YYYY-MM-DD format. + since_id: Return Tweets newer than this Tweet ID. + + source: Match the source application. + to_user: Filter replies sent to a username. until_date: End date in YYYY-MM-DD format. @@ -2324,6 +3635,10 @@ async def retrieve_tweets( verified_only: Only return tweets from verified authors. + within: Set the radius for the near filter. + + within_time: Match Tweets inside a recent time window. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -2344,34 +3659,53 @@ async def retrieve_tweets( query=await async_maybe_transform( { "any_words": any_words, + "blue_verified_only": blue_verified_only, + "card_name": card_name, "cashtags": cashtags, "conversation_id": conversation_id, "cursor": cursor, "exact_phrase": exact_phrase, + "exclude_source": exclude_source, "exclude_words": exclude_words, "from_user": from_user, + "geocode": geocode, "hashtags": hashtags, "include_parent_tweet": include_parent_tweet, "include_replies": include_replies, "in_reply_to_tweet_id": in_reply_to_tweet_id, "language": language, + "max_faves": max_faves, + "max_id": max_id, + "max_quotes": max_quotes, + "max_replies": max_replies, + "max_retweets": max_retweets, "media_type": media_type, "mentioning": mentioning, + "min_bookmarks": min_bookmarks, "min_faves": min_faves, "min_quotes": min_quotes, "min_replies": min_replies, "min_retweets": min_retweets, + "min_views": min_views, + "native_retweets": native_retweets, + "near": near, + "news": news, "page_size": page_size, "quotes": quotes, "quotes_of_tweet_id": quotes_of_tweet_id, "replies": replies, "retweets": retweets, "retweets_of_tweet_id": retweets_of_tweet_id, + "safe": safe, "since_date": since_date, + "since_id": since_id, + "source": source, "to_user": to_user, "until_date": until_date, "url": url, "verified_only": verified_only, + "within": within, + "within_time": within_time, }, user_retrieve_tweets_params.UserRetrieveTweetsParams, ), @@ -2383,25 +3717,78 @@ async def retrieve_verified_followers( self, id: str, *, + after: str | Omit = omit, + bio_contains: str | Omit = omit, cursor: str | Omit = omit, + has_location: bool | Omit = omit, + has_website: bool | Omit = omit, + limit: int | Omit = omit, + location_contains: str | Omit = omit, + max_followers: int | Omit = omit, + max_following: int | Omit = omit, + max_statuses: int | Omit = omit, + min_account_age_days: int | Omit = omit, + min_followers: int | Omit = omit, + min_following: int | Omit = omit, + min_statuses: int | Omit = omit, + mode: Literal["standard", "coverage"] | Omit = omit, page_size: int | Omit = omit, + username_contains: str | Omit = omit, + verified_only: bool | Omit = omit, + verified_type: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> PaginatedUsers: - """ - List verified followers of a user + ) -> UserRetrieveVerifiedFollowersResponse: + """List verified followers of a user Args: - cursor: Pagination cursor for verified followers + after: Legacy cursor alias. + + Prefer cursor. - page_size: Maximum user profiles requested from this page (20-200, default 200). The - response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + bio_contains: Match any comma-separated or line-separated bio term, ignoring case. + + cursor: Cursor from the previous response. Xquik cursors resume automatic coverage. + Existing unprefixed cursors keep legacy standard behavior. + + has_location: Only return profiles with a location. + + has_website: Only return profiles with a website. + + limit: Legacy page-size alias outside explicit coverage mode. Coverage accepts 1-10000. + Prefer pageSize. + + location_contains: Match a location substring, ignoring case. + + max_followers: Maximum follower count. Missing counts pass this maximum. + + max_following: Maximum following count. + + max_statuses: Maximum post count. maxPosts is also accepted. + + min_account_age_days: Minimum account age in whole days. + + min_followers: Minimum follower count. Filtering happens before billing. + + min_following: Minimum following count. + + min_statuses: Minimum post count. minPosts is also accepted. + + mode: Omit mode for resumable maximum coverage. Standard keeps legacy pagination. + Coverage returns diagnostics once and rejects cursors. + + page_size: Maximum user profiles: automatic 300; standard 200. Sources return fewer + profiles. Continue with has_next_page. + + username_contains: Match a username substring, ignoring case. + + verified_only: Only return verified profiles. + + verified_type: Match the verification type exactly, ignoring case. extra_headers: Send extra headers @@ -2413,22 +3800,44 @@ async def retrieve_verified_followers( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._get( - path_template("/x/users/{id}/verified-followers", id=id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "cursor": cursor, - "page_size": page_size, - }, - user_retrieve_verified_followers_params.UserRetrieveVerifiedFollowersParams, + return cast( + UserRetrieveVerifiedFollowersResponse, + await self._get( + path_template("/x/users/{id}/verified-followers", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "after": after, + "bio_contains": bio_contains, + "cursor": cursor, + "has_location": has_location, + "has_website": has_website, + "limit": limit, + "location_contains": location_contains, + "max_followers": max_followers, + "max_following": max_following, + "max_statuses": max_statuses, + "min_account_age_days": min_account_age_days, + "min_followers": min_followers, + "min_following": min_following, + "min_statuses": min_statuses, + "mode": mode, + "page_size": page_size, + "username_contains": username_contains, + "verified_only": verified_only, + "verified_type": verified_type, + }, + user_retrieve_verified_followers_params.UserRetrieveVerifiedFollowersParams, + ), ), + cast_to=cast( + Any, UserRetrieveVerifiedFollowersResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=PaginatedUsers, ) diff --git a/src/x_twitter_scraper/types/draw_export_params.py b/src/x_twitter_scraper/types/draw_export_params.py index 558c04f..c5395d7 100644 --- a/src/x_twitter_scraper/types/draw_export_params.py +++ b/src/x_twitter_scraper/types/draw_export_params.py @@ -13,7 +13,11 @@ class DrawExportParams(TypedDict, total=False): format: Required[Literal["csv", "json", "md", "md-document", "pdf", "txt", "xlsx"]] - """Export output format""" + """Export output format. + + PDF entry exports include up to 10,000 rows. Other entry formats include up to + 100,000 rows. + """ type: Literal["winners", "entries"] """Export winners or all entries""" diff --git a/src/x_twitter_scraper/types/draw_list_params.py b/src/x_twitter_scraper/types/draw_list_params.py index bec6d02..e0e1791 100644 --- a/src/x_twitter_scraper/types/draw_list_params.py +++ b/src/x_twitter_scraper/types/draw_list_params.py @@ -13,7 +13,7 @@ class DrawListParams(TypedDict, total=False): cursor: str - """Cursor for keyset pagination from prior response next_cursor""" + """Previous nextCursor.""" limit: int """Maximum number of items to return (1-100, default 50). diff --git a/src/x_twitter_scraper/types/event_list_params.py b/src/x_twitter_scraper/types/event_list_params.py index a7b5dc4..ea4730a 100644 --- a/src/x_twitter_scraper/types/event_list_params.py +++ b/src/x_twitter_scraper/types/event_list_params.py @@ -16,11 +16,14 @@ class EventListParams(TypedDict, total=False): cursor: str - """Cursor for keyset pagination from prior response next_cursor""" + """Previous nextCursor.""" event_type: Annotated[EventType, PropertyInfo(alias="eventType")] """Filter events by type""" + keyword_monitor_id: Annotated[str, PropertyInfo(alias="keywordMonitorId")] + """Keyword monitor ID.""" + limit: int """Maximum number of items to return (1-100, default 50). @@ -30,4 +33,4 @@ class EventListParams(TypedDict, total=False): """ monitor_id: Annotated[str, PropertyInfo(alias="monitorId")] - """Filter events by monitor ID""" + """Account monitor ID.""" diff --git a/src/x_twitter_scraper/types/extraction_estimate_cost_params.py b/src/x_twitter_scraper/types/extraction_estimate_cost_params.py index f4b2873..3e241f2 100644 --- a/src/x_twitter_scraper/types/extraction_estimate_cost_params.py +++ b/src/x_twitter_scraper/types/extraction_estimate_cost_params.py @@ -6,13 +6,14 @@ from __future__ import annotations -from typing import Union -from datetime import date -from typing_extensions import Literal, Required, Annotated, TypedDict +from typing import Union, Iterable +from datetime import date, datetime +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo -__all__ = ["ExtractionEstimateCostParams"] +__all__ = ["ExtractionEstimateCostParams", "RelationTarget", "Target", "TargetUnionMember1"] class ExtractionEstimateCostParams(TypedDict, total=False): @@ -49,133 +50,334 @@ class ExtractionEstimateCostParams(TypedDict, total=False): """Identifier for the extraction tool used to run a job.""" advanced_query: Annotated[str, PropertyInfo(alias="advancedQuery")] - """Raw advanced query string appended to the estimate (tweet_search_extractor)""" + """Raw advanced search query appended as-is (tweet_search_extractor)""" any_words: Annotated[str, PropertyInfo(alias="anyWords")] - """Alternative words or quoted phrases for estimated results. + """Words or quoted phrases where any one can match. - Separate with spaces, commas, or lines. + Separate with spaces, commas, or lines. (tweet_search_extractor) """ + bio_contains: Annotated[str, PropertyInfo(alias="bioContains")] + """Bio terms separated by commas or lines.""" + + blue_verified_only: Annotated[bool, PropertyInfo(alias="blueVerifiedOnly")] + """Return only Blue-verified Tweet authors.""" + bounding_box: Annotated[str, PropertyInfo(alias="boundingBox")] - """Geo bounding box used for estimation, e.g. + """Geo bounding box, e.g. -74.1 40.6 -73.9 40.8 (tweet_search_extractor)""" - -74.1 40.6 -73.9 40.8 (tweet_search_extractor) - """ + card_name: Annotated[str, PropertyInfo(alias="cardName")] + """Match the Tweet card name.""" cashtags: str - """Cashtags applied to the estimate, separated by spaces, commas, or lines.""" + """Cashtags separated by spaces, commas, or lines. (tweet_search_extractor)""" + + collection_strategy: Annotated[ + Literal["auto", "complete", "direct", "search", "thread"], PropertyInfo(alias="collectionStrategy") + ] + """Reply collection strategy.""" conversation_id: Annotated[str, PropertyInfo(alias="conversationId")] - """Conversation ID filter used for estimation (tweet_search_extractor)""" + """Conversation ID filter (tweet_search_extractor)""" + + dedupe_across_targets: Annotated[bool, PropertyInfo(alias="dedupeAcrossTargets")] + """Merge duplicate results across collection targets.""" + + dedupe_mode: Annotated[Literal["none", "first", "merge"], PropertyInfo(alias="dedupeMode")] + """Keep target duplicates, first rows, or merged overlap.""" exact_phrase: Annotated[str, PropertyInfo(alias="exactPhrase")] - """Exact phrase filter for search estimation""" + """Exact phrase to match (tweet_search_extractor)""" + + exclude_original_author: Annotated[bool, PropertyInfo(alias="excludeOriginalAuthor")] + """Exclude replies from the source author.""" + + exclude_source: Annotated[str, PropertyInfo(alias="excludeSource")] + """Exclude a source application.""" exclude_words: Annotated[str, PropertyInfo(alias="excludeWords")] - """Words or quoted phrases excluded from estimated results. + """Words or quoted phrases to exclude. - Separate with spaces, commas, or lines. + Separate with spaces, commas, or lines. (tweet_search_extractor) """ from_user: Annotated[str, PropertyInfo(alias="fromUser")] - """Estimate only tweets from this author username (tweet_search_extractor)""" + """Filter by author username (tweet_search_extractor)""" + + geocode: str + """Match latitude, longitude, and radius.""" hashtags: str - """Hashtags applied to the estimate, separated by spaces, commas, or lines.""" + """Hashtags separated by spaces, commas, or lines. (tweet_search_extractor)""" + + has_location: Annotated[bool, PropertyInfo(alias="hasLocation")] + """Require a profile location.""" + + has_media_only: Annotated[bool, PropertyInfo(alias="hasMediaOnly")] + """Return only replies with media.""" + + has_website: Annotated[bool, PropertyInfo(alias="hasWebsite")] + """Require a profile website.""" + + include_original_post: Annotated[bool, PropertyInfo(alias="includeOriginalPost")] + """Include the source post in reply results.""" + + include_search_terms: Annotated[bool, PropertyInfo(alias="includeSearchTerms")] + """Add matching search terms to collection metadata.""" + + include_target_metadata: Annotated[bool, PropertyInfo(alias="includeTargetMetadata")] + """Add source target metadata to each result.""" in_reply_to_tweet_id: Annotated[str, PropertyInfo(alias="inReplyToTweetId")] - """Estimate only replies to this tweet ID (tweet_search_extractor)""" + """Only replies to this tweet ID (tweet_search_extractor)""" language: str - """Language code used for estimate filtering (tweet_search_extractor)""" + """Language code filter (tweet_search_extractor)""" list_id: Annotated[str, PropertyInfo(alias="listId")] - """Estimate search results within this list ID (tweet_search_extractor)""" + """Search within a list ID (tweet_search_extractor)""" + + location_contains: Annotated[str, PropertyInfo(alias="locationContains")] + """Required profile location text.""" + + max_depth: Annotated[int, PropertyInfo(alias="maxDepth")] + """Maximum nested reply depth.""" + + max_followers: Annotated[int, PropertyInfo(alias="maxFollowers")] + """Maximum follower count for profile results.""" + + max_following: Annotated[int, PropertyInfo(alias="maxFollowing")] + """Maximum following count for profile results.""" + + max_id: Annotated[str, PropertyInfo(alias="maxId")] + """Return Tweets older than this Tweet ID.""" + + max_items_per_target: Annotated[int, PropertyInfo(alias="maxItemsPerTarget")] + """Maximum results collected for each target.""" + + max_likes: Annotated[int, PropertyInfo(alias="maxLikes")] + """Maximum Tweet like count.""" + + max_pages_per_target: Annotated[int, PropertyInfo(alias="maxPagesPerTarget")] + """Reply pages collected for each target.""" + + max_posts: Annotated[int, PropertyInfo(alias="maxPosts")] + """Maximum post count for profile results.""" + + max_quotes: Annotated[int, PropertyInfo(alias="maxQuotes")] + """Maximum Tweet quote count.""" + + max_replies: Annotated[int, PropertyInfo(alias="maxReplies")] + """Maximum Tweet reply count.""" + + max_retweets: Annotated[int, PropertyInfo(alias="maxRetweets")] + """Maximum Tweet repost count.""" media_type: Annotated[ Literal["images", "videos", "gifs", "media", "links", "none"], PropertyInfo(alias="mediaType") ] - """Media type used for estimate filtering (tweet_search_extractor)""" + """Media type filter (tweet_search_extractor)""" mentioning: str - """Estimate tweets mentioning this username (tweet_search_extractor)""" + """Filter tweets mentioning a username (tweet_search_extractor)""" + + min_account_age_days: Annotated[int, PropertyInfo(alias="minAccountAgeDays")] + """Minimum profile age in days.""" + + min_bookmarks: Annotated[int, PropertyInfo(alias="minBookmarks")] + """Minimum Tweet bookmark count.""" min_faves: Annotated[int, PropertyInfo(alias="minFaves")] - """Minimum likes threshold for estimated results (tweet_search_extractor)""" + """Minimum likes threshold (tweet_search_extractor)""" + + min_followers: Annotated[int, PropertyInfo(alias="minFollowers")] + """Minimum follower count for profile results.""" + + min_following: Annotated[int, PropertyInfo(alias="minFollowing")] + """Minimum following count for profile results.""" + + min_posts: Annotated[int, PropertyInfo(alias="minPosts")] + """Minimum post count for profile results.""" min_quotes: Annotated[int, PropertyInfo(alias="minQuotes")] - """Minimum quote count threshold for estimated results (tweet_search_extractor)""" + """Minimum quote count threshold (tweet_search_extractor)""" min_replies: Annotated[int, PropertyInfo(alias="minReplies")] - """Minimum replies threshold for estimated results (tweet_search_extractor)""" + """Minimum replies threshold (tweet_search_extractor)""" min_retweets: Annotated[int, PropertyInfo(alias="minRetweets")] - """Minimum retweets threshold for estimated results (tweet_search_extractor)""" + """Minimum retweets threshold (tweet_search_extractor)""" + + min_views: Annotated[int, PropertyInfo(alias="minViews")] + """Minimum Tweet view count.""" + + native_retweets: Annotated[bool, PropertyInfo(alias="nativeRetweets")] + """Only return native reposts.""" + + near: str + """Match a place name.""" + + news: bool + """Only return news results.""" + + overlap_mode: Annotated[bool, PropertyInfo(alias="overlapMode")] + """Shortcut for dedupeMode=merge.""" place: str - """Estimate search results within this place ID (tweet_search_extractor)""" + """Search within a place ID (tweet_search_extractor)""" place_country: Annotated[str, PropertyInfo(alias="placeCountry")] - """Estimate search results within this country code (tweet_search_extractor)""" + """Search within a country code (tweet_search_extractor)""" point_radius: Annotated[str, PropertyInfo(alias="pointRadius")] - """Geo point radius used for estimation, e.g. + """Geo point radius, e.g. -73.99 40.73 25mi (tweet_search_extractor)""" - -73.99 40.73 25mi (tweet_search_extractor) - """ + query_type: Annotated[Literal["Latest", "Top", "Both"], PropertyInfo(alias="queryType")] + """Search ranking applied to every query.""" quotes: Literal["include", "exclude", "only"] - """Quote mode used for estimation (tweet_search_extractor)""" + """Quote mode (tweet_search_extractor)""" quotes_of_tweet_id: Annotated[str, PropertyInfo(alias="quotesOfTweetId")] - """Estimate only quotes of this tweet ID (tweet_search_extractor)""" + """Only quotes of this tweet ID (tweet_search_extractor)""" + + relation_targets: Annotated[Iterable[RelationTarget], PropertyInfo(alias="relationTargets")] + """Profile relations processed within one job.""" replies: Literal["include", "exclude", "only"] - """Reply mode used for estimation (tweet_search_extractor)""" + """Reply mode (tweet_search_extractor)""" results_limit: Annotated[int, PropertyInfo(alias="resultsLimit")] - """Maximum number of results to estimate. + """Maximum number of results to extract. - When set, the estimate caps projected results to this value. + When set, the extraction stops after reaching this limit. """ retweets: Literal["include", "exclude", "only"] - """Retweet mode used for estimation (tweet_search_extractor)""" + """Retweet mode (tweet_search_extractor)""" retweets_of_tweet_id: Annotated[str, PropertyInfo(alias="retweetsOfTweetId")] - """Estimate only retweets of this tweet ID (tweet_search_extractor)""" + """Only retweets of this tweet ID (tweet_search_extractor)""" + + safe: bool + """Enable the safe-search filter.""" + + scope: Literal["all", "direct", "nested"] + """Reply depth scope.""" + + search_queries: Annotated[SequenceNotStr[str], PropertyInfo(alias="searchQueries")] + """Search queries processed as one collection job.""" search_query: Annotated[str, PropertyInfo(alias="searchQuery")] - """Query used to price tweet_search_extractor or community_search.""" + """Required for tweet_search_extractor & community_search.""" since_date: Annotated[Union[str, date], PropertyInfo(alias="sinceDate", format="iso8601")] - """Estimate start date in YYYY-MM-DD format (tweet_search_extractor)""" + """Start date YYYY-MM-DD (tweet_search_extractor)""" + + since_id: Annotated[str, PropertyInfo(alias="sinceId")] + """Return Tweets newer than this Tweet ID.""" + + since_time: Annotated[Union[Union[str, datetime], int], PropertyInfo(alias="sinceTime", format="iso8601")] + """Reply start time as ISO 8601 or Unix seconds.""" + + sort: Literal["relevance", "latest", "oldest", "likes"] + """Reply result order.""" + + source: str + """Match the source application.""" + + start_cursor: Annotated[str, PropertyInfo(alias="startCursor")] + """Resume one reply target from this cursor.""" target_community_id: Annotated[str, PropertyInfo(alias="targetCommunityId")] - """Community ID used to price community_post_extractor or community_search.""" + """Required for community_post_extractor & community_search.""" + + target_community_ids: Annotated[SequenceNotStr[str], PropertyInfo(alias="targetCommunityIds")] + """Community IDs processed as one collection job.""" target_list_id: Annotated[str, PropertyInfo(alias="targetListId")] """ - List ID used to price list_follower_explorer, list_member_extractor, or + Required for list_follower_explorer, list_member_extractor & list_post_extractor. """ + target_list_ids: Annotated[SequenceNotStr[str], PropertyInfo(alias="targetListIds")] + """List IDs processed as one collection job.""" + + targets: SequenceNotStr[Target] + """Mixed targets auto-routed within one job.""" + target_space_id: Annotated[str, PropertyInfo(alias="targetSpaceId")] - """Space ID used to price space_explorer.""" + """Required for space_explorer.""" target_tweet_id: Annotated[str, PropertyInfo(alias="targetTweetId")] + target_tweet_ids: Annotated[SequenceNotStr[str], PropertyInfo(alias="targetTweetIds")] + """Tweet IDs processed as one collection job.""" + target_username: Annotated[str, PropertyInfo(alias="targetUsername")] + target_usernames: Annotated[SequenceNotStr[str], PropertyInfo(alias="targetUsernames")] + """Usernames processed as one collection job.""" + to_user: Annotated[str, PropertyInfo(alias="toUser")] - """Estimate replies sent to this username (tweet_search_extractor)""" + """Filter replies sent to a username (tweet_search_extractor)""" until_date: Annotated[Union[str, date], PropertyInfo(alias="untilDate", format="iso8601")] - """Estimate end date in YYYY-MM-DD format (tweet_search_extractor)""" + """End date YYYY-MM-DD (tweet_search_extractor)""" + + until_time: Annotated[Union[Union[str, datetime], int], PropertyInfo(alias="untilTime", format="iso8601")] + """Reply end time as ISO 8601 or Unix seconds.""" url: str - """URL substring or domain filter used for estimation (tweet_search_extractor)""" + """URL substring or domain filter (tweet_search_extractor)""" + + username_contains: Annotated[str, PropertyInfo(alias="usernameContains")] + """Required username text.""" verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] - """Estimate only verified authors (tweet_search_extractor)""" + """Only verified authors (tweet_search_extractor)""" + + verified_type: Annotated[str, PropertyInfo(alias="verifiedType")] + """Exact profile verification type.""" + + within: str + """Set the radius for the near filter.""" + + within_time: Annotated[str, PropertyInfo(alias="withinTime")] + """Match Tweets inside a recent time window.""" + + +class RelationTarget(TypedDict, total=False): + """One target and relation in a mixed profile collection.""" + + relation: Required[ + Literal["community_members", "followers", "following", "list_followers", "list_members", "verified_followers"] + ] + + value: Required[str] + + +class TargetUnionMember1(TypedDict, total=False): + kind: Required[ + Literal[ + "favoriters", + "list", + "profile", + "profile_likes", + "profile_media", + "profile_replies", + "quotes", + "replies", + "retweeters", + "search", + "thread", + "tweet", + ] + ] + + value: Required[str] + + +Target: TypeAlias = Union[str, TargetUnionMember1] diff --git a/src/x_twitter_scraper/types/extraction_estimate_cost_response.py b/src/x_twitter_scraper/types/extraction_estimate_cost_response.py index 3dd72af..402c42d 100644 --- a/src/x_twitter_scraper/types/extraction_estimate_cost_response.py +++ b/src/x_twitter_scraper/types/extraction_estimate_cost_response.py @@ -26,6 +26,7 @@ class ExtractionEstimateCostResponse(BaseModel): source: Literal[ "followers", "following", + "collection", "paginationCap", "posts", "quoteCount", diff --git a/src/x_twitter_scraper/types/extraction_export_results_params.py b/src/x_twitter_scraper/types/extraction_export_results_params.py index 6c1bd7b..f8114fb 100644 --- a/src/x_twitter_scraper/types/extraction_export_results_params.py +++ b/src/x_twitter_scraper/types/extraction_export_results_params.py @@ -6,7 +6,11 @@ from __future__ import annotations -from typing_extensions import Literal, Required, TypedDict +from typing import Union +from datetime import date +from typing_extensions import Literal, Required, Annotated, TypedDict + +from .._utils import PropertyInfo __all__ = ["ExtractionExportResultsParams"] @@ -14,3 +18,57 @@ class ExtractionExportResultsParams(TypedDict, total=False): format: Required[Literal["csv", "json", "md", "md-document", "pdf", "txt", "xlsx"]] """Export file format""" + + has_description: Annotated[bool, PropertyInfo(alias="hasDescription")] + """Require a non-empty description.""" + + has_location: Annotated[bool, PropertyInfo(alias="hasLocation")] + """Require a non-empty location.""" + + has_media: Annotated[bool, PropertyInfo(alias="hasMedia")] + """Require media.""" + + lang: str + """Filter by language code.""" + + max_followers: Annotated[int, PropertyInfo(alias="maxFollowers")] + """Maximum follower count.""" + + max_following: Annotated[int, PropertyInfo(alias="maxFollowing")] + """Maximum following count.""" + + max_posts: Annotated[int, PropertyInfo(alias="maxPosts")] + """Maximum post count.""" + + min_followers: Annotated[int, PropertyInfo(alias="minFollowers")] + """Minimum follower count.""" + + min_following: Annotated[int, PropertyInfo(alias="minFollowing")] + """Minimum following count.""" + + min_likes: Annotated[int, PropertyInfo(alias="minLikes")] + """Minimum like count.""" + + min_posts: Annotated[int, PropertyInfo(alias="minPosts")] + """Minimum post count.""" + + min_replies: Annotated[int, PropertyInfo(alias="minReplies")] + """Minimum reply count.""" + + min_retweets: Annotated[int, PropertyInfo(alias="minRetweets")] + """Minimum repost count.""" + + min_views: Annotated[int, PropertyInfo(alias="minViews")] + """Minimum view count.""" + + search: str + """Search exported result text.""" + + since_date: Annotated[Union[str, date], PropertyInfo(alias="sinceDate", format="iso8601")] + """Include results on or after this date.""" + + until_date: Annotated[Union[str, date], PropertyInfo(alias="untilDate", format="iso8601")] + """Include results on or before this date.""" + + verified: bool + """Filter by verified status.""" diff --git a/src/x_twitter_scraper/types/extraction_list_params.py b/src/x_twitter_scraper/types/extraction_list_params.py index 30325af..f97b8d4 100644 --- a/src/x_twitter_scraper/types/extraction_list_params.py +++ b/src/x_twitter_scraper/types/extraction_list_params.py @@ -15,7 +15,7 @@ class ExtractionListParams(TypedDict, total=False): cursor: str - """Cursor for keyset pagination from prior response next_cursor""" + """Previous nextCursor.""" limit: int """Maximum number of items to return (1-100, default 50). diff --git a/src/x_twitter_scraper/types/extraction_retrieve_params.py b/src/x_twitter_scraper/types/extraction_retrieve_params.py index acda1bd..f756579 100644 --- a/src/x_twitter_scraper/types/extraction_retrieve_params.py +++ b/src/x_twitter_scraper/types/extraction_retrieve_params.py @@ -6,14 +6,28 @@ from __future__ import annotations -from typing_extensions import TypedDict +from typing_extensions import Literal, Annotated, TypedDict + +from .._utils import PropertyInfo __all__ = ["ExtractionRetrieveParams"] class ExtractionRetrieveParams(TypedDict, total=False): cursor: str - """Cursor for keyset pagination from prior response next_cursor""" + """Previous nextCursor.""" + + field_style: Annotated[Literal["source", "camelCase", "snake_case"], PropertyInfo(alias="fieldStyle")] + """Preserve source keys or convert result field names.""" + + include_raw: Annotated[bool, PropertyInfo(alias="includeRaw")] + """Use outputMode=raw instead.""" limit: int """Maximum number of results to return (1-1000, default 100)""" + + output_mode: Annotated[Literal["compact", "full", "raw"], PropertyInfo(alias="outputMode")] + """Select compact, full, or raw-compatible result fields.""" + + output_preset: Annotated[Literal["nested", "flat"], PropertyInfo(alias="outputPreset")] + """Keep enrichment nested or merge it into each result.""" diff --git a/src/x_twitter_scraper/types/extraction_run_params.py b/src/x_twitter_scraper/types/extraction_run_params.py index bf4b15a..34f063e 100644 --- a/src/x_twitter_scraper/types/extraction_run_params.py +++ b/src/x_twitter_scraper/types/extraction_run_params.py @@ -6,13 +6,14 @@ from __future__ import annotations -from typing import Union -from datetime import date -from typing_extensions import Literal, Required, Annotated, TypedDict +from typing import Union, Iterable +from datetime import date, datetime +from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from .._types import SequenceNotStr from .._utils import PropertyInfo -__all__ = ["ExtractionRunParams"] +__all__ = ["ExtractionRunParams", "RelationTarget", "Target", "TargetUnionMember1"] class ExtractionRunParams(TypedDict, total=False): @@ -48,6 +49,9 @@ class ExtractionRunParams(TypedDict, total=False): ] """Identifier for the extraction tool used to run a job.""" + dry_run: bool + """Estimate cost without creating an extraction.""" + advanced_query: Annotated[str, PropertyInfo(alias="advancedQuery")] """Raw advanced search query appended as-is (tweet_search_extractor)""" @@ -57,18 +61,44 @@ class ExtractionRunParams(TypedDict, total=False): Separate with spaces, commas, or lines. (tweet_search_extractor) """ + bio_contains: Annotated[str, PropertyInfo(alias="bioContains")] + """Bio terms separated by commas or lines.""" + + blue_verified_only: Annotated[bool, PropertyInfo(alias="blueVerifiedOnly")] + """Return only Blue-verified Tweet authors.""" + bounding_box: Annotated[str, PropertyInfo(alias="boundingBox")] """Geo bounding box, e.g. -74.1 40.6 -73.9 40.8 (tweet_search_extractor)""" + card_name: Annotated[str, PropertyInfo(alias="cardName")] + """Match the Tweet card name.""" + cashtags: str """Cashtags separated by spaces, commas, or lines. (tweet_search_extractor)""" + collection_strategy: Annotated[ + Literal["auto", "complete", "direct", "search", "thread"], PropertyInfo(alias="collectionStrategy") + ] + """Reply collection strategy.""" + conversation_id: Annotated[str, PropertyInfo(alias="conversationId")] """Conversation ID filter (tweet_search_extractor)""" + dedupe_across_targets: Annotated[bool, PropertyInfo(alias="dedupeAcrossTargets")] + """Merge duplicate results across collection targets.""" + + dedupe_mode: Annotated[Literal["none", "first", "merge"], PropertyInfo(alias="dedupeMode")] + """Keep target duplicates, first rows, or merged overlap.""" + exact_phrase: Annotated[str, PropertyInfo(alias="exactPhrase")] """Exact phrase to match (tweet_search_extractor)""" + exclude_original_author: Annotated[bool, PropertyInfo(alias="excludeOriginalAuthor")] + """Exclude replies from the source author.""" + + exclude_source: Annotated[str, PropertyInfo(alias="excludeSource")] + """Exclude a source application.""" + exclude_words: Annotated[str, PropertyInfo(alias="excludeWords")] """Words or quoted phrases to exclude. @@ -78,9 +108,30 @@ class ExtractionRunParams(TypedDict, total=False): from_user: Annotated[str, PropertyInfo(alias="fromUser")] """Filter by author username (tweet_search_extractor)""" + geocode: str + """Match latitude, longitude, and radius.""" + hashtags: str """Hashtags separated by spaces, commas, or lines. (tweet_search_extractor)""" + has_location: Annotated[bool, PropertyInfo(alias="hasLocation")] + """Require a profile location.""" + + has_media_only: Annotated[bool, PropertyInfo(alias="hasMediaOnly")] + """Return only replies with media.""" + + has_website: Annotated[bool, PropertyInfo(alias="hasWebsite")] + """Require a profile website.""" + + include_original_post: Annotated[bool, PropertyInfo(alias="includeOriginalPost")] + """Include the source post in reply results.""" + + include_search_terms: Annotated[bool, PropertyInfo(alias="includeSearchTerms")] + """Add matching search terms to collection metadata.""" + + include_target_metadata: Annotated[bool, PropertyInfo(alias="includeTargetMetadata")] + """Add source target metadata to each result.""" + in_reply_to_tweet_id: Annotated[str, PropertyInfo(alias="inReplyToTweetId")] """Only replies to this tweet ID (tweet_search_extractor)""" @@ -90,6 +141,42 @@ class ExtractionRunParams(TypedDict, total=False): list_id: Annotated[str, PropertyInfo(alias="listId")] """Search within a list ID (tweet_search_extractor)""" + location_contains: Annotated[str, PropertyInfo(alias="locationContains")] + """Required profile location text.""" + + max_depth: Annotated[int, PropertyInfo(alias="maxDepth")] + """Maximum nested reply depth.""" + + max_followers: Annotated[int, PropertyInfo(alias="maxFollowers")] + """Maximum follower count for profile results.""" + + max_following: Annotated[int, PropertyInfo(alias="maxFollowing")] + """Maximum following count for profile results.""" + + max_id: Annotated[str, PropertyInfo(alias="maxId")] + """Return Tweets older than this Tweet ID.""" + + max_items_per_target: Annotated[int, PropertyInfo(alias="maxItemsPerTarget")] + """Maximum results collected for each target.""" + + max_likes: Annotated[int, PropertyInfo(alias="maxLikes")] + """Maximum Tweet like count.""" + + max_pages_per_target: Annotated[int, PropertyInfo(alias="maxPagesPerTarget")] + """Reply pages collected for each target.""" + + max_posts: Annotated[int, PropertyInfo(alias="maxPosts")] + """Maximum post count for profile results.""" + + max_quotes: Annotated[int, PropertyInfo(alias="maxQuotes")] + """Maximum Tweet quote count.""" + + max_replies: Annotated[int, PropertyInfo(alias="maxReplies")] + """Maximum Tweet reply count.""" + + max_retweets: Annotated[int, PropertyInfo(alias="maxRetweets")] + """Maximum Tweet repost count.""" + media_type: Annotated[ Literal["images", "videos", "gifs", "media", "links", "none"], PropertyInfo(alias="mediaType") ] @@ -98,9 +185,24 @@ class ExtractionRunParams(TypedDict, total=False): mentioning: str """Filter tweets mentioning a username (tweet_search_extractor)""" + min_account_age_days: Annotated[int, PropertyInfo(alias="minAccountAgeDays")] + """Minimum profile age in days.""" + + min_bookmarks: Annotated[int, PropertyInfo(alias="minBookmarks")] + """Minimum Tweet bookmark count.""" + min_faves: Annotated[int, PropertyInfo(alias="minFaves")] """Minimum likes threshold (tweet_search_extractor)""" + min_followers: Annotated[int, PropertyInfo(alias="minFollowers")] + """Minimum follower count for profile results.""" + + min_following: Annotated[int, PropertyInfo(alias="minFollowing")] + """Minimum following count for profile results.""" + + min_posts: Annotated[int, PropertyInfo(alias="minPosts")] + """Minimum post count for profile results.""" + min_quotes: Annotated[int, PropertyInfo(alias="minQuotes")] """Minimum quote count threshold (tweet_search_extractor)""" @@ -110,6 +212,21 @@ class ExtractionRunParams(TypedDict, total=False): min_retweets: Annotated[int, PropertyInfo(alias="minRetweets")] """Minimum retweets threshold (tweet_search_extractor)""" + min_views: Annotated[int, PropertyInfo(alias="minViews")] + """Minimum Tweet view count.""" + + native_retweets: Annotated[bool, PropertyInfo(alias="nativeRetweets")] + """Only return native reposts.""" + + near: str + """Match a place name.""" + + news: bool + """Only return news results.""" + + overlap_mode: Annotated[bool, PropertyInfo(alias="overlapMode")] + """Shortcut for dedupeMode=merge.""" + place: str """Search within a place ID (tweet_search_extractor)""" @@ -119,12 +236,18 @@ class ExtractionRunParams(TypedDict, total=False): point_radius: Annotated[str, PropertyInfo(alias="pointRadius")] """Geo point radius, e.g. -73.99 40.73 25mi (tweet_search_extractor)""" + query_type: Annotated[Literal["Latest", "Top", "Both"], PropertyInfo(alias="queryType")] + """Search ranking applied to every query.""" + quotes: Literal["include", "exclude", "only"] """Quote mode (tweet_search_extractor)""" quotes_of_tweet_id: Annotated[str, PropertyInfo(alias="quotesOfTweetId")] """Only quotes of this tweet ID (tweet_search_extractor)""" + relation_targets: Annotated[Iterable[RelationTarget], PropertyInfo(alias="relationTargets")] + """Profile relations processed within one job.""" + replies: Literal["include", "exclude", "only"] """Reply mode (tweet_search_extractor)""" @@ -140,36 +263,124 @@ class ExtractionRunParams(TypedDict, total=False): retweets_of_tweet_id: Annotated[str, PropertyInfo(alias="retweetsOfTweetId")] """Only retweets of this tweet ID (tweet_search_extractor)""" + safe: bool + """Enable the safe-search filter.""" + + scope: Literal["all", "direct", "nested"] + """Reply depth scope.""" + + search_queries: Annotated[SequenceNotStr[str], PropertyInfo(alias="searchQueries")] + """Search queries processed as one collection job.""" + search_query: Annotated[str, PropertyInfo(alias="searchQuery")] """Required for tweet_search_extractor & community_search.""" since_date: Annotated[Union[str, date], PropertyInfo(alias="sinceDate", format="iso8601")] """Start date YYYY-MM-DD (tweet_search_extractor)""" + since_id: Annotated[str, PropertyInfo(alias="sinceId")] + """Return Tweets newer than this Tweet ID.""" + + since_time: Annotated[Union[Union[str, datetime], int], PropertyInfo(alias="sinceTime", format="iso8601")] + """Reply start time as ISO 8601 or Unix seconds.""" + + sort: Literal["relevance", "latest", "oldest", "likes"] + """Reply result order.""" + + source: str + """Match the source application.""" + + start_cursor: Annotated[str, PropertyInfo(alias="startCursor")] + """Resume one reply target from this cursor.""" + target_community_id: Annotated[str, PropertyInfo(alias="targetCommunityId")] """Required for community_post_extractor & community_search.""" + target_community_ids: Annotated[SequenceNotStr[str], PropertyInfo(alias="targetCommunityIds")] + """Community IDs processed as one collection job.""" + target_list_id: Annotated[str, PropertyInfo(alias="targetListId")] """ Required for list_follower_explorer, list_member_extractor & list_post_extractor. """ + target_list_ids: Annotated[SequenceNotStr[str], PropertyInfo(alias="targetListIds")] + """List IDs processed as one collection job.""" + + targets: SequenceNotStr[Target] + """Mixed targets auto-routed within one job.""" + target_space_id: Annotated[str, PropertyInfo(alias="targetSpaceId")] """Required for space_explorer.""" target_tweet_id: Annotated[str, PropertyInfo(alias="targetTweetId")] + target_tweet_ids: Annotated[SequenceNotStr[str], PropertyInfo(alias="targetTweetIds")] + """Tweet IDs processed as one collection job.""" + target_username: Annotated[str, PropertyInfo(alias="targetUsername")] + target_usernames: Annotated[SequenceNotStr[str], PropertyInfo(alias="targetUsernames")] + """Usernames processed as one collection job.""" + to_user: Annotated[str, PropertyInfo(alias="toUser")] """Filter replies sent to a username (tweet_search_extractor)""" until_date: Annotated[Union[str, date], PropertyInfo(alias="untilDate", format="iso8601")] """End date YYYY-MM-DD (tweet_search_extractor)""" + until_time: Annotated[Union[Union[str, datetime], int], PropertyInfo(alias="untilTime", format="iso8601")] + """Reply end time as ISO 8601 or Unix seconds.""" + url: str """URL substring or domain filter (tweet_search_extractor)""" + username_contains: Annotated[str, PropertyInfo(alias="usernameContains")] + """Required username text.""" + verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] """Only verified authors (tweet_search_extractor)""" + + verified_type: Annotated[str, PropertyInfo(alias="verifiedType")] + """Exact profile verification type.""" + + within: str + """Set the radius for the near filter.""" + + within_time: Annotated[str, PropertyInfo(alias="withinTime")] + """Match Tweets inside a recent time window.""" + + +class RelationTarget(TypedDict, total=False): + """One target and relation in a mixed profile collection.""" + + relation: Required[ + Literal["community_members", "followers", "following", "list_followers", "list_members", "verified_followers"] + ] + + value: Required[str] + + +class TargetUnionMember1(TypedDict, total=False): + kind: Required[ + Literal[ + "favoriters", + "list", + "profile", + "profile_likes", + "profile_media", + "profile_replies", + "quotes", + "replies", + "retweeters", + "search", + "thread", + "tweet", + ] + ] + + value: Required[str] + + +Target: TypeAlias = Union[str, TargetUnionMember1] diff --git a/src/x_twitter_scraper/types/extraction_run_response.py b/src/x_twitter_scraper/types/extraction_run_response.py index d05ff94..4ee0209 100644 --- a/src/x_twitter_scraper/types/extraction_run_response.py +++ b/src/x_twitter_scraper/types/extraction_run_response.py @@ -4,7 +4,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing_extensions import Literal +from typing import Optional from pydantic import Field as FieldInfo @@ -14,33 +14,14 @@ class ExtractionRunResponse(BaseModel): - id: str - - status: Literal["running"] - - tool_type: Literal[ - "article_extractor", - "community_extractor", - "community_moderator_explorer", - "community_post_extractor", - "community_search", - "favoriters", - "follower_explorer", - "following_explorer", - "list_follower_explorer", - "list_member_extractor", - "list_post_extractor", - "mention_extractor", - "people_search", - "post_extractor", - "quote_extractor", - "reply_extractor", - "repost_extractor", - "space_explorer", - "thread_extractor", - "tweet_search_extractor", - "user_likes", - "user_media", - "verified_follower_explorer", - ] = FieldInfo(alias="toolType") - """Identifier for the extraction tool used to run a job.""" + allowed: bool + + credits_available: str = FieldInfo(alias="creditsAvailable") + + credits_required: str = FieldInfo(alias="creditsRequired") + + estimated_results: int = FieldInfo(alias="estimatedResults") + + source: str + + resolved_x_user_id: Optional[str] = FieldInfo(alias="resolvedXUserId", default=None) diff --git a/src/x_twitter_scraper/types/monitor.py b/src/x_twitter_scraper/types/monitor.py index c820e7e..e9f29e3 100644 --- a/src/x_twitter_scraper/types/monitor.py +++ b/src/x_twitter_scraper/types/monitor.py @@ -4,8 +4,9 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List +from typing import List, Optional from datetime import datetime +from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -33,3 +34,9 @@ class Monitor(BaseModel): username: str x_user_id: str = FieldInfo(alias="xUserId") + + paused_at: Optional[datetime] = FieldInfo(alias="pausedAt", default=None) + """When Xquik automatically paused this monitor.""" + + paused_reason: Optional[Literal["x_user_not_found"]] = FieldInfo(alias="pausedReason", default=None) + """Why Xquik automatically paused this monitor.""" diff --git a/src/x_twitter_scraper/types/shared/error.py b/src/x_twitter_scraper/types/shared/error.py index 892cb9a..0e16514 100644 --- a/src/x_twitter_scraper/types/shared/error.py +++ b/src/x_twitter_scraper/types/shared/error.py @@ -43,6 +43,7 @@ class ErrorValueStructuredError(BaseModel): "missing_params", "missing_query", "monitor_already_exists", + "monitor_profile_unavailable", "no_media", "no_credits", "no_subscription", @@ -60,6 +61,8 @@ class ErrorValueStructuredError(BaseModel): "checkout_unavailable", "connection_challenge_expired", "connection_challenge_inactive", + "coverage_cursor_gone", + "coverage_cursor_unavailable", "draft_not_found", "favoriters_unavailable", "forbidden", @@ -69,6 +72,7 @@ class ErrorValueStructuredError(BaseModel): "idempotency_conflict", "idempotency_key_conflict", "invalid_community_id", + "invalid_coverage_cursor", "invalid_idempotency_key", "invalid_list_id", "invalid_payment_amount", @@ -159,6 +163,7 @@ class ErrorValueStructuredError(BaseModel): "missing_params", "missing_query", "monitor_already_exists", + "monitor_profile_unavailable", "no_media", "no_credits", "no_subscription", @@ -176,6 +181,8 @@ class ErrorValueStructuredError(BaseModel): "checkout_unavailable", "connection_challenge_expired", "connection_challenge_inactive", + "coverage_cursor_gone", + "coverage_cursor_unavailable", "draft_not_found", "favoriters_unavailable", "forbidden", @@ -185,6 +192,7 @@ class ErrorValueStructuredError(BaseModel): "idempotency_conflict", "idempotency_key_conflict", "invalid_community_id", + "invalid_coverage_cursor", "invalid_idempotency_key", "invalid_list_id", "invalid_payment_amount", diff --git a/src/x_twitter_scraper/types/shared/paginated_tweets.py b/src/x_twitter_scraper/types/shared/paginated_tweets.py index 4ad997a..b2800e6 100644 --- a/src/x_twitter_scraper/types/shared/paginated_tweets.py +++ b/src/x_twitter_scraper/types/shared/paginated_tweets.py @@ -14,9 +14,8 @@ class PaginatedTweets(BaseModel): - """Paginated tweets. - - Source visibility, filters, or remaining credits can reduce results. An empty filtered page can still have has_next_page true. Follow next_cursor while has_next_page is true. Zero affordable results returns 402 insufficient_credits. + """ + No-mode search, user Tweet, user reply, and direct reply reads use automatic coverage. Shape, filters, aliases, and billing stay compatible. Unprefixed cursors remain legacy. Follow next_cursor while has_next_page is true. An empty filtered page can still have has_next_page true. """ has_next_page: bool diff --git a/src/x_twitter_scraper/types/shared/paginated_users.py b/src/x_twitter_scraper/types/shared/paginated_users.py index 11580a9..a789246 100644 --- a/src/x_twitter_scraper/types/shared/paginated_users.py +++ b/src/x_twitter_scraper/types/shared/paginated_users.py @@ -15,7 +15,7 @@ class PaginatedUsers(BaseModel): """Paginated user profiles. - The item count can be lower than pageSize when the source returns fewer profiles or remaining credits cover fewer results. Follow next_cursor while has_next_page is true. A relationship can naturally contain fewer profiles than requested. Zero affordable results returns 402 insufficient_credits. + No-mode follower, following, and verified follower requests merge independent views automatically. Response fields, page size, aliases, filters, and per-returned-profile billing stay unchanged. Existing unprefixed cursors retain legacy behavior. Follow next_cursor while has_next_page is true. """ has_next_page: bool diff --git a/src/x_twitter_scraper/types/x/__init__.py b/src/x_twitter_scraper/types/x/__init__.py index dfb924b..86b1a70 100644 --- a/src/x_twitter_scraper/types/x/__init__.py +++ b/src/x_twitter_scraper/types/x/__init__.py @@ -27,6 +27,7 @@ from .profile_update_params import ProfileUpdateParams as ProfileUpdateParams from .tweet_create_response import TweetCreateResponse as TweetCreateResponse from .tweet_delete_response import TweetDeleteResponse as TweetDeleteResponse +from .tweet_search_response import TweetSearchResponse as TweetSearchResponse from .account_create_response import AccountCreateResponse as AccountCreateResponse from .account_delete_response import AccountDeleteResponse as AccountDeleteResponse from .account_reauth_response import AccountReauthResponse as AccountReauthResponse @@ -69,6 +70,8 @@ from .write_action_retrieve_response import WriteActionRetrieveResponse as WriteActionRetrieveResponse from .community_retrieve_info_response import CommunityRetrieveInfoResponse as CommunityRetrieveInfoResponse from .community_retrieve_search_params import CommunityRetrieveSearchParams as CommunityRetrieveSearchParams +from .user_retrieve_followers_response import UserRetrieveFollowersResponse as UserRetrieveFollowersResponse +from .user_retrieve_following_response import UserRetrieveFollowingResponse as UserRetrieveFollowingResponse from .community_retrieve_members_params import CommunityRetrieveMembersParams as CommunityRetrieveMembersParams from .bookmark_retrieve_folders_response import BookmarkRetrieveFoldersResponse as BookmarkRetrieveFoldersResponse from .community_retrieve_moderators_params import CommunityRetrieveModeratorsParams as CommunityRetrieveModeratorsParams @@ -78,6 +81,9 @@ from .user_retrieve_verified_followers_params import ( UserRetrieveVerifiedFollowersParams as UserRetrieveVerifiedFollowersParams, ) +from .user_retrieve_verified_followers_response import ( + UserRetrieveVerifiedFollowersResponse as UserRetrieveVerifiedFollowersResponse, +) from .account_connection_challenge_submit_params import ( AccountConnectionChallengeSubmitParams as AccountConnectionChallengeSubmitParams, ) diff --git a/src/x_twitter_scraper/types/x/community_retrieve_members_params.py b/src/x_twitter_scraper/types/x/community_retrieve_members_params.py index 463385a..6d0bed5 100644 --- a/src/x_twitter_scraper/types/x/community_retrieve_members_params.py +++ b/src/x_twitter_scraper/types/x/community_retrieve_members_params.py @@ -14,9 +14,42 @@ class CommunityRetrieveMembersParams(TypedDict, total=False): + bio_contains: Annotated[str, PropertyInfo(alias="bioContains")] + """Match any comma-separated or line-separated bio term, ignoring case.""" + cursor: str """Pagination cursor""" + has_location: Annotated[bool, PropertyInfo(alias="hasLocation")] + """Only return profiles with a location.""" + + has_website: Annotated[bool, PropertyInfo(alias="hasWebsite")] + """Only return profiles with a website.""" + + location_contains: Annotated[str, PropertyInfo(alias="locationContains")] + """Match a location substring, ignoring case.""" + + max_followers: Annotated[int, PropertyInfo(alias="maxFollowers")] + """Maximum follower count. Missing counts pass this maximum.""" + + max_following: Annotated[int, PropertyInfo(alias="maxFollowing")] + """Maximum following count.""" + + max_statuses: Annotated[int, PropertyInfo(alias="maxStatuses")] + """Maximum post count. maxPosts is also accepted.""" + + min_account_age_days: Annotated[int, PropertyInfo(alias="minAccountAgeDays")] + """Minimum account age in whole days.""" + + min_followers: Annotated[int, PropertyInfo(alias="minFollowers")] + """Minimum follower count. Filtering happens before billing.""" + + min_following: Annotated[int, PropertyInfo(alias="minFollowing")] + """Minimum following count.""" + + min_statuses: Annotated[int, PropertyInfo(alias="minStatuses")] + """Minimum post count. minPosts is also accepted.""" + page_size: Annotated[int, PropertyInfo(alias="pageSize")] """Items per page (20-200, default 20). @@ -24,3 +57,12 @@ class CommunityRetrieveMembersParams(TypedDict, total=False): reduce the returned page size, and zero affordable results returns 402 insufficient_credits. """ + + username_contains: Annotated[str, PropertyInfo(alias="usernameContains")] + """Match a username substring, ignoring case.""" + + verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] + """Only return verified profiles.""" + + verified_type: Annotated[str, PropertyInfo(alias="verifiedType")] + """Match the verification type exactly, ignoring case.""" diff --git a/src/x_twitter_scraper/types/x/community_retrieve_moderators_params.py b/src/x_twitter_scraper/types/x/community_retrieve_moderators_params.py index a5f9031..36d4bc7 100644 --- a/src/x_twitter_scraper/types/x/community_retrieve_moderators_params.py +++ b/src/x_twitter_scraper/types/x/community_retrieve_moderators_params.py @@ -6,11 +6,55 @@ from __future__ import annotations -from typing_extensions import TypedDict +from typing_extensions import Annotated, TypedDict + +from ..._utils import PropertyInfo __all__ = ["CommunityRetrieveModeratorsParams"] class CommunityRetrieveModeratorsParams(TypedDict, total=False): + bio_contains: Annotated[str, PropertyInfo(alias="bioContains")] + """Match any comma-separated or line-separated bio term, ignoring case.""" + cursor: str """Pagination cursor for community moderators""" + + has_location: Annotated[bool, PropertyInfo(alias="hasLocation")] + """Only return profiles with a location.""" + + has_website: Annotated[bool, PropertyInfo(alias="hasWebsite")] + """Only return profiles with a website.""" + + location_contains: Annotated[str, PropertyInfo(alias="locationContains")] + """Match a location substring, ignoring case.""" + + max_followers: Annotated[int, PropertyInfo(alias="maxFollowers")] + """Maximum follower count. Missing counts pass this maximum.""" + + max_following: Annotated[int, PropertyInfo(alias="maxFollowing")] + """Maximum following count.""" + + max_statuses: Annotated[int, PropertyInfo(alias="maxStatuses")] + """Maximum post count. maxPosts is also accepted.""" + + min_account_age_days: Annotated[int, PropertyInfo(alias="minAccountAgeDays")] + """Minimum account age in whole days.""" + + min_followers: Annotated[int, PropertyInfo(alias="minFollowers")] + """Minimum follower count. Filtering happens before billing.""" + + min_following: Annotated[int, PropertyInfo(alias="minFollowing")] + """Minimum following count.""" + + min_statuses: Annotated[int, PropertyInfo(alias="minStatuses")] + """Minimum post count. minPosts is also accepted.""" + + username_contains: Annotated[str, PropertyInfo(alias="usernameContains")] + """Match a username substring, ignoring case.""" + + verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] + """Only return verified profiles.""" + + verified_type: Annotated[str, PropertyInfo(alias="verifiedType")] + """Match the verification type exactly, ignoring case.""" diff --git a/src/x_twitter_scraper/types/x/list_retrieve_followers_params.py b/src/x_twitter_scraper/types/x/list_retrieve_followers_params.py index 1a0c1f3..c4067cf 100644 --- a/src/x_twitter_scraper/types/x/list_retrieve_followers_params.py +++ b/src/x_twitter_scraper/types/x/list_retrieve_followers_params.py @@ -14,13 +14,54 @@ class ListRetrieveFollowersParams(TypedDict, total=False): + bio_contains: Annotated[str, PropertyInfo(alias="bioContains")] + """Match any comma-separated or line-separated bio term, ignoring case.""" + cursor: str """Pagination cursor for list followers""" + has_location: Annotated[bool, PropertyInfo(alias="hasLocation")] + """Only return profiles with a location.""" + + has_website: Annotated[bool, PropertyInfo(alias="hasWebsite")] + """Only return profiles with a website.""" + + location_contains: Annotated[str, PropertyInfo(alias="locationContains")] + """Match a location substring, ignoring case.""" + + max_followers: Annotated[int, PropertyInfo(alias="maxFollowers")] + """Maximum follower count. Missing counts pass this maximum.""" + + max_following: Annotated[int, PropertyInfo(alias="maxFollowing")] + """Maximum following count.""" + + max_statuses: Annotated[int, PropertyInfo(alias="maxStatuses")] + """Maximum post count. maxPosts is also accepted.""" + + min_account_age_days: Annotated[int, PropertyInfo(alias="minAccountAgeDays")] + """Minimum account age in whole days.""" + + min_followers: Annotated[int, PropertyInfo(alias="minFollowers")] + """Minimum follower count. Filtering happens before billing.""" + + min_following: Annotated[int, PropertyInfo(alias="minFollowing")] + """Minimum following count.""" + + min_statuses: Annotated[int, PropertyInfo(alias="minStatuses")] + """Minimum post count. minPosts is also accepted.""" + page_size: Annotated[int, PropertyInfo(alias="pageSize")] """Maximum user profiles requested from this page (20-200, default 200). - The response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + Source, filters, or credits can return fewer profiles. Keep requesting + next_cursor while has_next_page is true. Deprecated aliases remain accepted. """ + + username_contains: Annotated[str, PropertyInfo(alias="usernameContains")] + """Match a username substring, ignoring case.""" + + verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] + """Only return verified profiles.""" + + verified_type: Annotated[str, PropertyInfo(alias="verifiedType")] + """Match the verification type exactly, ignoring case.""" diff --git a/src/x_twitter_scraper/types/x/list_retrieve_members_params.py b/src/x_twitter_scraper/types/x/list_retrieve_members_params.py index 6460986..9a1b394 100644 --- a/src/x_twitter_scraper/types/x/list_retrieve_members_params.py +++ b/src/x_twitter_scraper/types/x/list_retrieve_members_params.py @@ -14,8 +14,50 @@ class ListRetrieveMembersParams(TypedDict, total=False): + bio_contains: Annotated[str, PropertyInfo(alias="bioContains")] + """Match any comma-separated or line-separated bio term, ignoring case.""" + cursor: str """Pagination cursor for list members""" + has_location: Annotated[bool, PropertyInfo(alias="hasLocation")] + """Only return profiles with a location.""" + + has_website: Annotated[bool, PropertyInfo(alias="hasWebsite")] + """Only return profiles with a website.""" + + location_contains: Annotated[str, PropertyInfo(alias="locationContains")] + """Match a location substring, ignoring case.""" + + max_followers: Annotated[int, PropertyInfo(alias="maxFollowers")] + """Maximum follower count. Missing counts pass this maximum.""" + + max_following: Annotated[int, PropertyInfo(alias="maxFollowing")] + """Maximum following count.""" + + max_statuses: Annotated[int, PropertyInfo(alias="maxStatuses")] + """Maximum post count. maxPosts is also accepted.""" + + min_account_age_days: Annotated[int, PropertyInfo(alias="minAccountAgeDays")] + """Minimum account age in whole days.""" + + min_followers: Annotated[int, PropertyInfo(alias="minFollowers")] + """Minimum follower count. Filtering happens before billing.""" + + min_following: Annotated[int, PropertyInfo(alias="minFollowing")] + """Minimum following count.""" + + min_statuses: Annotated[int, PropertyInfo(alias="minStatuses")] + """Minimum post count. minPosts is also accepted.""" + page_size: Annotated[int, PropertyInfo(alias="pageSize")] """Members per page (20-200, default 20)""" + + username_contains: Annotated[str, PropertyInfo(alias="usernameContains")] + """Match a username substring, ignoring case.""" + + verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] + """Only return verified profiles.""" + + verified_type: Annotated[str, PropertyInfo(alias="verifiedType")] + """Match the verification type exactly, ignoring case.""" diff --git a/src/x_twitter_scraper/types/x/tweet_get_favoriters_params.py b/src/x_twitter_scraper/types/x/tweet_get_favoriters_params.py index dcd4fb9..6370c23 100644 --- a/src/x_twitter_scraper/types/x/tweet_get_favoriters_params.py +++ b/src/x_twitter_scraper/types/x/tweet_get_favoriters_params.py @@ -14,13 +14,54 @@ class TweetGetFavoritersParams(TypedDict, total=False): + bio_contains: Annotated[str, PropertyInfo(alias="bioContains")] + """Match any comma-separated or line-separated bio term, ignoring case.""" + cursor: str """Pagination cursor for favoriters""" + has_location: Annotated[bool, PropertyInfo(alias="hasLocation")] + """Only return profiles with a location.""" + + has_website: Annotated[bool, PropertyInfo(alias="hasWebsite")] + """Only return profiles with a website.""" + + location_contains: Annotated[str, PropertyInfo(alias="locationContains")] + """Match a location substring, ignoring case.""" + + max_followers: Annotated[int, PropertyInfo(alias="maxFollowers")] + """Maximum follower count. Missing counts pass this maximum.""" + + max_following: Annotated[int, PropertyInfo(alias="maxFollowing")] + """Maximum following count.""" + + max_statuses: Annotated[int, PropertyInfo(alias="maxStatuses")] + """Maximum post count. maxPosts is also accepted.""" + + min_account_age_days: Annotated[int, PropertyInfo(alias="minAccountAgeDays")] + """Minimum account age in whole days.""" + + min_followers: Annotated[int, PropertyInfo(alias="minFollowers")] + """Minimum follower count. Filtering happens before billing.""" + + min_following: Annotated[int, PropertyInfo(alias="minFollowing")] + """Minimum following count.""" + + min_statuses: Annotated[int, PropertyInfo(alias="minStatuses")] + """Minimum post count. minPosts is also accepted.""" + page_size: Annotated[int, PropertyInfo(alias="pageSize")] """Maximum user profiles requested from this page (20-200, default 200). - The response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + Source, filters, or credits can return fewer profiles. Keep requesting + next_cursor while has_next_page is true. Deprecated aliases remain accepted. """ + + username_contains: Annotated[str, PropertyInfo(alias="usernameContains")] + """Match a username substring, ignoring case.""" + + verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] + """Only return verified profiles.""" + + verified_type: Annotated[str, PropertyInfo(alias="verifiedType")] + """Match the verification type exactly, ignoring case.""" diff --git a/src/x_twitter_scraper/types/x/tweet_get_quotes_params.py b/src/x_twitter_scraper/types/x/tweet_get_quotes_params.py index 64babcd..05518fd 100644 --- a/src/x_twitter_scraper/types/x/tweet_get_quotes_params.py +++ b/src/x_twitter_scraper/types/x/tweet_get_quotes_params.py @@ -22,6 +22,12 @@ class TweetGetQuotesParams(TypedDict, total=False): Separate with spaces, commas, or lines. """ + blue_verified_only: Annotated[bool, PropertyInfo(alias="blueVerifiedOnly")] + """Only return tweets from Blue-verified authors.""" + + card_name: Annotated[str, PropertyInfo(alias="cardName")] + """Match the Tweet card name.""" + cashtags: str """Cashtags separated by spaces, commas, or lines.""" @@ -34,12 +40,18 @@ class TweetGetQuotesParams(TypedDict, total=False): exact_phrase: Annotated[str, PropertyInfo(alias="exactPhrase")] """Exact phrase to match.""" + exclude_source: Annotated[str, PropertyInfo(alias="excludeSource")] + """Exclude a source application.""" + exclude_words: Annotated[str, PropertyInfo(alias="excludeWords")] """Words or quoted phrases to exclude. Separate with spaces, commas, or lines.""" from_user: Annotated[str, PropertyInfo(alias="fromUser")] """Filter by author username.""" + geocode: str + """Match latitude, longitude, and radius.""" + hashtags: str """Hashtags separated by spaces, commas, or lines.""" @@ -52,6 +64,21 @@ class TweetGetQuotesParams(TypedDict, total=False): language: str """Language code filter, e.g. en or tr.""" + max_faves: Annotated[int, PropertyInfo(alias="maxFaves")] + """Maximum likes threshold. maxLikes is also accepted.""" + + max_id: Annotated[str, PropertyInfo(alias="maxId")] + """Return Tweets older than this Tweet ID.""" + + max_quotes: Annotated[int, PropertyInfo(alias="maxQuotes")] + """Maximum quotes threshold.""" + + max_replies: Annotated[int, PropertyInfo(alias="maxReplies")] + """Maximum replies threshold.""" + + max_retweets: Annotated[int, PropertyInfo(alias="maxRetweets")] + """Maximum retweets threshold.""" + media_type: Annotated[ Literal["images", "videos", "gifs", "media", "links", "none"], PropertyInfo(alias="mediaType") ] @@ -60,6 +87,9 @@ class TweetGetQuotesParams(TypedDict, total=False): mentioning: str """Filter tweets mentioning a username.""" + min_bookmarks: Annotated[int, PropertyInfo(alias="minBookmarks")] + """Minimum bookmark count threshold.""" + min_faves: Annotated[int, PropertyInfo(alias="minFaves")] """Minimum likes threshold.""" @@ -72,6 +102,18 @@ class TweetGetQuotesParams(TypedDict, total=False): min_retweets: Annotated[int, PropertyInfo(alias="minRetweets")] """Minimum retweets threshold.""" + min_views: Annotated[int, PropertyInfo(alias="minViews")] + """Minimum view count threshold.""" + + native_retweets: Annotated[bool, PropertyInfo(alias="nativeRetweets")] + """Only return native reposts.""" + + near: str + """Match a place name.""" + + news: bool + """Only return news results.""" + page_size: Annotated[int, PropertyInfo(alias="pageSize")] """Maximum page items (1-100, default 20). @@ -94,12 +136,21 @@ class TweetGetQuotesParams(TypedDict, total=False): retweets_of_tweet_id: Annotated[str, PropertyInfo(alias="retweetsOfTweetId")] """Only retweets of this tweet ID.""" + safe: bool + """Enable the safe-search filter.""" + since_date: Annotated[Union[str, date], PropertyInfo(alias="sinceDate", format="iso8601")] """Start date in YYYY-MM-DD format.""" + since_id: Annotated[str, PropertyInfo(alias="sinceId")] + """Return Tweets newer than this Tweet ID.""" + since_time: Annotated[str, PropertyInfo(alias="sinceTime")] """Unix timestamp - return quotes posted after this time""" + source: str + """Match the source application.""" + to_user: Annotated[str, PropertyInfo(alias="toUser")] """Filter replies sent to a username.""" @@ -114,3 +165,9 @@ class TweetGetQuotesParams(TypedDict, total=False): verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] """Only return tweets from verified authors.""" + + within: str + """Set the radius for the near filter.""" + + within_time: Annotated[str, PropertyInfo(alias="withinTime")] + """Match Tweets inside a recent time window.""" diff --git a/src/x_twitter_scraper/types/x/tweet_get_replies_params.py b/src/x_twitter_scraper/types/x/tweet_get_replies_params.py index f505b0d..af8fe78 100644 --- a/src/x_twitter_scraper/types/x/tweet_get_replies_params.py +++ b/src/x_twitter_scraper/types/x/tweet_get_replies_params.py @@ -22,6 +22,12 @@ class TweetGetRepliesParams(TypedDict, total=False): Separate with spaces, commas, or lines. """ + blue_verified_only: Annotated[bool, PropertyInfo(alias="blueVerifiedOnly")] + """Only return tweets from Blue-verified authors.""" + + card_name: Annotated[str, PropertyInfo(alias="cardName")] + """Match the Tweet card name.""" + cashtags: str """Cashtags separated by spaces, commas, or lines.""" @@ -29,20 +35,39 @@ class TweetGetRepliesParams(TypedDict, total=False): """Conversation ID filter.""" cursor: str - """Pagination cursor for tweet replies""" + """Cursor from the previous response. + + Xquik cursors resume automatic coverage. Existing unprefixed cursors keep legacy + standard behavior. + """ exact_phrase: Annotated[str, PropertyInfo(alias="exactPhrase")] """Exact phrase to match.""" + exclude_original_author: Annotated[bool, PropertyInfo(alias="excludeOriginalAuthor")] + """Exclude replies written by the source-post author.""" + + exclude_source: Annotated[str, PropertyInfo(alias="excludeSource")] + """Exclude a source application.""" + exclude_words: Annotated[str, PropertyInfo(alias="excludeWords")] """Words or quoted phrases to exclude. Separate with spaces, commas, or lines.""" from_user: Annotated[str, PropertyInfo(alias="fromUser")] """Filter by author username.""" + geocode: str + """Match latitude, longitude, and radius.""" + hashtags: str """Hashtags separated by spaces, commas, or lines.""" + has_media_only: Annotated[bool, PropertyInfo(alias="hasMediaOnly")] + """Only return replies containing media.""" + + include_original_post: Annotated[bool, PropertyInfo(alias="includeOriginalPost")] + """Include the source post and count it toward limit.""" + in_reply_to_tweet_id: Annotated[str, PropertyInfo(alias="inReplyToTweetId")] """Only replies to this tweet ID.""" @@ -50,11 +75,29 @@ class TweetGetRepliesParams(TypedDict, total=False): """Language code filter, e.g. en or tr.""" limit: int - """With mode=complete, maximum combined direct and nested reply rows (1-25000). - - Without complete mode, this is the deprecated pageSize alias and uses the normal - 1-100 page range. """ + With mode=complete, maximum combined direct and nested reply rows (1-25000, + default 25000). Automatic pages accept 1-300. Standard pages accept 1-100. + Prefer pageSize outside complete mode. + """ + + max_depth: Annotated[int, PropertyInfo(alias="maxDepth")] + """Maximum reply depth from the source post.""" + + max_faves: Annotated[int, PropertyInfo(alias="maxFaves")] + """Maximum likes threshold. maxLikes is also accepted.""" + + max_id: Annotated[str, PropertyInfo(alias="maxId")] + """Return Tweets older than this Tweet ID.""" + + max_quotes: Annotated[int, PropertyInfo(alias="maxQuotes")] + """Maximum quotes threshold.""" + + max_replies: Annotated[int, PropertyInfo(alias="maxReplies")] + """Maximum replies threshold.""" + + max_retweets: Annotated[int, PropertyInfo(alias="maxRetweets")] + """Maximum retweets threshold.""" media_type: Annotated[ Literal["images", "videos", "gifs", "media", "links", "none"], PropertyInfo(alias="mediaType") @@ -64,6 +107,9 @@ class TweetGetRepliesParams(TypedDict, total=False): mentioning: str """Filter tweets mentioning a username.""" + min_bookmarks: Annotated[int, PropertyInfo(alias="minBookmarks")] + """Minimum bookmark count threshold.""" + min_faves: Annotated[int, PropertyInfo(alias="minFaves")] """Minimum likes threshold.""" @@ -76,18 +122,31 @@ class TweetGetRepliesParams(TypedDict, total=False): min_retweets: Annotated[int, PropertyInfo(alias="minRetweets")] """Minimum retweets threshold.""" - mode: Literal["complete"] - """Set complete for maximum-coverage collection. + min_views: Annotated[int, PropertyInfo(alias="minViews")] + """Minimum view count threshold.""" + + mode: Literal["standard", "complete"] + """Optional advanced override. - Complete mode accepts only limit. Remove cursor, pageSize, count, time ranges, - and tweet filters. + Omit mode for automatic maximum direct reply coverage with pagination. Standard + keeps legacy pagination. Complete returns direct and nested replies with + diagnostics, scope, depth, sorting, and original-post controls. """ + native_retweets: Annotated[bool, PropertyInfo(alias="nativeRetweets")] + """Only return native reposts.""" + + near: str + """Match a place name.""" + + news: bool + """Only return news results.""" + page_size: Annotated[int, PropertyInfo(alias="pageSize")] - """Maximum page items (1-100, default 20). + """Automatic pages accept 1-300 Tweets. - Source, filters, or credits can reduce results. Continue while has_next_page is - true. Deprecated limit and count aliases remain accepted. + Standard pages keep 1-100. Default 20. Continue while has_next_page is true. + Deprecated aliases remain accepted. """ quotes: Literal["include", "exclude", "only"] @@ -105,12 +164,27 @@ class TweetGetRepliesParams(TypedDict, total=False): retweets_of_tweet_id: Annotated[str, PropertyInfo(alias="retweetsOfTweetId")] """Only retweets of this tweet ID.""" + safe: bool + """Enable the safe-search filter.""" + + scope: Literal["all", "direct", "nested"] + """Select all replies, direct replies, or nested replies.""" + since_date: Annotated[Union[str, date], PropertyInfo(alias="sinceDate", format="iso8601")] """Start date in YYYY-MM-DD format.""" + since_id: Annotated[str, PropertyInfo(alias="sinceId")] + """Return Tweets newer than this Tweet ID.""" + since_time: Annotated[str, PropertyInfo(alias="sinceTime")] """Unix timestamp - return replies posted after this time""" + sort: Literal["relevance", "latest", "oldest", "likes"] + """Sort the selected replies before applying limit.""" + + source: str + """Match the source application.""" + to_user: Annotated[str, PropertyInfo(alias="toUser")] """Filter replies sent to a username.""" @@ -125,3 +199,9 @@ class TweetGetRepliesParams(TypedDict, total=False): verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] """Only return tweets from verified authors.""" + + within: str + """Set the radius for the near filter.""" + + within_time: Annotated[str, PropertyInfo(alias="withinTime")] + """Match Tweets inside a recent time window.""" diff --git a/src/x_twitter_scraper/types/x/tweet_get_replies_response.py b/src/x_twitter_scraper/types/x/tweet_get_replies_response.py index 5b55421..abdf911 100644 --- a/src/x_twitter_scraper/types/x/tweet_get_replies_response.py +++ b/src/x_twitter_scraper/types/x/tweet_get_replies_response.py @@ -136,9 +136,9 @@ class TweetGetRepliesResponseDiagnostic(BaseModel): class TweetGetRepliesResponse(PaginatedTweets): - """Reply rows. + """Direct reply rows. - Complete mode also returns nested replies and coverage diagnostics. Keep nested replies separate from direct coverage. + No-mode requests use resumable automatic coverage. Complete mode also returns nested replies and coverage diagnostics. Keep nested replies separate from direct coverage. """ diagnostic: Optional[TweetGetRepliesResponseDiagnostic] = None diff --git a/src/x_twitter_scraper/types/x/tweet_get_retweeters_params.py b/src/x_twitter_scraper/types/x/tweet_get_retweeters_params.py index 744d5dc..dbfe740 100644 --- a/src/x_twitter_scraper/types/x/tweet_get_retweeters_params.py +++ b/src/x_twitter_scraper/types/x/tweet_get_retweeters_params.py @@ -14,13 +14,54 @@ class TweetGetRetweetersParams(TypedDict, total=False): + bio_contains: Annotated[str, PropertyInfo(alias="bioContains")] + """Match any comma-separated or line-separated bio term, ignoring case.""" + cursor: str """Pagination cursor for retweeters""" + has_location: Annotated[bool, PropertyInfo(alias="hasLocation")] + """Only return profiles with a location.""" + + has_website: Annotated[bool, PropertyInfo(alias="hasWebsite")] + """Only return profiles with a website.""" + + location_contains: Annotated[str, PropertyInfo(alias="locationContains")] + """Match a location substring, ignoring case.""" + + max_followers: Annotated[int, PropertyInfo(alias="maxFollowers")] + """Maximum follower count. Missing counts pass this maximum.""" + + max_following: Annotated[int, PropertyInfo(alias="maxFollowing")] + """Maximum following count.""" + + max_statuses: Annotated[int, PropertyInfo(alias="maxStatuses")] + """Maximum post count. maxPosts is also accepted.""" + + min_account_age_days: Annotated[int, PropertyInfo(alias="minAccountAgeDays")] + """Minimum account age in whole days.""" + + min_followers: Annotated[int, PropertyInfo(alias="minFollowers")] + """Minimum follower count. Filtering happens before billing.""" + + min_following: Annotated[int, PropertyInfo(alias="minFollowing")] + """Minimum following count.""" + + min_statuses: Annotated[int, PropertyInfo(alias="minStatuses")] + """Minimum post count. minPosts is also accepted.""" + page_size: Annotated[int, PropertyInfo(alias="pageSize")] """Maximum user profiles requested from this page (20-200, default 200). - The response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + Source, filters, or credits can return fewer profiles. Keep requesting + next_cursor while has_next_page is true. Deprecated aliases remain accepted. """ + + username_contains: Annotated[str, PropertyInfo(alias="usernameContains")] + """Match a username substring, ignoring case.""" + + verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] + """Only return verified profiles.""" + + verified_type: Annotated[str, PropertyInfo(alias="verifiedType")] + """Match the verification type exactly, ignoring case.""" diff --git a/src/x_twitter_scraper/types/x/tweet_search_params.py b/src/x_twitter_scraper/types/x/tweet_search_params.py index 25e4991..84ecbd7 100644 --- a/src/x_twitter_scraper/types/x/tweet_search_params.py +++ b/src/x_twitter_scraper/types/x/tweet_search_params.py @@ -17,7 +17,7 @@ class TweetSearchParams(TypedDict, total=False): q: Required[str] - """Search query (keywords,""" + """Query, Tweet ID, or status URL. Valid inline bounds apply per page.""" advanced_query: Annotated[str, PropertyInfo(alias="advancedQuery")] """Raw advanced search query appended as-is.""" @@ -28,9 +28,15 @@ class TweetSearchParams(TypedDict, total=False): Separate with spaces, commas, or lines. """ + blue_verified_only: Annotated[bool, PropertyInfo(alias="blueVerifiedOnly")] + """Only return tweets from Blue-verified authors.""" + bounding_box: Annotated[str, PropertyInfo(alias="boundingBox")] """Geo bounding box, e.g. -74.1 40.6 -73.9 40.8.""" + card_name: Annotated[str, PropertyInfo(alias="cardName")] + """Match the Tweet card name.""" + cashtags: str """Cashtags separated by spaces, commas, or lines.""" @@ -38,17 +44,27 @@ class TweetSearchParams(TypedDict, total=False): """Conversation ID filter.""" cursor: str - """Pagination cursor from previous response""" + """Cursor from the previous response. + + Xquik cursors resume automatic coverage. Existing unprefixed cursors keep legacy + standard behavior. + """ exact_phrase: Annotated[str, PropertyInfo(alias="exactPhrase")] """Exact phrase to match.""" + exclude_source: Annotated[str, PropertyInfo(alias="excludeSource")] + """Exclude a source application.""" + exclude_words: Annotated[str, PropertyInfo(alias="excludeWords")] """Words or quoted phrases to exclude. Separate with spaces, commas, or lines.""" from_user: Annotated[str, PropertyInfo(alias="fromUser")] """Filter by author username.""" + geocode: str + """Match latitude, longitude, and radius.""" + hashtags: str """Hashtags separated by spaces, commas, or lines.""" @@ -59,16 +75,31 @@ class TweetSearchParams(TypedDict, total=False): """Language code filter, e.g. en or tr.""" limit: int - """Max tweets to return (server paginates internally). + """Result upper bound. - Omit for single page (~20). This is an upper bound for paid authenticated calls: - remaining credits can reduce the returned page size, and zero affordable results - returns 402 insufficient_credits. + Omit it for the existing 20-row page size. Explicit coverage defaults to 2000 + and allows 10000. For paid requests, remaining credits can reduce results. Zero + affordable results returns 402. """ list_id: Annotated[str, PropertyInfo(alias="listId")] """Search within a list ID.""" + max_faves: Annotated[int, PropertyInfo(alias="maxFaves")] + """Maximum likes threshold. maxLikes is also accepted.""" + + max_id: Annotated[str, PropertyInfo(alias="maxId")] + """Return Tweets older than this Tweet ID.""" + + max_quotes: Annotated[int, PropertyInfo(alias="maxQuotes")] + """Maximum quotes threshold.""" + + max_replies: Annotated[int, PropertyInfo(alias="maxReplies")] + """Maximum replies threshold.""" + + max_retweets: Annotated[int, PropertyInfo(alias="maxRetweets")] + """Maximum retweets threshold.""" + media_type: Annotated[ Literal["images", "videos", "gifs", "media", "links", "none"], PropertyInfo(alias="mediaType") ] @@ -77,6 +108,9 @@ class TweetSearchParams(TypedDict, total=False): mentioning: str """Filter tweets mentioning a username.""" + min_bookmarks: Annotated[int, PropertyInfo(alias="minBookmarks")] + """Minimum bookmark count threshold.""" + min_faves: Annotated[int, PropertyInfo(alias="minFaves")] """Minimum likes threshold.""" @@ -89,6 +123,25 @@ class TweetSearchParams(TypedDict, total=False): min_retweets: Annotated[int, PropertyInfo(alias="minRetweets")] """Minimum retweets threshold.""" + min_views: Annotated[int, PropertyInfo(alias="minViews")] + """Minimum view count threshold.""" + + mode: Literal["standard", "coverage"] + """Omit mode for resumable maximum coverage. + + Standard keeps legacy pagination. Coverage returns diagnostics once and rejects + cursors. + """ + + native_retweets: Annotated[bool, PropertyInfo(alias="nativeRetweets")] + """Only return native reposts.""" + + near: str + """Match a place name.""" + + news: bool + """Only return news results.""" + place: str """Search within a place ID.""" @@ -116,11 +169,20 @@ class TweetSearchParams(TypedDict, total=False): retweets_of_tweet_id: Annotated[str, PropertyInfo(alias="retweetsOfTweetId")] """Only retweets of this tweet ID.""" + safe: bool + """Enable the safe-search filter.""" + since_date: Annotated[Union[str, date], PropertyInfo(alias="sinceDate", format="iso8601")] """Start date in YYYY-MM-DD format.""" + since_id: Annotated[str, PropertyInfo(alias="sinceId")] + """Return Tweets newer than this Tweet ID.""" + since_time: Annotated[str, PropertyInfo(alias="sinceTime")] - """ISO 8601 timestamp - only return tweets after this time""" + """Inclusive ISO bound.""" + + source: str + """Match the source application.""" to_user: Annotated[str, PropertyInfo(alias="toUser")] """Filter replies sent to a username.""" @@ -129,10 +191,16 @@ class TweetSearchParams(TypedDict, total=False): """End date in YYYY-MM-DD format.""" until_time: Annotated[str, PropertyInfo(alias="untilTime")] - """ISO 8601 timestamp - only return tweets before this time""" + """Exclusive ISO bound.""" url: str """URL substring or domain filter.""" verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] """Only return tweets from verified authors.""" + + within: str + """Set the radius for the near filter.""" + + within_time: Annotated[str, PropertyInfo(alias="withinTime")] + """Match Tweets inside a recent time window.""" diff --git a/src/x_twitter_scraper/types/x/tweet_search_response.py b/src/x_twitter_scraper/types/x/tweet_search_response.py new file mode 100644 index 0000000..c3e4f1d --- /dev/null +++ b/src/x_twitter_scraper/types/x/tweet_search_response.py @@ -0,0 +1,102 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union, Optional +from datetime import datetime +from typing_extensions import Literal, TypeAlias + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel +from ..shared.paginated_tweets import PaginatedTweets + +__all__ = [ + "TweetSearchResponse", + "TweetSearchCoverageResponse", + "TweetSearchCoverageResponseDiagnostic", + "TweetSearchCoverageResponseDiagnosticStrategy", + "TweetSearchCoverageResponseDiagnosticStrategyWindow", +] + + +class TweetSearchCoverageResponseDiagnosticStrategyWindow(BaseModel): + """Non-overlapping time partition used by one strategy.""" + + since_time: datetime = FieldInfo(alias="sinceTime") + + until_time: datetime = FieldInfo(alias="untilTime") + + +class TweetSearchCoverageResponseDiagnosticStrategy(BaseModel): + duplicate_count: int = FieldInfo(alias="duplicateCount") + + pages_fetched: int = FieldInfo(alias="pagesFetched") + + query_type: Literal["Latest", "Top"] = FieldInfo(alias="queryType") + + stop_reason: Literal[ + "cursor_failure", "deadline", "exhausted", "failed", "page_limit", "result_limit", "stalled" + ] = FieldInfo(alias="stopReason") + + strategy: int + + unique_added: int = FieldInfo(alias="uniqueAdded") + + window: Optional[TweetSearchCoverageResponseDiagnosticStrategyWindow] = None + """Non-overlapping time partition used by one strategy.""" + + +class TweetSearchCoverageResponseDiagnostic(BaseModel): + """Coverage evidence across parallel search strategies.""" + + complete: bool + """True when every strategy exhausted its source.""" + + cursor_failure_count: int = FieldInfo(alias="cursorFailureCount") + + deadline_reached: bool = FieldInfo(alias="deadlineReached") + + duplicate_count: int = FieldInfo(alias="duplicateCount") + + failed_strategy_count: int = FieldInfo(alias="failedStrategyCount") + + malformed_count: int = FieldInfo(alias="malformedCount") + + pages_fetched: int = FieldInfo(alias="pagesFetched") + + partitioned: bool + """Whether bounded time windows ran in parallel.""" + + response_truncated: bool = FieldInfo(alias="responseTruncated") + """Whether credits or the requested limit reduced output.""" + + result_limit_reached: bool = FieldInfo(alias="resultLimitReached") + + returned_tweets: int = FieldInfo(alias="returnedTweets") + + stalled_strategy_count: int = FieldInfo(alias="stalledStrategyCount") + + strategies: List[TweetSearchCoverageResponseDiagnosticStrategy] + + strategy_count: int = FieldInfo(alias="strategyCount") + + unique_tweets: int = FieldInfo(alias="uniqueTweets") + + +class TweetSearchCoverageResponse(PaginatedTweets): + """ + No-mode search, user Tweet, user reply, and direct reply reads use automatic coverage. Shape, filters, aliases, and billing stay compatible. Unprefixed cursors remain legacy. Follow next_cursor while has_next_page is true. An empty filtered page can still have has_next_page true. + """ + + diagnostic: TweetSearchCoverageResponseDiagnostic + """Coverage evidence across parallel search strategies.""" + + has_next_page: Optional[Literal[False]] = None # type: ignore + + next_cursor: Optional[Literal[""]] = None # type: ignore + + +TweetSearchResponse: TypeAlias = Union["PaginatedTweets", TweetSearchCoverageResponse] + +from ..shared.paginated_tweets import PaginatedTweets diff --git a/src/x_twitter_scraper/types/x/user_retrieve_followers_params.py b/src/x_twitter_scraper/types/x/user_retrieve_followers_params.py index 14ccbc1..b8b98a7 100644 --- a/src/x_twitter_scraper/types/x/user_retrieve_followers_params.py +++ b/src/x_twitter_scraper/types/x/user_retrieve_followers_params.py @@ -6,7 +6,7 @@ from __future__ import annotations -from typing_extensions import Annotated, TypedDict +from typing_extensions import Literal, Annotated, TypedDict from ..._utils import PropertyInfo @@ -17,16 +17,70 @@ class UserRetrieveFollowersParams(TypedDict, total=False): after: str """Legacy cursor alias. Prefer cursor.""" + bio_contains: Annotated[str, PropertyInfo(alias="bioContains")] + """Match any comma-separated or line-separated bio term, ignoring case.""" + cursor: str - """Pagination cursor for followers list""" + """Cursor from the previous response. + + Xquik cursors resume automatic coverage. Existing unprefixed cursors keep legacy + standard behavior. + """ + + has_location: Annotated[bool, PropertyInfo(alias="hasLocation")] + """Only return profiles with a location.""" + + has_website: Annotated[bool, PropertyInfo(alias="hasWebsite")] + """Only return profiles with a website.""" limit: int - """Legacy integer page size alias for following lists. Prefer pageSize.""" + """Legacy page-size alias outside explicit coverage mode. + + Coverage accepts 1-10000. Prefer pageSize. + """ + + location_contains: Annotated[str, PropertyInfo(alias="locationContains")] + """Match a location substring, ignoring case.""" + + max_followers: Annotated[int, PropertyInfo(alias="maxFollowers")] + """Maximum follower count. Missing counts pass this maximum.""" + + max_following: Annotated[int, PropertyInfo(alias="maxFollowing")] + """Maximum following count.""" + + max_statuses: Annotated[int, PropertyInfo(alias="maxStatuses")] + """Maximum post count. maxPosts is also accepted.""" + + min_account_age_days: Annotated[int, PropertyInfo(alias="minAccountAgeDays")] + """Minimum account age in whole days.""" + + min_followers: Annotated[int, PropertyInfo(alias="minFollowers")] + """Minimum follower count. Filtering happens before billing.""" + + min_following: Annotated[int, PropertyInfo(alias="minFollowing")] + """Minimum following count.""" + + min_statuses: Annotated[int, PropertyInfo(alias="minStatuses")] + """Minimum post count. minPosts is also accepted.""" + + mode: Literal["standard", "coverage"] + """Omit mode for resumable maximum coverage. + + Standard keeps legacy pagination. Coverage returns diagnostics once and rejects + cursors. + """ page_size: Annotated[int, PropertyInfo(alias="pageSize")] - """Maximum user profiles requested from this page (20-200, default 200). + """Maximum user profiles: automatic 300; standard 200. - The response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + Sources return fewer profiles. Continue with has_next_page. """ + + username_contains: Annotated[str, PropertyInfo(alias="usernameContains")] + """Match a username substring, ignoring case.""" + + verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] + """Only return verified profiles.""" + + verified_type: Annotated[str, PropertyInfo(alias="verifiedType")] + """Match the verification type exactly, ignoring case.""" diff --git a/src/x_twitter_scraper/types/x/user_retrieve_followers_response.py b/src/x_twitter_scraper/types/x/user_retrieve_followers_response.py new file mode 100644 index 0000000..af8971e --- /dev/null +++ b/src/x_twitter_scraper/types/x/user_retrieve_followers_response.py @@ -0,0 +1,81 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal, TypeAlias + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel +from ..shared.paginated_users import PaginatedUsers + +__all__ = [ + "UserRetrieveFollowersResponse", + "UserListCoverageResponse", + "UserListCoverageResponseDiagnostic", + "UserListCoverageResponseDiagnosticStrategy", +] + + +class UserListCoverageResponseDiagnosticStrategy(BaseModel): + duplicate_count: int = FieldInfo(alias="duplicateCount") + + pages_fetched: int = FieldInfo(alias="pagesFetched") + + stop_reason: Literal[ + "cursor_failure", "deadline", "exhausted", "failed", "page_limit", "result_limit", "stalled" + ] = FieldInfo(alias="stopReason") + + strategy: int + + unique_added: int = FieldInfo(alias="uniqueAdded") + + +class UserListCoverageResponseDiagnostic(BaseModel): + """Coverage evidence across parallel relationship strategies.""" + + complete: bool + """True when every strategy exhausted its source.""" + + cursor_failure_count: int = FieldInfo(alias="cursorFailureCount") + + deadline_reached: bool = FieldInfo(alias="deadlineReached") + + duplicate_count: int = FieldInfo(alias="duplicateCount") + + failed_strategy_count: int = FieldInfo(alias="failedStrategyCount") + + malformed_count: int = FieldInfo(alias="malformedCount") + + pages_fetched: int = FieldInfo(alias="pagesFetched") + + response_truncated: bool = FieldInfo(alias="responseTruncated") + """Whether credits or the requested limit reduced output.""" + + result_limit_reached: bool = FieldInfo(alias="resultLimitReached") + + returned_users: int = FieldInfo(alias="returnedUsers") + + stalled_strategy_count: int = FieldInfo(alias="stalledStrategyCount") + + strategies: List[UserListCoverageResponseDiagnosticStrategy] + + strategy_count: int = FieldInfo(alias="strategyCount") + + unique_users: int = FieldInfo(alias="uniqueUsers") + + +class UserListCoverageResponse(PaginatedUsers): + """Paginated user profiles. + + No-mode follower, following, and verified follower requests merge independent views automatically. Response fields, page size, aliases, filters, and per-returned-profile billing stay unchanged. Existing unprefixed cursors retain legacy behavior. Follow next_cursor while has_next_page is true. + """ + + diagnostic: UserListCoverageResponseDiagnostic + """Coverage evidence across parallel relationship strategies.""" + + has_next_page: Optional[Literal[False]] = None # type: ignore + + next_cursor: Optional[Literal[""]] = None # type: ignore + + +UserRetrieveFollowersResponse: TypeAlias = Union[PaginatedUsers, UserListCoverageResponse] diff --git a/src/x_twitter_scraper/types/x/user_retrieve_followers_you_know_params.py b/src/x_twitter_scraper/types/x/user_retrieve_followers_you_know_params.py index d357835..5e436e7 100644 --- a/src/x_twitter_scraper/types/x/user_retrieve_followers_you_know_params.py +++ b/src/x_twitter_scraper/types/x/user_retrieve_followers_you_know_params.py @@ -14,13 +14,54 @@ class UserRetrieveFollowersYouKnowParams(TypedDict, total=False): + bio_contains: Annotated[str, PropertyInfo(alias="bioContains")] + """Match any comma-separated or line-separated bio term, ignoring case.""" + cursor: str """Pagination cursor for followers-you-know""" + has_location: Annotated[bool, PropertyInfo(alias="hasLocation")] + """Only return profiles with a location.""" + + has_website: Annotated[bool, PropertyInfo(alias="hasWebsite")] + """Only return profiles with a website.""" + + location_contains: Annotated[str, PropertyInfo(alias="locationContains")] + """Match a location substring, ignoring case.""" + + max_followers: Annotated[int, PropertyInfo(alias="maxFollowers")] + """Maximum follower count. Missing counts pass this maximum.""" + + max_following: Annotated[int, PropertyInfo(alias="maxFollowing")] + """Maximum following count.""" + + max_statuses: Annotated[int, PropertyInfo(alias="maxStatuses")] + """Maximum post count. maxPosts is also accepted.""" + + min_account_age_days: Annotated[int, PropertyInfo(alias="minAccountAgeDays")] + """Minimum account age in whole days.""" + + min_followers: Annotated[int, PropertyInfo(alias="minFollowers")] + """Minimum follower count. Filtering happens before billing.""" + + min_following: Annotated[int, PropertyInfo(alias="minFollowing")] + """Minimum following count.""" + + min_statuses: Annotated[int, PropertyInfo(alias="minStatuses")] + """Minimum post count. minPosts is also accepted.""" + page_size: Annotated[int, PropertyInfo(alias="pageSize")] """Maximum user profiles requested from this page (20-200, default 200). - The response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + Source, filters, or credits can return fewer profiles. Keep requesting + next_cursor while has_next_page is true. Deprecated aliases remain accepted. """ + + username_contains: Annotated[str, PropertyInfo(alias="usernameContains")] + """Match a username substring, ignoring case.""" + + verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] + """Only return verified profiles.""" + + verified_type: Annotated[str, PropertyInfo(alias="verifiedType")] + """Match the verification type exactly, ignoring case.""" diff --git a/src/x_twitter_scraper/types/x/user_retrieve_following_params.py b/src/x_twitter_scraper/types/x/user_retrieve_following_params.py index 3784f9c..f0f926a 100644 --- a/src/x_twitter_scraper/types/x/user_retrieve_following_params.py +++ b/src/x_twitter_scraper/types/x/user_retrieve_following_params.py @@ -6,7 +6,7 @@ from __future__ import annotations -from typing_extensions import Annotated, TypedDict +from typing_extensions import Literal, Annotated, TypedDict from ..._utils import PropertyInfo @@ -17,16 +17,70 @@ class UserRetrieveFollowingParams(TypedDict, total=False): after: str """Deprecated following cursor alias. Prefer cursor.""" + bio_contains: Annotated[str, PropertyInfo(alias="bioContains")] + """Match any comma-separated or line-separated bio term, ignoring case.""" + cursor: str - """Pagination cursor for following list""" + """Cursor from the previous response. + + Xquik cursors resume automatic coverage. Existing unprefixed cursors keep legacy + standard behavior. + """ + + has_location: Annotated[bool, PropertyInfo(alias="hasLocation")] + """Only return profiles with a location.""" + + has_website: Annotated[bool, PropertyInfo(alias="hasWebsite")] + """Only return profiles with a website.""" limit: int - """Legacy page size alias. Prefer pageSize.""" + """Legacy page-size alias outside explicit coverage mode. + + Coverage accepts 1-10000. Prefer pageSize. + """ + + location_contains: Annotated[str, PropertyInfo(alias="locationContains")] + """Match a location substring, ignoring case.""" + + max_followers: Annotated[int, PropertyInfo(alias="maxFollowers")] + """Maximum follower count. Missing counts pass this maximum.""" + + max_following: Annotated[int, PropertyInfo(alias="maxFollowing")] + """Maximum following count.""" + + max_statuses: Annotated[int, PropertyInfo(alias="maxStatuses")] + """Maximum post count. maxPosts is also accepted.""" + + min_account_age_days: Annotated[int, PropertyInfo(alias="minAccountAgeDays")] + """Minimum account age in whole days.""" + + min_followers: Annotated[int, PropertyInfo(alias="minFollowers")] + """Minimum follower count. Filtering happens before billing.""" + + min_following: Annotated[int, PropertyInfo(alias="minFollowing")] + """Minimum following count.""" + + min_statuses: Annotated[int, PropertyInfo(alias="minStatuses")] + """Minimum post count. minPosts is also accepted.""" + + mode: Literal["standard", "coverage"] + """Omit mode for resumable maximum coverage. + + Standard keeps legacy pagination. Coverage returns diagnostics once and rejects + cursors. + """ page_size: Annotated[int, PropertyInfo(alias="pageSize")] - """Maximum user profiles requested from this page (20-200, default 200). + """Maximum user profiles: automatic 300; standard 200. - The response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + Sources return fewer profiles. Continue with has_next_page. """ + + username_contains: Annotated[str, PropertyInfo(alias="usernameContains")] + """Match a username substring, ignoring case.""" + + verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] + """Only return verified profiles.""" + + verified_type: Annotated[str, PropertyInfo(alias="verifiedType")] + """Match the verification type exactly, ignoring case.""" diff --git a/src/x_twitter_scraper/types/x/user_retrieve_following_response.py b/src/x_twitter_scraper/types/x/user_retrieve_following_response.py new file mode 100644 index 0000000..cd0c867 --- /dev/null +++ b/src/x_twitter_scraper/types/x/user_retrieve_following_response.py @@ -0,0 +1,81 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal, TypeAlias + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel +from ..shared.paginated_users import PaginatedUsers + +__all__ = [ + "UserRetrieveFollowingResponse", + "UserListCoverageResponse", + "UserListCoverageResponseDiagnostic", + "UserListCoverageResponseDiagnosticStrategy", +] + + +class UserListCoverageResponseDiagnosticStrategy(BaseModel): + duplicate_count: int = FieldInfo(alias="duplicateCount") + + pages_fetched: int = FieldInfo(alias="pagesFetched") + + stop_reason: Literal[ + "cursor_failure", "deadline", "exhausted", "failed", "page_limit", "result_limit", "stalled" + ] = FieldInfo(alias="stopReason") + + strategy: int + + unique_added: int = FieldInfo(alias="uniqueAdded") + + +class UserListCoverageResponseDiagnostic(BaseModel): + """Coverage evidence across parallel relationship strategies.""" + + complete: bool + """True when every strategy exhausted its source.""" + + cursor_failure_count: int = FieldInfo(alias="cursorFailureCount") + + deadline_reached: bool = FieldInfo(alias="deadlineReached") + + duplicate_count: int = FieldInfo(alias="duplicateCount") + + failed_strategy_count: int = FieldInfo(alias="failedStrategyCount") + + malformed_count: int = FieldInfo(alias="malformedCount") + + pages_fetched: int = FieldInfo(alias="pagesFetched") + + response_truncated: bool = FieldInfo(alias="responseTruncated") + """Whether credits or the requested limit reduced output.""" + + result_limit_reached: bool = FieldInfo(alias="resultLimitReached") + + returned_users: int = FieldInfo(alias="returnedUsers") + + stalled_strategy_count: int = FieldInfo(alias="stalledStrategyCount") + + strategies: List[UserListCoverageResponseDiagnosticStrategy] + + strategy_count: int = FieldInfo(alias="strategyCount") + + unique_users: int = FieldInfo(alias="uniqueUsers") + + +class UserListCoverageResponse(PaginatedUsers): + """Paginated user profiles. + + No-mode follower, following, and verified follower requests merge independent views automatically. Response fields, page size, aliases, filters, and per-returned-profile billing stay unchanged. Existing unprefixed cursors retain legacy behavior. Follow next_cursor while has_next_page is true. + """ + + diagnostic: UserListCoverageResponseDiagnostic + """Coverage evidence across parallel relationship strategies.""" + + has_next_page: Optional[Literal[False]] = None # type: ignore + + next_cursor: Optional[Literal[""]] = None # type: ignore + + +UserRetrieveFollowingResponse: TypeAlias = Union[PaginatedUsers, UserListCoverageResponse] diff --git a/src/x_twitter_scraper/types/x/user_retrieve_likes_params.py b/src/x_twitter_scraper/types/x/user_retrieve_likes_params.py index 255f9d9..6ddf22e 100644 --- a/src/x_twitter_scraper/types/x/user_retrieve_likes_params.py +++ b/src/x_twitter_scraper/types/x/user_retrieve_likes_params.py @@ -22,6 +22,12 @@ class UserRetrieveLikesParams(TypedDict, total=False): Separate with spaces, commas, or lines. """ + blue_verified_only: Annotated[bool, PropertyInfo(alias="blueVerifiedOnly")] + """Only return tweets from Blue-verified authors.""" + + card_name: Annotated[str, PropertyInfo(alias="cardName")] + """Match the Tweet card name.""" + cashtags: str """Cashtags separated by spaces, commas, or lines.""" @@ -34,12 +40,18 @@ class UserRetrieveLikesParams(TypedDict, total=False): exact_phrase: Annotated[str, PropertyInfo(alias="exactPhrase")] """Exact phrase to match.""" + exclude_source: Annotated[str, PropertyInfo(alias="excludeSource")] + """Exclude a source application.""" + exclude_words: Annotated[str, PropertyInfo(alias="excludeWords")] """Words or quoted phrases to exclude. Separate with spaces, commas, or lines.""" from_user: Annotated[str, PropertyInfo(alias="fromUser")] """Filter by author username.""" + geocode: str + """Match latitude, longitude, and radius.""" + hashtags: str """Hashtags separated by spaces, commas, or lines.""" @@ -49,6 +61,21 @@ class UserRetrieveLikesParams(TypedDict, total=False): language: str """Language code filter, e.g. en or tr.""" + max_faves: Annotated[int, PropertyInfo(alias="maxFaves")] + """Maximum likes threshold. maxLikes is also accepted.""" + + max_id: Annotated[str, PropertyInfo(alias="maxId")] + """Return Tweets older than this Tweet ID.""" + + max_quotes: Annotated[int, PropertyInfo(alias="maxQuotes")] + """Maximum quotes threshold.""" + + max_replies: Annotated[int, PropertyInfo(alias="maxReplies")] + """Maximum replies threshold.""" + + max_retweets: Annotated[int, PropertyInfo(alias="maxRetweets")] + """Maximum retweets threshold.""" + media_type: Annotated[ Literal["images", "videos", "gifs", "media", "links", "none"], PropertyInfo(alias="mediaType") ] @@ -57,6 +84,9 @@ class UserRetrieveLikesParams(TypedDict, total=False): mentioning: str """Filter tweets mentioning a username.""" + min_bookmarks: Annotated[int, PropertyInfo(alias="minBookmarks")] + """Minimum bookmark count threshold.""" + min_faves: Annotated[int, PropertyInfo(alias="minFaves")] """Minimum likes threshold.""" @@ -69,6 +99,18 @@ class UserRetrieveLikesParams(TypedDict, total=False): min_retweets: Annotated[int, PropertyInfo(alias="minRetweets")] """Minimum retweets threshold.""" + min_views: Annotated[int, PropertyInfo(alias="minViews")] + """Minimum view count threshold.""" + + native_retweets: Annotated[bool, PropertyInfo(alias="nativeRetweets")] + """Only return native reposts.""" + + near: str + """Match a place name.""" + + news: bool + """Only return news results.""" + page_size: Annotated[int, PropertyInfo(alias="pageSize")] """Maximum page items (1-100, default 20). @@ -91,9 +133,18 @@ class UserRetrieveLikesParams(TypedDict, total=False): retweets_of_tweet_id: Annotated[str, PropertyInfo(alias="retweetsOfTweetId")] """Only retweets of this tweet ID.""" + safe: bool + """Enable the safe-search filter.""" + since_date: Annotated[Union[str, date], PropertyInfo(alias="sinceDate", format="iso8601")] """Start date in YYYY-MM-DD format.""" + since_id: Annotated[str, PropertyInfo(alias="sinceId")] + """Return Tweets newer than this Tweet ID.""" + + source: str + """Match the source application.""" + to_user: Annotated[str, PropertyInfo(alias="toUser")] """Filter replies sent to a username.""" @@ -105,3 +156,9 @@ class UserRetrieveLikesParams(TypedDict, total=False): verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] """Only return tweets from verified authors.""" + + within: str + """Set the radius for the near filter.""" + + within_time: Annotated[str, PropertyInfo(alias="withinTime")] + """Match Tweets inside a recent time window.""" diff --git a/src/x_twitter_scraper/types/x/user_retrieve_media_params.py b/src/x_twitter_scraper/types/x/user_retrieve_media_params.py index 3730305..04c9a91 100644 --- a/src/x_twitter_scraper/types/x/user_retrieve_media_params.py +++ b/src/x_twitter_scraper/types/x/user_retrieve_media_params.py @@ -22,6 +22,12 @@ class UserRetrieveMediaParams(TypedDict, total=False): Separate with spaces, commas, or lines. """ + blue_verified_only: Annotated[bool, PropertyInfo(alias="blueVerifiedOnly")] + """Only return tweets from Blue-verified authors.""" + + card_name: Annotated[str, PropertyInfo(alias="cardName")] + """Match the Tweet card name.""" + cashtags: str """Cashtags separated by spaces, commas, or lines.""" @@ -34,12 +40,18 @@ class UserRetrieveMediaParams(TypedDict, total=False): exact_phrase: Annotated[str, PropertyInfo(alias="exactPhrase")] """Exact phrase to match.""" + exclude_source: Annotated[str, PropertyInfo(alias="excludeSource")] + """Exclude a source application.""" + exclude_words: Annotated[str, PropertyInfo(alias="excludeWords")] """Words or quoted phrases to exclude. Separate with spaces, commas, or lines.""" from_user: Annotated[str, PropertyInfo(alias="fromUser")] """Filter by author username.""" + geocode: str + """Match latitude, longitude, and radius.""" + hashtags: str """Hashtags separated by spaces, commas, or lines.""" @@ -49,6 +61,21 @@ class UserRetrieveMediaParams(TypedDict, total=False): language: str """Language code filter, e.g. en or tr.""" + max_faves: Annotated[int, PropertyInfo(alias="maxFaves")] + """Maximum likes threshold. maxLikes is also accepted.""" + + max_id: Annotated[str, PropertyInfo(alias="maxId")] + """Return Tweets older than this Tweet ID.""" + + max_quotes: Annotated[int, PropertyInfo(alias="maxQuotes")] + """Maximum quotes threshold.""" + + max_replies: Annotated[int, PropertyInfo(alias="maxReplies")] + """Maximum replies threshold.""" + + max_retweets: Annotated[int, PropertyInfo(alias="maxRetweets")] + """Maximum retweets threshold.""" + media_type: Annotated[ Literal["images", "videos", "gifs", "media", "links", "none"], PropertyInfo(alias="mediaType") ] @@ -57,6 +84,9 @@ class UserRetrieveMediaParams(TypedDict, total=False): mentioning: str """Filter tweets mentioning a username.""" + min_bookmarks: Annotated[int, PropertyInfo(alias="minBookmarks")] + """Minimum bookmark count threshold.""" + min_faves: Annotated[int, PropertyInfo(alias="minFaves")] """Minimum likes threshold.""" @@ -69,6 +99,18 @@ class UserRetrieveMediaParams(TypedDict, total=False): min_retweets: Annotated[int, PropertyInfo(alias="minRetweets")] """Minimum retweets threshold.""" + min_views: Annotated[int, PropertyInfo(alias="minViews")] + """Minimum view count threshold.""" + + native_retweets: Annotated[bool, PropertyInfo(alias="nativeRetweets")] + """Only return native reposts.""" + + near: str + """Match a place name.""" + + news: bool + """Only return news results.""" + page_size: Annotated[int, PropertyInfo(alias="pageSize")] """Maximum page items (1-100, default 20). @@ -91,9 +133,18 @@ class UserRetrieveMediaParams(TypedDict, total=False): retweets_of_tweet_id: Annotated[str, PropertyInfo(alias="retweetsOfTweetId")] """Only retweets of this tweet ID.""" + safe: bool + """Enable the safe-search filter.""" + since_date: Annotated[Union[str, date], PropertyInfo(alias="sinceDate", format="iso8601")] """Start date in YYYY-MM-DD format.""" + since_id: Annotated[str, PropertyInfo(alias="sinceId")] + """Return Tweets newer than this Tweet ID.""" + + source: str + """Match the source application.""" + to_user: Annotated[str, PropertyInfo(alias="toUser")] """Filter replies sent to a username.""" @@ -105,3 +156,9 @@ class UserRetrieveMediaParams(TypedDict, total=False): verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] """Only return tweets from verified authors.""" + + within: str + """Set the radius for the near filter.""" + + within_time: Annotated[str, PropertyInfo(alias="withinTime")] + """Match Tweets inside a recent time window.""" diff --git a/src/x_twitter_scraper/types/x/user_retrieve_mentions_params.py b/src/x_twitter_scraper/types/x/user_retrieve_mentions_params.py index 8731903..07598a6 100644 --- a/src/x_twitter_scraper/types/x/user_retrieve_mentions_params.py +++ b/src/x_twitter_scraper/types/x/user_retrieve_mentions_params.py @@ -22,6 +22,12 @@ class UserRetrieveMentionsParams(TypedDict, total=False): Separate with spaces, commas, or lines. """ + blue_verified_only: Annotated[bool, PropertyInfo(alias="blueVerifiedOnly")] + """Only return tweets from Blue-verified authors.""" + + card_name: Annotated[str, PropertyInfo(alias="cardName")] + """Match the Tweet card name.""" + cashtags: str """Cashtags separated by spaces, commas, or lines.""" @@ -34,12 +40,18 @@ class UserRetrieveMentionsParams(TypedDict, total=False): exact_phrase: Annotated[str, PropertyInfo(alias="exactPhrase")] """Exact phrase to match.""" + exclude_source: Annotated[str, PropertyInfo(alias="excludeSource")] + """Exclude a source application.""" + exclude_words: Annotated[str, PropertyInfo(alias="excludeWords")] """Words or quoted phrases to exclude. Separate with spaces, commas, or lines.""" from_user: Annotated[str, PropertyInfo(alias="fromUser")] """Filter by author username.""" + geocode: str + """Match latitude, longitude, and radius.""" + hashtags: str """Hashtags separated by spaces, commas, or lines.""" @@ -49,6 +61,21 @@ class UserRetrieveMentionsParams(TypedDict, total=False): language: str """Language code filter, e.g. en or tr.""" + max_faves: Annotated[int, PropertyInfo(alias="maxFaves")] + """Maximum likes threshold. maxLikes is also accepted.""" + + max_id: Annotated[str, PropertyInfo(alias="maxId")] + """Return Tweets older than this Tweet ID.""" + + max_quotes: Annotated[int, PropertyInfo(alias="maxQuotes")] + """Maximum quotes threshold.""" + + max_replies: Annotated[int, PropertyInfo(alias="maxReplies")] + """Maximum replies threshold.""" + + max_retweets: Annotated[int, PropertyInfo(alias="maxRetweets")] + """Maximum retweets threshold.""" + media_type: Annotated[ Literal["images", "videos", "gifs", "media", "links", "none"], PropertyInfo(alias="mediaType") ] @@ -57,6 +84,9 @@ class UserRetrieveMentionsParams(TypedDict, total=False): mentioning: str """Filter tweets mentioning a username.""" + min_bookmarks: Annotated[int, PropertyInfo(alias="minBookmarks")] + """Minimum bookmark count threshold.""" + min_faves: Annotated[int, PropertyInfo(alias="minFaves")] """Minimum likes threshold.""" @@ -69,6 +99,18 @@ class UserRetrieveMentionsParams(TypedDict, total=False): min_retweets: Annotated[int, PropertyInfo(alias="minRetweets")] """Minimum retweets threshold.""" + min_views: Annotated[int, PropertyInfo(alias="minViews")] + """Minimum view count threshold.""" + + native_retweets: Annotated[bool, PropertyInfo(alias="nativeRetweets")] + """Only return native reposts.""" + + near: str + """Match a place name.""" + + news: bool + """Only return news results.""" + page_size: Annotated[int, PropertyInfo(alias="pageSize")] """Maximum page items (1-100, default 20). @@ -91,12 +133,21 @@ class UserRetrieveMentionsParams(TypedDict, total=False): retweets_of_tweet_id: Annotated[str, PropertyInfo(alias="retweetsOfTweetId")] """Only retweets of this tweet ID.""" + safe: bool + """Enable the safe-search filter.""" + since_date: Annotated[Union[str, date], PropertyInfo(alias="sinceDate", format="iso8601")] """Start date in YYYY-MM-DD format.""" + since_id: Annotated[str, PropertyInfo(alias="sinceId")] + """Return Tweets newer than this Tweet ID.""" + since_time: Annotated[str, PropertyInfo(alias="sinceTime")] """Unix timestamp - return mentions after this time""" + source: str + """Match the source application.""" + to_user: Annotated[str, PropertyInfo(alias="toUser")] """Filter replies sent to a username.""" @@ -111,3 +162,9 @@ class UserRetrieveMentionsParams(TypedDict, total=False): verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] """Only return tweets from verified authors.""" + + within: str + """Set the radius for the near filter.""" + + within_time: Annotated[str, PropertyInfo(alias="withinTime")] + """Match Tweets inside a recent time window.""" diff --git a/src/x_twitter_scraper/types/x/user_retrieve_replies_params.py b/src/x_twitter_scraper/types/x/user_retrieve_replies_params.py index fa091ad..a29f21d 100644 --- a/src/x_twitter_scraper/types/x/user_retrieve_replies_params.py +++ b/src/x_twitter_scraper/types/x/user_retrieve_replies_params.py @@ -22,6 +22,12 @@ class UserRetrieveRepliesParams(TypedDict, total=False): Separate with spaces, commas, or lines. """ + blue_verified_only: Annotated[bool, PropertyInfo(alias="blueVerifiedOnly")] + """Only return tweets from Blue-verified authors.""" + + card_name: Annotated[str, PropertyInfo(alias="cardName")] + """Match the Tweet card name.""" + cashtags: str """Cashtags separated by spaces, commas, or lines.""" @@ -29,17 +35,27 @@ class UserRetrieveRepliesParams(TypedDict, total=False): """Conversation ID filter.""" cursor: str - """Pagination cursor for user replies""" + """Cursor from the previous response. + + Xquik cursors resume automatic coverage. Existing unprefixed cursors keep legacy + standard behavior. + """ exact_phrase: Annotated[str, PropertyInfo(alias="exactPhrase")] """Exact phrase to match.""" + exclude_source: Annotated[str, PropertyInfo(alias="excludeSource")] + """Exclude a source application.""" + exclude_words: Annotated[str, PropertyInfo(alias="excludeWords")] """Words or quoted phrases to exclude. Separate with spaces, commas, or lines.""" from_user: Annotated[str, PropertyInfo(alias="fromUser")] """Filter by author username.""" + geocode: str + """Match latitude, longitude, and radius.""" + hashtags: str """Hashtags separated by spaces, commas, or lines.""" @@ -52,6 +68,21 @@ class UserRetrieveRepliesParams(TypedDict, total=False): language: str """Language code filter, e.g. en or tr.""" + max_faves: Annotated[int, PropertyInfo(alias="maxFaves")] + """Maximum likes threshold. maxLikes is also accepted.""" + + max_id: Annotated[str, PropertyInfo(alias="maxId")] + """Return Tweets older than this Tweet ID.""" + + max_quotes: Annotated[int, PropertyInfo(alias="maxQuotes")] + """Maximum quotes threshold.""" + + max_replies: Annotated[int, PropertyInfo(alias="maxReplies")] + """Maximum replies threshold.""" + + max_retweets: Annotated[int, PropertyInfo(alias="maxRetweets")] + """Maximum retweets threshold.""" + media_type: Annotated[ Literal["images", "videos", "gifs", "media", "links", "none"], PropertyInfo(alias="mediaType") ] @@ -60,6 +91,9 @@ class UserRetrieveRepliesParams(TypedDict, total=False): mentioning: str """Filter tweets mentioning a username.""" + min_bookmarks: Annotated[int, PropertyInfo(alias="minBookmarks")] + """Minimum bookmark count threshold.""" + min_faves: Annotated[int, PropertyInfo(alias="minFaves")] """Minimum likes threshold.""" @@ -72,11 +106,23 @@ class UserRetrieveRepliesParams(TypedDict, total=False): min_retweets: Annotated[int, PropertyInfo(alias="minRetweets")] """Minimum retweets threshold.""" + min_views: Annotated[int, PropertyInfo(alias="minViews")] + """Minimum view count threshold.""" + + native_retweets: Annotated[bool, PropertyInfo(alias="nativeRetweets")] + """Only return native reposts.""" + + near: str + """Match a place name.""" + + news: bool + """Only return news results.""" + page_size: Annotated[int, PropertyInfo(alias="pageSize")] - """Maximum page items (1-100, default 20). + """Automatic pages accept 1-300 Tweets. - Source, filters, or credits can reduce results. Continue while has_next_page is - true. Deprecated limit and count aliases remain accepted. + Standard pages keep 1-100. Default 20. Continue while has_next_page is true. + Deprecated aliases remain accepted. """ quotes: Literal["include", "exclude", "only"] @@ -94,9 +140,18 @@ class UserRetrieveRepliesParams(TypedDict, total=False): retweets_of_tweet_id: Annotated[str, PropertyInfo(alias="retweetsOfTweetId")] """Only retweets of this tweet ID.""" + safe: bool + """Enable the safe-search filter.""" + since_date: Annotated[Union[str, date], PropertyInfo(alias="sinceDate", format="iso8601")] """Start date in YYYY-MM-DD format.""" + since_id: Annotated[str, PropertyInfo(alias="sinceId")] + """Return Tweets newer than this Tweet ID.""" + + source: str + """Match the source application.""" + to_user: Annotated[str, PropertyInfo(alias="toUser")] """Filter replies sent to a username.""" @@ -108,3 +163,9 @@ class UserRetrieveRepliesParams(TypedDict, total=False): verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] """Only return tweets from verified authors.""" + + within: str + """Set the radius for the near filter.""" + + within_time: Annotated[str, PropertyInfo(alias="withinTime")] + """Match Tweets inside a recent time window.""" diff --git a/src/x_twitter_scraper/types/x/user_retrieve_search_params.py b/src/x_twitter_scraper/types/x/user_retrieve_search_params.py index 59be296..16d55a8 100644 --- a/src/x_twitter_scraper/types/x/user_retrieve_search_params.py +++ b/src/x_twitter_scraper/types/x/user_retrieve_search_params.py @@ -6,7 +6,9 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo __all__ = ["UserRetrieveSearchParams"] @@ -15,5 +17,47 @@ class UserRetrieveSearchParams(TypedDict, total=False): q: Required[str] """User search query""" + bio_contains: Annotated[str, PropertyInfo(alias="bioContains")] + """Match any comma-separated or line-separated bio term, ignoring case.""" + cursor: str """Pagination cursor for user search""" + + has_location: Annotated[bool, PropertyInfo(alias="hasLocation")] + """Only return profiles with a location.""" + + has_website: Annotated[bool, PropertyInfo(alias="hasWebsite")] + """Only return profiles with a website.""" + + location_contains: Annotated[str, PropertyInfo(alias="locationContains")] + """Match a location substring, ignoring case.""" + + max_followers: Annotated[int, PropertyInfo(alias="maxFollowers")] + """Maximum follower count. Missing counts pass this maximum.""" + + max_following: Annotated[int, PropertyInfo(alias="maxFollowing")] + """Maximum following count.""" + + max_statuses: Annotated[int, PropertyInfo(alias="maxStatuses")] + """Maximum post count. maxPosts is also accepted.""" + + min_account_age_days: Annotated[int, PropertyInfo(alias="minAccountAgeDays")] + """Minimum account age in whole days.""" + + min_followers: Annotated[int, PropertyInfo(alias="minFollowers")] + """Minimum follower count. Filtering happens before billing.""" + + min_following: Annotated[int, PropertyInfo(alias="minFollowing")] + """Minimum following count.""" + + min_statuses: Annotated[int, PropertyInfo(alias="minStatuses")] + """Minimum post count. minPosts is also accepted.""" + + username_contains: Annotated[str, PropertyInfo(alias="usernameContains")] + """Match a username substring, ignoring case.""" + + verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] + """Only return verified profiles.""" + + verified_type: Annotated[str, PropertyInfo(alias="verifiedType")] + """Match the verification type exactly, ignoring case.""" diff --git a/src/x_twitter_scraper/types/x/user_retrieve_tweets_params.py b/src/x_twitter_scraper/types/x/user_retrieve_tweets_params.py index d2faa4f..7dd315c 100644 --- a/src/x_twitter_scraper/types/x/user_retrieve_tweets_params.py +++ b/src/x_twitter_scraper/types/x/user_retrieve_tweets_params.py @@ -22,6 +22,12 @@ class UserRetrieveTweetsParams(TypedDict, total=False): Separate with spaces, commas, or lines. """ + blue_verified_only: Annotated[bool, PropertyInfo(alias="blueVerifiedOnly")] + """Only return tweets from Blue-verified authors.""" + + card_name: Annotated[str, PropertyInfo(alias="cardName")] + """Match the Tweet card name.""" + cashtags: str """Cashtags separated by spaces, commas, or lines.""" @@ -29,17 +35,27 @@ class UserRetrieveTweetsParams(TypedDict, total=False): """Conversation ID filter.""" cursor: str - """Pagination cursor for user tweets""" + """Cursor from the previous response. + + Xquik cursors resume automatic coverage. Existing unprefixed cursors keep legacy + standard behavior. + """ exact_phrase: Annotated[str, PropertyInfo(alias="exactPhrase")] """Exact phrase to match.""" + exclude_source: Annotated[str, PropertyInfo(alias="excludeSource")] + """Exclude a source application.""" + exclude_words: Annotated[str, PropertyInfo(alias="excludeWords")] """Words or quoted phrases to exclude. Separate with spaces, commas, or lines.""" from_user: Annotated[str, PropertyInfo(alias="fromUser")] """Filter by author username.""" + geocode: str + """Match latitude, longitude, and radius.""" + hashtags: str """Hashtags separated by spaces, commas, or lines.""" @@ -55,6 +71,21 @@ class UserRetrieveTweetsParams(TypedDict, total=False): language: str """Language code filter, e.g. en or tr.""" + max_faves: Annotated[int, PropertyInfo(alias="maxFaves")] + """Maximum likes threshold. maxLikes is also accepted.""" + + max_id: Annotated[str, PropertyInfo(alias="maxId")] + """Return Tweets older than this Tweet ID.""" + + max_quotes: Annotated[int, PropertyInfo(alias="maxQuotes")] + """Maximum quotes threshold.""" + + max_replies: Annotated[int, PropertyInfo(alias="maxReplies")] + """Maximum replies threshold.""" + + max_retweets: Annotated[int, PropertyInfo(alias="maxRetweets")] + """Maximum retweets threshold.""" + media_type: Annotated[ Literal["images", "videos", "gifs", "media", "links", "none"], PropertyInfo(alias="mediaType") ] @@ -63,6 +94,9 @@ class UserRetrieveTweetsParams(TypedDict, total=False): mentioning: str """Filter tweets mentioning a username.""" + min_bookmarks: Annotated[int, PropertyInfo(alias="minBookmarks")] + """Minimum bookmark count threshold.""" + min_faves: Annotated[int, PropertyInfo(alias="minFaves")] """Minimum likes threshold.""" @@ -75,11 +109,23 @@ class UserRetrieveTweetsParams(TypedDict, total=False): min_retweets: Annotated[int, PropertyInfo(alias="minRetweets")] """Minimum retweets threshold.""" + min_views: Annotated[int, PropertyInfo(alias="minViews")] + """Minimum view count threshold.""" + + native_retweets: Annotated[bool, PropertyInfo(alias="nativeRetweets")] + """Only return native reposts.""" + + near: str + """Match a place name.""" + + news: bool + """Only return news results.""" + page_size: Annotated[int, PropertyInfo(alias="pageSize")] - """Maximum page items (1-100, default 20). + """Automatic pages accept 1-300 Tweets. - Source, filters, or credits can reduce results. Continue while has_next_page is - true. Deprecated limit and count aliases remain accepted. + Standard pages keep 1-100. Default 20. Continue while has_next_page is true. + Deprecated aliases remain accepted. """ quotes: Literal["include", "exclude", "only"] @@ -97,9 +143,18 @@ class UserRetrieveTweetsParams(TypedDict, total=False): retweets_of_tweet_id: Annotated[str, PropertyInfo(alias="retweetsOfTweetId")] """Only retweets of this tweet ID.""" + safe: bool + """Enable the safe-search filter.""" + since_date: Annotated[Union[str, date], PropertyInfo(alias="sinceDate", format="iso8601")] """Start date in YYYY-MM-DD format.""" + since_id: Annotated[str, PropertyInfo(alias="sinceId")] + """Return Tweets newer than this Tweet ID.""" + + source: str + """Match the source application.""" + to_user: Annotated[str, PropertyInfo(alias="toUser")] """Filter replies sent to a username.""" @@ -111,3 +166,9 @@ class UserRetrieveTweetsParams(TypedDict, total=False): verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] """Only return tweets from verified authors.""" + + within: str + """Set the radius for the near filter.""" + + within_time: Annotated[str, PropertyInfo(alias="withinTime")] + """Match Tweets inside a recent time window.""" diff --git a/src/x_twitter_scraper/types/x/user_retrieve_verified_followers_params.py b/src/x_twitter_scraper/types/x/user_retrieve_verified_followers_params.py index 7840646..4e6f09c 100644 --- a/src/x_twitter_scraper/types/x/user_retrieve_verified_followers_params.py +++ b/src/x_twitter_scraper/types/x/user_retrieve_verified_followers_params.py @@ -6,7 +6,7 @@ from __future__ import annotations -from typing_extensions import Annotated, TypedDict +from typing_extensions import Literal, Annotated, TypedDict from ..._utils import PropertyInfo @@ -14,13 +14,73 @@ class UserRetrieveVerifiedFollowersParams(TypedDict, total=False): + after: str + """Legacy cursor alias. Prefer cursor.""" + + bio_contains: Annotated[str, PropertyInfo(alias="bioContains")] + """Match any comma-separated or line-separated bio term, ignoring case.""" + cursor: str - """Pagination cursor for verified followers""" + """Cursor from the previous response. + + Xquik cursors resume automatic coverage. Existing unprefixed cursors keep legacy + standard behavior. + """ + + has_location: Annotated[bool, PropertyInfo(alias="hasLocation")] + """Only return profiles with a location.""" + + has_website: Annotated[bool, PropertyInfo(alias="hasWebsite")] + """Only return profiles with a website.""" + + limit: int + """Legacy page-size alias outside explicit coverage mode. + + Coverage accepts 1-10000. Prefer pageSize. + """ + + location_contains: Annotated[str, PropertyInfo(alias="locationContains")] + """Match a location substring, ignoring case.""" + + max_followers: Annotated[int, PropertyInfo(alias="maxFollowers")] + """Maximum follower count. Missing counts pass this maximum.""" + + max_following: Annotated[int, PropertyInfo(alias="maxFollowing")] + """Maximum following count.""" + + max_statuses: Annotated[int, PropertyInfo(alias="maxStatuses")] + """Maximum post count. maxPosts is also accepted.""" + + min_account_age_days: Annotated[int, PropertyInfo(alias="minAccountAgeDays")] + """Minimum account age in whole days.""" + + min_followers: Annotated[int, PropertyInfo(alias="minFollowers")] + """Minimum follower count. Filtering happens before billing.""" + + min_following: Annotated[int, PropertyInfo(alias="minFollowing")] + """Minimum following count.""" + + min_statuses: Annotated[int, PropertyInfo(alias="minStatuses")] + """Minimum post count. minPosts is also accepted.""" + + mode: Literal["standard", "coverage"] + """Omit mode for resumable maximum coverage. + + Standard keeps legacy pagination. Coverage returns diagnostics once and rejects + cursors. + """ page_size: Annotated[int, PropertyInfo(alias="pageSize")] - """Maximum user profiles requested from this page (20-200, default 200). + """Maximum user profiles: automatic 300; standard 200. - The response can contain fewer profiles because the source returned fewer or - remaining credits cover fewer results. Keep requesting next_cursor while - has_next_page is true. The deprecated limit and count aliases remain accepted. + Sources return fewer profiles. Continue with has_next_page. """ + + username_contains: Annotated[str, PropertyInfo(alias="usernameContains")] + """Match a username substring, ignoring case.""" + + verified_only: Annotated[bool, PropertyInfo(alias="verifiedOnly")] + """Only return verified profiles.""" + + verified_type: Annotated[str, PropertyInfo(alias="verifiedType")] + """Match the verification type exactly, ignoring case.""" diff --git a/src/x_twitter_scraper/types/x/user_retrieve_verified_followers_response.py b/src/x_twitter_scraper/types/x/user_retrieve_verified_followers_response.py new file mode 100644 index 0000000..c1fb892 --- /dev/null +++ b/src/x_twitter_scraper/types/x/user_retrieve_verified_followers_response.py @@ -0,0 +1,81 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal, TypeAlias + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel +from ..shared.paginated_users import PaginatedUsers + +__all__ = [ + "UserRetrieveVerifiedFollowersResponse", + "UserListCoverageResponse", + "UserListCoverageResponseDiagnostic", + "UserListCoverageResponseDiagnosticStrategy", +] + + +class UserListCoverageResponseDiagnosticStrategy(BaseModel): + duplicate_count: int = FieldInfo(alias="duplicateCount") + + pages_fetched: int = FieldInfo(alias="pagesFetched") + + stop_reason: Literal[ + "cursor_failure", "deadline", "exhausted", "failed", "page_limit", "result_limit", "stalled" + ] = FieldInfo(alias="stopReason") + + strategy: int + + unique_added: int = FieldInfo(alias="uniqueAdded") + + +class UserListCoverageResponseDiagnostic(BaseModel): + """Coverage evidence across parallel relationship strategies.""" + + complete: bool + """True when every strategy exhausted its source.""" + + cursor_failure_count: int = FieldInfo(alias="cursorFailureCount") + + deadline_reached: bool = FieldInfo(alias="deadlineReached") + + duplicate_count: int = FieldInfo(alias="duplicateCount") + + failed_strategy_count: int = FieldInfo(alias="failedStrategyCount") + + malformed_count: int = FieldInfo(alias="malformedCount") + + pages_fetched: int = FieldInfo(alias="pagesFetched") + + response_truncated: bool = FieldInfo(alias="responseTruncated") + """Whether credits or the requested limit reduced output.""" + + result_limit_reached: bool = FieldInfo(alias="resultLimitReached") + + returned_users: int = FieldInfo(alias="returnedUsers") + + stalled_strategy_count: int = FieldInfo(alias="stalledStrategyCount") + + strategies: List[UserListCoverageResponseDiagnosticStrategy] + + strategy_count: int = FieldInfo(alias="strategyCount") + + unique_users: int = FieldInfo(alias="uniqueUsers") + + +class UserListCoverageResponse(PaginatedUsers): + """Paginated user profiles. + + No-mode follower, following, and verified follower requests merge independent views automatically. Response fields, page size, aliases, filters, and per-returned-profile billing stay unchanged. Existing unprefixed cursors retain legacy behavior. Follow next_cursor while has_next_page is true. + """ + + diagnostic: UserListCoverageResponseDiagnostic + """Coverage evidence across parallel relationship strategies.""" + + has_next_page: Optional[Literal[False]] = None # type: ignore + + next_cursor: Optional[Literal[""]] = None # type: ignore + + +UserRetrieveVerifiedFollowersResponse: TypeAlias = Union[PaginatedUsers, UserListCoverageResponse] diff --git a/src/x_twitter_scraper/types/x/x_account.py b/src/x_twitter_scraper/types/x/x_account.py index 01ffda7..b920864 100644 --- a/src/x_twitter_scraper/types/x/x_account.py +++ b/src/x_twitter_scraper/types/x/x_account.py @@ -25,13 +25,11 @@ class XAccount(BaseModel): created_at: datetime = FieldInfo(alias="createdAt") health: Literal["healthy", "locked", "needsReauth", "recovering", "suspended", "temporaryIssue"] - """Derived connection health. + """Derived health. - `healthy` = ready to use. `needsReauth` = user must submit fresh credentials. - `locked` = X locked the account; unlock on x.com first. `suspended` = X banned - the account. `recovering` = cooldown ended; the account can reconnect on its - next use. `temporaryIssue` = temporary connection problem; wait before the next - use. + `healthy` is ready. `needsReauth` needs credentials. `locked` must be unlocked + on X. `suspended` is banned. `recovering` can reconnect. Wait before using + `temporaryIssue`. """ status: str diff --git a/tests/api_resources/support/test_attachments.py b/tests/api_resources/support/test_attachments.py new file mode 100644 index 0000000..60ccb93 --- /dev/null +++ b/tests/api_resources/support/test_attachments.py @@ -0,0 +1,176 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import httpx +import pytest +from respx import MockRouter + +from x_twitter_scraper import XTwitterScraper, AsyncXTwitterScraper +from x_twitter_scraper._response import ( + BinaryAPIResponse, + AsyncBinaryAPIResponse, + StreamedBinaryAPIResponse, + AsyncStreamedBinaryAPIResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestAttachments: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_method_download(self, client: XTwitterScraper, respx_mock: MockRouter) -> None: + respx_mock.get("/support/attachments/att_a1b2c3d4e5f6a1b2c3d4e5f6").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + attachment = client.support.attachments.download( + id="att_a1b2c3d4e5f6a1b2c3d4e5f6", + ) + assert attachment.is_closed + assert attachment.json() == {"foo": "bar"} + assert cast(Any, attachment.is_closed) is True + assert isinstance(attachment, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_method_download_with_all_params(self, client: XTwitterScraper, respx_mock: MockRouter) -> None: + respx_mock.get("/support/attachments/att_a1b2c3d4e5f6a1b2c3d4e5f6").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + attachment = client.support.attachments.download( + id="att_a1b2c3d4e5f6a1b2c3d4e5f6", + range="bytes=0-1048575", + ) + assert attachment.is_closed + assert attachment.json() == {"foo": "bar"} + assert cast(Any, attachment.is_closed) is True + assert isinstance(attachment, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_raw_response_download(self, client: XTwitterScraper, respx_mock: MockRouter) -> None: + respx_mock.get("/support/attachments/att_a1b2c3d4e5f6a1b2c3d4e5f6").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + + attachment = client.support.attachments.with_raw_response.download( + id="att_a1b2c3d4e5f6a1b2c3d4e5f6", + ) + + assert attachment.is_closed is True + assert attachment.http_request.headers.get("X-Stainless-Lang") == "python" + assert attachment.json() == {"foo": "bar"} + assert isinstance(attachment, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_streaming_response_download(self, client: XTwitterScraper, respx_mock: MockRouter) -> None: + respx_mock.get("/support/attachments/att_a1b2c3d4e5f6a1b2c3d4e5f6").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + with client.support.attachments.with_streaming_response.download( + id="att_a1b2c3d4e5f6a1b2c3d4e5f6", + ) as attachment: + assert not attachment.is_closed + assert attachment.http_request.headers.get("X-Stainless-Lang") == "python" + + assert attachment.json() == {"foo": "bar"} + assert cast(Any, attachment.is_closed) is True + assert isinstance(attachment, StreamedBinaryAPIResponse) + + assert cast(Any, attachment.is_closed) is True + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_path_params_download(self, client: XTwitterScraper) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.support.attachments.with_raw_response.download( + id="", + ) + + +class TestAsyncAttachments: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_method_download(self, async_client: AsyncXTwitterScraper, respx_mock: MockRouter) -> None: + respx_mock.get("/support/attachments/att_a1b2c3d4e5f6a1b2c3d4e5f6").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + attachment = await async_client.support.attachments.download( + id="att_a1b2c3d4e5f6a1b2c3d4e5f6", + ) + assert attachment.is_closed + assert await attachment.json() == {"foo": "bar"} + assert cast(Any, attachment.is_closed) is True + assert isinstance(attachment, AsyncBinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_method_download_with_all_params( + self, async_client: AsyncXTwitterScraper, respx_mock: MockRouter + ) -> None: + respx_mock.get("/support/attachments/att_a1b2c3d4e5f6a1b2c3d4e5f6").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + attachment = await async_client.support.attachments.download( + id="att_a1b2c3d4e5f6a1b2c3d4e5f6", + range="bytes=0-1048575", + ) + assert attachment.is_closed + assert await attachment.json() == {"foo": "bar"} + assert cast(Any, attachment.is_closed) is True + assert isinstance(attachment, AsyncBinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_raw_response_download(self, async_client: AsyncXTwitterScraper, respx_mock: MockRouter) -> None: + respx_mock.get("/support/attachments/att_a1b2c3d4e5f6a1b2c3d4e5f6").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + + attachment = await async_client.support.attachments.with_raw_response.download( + id="att_a1b2c3d4e5f6a1b2c3d4e5f6", + ) + + assert attachment.is_closed is True + assert attachment.http_request.headers.get("X-Stainless-Lang") == "python" + assert await attachment.json() == {"foo": "bar"} + assert isinstance(attachment, AsyncBinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_streaming_response_download( + self, async_client: AsyncXTwitterScraper, respx_mock: MockRouter + ) -> None: + respx_mock.get("/support/attachments/att_a1b2c3d4e5f6a1b2c3d4e5f6").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + async with async_client.support.attachments.with_streaming_response.download( + id="att_a1b2c3d4e5f6a1b2c3d4e5f6", + ) as attachment: + assert not attachment.is_closed + assert attachment.http_request.headers.get("X-Stainless-Lang") == "python" + + assert await attachment.json() == {"foo": "bar"} + assert cast(Any, attachment.is_closed) is True + assert isinstance(attachment, AsyncStreamedBinaryAPIResponse) + + assert cast(Any, attachment.is_closed) is True + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_path_params_download(self, async_client: AsyncXTwitterScraper) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.support.attachments.with_raw_response.download( + id="", + ) diff --git a/tests/api_resources/test_events.py b/tests/api_resources/test_events.py index a857097..2855501 100644 --- a/tests/api_resources/test_events.py +++ b/tests/api_resources/test_events.py @@ -75,6 +75,7 @@ def test_method_list_with_all_params(self, client: XTwitterScraper) -> None: event = client.events.list( cursor="cursor", event_type="tweet.new", + keyword_monitor_id="keywordMonitorId", limit=1, monitor_id="monitorId", ) @@ -162,6 +163,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncXTwitterScra event = await async_client.events.list( cursor="cursor", event_type="tweet.new", + keyword_monitor_id="keywordMonitorId", limit=1, monitor_id="monitorId", ) diff --git a/tests/api_resources/test_extractions.py b/tests/api_resources/test_extractions.py index 7a0c0d5..6474d1d 100644 --- a/tests/api_resources/test_extractions.py +++ b/tests/api_resources/test_extractions.py @@ -21,7 +21,7 @@ ExtractionRetrieveResponse, ExtractionEstimateCostResponse, ) -from x_twitter_scraper._utils import parse_date +from x_twitter_scraper._utils import parse_date, parse_datetime from x_twitter_scraper._response import ( BinaryAPIResponse, AsyncBinaryAPIResponse, @@ -49,7 +49,11 @@ def test_method_retrieve_with_all_params(self, client: XTwitterScraper) -> None: extraction = client.extractions.retrieve( id="id", cursor="cursor", + field_style="source", + include_raw=True, limit=1, + output_mode="compact", + output_preset="nested", ) assert_matches_type(ExtractionRetrieveResponse, extraction, path=["response"]) @@ -141,42 +145,104 @@ def test_method_estimate_cost_with_all_params(self, client: XTwitterScraper) -> tool_type="follower_explorer", advanced_query="min_faves:100", any_words="ChatGPT AI model", + bio_contains="bioContains", + blue_verified_only=True, bounding_box="-74.1 40.6 -73.9 40.8", + card_name="cardName", cashtags="$TSLA $NVDA", + collection_strategy="auto", conversation_id="1234567890", + dedupe_across_targets=True, + dedupe_mode="none", exact_phrase="artificial intelligence", + exclude_original_author=True, + exclude_source="excludeSource", exclude_words="spam", from_user="nasa", + geocode="geocode", hashtags="#AI startups", + has_location=True, + has_media_only=True, + has_website=True, + include_original_post=True, + include_search_terms=True, + include_target_metadata=True, in_reply_to_tweet_id="1234567890", language="en", list_id="1234567890", + location_contains="locationContains", + max_depth=1, + max_followers=0, + max_following=0, + max_id="maxId", + max_items_per_target=1, + max_likes=0, + max_pages_per_target=1, + max_posts=0, + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="example_user", + min_account_age_days=0, + min_bookmarks=0, min_faves=10, + min_followers=0, + min_following=0, + min_posts=0, min_quotes=2, min_replies=3, min_retweets=5, + min_views=0, + native_retweets=True, + near="near", + news=True, + overlap_mode=True, place="96683cc9126741d1", place_country="US", point_radius="-73.99 40.73 25mi", + query_type="Latest", quotes="include", quotes_of_tweet_id="1234567890", + relation_targets=[ + { + "relation": "community_members", + "value": "x", + } + ], replies="include", results_limit=1000, retweets="exclude", retweets_of_tweet_id="1234567890", + safe=True, + scope="all", + search_queries=["string"], search_query="AI trends 2025", since_date=parse_date("2025-01-01"), + since_id="sinceId", + since_time=parse_datetime("2019-12-27T18:11:19.117Z"), + sort="relevance", + source="source", + start_cursor="x", target_community_id="1500000000000000000", + target_community_ids=["string"], target_list_id="1234567890", + target_list_ids=["string"], + targets=["string"], target_space_id="1vOGwMdBqpwGB", target_tweet_id="1234567890", + target_tweet_ids=["string"], target_username="elonmusk", + target_usernames=["string"], to_user="openai", until_date=parse_date("2025-12-31"), + until_time=parse_datetime("2019-12-27T18:11:19.117Z"), url="example.com", + username_contains="usernameContains", verified_only=False, + verified_type="verifiedType", + within="within", + within_time="withinTime", ) assert_matches_type(ExtractionEstimateCostResponse, extraction, path=["response"]) @@ -219,6 +285,37 @@ def test_method_export_results(self, client: XTwitterScraper, respx_mock: MockRo assert cast(Any, extraction.is_closed) is True assert isinstance(extraction, BinaryAPIResponse) + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_method_export_results_with_all_params(self, client: XTwitterScraper, respx_mock: MockRouter) -> None: + respx_mock.get("/extractions/id/export").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + extraction = client.extractions.export_results( + id="id", + format="csv", + has_description=True, + has_location=True, + has_media=True, + lang="lang", + max_followers=0, + max_following=0, + max_posts=0, + min_followers=0, + min_following=0, + min_likes=0, + min_posts=0, + min_replies=0, + min_retweets=0, + min_views=0, + search="search", + since_date=parse_date("2019-12-27"), + until_date=parse_date("2019-12-27"), + verified=True, + ) + assert extraction.is_closed + assert extraction.json() == {"foo": "bar"} + assert cast(Any, extraction.is_closed) is True + assert isinstance(extraction, BinaryAPIResponse) + @parametrize @pytest.mark.respx(base_url=base_url) def test_raw_response_export_results(self, client: XTwitterScraper, respx_mock: MockRouter) -> None: @@ -273,44 +370,107 @@ def test_method_run(self, client: XTwitterScraper) -> None: def test_method_run_with_all_params(self, client: XTwitterScraper) -> None: extraction = client.extractions.run( tool_type="follower_explorer", + dry_run=True, advanced_query="min_faves:100", any_words="ChatGPT AI model", + bio_contains="bioContains", + blue_verified_only=True, bounding_box="-74.1 40.6 -73.9 40.8", + card_name="cardName", cashtags="$TSLA $NVDA", + collection_strategy="auto", conversation_id="1234567890", + dedupe_across_targets=True, + dedupe_mode="none", exact_phrase="artificial intelligence", + exclude_original_author=True, + exclude_source="excludeSource", exclude_words="spam", from_user="nasa", + geocode="geocode", hashtags="#AI startups", + has_location=True, + has_media_only=True, + has_website=True, + include_original_post=True, + include_search_terms=True, + include_target_metadata=True, in_reply_to_tweet_id="1234567890", language="en", list_id="1234567890", + location_contains="locationContains", + max_depth=1, + max_followers=0, + max_following=0, + max_id="maxId", + max_items_per_target=1, + max_likes=0, + max_pages_per_target=1, + max_posts=0, + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="example_user", + min_account_age_days=0, + min_bookmarks=0, min_faves=10, + min_followers=0, + min_following=0, + min_posts=0, min_quotes=2, min_replies=3, min_retweets=5, + min_views=0, + native_retweets=True, + near="near", + news=True, + overlap_mode=True, place="96683cc9126741d1", place_country="US", point_radius="-73.99 40.73 25mi", + query_type="Latest", quotes="include", quotes_of_tweet_id="1234567890", + relation_targets=[ + { + "relation": "community_members", + "value": "x", + } + ], replies="include", results_limit=1000, retweets="exclude", retweets_of_tweet_id="1234567890", + safe=True, + scope="all", + search_queries=["string"], search_query="AI trends 2025", since_date=parse_date("2025-01-01"), + since_id="sinceId", + since_time=parse_datetime("2019-12-27T18:11:19.117Z"), + sort="relevance", + source="source", + start_cursor="x", target_community_id="1500000000000000000", + target_community_ids=["string"], target_list_id="1234567890", + target_list_ids=["string"], + targets=["string"], target_space_id="1vOGwMdBqpwGB", target_tweet_id="1234567890", + target_tweet_ids=["string"], target_username="elonmusk", + target_usernames=["string"], to_user="openai", until_date=parse_date("2025-12-31"), + until_time=parse_datetime("2019-12-27T18:11:19.117Z"), url="example.com", + username_contains="usernameContains", verified_only=False, + verified_type="verifiedType", + within="within", + within_time="withinTime", ) assert_matches_type(ExtractionRunResponse, extraction, path=["response"]) @@ -360,7 +520,11 @@ async def test_method_retrieve_with_all_params(self, async_client: AsyncXTwitter extraction = await async_client.extractions.retrieve( id="id", cursor="cursor", + field_style="source", + include_raw=True, limit=1, + output_mode="compact", + output_preset="nested", ) assert_matches_type(ExtractionRetrieveResponse, extraction, path=["response"]) @@ -452,42 +616,104 @@ async def test_method_estimate_cost_with_all_params(self, async_client: AsyncXTw tool_type="follower_explorer", advanced_query="min_faves:100", any_words="ChatGPT AI model", + bio_contains="bioContains", + blue_verified_only=True, bounding_box="-74.1 40.6 -73.9 40.8", + card_name="cardName", cashtags="$TSLA $NVDA", + collection_strategy="auto", conversation_id="1234567890", + dedupe_across_targets=True, + dedupe_mode="none", exact_phrase="artificial intelligence", + exclude_original_author=True, + exclude_source="excludeSource", exclude_words="spam", from_user="nasa", + geocode="geocode", hashtags="#AI startups", + has_location=True, + has_media_only=True, + has_website=True, + include_original_post=True, + include_search_terms=True, + include_target_metadata=True, in_reply_to_tweet_id="1234567890", language="en", list_id="1234567890", + location_contains="locationContains", + max_depth=1, + max_followers=0, + max_following=0, + max_id="maxId", + max_items_per_target=1, + max_likes=0, + max_pages_per_target=1, + max_posts=0, + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="example_user", + min_account_age_days=0, + min_bookmarks=0, min_faves=10, + min_followers=0, + min_following=0, + min_posts=0, min_quotes=2, min_replies=3, min_retweets=5, + min_views=0, + native_retweets=True, + near="near", + news=True, + overlap_mode=True, place="96683cc9126741d1", place_country="US", point_radius="-73.99 40.73 25mi", + query_type="Latest", quotes="include", quotes_of_tweet_id="1234567890", + relation_targets=[ + { + "relation": "community_members", + "value": "x", + } + ], replies="include", results_limit=1000, retweets="exclude", retweets_of_tweet_id="1234567890", + safe=True, + scope="all", + search_queries=["string"], search_query="AI trends 2025", since_date=parse_date("2025-01-01"), + since_id="sinceId", + since_time=parse_datetime("2019-12-27T18:11:19.117Z"), + sort="relevance", + source="source", + start_cursor="x", target_community_id="1500000000000000000", + target_community_ids=["string"], target_list_id="1234567890", + target_list_ids=["string"], + targets=["string"], target_space_id="1vOGwMdBqpwGB", target_tweet_id="1234567890", + target_tweet_ids=["string"], target_username="elonmusk", + target_usernames=["string"], to_user="openai", until_date=parse_date("2025-12-31"), + until_time=parse_datetime("2019-12-27T18:11:19.117Z"), url="example.com", + username_contains="usernameContains", verified_only=False, + verified_type="verifiedType", + within="within", + within_time="withinTime", ) assert_matches_type(ExtractionEstimateCostResponse, extraction, path=["response"]) @@ -530,6 +756,39 @@ async def test_method_export_results(self, async_client: AsyncXTwitterScraper, r assert cast(Any, extraction.is_closed) is True assert isinstance(extraction, AsyncBinaryAPIResponse) + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_method_export_results_with_all_params( + self, async_client: AsyncXTwitterScraper, respx_mock: MockRouter + ) -> None: + respx_mock.get("/extractions/id/export").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + extraction = await async_client.extractions.export_results( + id="id", + format="csv", + has_description=True, + has_location=True, + has_media=True, + lang="lang", + max_followers=0, + max_following=0, + max_posts=0, + min_followers=0, + min_following=0, + min_likes=0, + min_posts=0, + min_replies=0, + min_retweets=0, + min_views=0, + search="search", + since_date=parse_date("2019-12-27"), + until_date=parse_date("2019-12-27"), + verified=True, + ) + assert extraction.is_closed + assert await extraction.json() == {"foo": "bar"} + assert cast(Any, extraction.is_closed) is True + assert isinstance(extraction, AsyncBinaryAPIResponse) + @parametrize @pytest.mark.respx(base_url=base_url) async def test_raw_response_export_results( @@ -588,44 +847,107 @@ async def test_method_run(self, async_client: AsyncXTwitterScraper) -> None: async def test_method_run_with_all_params(self, async_client: AsyncXTwitterScraper) -> None: extraction = await async_client.extractions.run( tool_type="follower_explorer", + dry_run=True, advanced_query="min_faves:100", any_words="ChatGPT AI model", + bio_contains="bioContains", + blue_verified_only=True, bounding_box="-74.1 40.6 -73.9 40.8", + card_name="cardName", cashtags="$TSLA $NVDA", + collection_strategy="auto", conversation_id="1234567890", + dedupe_across_targets=True, + dedupe_mode="none", exact_phrase="artificial intelligence", + exclude_original_author=True, + exclude_source="excludeSource", exclude_words="spam", from_user="nasa", + geocode="geocode", hashtags="#AI startups", + has_location=True, + has_media_only=True, + has_website=True, + include_original_post=True, + include_search_terms=True, + include_target_metadata=True, in_reply_to_tweet_id="1234567890", language="en", list_id="1234567890", + location_contains="locationContains", + max_depth=1, + max_followers=0, + max_following=0, + max_id="maxId", + max_items_per_target=1, + max_likes=0, + max_pages_per_target=1, + max_posts=0, + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="example_user", + min_account_age_days=0, + min_bookmarks=0, min_faves=10, + min_followers=0, + min_following=0, + min_posts=0, min_quotes=2, min_replies=3, min_retweets=5, + min_views=0, + native_retweets=True, + near="near", + news=True, + overlap_mode=True, place="96683cc9126741d1", place_country="US", point_radius="-73.99 40.73 25mi", + query_type="Latest", quotes="include", quotes_of_tweet_id="1234567890", + relation_targets=[ + { + "relation": "community_members", + "value": "x", + } + ], replies="include", results_limit=1000, retweets="exclude", retweets_of_tweet_id="1234567890", + safe=True, + scope="all", + search_queries=["string"], search_query="AI trends 2025", since_date=parse_date("2025-01-01"), + since_id="sinceId", + since_time=parse_datetime("2019-12-27T18:11:19.117Z"), + sort="relevance", + source="source", + start_cursor="x", target_community_id="1500000000000000000", + target_community_ids=["string"], target_list_id="1234567890", + target_list_ids=["string"], + targets=["string"], target_space_id="1vOGwMdBqpwGB", target_tweet_id="1234567890", + target_tweet_ids=["string"], target_username="elonmusk", + target_usernames=["string"], to_user="openai", until_date=parse_date("2025-12-31"), + until_time=parse_datetime("2019-12-27T18:11:19.117Z"), url="example.com", + username_contains="usernameContains", verified_only=False, + verified_type="verifiedType", + within="within", + within_time="withinTime", ) assert_matches_type(ExtractionRunResponse, extraction, path=["response"]) diff --git a/tests/api_resources/x/test_communities.py b/tests/api_resources/x/test_communities.py index 28d92b3..a556d77 100644 --- a/tests/api_resources/x/test_communities.py +++ b/tests/api_resources/x/test_communities.py @@ -186,8 +186,22 @@ def test_method_retrieve_members(self, client: XTwitterScraper) -> None: def test_method_retrieve_members_with_all_params(self, client: XTwitterScraper) -> None: community = client.x.communities.retrieve_members( id="id", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, community, path=["response"]) @@ -238,7 +252,21 @@ def test_method_retrieve_moderators(self, client: XTwitterScraper) -> None: def test_method_retrieve_moderators_with_all_params(self, client: XTwitterScraper) -> None: community = client.x.communities.retrieve_moderators( id="id", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, community, path=["response"]) @@ -491,8 +519,22 @@ async def test_method_retrieve_members(self, async_client: AsyncXTwitterScraper) async def test_method_retrieve_members_with_all_params(self, async_client: AsyncXTwitterScraper) -> None: community = await async_client.x.communities.retrieve_members( id="id", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, community, path=["response"]) @@ -543,7 +585,21 @@ async def test_method_retrieve_moderators(self, async_client: AsyncXTwitterScrap async def test_method_retrieve_moderators_with_all_params(self, async_client: AsyncXTwitterScraper) -> None: community = await async_client.x.communities.retrieve_moderators( id="id", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, community, path=["response"]) diff --git a/tests/api_resources/x/test_lists.py b/tests/api_resources/x/test_lists.py index b501e95..a6a3206 100644 --- a/tests/api_resources/x/test_lists.py +++ b/tests/api_resources/x/test_lists.py @@ -34,8 +34,22 @@ def test_method_retrieve_followers(self, client: XTwitterScraper) -> None: def test_method_retrieve_followers_with_all_params(self, client: XTwitterScraper) -> None: list_ = client.x.lists.retrieve_followers( id="id", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, list_, path=["response"]) @@ -86,8 +100,22 @@ def test_method_retrieve_members(self, client: XTwitterScraper) -> None: def test_method_retrieve_members_with_all_params(self, client: XTwitterScraper) -> None: list_ = client.x.lists.retrieve_members( id="id", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, list_, path=["response"]) @@ -199,8 +227,22 @@ async def test_method_retrieve_followers(self, async_client: AsyncXTwitterScrape async def test_method_retrieve_followers_with_all_params(self, async_client: AsyncXTwitterScraper) -> None: list_ = await async_client.x.lists.retrieve_followers( id="id", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, list_, path=["response"]) @@ -251,8 +293,22 @@ async def test_method_retrieve_members(self, async_client: AsyncXTwitterScraper) async def test_method_retrieve_members_with_all_params(self, async_client: AsyncXTwitterScraper) -> None: list_ = await async_client.x.lists.retrieve_members( id="id", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, list_, path=["response"]) diff --git a/tests/api_resources/x/test_tweets.py b/tests/api_resources/x/test_tweets.py index 6b447d9..7ce7b7c 100644 --- a/tests/api_resources/x/test_tweets.py +++ b/tests/api_resources/x/test_tweets.py @@ -17,6 +17,7 @@ from x_twitter_scraper.types.x import ( TweetCreateResponse, TweetDeleteResponse, + TweetSearchResponse, TweetRetrieveResponse, TweetGetRepliesResponse, ) @@ -218,8 +219,22 @@ def test_method_get_favoriters(self, client: XTwitterScraper) -> None: def test_method_get_favoriters_with_all_params(self, client: XTwitterScraper) -> None: tweet = client.x.tweets.get_favoriters( id="id", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, tweet, path=["response"]) @@ -271,35 +286,54 @@ def test_method_get_quotes_with_all_params(self, client: XTwitterScraper) -> Non tweet = client.x.tweets.get_quotes( id="id", any_words="anyWords", + blue_verified_only=True, + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", include_replies=True, in_reply_to_tweet_id="inReplyToTweetId", language="language", + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, + min_views=0, + native_retweets=True, + near="near", + news=True, page_size=1, quotes="include", quotes_of_tweet_id="quotesOfTweetId", replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, since_date=parse_date("2019-12-27"), + since_id="sinceId", since_time="sinceTime", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), until_time="untilTime", url="url", verified_only=True, + within="within", + within_time="withinTime", ) assert_matches_type(PaginatedTweets, tweet, path=["response"]) @@ -351,36 +385,61 @@ def test_method_get_replies_with_all_params(self, client: XTwitterScraper) -> No tweet = client.x.tweets.get_replies( id="id", any_words="anyWords", + blue_verified_only=True, + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_original_author=True, + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", + has_media_only=True, + include_original_post=True, in_reply_to_tweet_id="inReplyToTweetId", language="language", limit=1, + max_depth=1, + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, - mode="complete", + min_views=0, + mode="standard", + native_retweets=True, + near="near", + news=True, page_size=1, quotes="include", quotes_of_tweet_id="quotesOfTweetId", replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, + scope="all", since_date=parse_date("2019-12-27"), + since_id="sinceId", since_time="sinceTime", + sort="relevance", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), until_time="untilTime", url="url", verified_only=True, + within="within", + within_time="withinTime", ) assert_matches_type(TweetGetRepliesResponse, tweet, path=["response"]) @@ -431,8 +490,22 @@ def test_method_get_retweeters(self, client: XTwitterScraper) -> None: def test_method_get_retweeters_with_all_params(self, client: XTwitterScraper) -> None: tweet = client.x.tweets.get_retweeters( id="id", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, tweet, path=["response"]) @@ -528,7 +601,7 @@ def test_method_search(self, client: XTwitterScraper) -> None: tweet = client.x.tweets.search( q="q", ) - assert_matches_type(PaginatedTweets, tweet, path=["response"]) + assert_matches_type(TweetSearchResponse, tweet, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -537,24 +610,39 @@ def test_method_search_with_all_params(self, client: XTwitterScraper) -> None: q="q", advanced_query="advancedQuery", any_words="anyWords", + blue_verified_only=True, bounding_box="boundingBox", + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", in_reply_to_tweet_id="inReplyToTweetId", language="language", - limit=200, + limit=1, list_id="listId", + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, + min_views=0, + mode="standard", + native_retweets=True, + near="near", + news=True, place="place", place_country="placeCountry", point_radius="pointRadius", @@ -564,15 +652,20 @@ def test_method_search_with_all_params(self, client: XTwitterScraper) -> None: replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, since_date=parse_date("2019-12-27"), + since_id="sinceId", since_time="sinceTime", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), until_time="untilTime", url="url", verified_only=True, + within="within", + within_time="withinTime", ) - assert_matches_type(PaginatedTweets, tweet, path=["response"]) + assert_matches_type(TweetSearchResponse, tweet, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -584,7 +677,7 @@ def test_raw_response_search(self, client: XTwitterScraper) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" tweet = response.parse() - assert_matches_type(PaginatedTweets, tweet, path=["response"]) + assert_matches_type(TweetSearchResponse, tweet, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -596,7 +689,7 @@ def test_streaming_response_search(self, client: XTwitterScraper) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" tweet = response.parse() - assert_matches_type(PaginatedTweets, tweet, path=["response"]) + assert_matches_type(TweetSearchResponse, tweet, path=["response"]) assert cast(Any, response.is_closed) is True @@ -796,8 +889,22 @@ async def test_method_get_favoriters(self, async_client: AsyncXTwitterScraper) - async def test_method_get_favoriters_with_all_params(self, async_client: AsyncXTwitterScraper) -> None: tweet = await async_client.x.tweets.get_favoriters( id="id", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, tweet, path=["response"]) @@ -849,35 +956,54 @@ async def test_method_get_quotes_with_all_params(self, async_client: AsyncXTwitt tweet = await async_client.x.tweets.get_quotes( id="id", any_words="anyWords", + blue_verified_only=True, + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", include_replies=True, in_reply_to_tweet_id="inReplyToTweetId", language="language", + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, + min_views=0, + native_retweets=True, + near="near", + news=True, page_size=1, quotes="include", quotes_of_tweet_id="quotesOfTweetId", replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, since_date=parse_date("2019-12-27"), + since_id="sinceId", since_time="sinceTime", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), until_time="untilTime", url="url", verified_only=True, + within="within", + within_time="withinTime", ) assert_matches_type(PaginatedTweets, tweet, path=["response"]) @@ -929,36 +1055,61 @@ async def test_method_get_replies_with_all_params(self, async_client: AsyncXTwit tweet = await async_client.x.tweets.get_replies( id="id", any_words="anyWords", + blue_verified_only=True, + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_original_author=True, + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", + has_media_only=True, + include_original_post=True, in_reply_to_tweet_id="inReplyToTweetId", language="language", limit=1, + max_depth=1, + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, - mode="complete", + min_views=0, + mode="standard", + native_retweets=True, + near="near", + news=True, page_size=1, quotes="include", quotes_of_tweet_id="quotesOfTweetId", replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, + scope="all", since_date=parse_date("2019-12-27"), + since_id="sinceId", since_time="sinceTime", + sort="relevance", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), until_time="untilTime", url="url", verified_only=True, + within="within", + within_time="withinTime", ) assert_matches_type(TweetGetRepliesResponse, tweet, path=["response"]) @@ -1009,8 +1160,22 @@ async def test_method_get_retweeters(self, async_client: AsyncXTwitterScraper) - async def test_method_get_retweeters_with_all_params(self, async_client: AsyncXTwitterScraper) -> None: tweet = await async_client.x.tweets.get_retweeters( id="id", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, tweet, path=["response"]) @@ -1106,7 +1271,7 @@ async def test_method_search(self, async_client: AsyncXTwitterScraper) -> None: tweet = await async_client.x.tweets.search( q="q", ) - assert_matches_type(PaginatedTweets, tweet, path=["response"]) + assert_matches_type(TweetSearchResponse, tweet, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1115,24 +1280,39 @@ async def test_method_search_with_all_params(self, async_client: AsyncXTwitterSc q="q", advanced_query="advancedQuery", any_words="anyWords", + blue_verified_only=True, bounding_box="boundingBox", + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", in_reply_to_tweet_id="inReplyToTweetId", language="language", - limit=200, + limit=1, list_id="listId", + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, + min_views=0, + mode="standard", + native_retweets=True, + near="near", + news=True, place="place", place_country="placeCountry", point_radius="pointRadius", @@ -1142,15 +1322,20 @@ async def test_method_search_with_all_params(self, async_client: AsyncXTwitterSc replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, since_date=parse_date("2019-12-27"), + since_id="sinceId", since_time="sinceTime", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), until_time="untilTime", url="url", verified_only=True, + within="within", + within_time="withinTime", ) - assert_matches_type(PaginatedTweets, tweet, path=["response"]) + assert_matches_type(TweetSearchResponse, tweet, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1162,7 +1347,7 @@ async def test_raw_response_search(self, async_client: AsyncXTwitterScraper) -> assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" tweet = await response.parse() - assert_matches_type(PaginatedTweets, tweet, path=["response"]) + assert_matches_type(TweetSearchResponse, tweet, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1174,6 +1359,6 @@ async def test_streaming_response_search(self, async_client: AsyncXTwitterScrape assert response.http_request.headers.get("X-Stainless-Lang") == "python" tweet = await response.parse() - assert_matches_type(PaginatedTweets, tweet, path=["response"]) + assert_matches_type(TweetSearchResponse, tweet, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/x/test_users.py b/tests/api_resources/x/test_users.py index 69db1d2..f663bb4 100644 --- a/tests/api_resources/x/test_users.py +++ b/tests/api_resources/x/test_users.py @@ -17,6 +17,9 @@ from x_twitter_scraper.types.x import ( UserRetrieveBatchResponse, UserRemoveFollowerResponse, + UserRetrieveFollowersResponse, + UserRetrieveFollowingResponse, + UserRetrieveVerifiedFollowersResponse, ) from x_twitter_scraper.types.shared import UserProfile, PaginatedUsers, PaginatedTweets @@ -158,7 +161,7 @@ def test_method_retrieve_followers(self, client: XTwitterScraper) -> None: user = client.x.users.retrieve_followers( id="id", ) - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowersResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -166,11 +169,26 @@ def test_method_retrieve_followers_with_all_params(self, client: XTwitterScraper user = client.x.users.retrieve_followers( id="id", after="after", + bio_contains="bioContains", cursor="cursor", - limit=0, + has_location=True, + has_website=True, + limit=1, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, + mode="standard", page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowersResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -182,7 +200,7 @@ def test_raw_response_retrieve_followers(self, client: XTwitterScraper) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" user = response.parse() - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowersResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -194,7 +212,7 @@ def test_streaming_response_retrieve_followers(self, client: XTwitterScraper) -> assert response.http_request.headers.get("X-Stainless-Lang") == "python" user = response.parse() - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowersResponse, user, path=["response"]) assert cast(Any, response.is_closed) is True @@ -219,8 +237,22 @@ def test_method_retrieve_followers_you_know(self, client: XTwitterScraper) -> No def test_method_retrieve_followers_you_know_with_all_params(self, client: XTwitterScraper) -> None: user = client.x.users.retrieve_followers_you_know( id="id", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, user, path=["response"]) @@ -264,7 +296,7 @@ def test_method_retrieve_following(self, client: XTwitterScraper) -> None: user = client.x.users.retrieve_following( id="id", ) - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowingResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -272,11 +304,26 @@ def test_method_retrieve_following_with_all_params(self, client: XTwitterScraper user = client.x.users.retrieve_following( id="id", after="after", + bio_contains="bioContains", cursor="cursor", - limit=0, + has_location=True, + has_website=True, + limit=1, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, + mode="standard", page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowingResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -288,7 +335,7 @@ def test_raw_response_retrieve_following(self, client: XTwitterScraper) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" user = response.parse() - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowingResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -300,7 +347,7 @@ def test_streaming_response_retrieve_following(self, client: XTwitterScraper) -> assert response.http_request.headers.get("X-Stainless-Lang") == "python" user = response.parse() - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowingResponse, user, path=["response"]) assert cast(Any, response.is_closed) is True @@ -326,32 +373,51 @@ def test_method_retrieve_likes_with_all_params(self, client: XTwitterScraper) -> user = client.x.users.retrieve_likes( id="id", any_words="anyWords", + blue_verified_only=True, + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", in_reply_to_tweet_id="inReplyToTweetId", language="language", + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, + min_views=0, + native_retweets=True, + near="near", + news=True, page_size=1, quotes="include", quotes_of_tweet_id="quotesOfTweetId", replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, since_date=parse_date("2019-12-27"), + since_id="sinceId", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), url="url", verified_only=True, + within="within", + within_time="withinTime", ) assert_matches_type(PaginatedTweets, user, path=["response"]) @@ -403,32 +469,51 @@ def test_method_retrieve_media_with_all_params(self, client: XTwitterScraper) -> user = client.x.users.retrieve_media( id="id", any_words="anyWords", + blue_verified_only=True, + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", in_reply_to_tweet_id="inReplyToTweetId", language="language", + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, + min_views=0, + native_retweets=True, + near="near", + news=True, page_size=1, quotes="include", quotes_of_tweet_id="quotesOfTweetId", replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, since_date=parse_date("2019-12-27"), + since_id="sinceId", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), url="url", verified_only=True, + within="within", + within_time="withinTime", ) assert_matches_type(PaginatedTweets, user, path=["response"]) @@ -480,34 +565,53 @@ def test_method_retrieve_mentions_with_all_params(self, client: XTwitterScraper) user = client.x.users.retrieve_mentions( id="id", any_words="anyWords", + blue_verified_only=True, + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", in_reply_to_tweet_id="inReplyToTweetId", language="language", + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, + min_views=0, + native_retweets=True, + near="near", + news=True, page_size=1, quotes="include", quotes_of_tweet_id="quotesOfTweetId", replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, since_date=parse_date("2019-12-27"), + since_id="sinceId", since_time="sinceTime", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), until_time="untilTime", url="url", verified_only=True, + within="within", + within_time="withinTime", ) assert_matches_type(PaginatedTweets, user, path=["response"]) @@ -559,33 +663,52 @@ def test_method_retrieve_replies_with_all_params(self, client: XTwitterScraper) user = client.x.users.retrieve_replies( id="id", any_words="anyWords", + blue_verified_only=True, + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", include_parent_tweet=True, in_reply_to_tweet_id="inReplyToTweetId", language="language", + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, + min_views=0, + native_retweets=True, + near="near", + news=True, page_size=1, quotes="include", quotes_of_tweet_id="quotesOfTweetId", replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, since_date=parse_date("2019-12-27"), + since_id="sinceId", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), url="url", verified_only=True, + within="within", + within_time="withinTime", ) assert_matches_type(PaginatedTweets, user, path=["response"]) @@ -636,7 +759,21 @@ def test_method_retrieve_search(self, client: XTwitterScraper) -> None: def test_method_retrieve_search_with_all_params(self, client: XTwitterScraper) -> None: user = client.x.users.retrieve_search( q="q", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, user, path=["response"]) @@ -680,34 +817,53 @@ def test_method_retrieve_tweets_with_all_params(self, client: XTwitterScraper) - user = client.x.users.retrieve_tweets( id="id", any_words="anyWords", + blue_verified_only=True, + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", include_parent_tweet=True, include_replies=True, in_reply_to_tweet_id="inReplyToTweetId", language="language", + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, + min_views=0, + native_retweets=True, + near="near", + news=True, page_size=1, quotes="include", quotes_of_tweet_id="quotesOfTweetId", replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, since_date=parse_date("2019-12-27"), + since_id="sinceId", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), url="url", verified_only=True, + within="within", + within_time="withinTime", ) assert_matches_type(PaginatedTweets, user, path=["response"]) @@ -751,17 +907,34 @@ def test_method_retrieve_verified_followers(self, client: XTwitterScraper) -> No user = client.x.users.retrieve_verified_followers( id="id", ) - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveVerifiedFollowersResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_retrieve_verified_followers_with_all_params(self, client: XTwitterScraper) -> None: user = client.x.users.retrieve_verified_followers( id="id", + after="after", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + limit=1, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, + mode="standard", page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveVerifiedFollowersResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -773,7 +946,7 @@ def test_raw_response_retrieve_verified_followers(self, client: XTwitterScraper) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" user = response.parse() - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveVerifiedFollowersResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -785,7 +958,7 @@ def test_streaming_response_retrieve_verified_followers(self, client: XTwitterSc assert response.http_request.headers.get("X-Stainless-Lang") == "python" user = response.parse() - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveVerifiedFollowersResponse, user, path=["response"]) assert cast(Any, response.is_closed) is True @@ -935,7 +1108,7 @@ async def test_method_retrieve_followers(self, async_client: AsyncXTwitterScrape user = await async_client.x.users.retrieve_followers( id="id", ) - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowersResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -943,11 +1116,26 @@ async def test_method_retrieve_followers_with_all_params(self, async_client: Asy user = await async_client.x.users.retrieve_followers( id="id", after="after", + bio_contains="bioContains", cursor="cursor", - limit=0, + has_location=True, + has_website=True, + limit=1, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, + mode="standard", page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowersResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -959,7 +1147,7 @@ async def test_raw_response_retrieve_followers(self, async_client: AsyncXTwitter assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" user = await response.parse() - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowersResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -971,7 +1159,7 @@ async def test_streaming_response_retrieve_followers(self, async_client: AsyncXT assert response.http_request.headers.get("X-Stainless-Lang") == "python" user = await response.parse() - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowersResponse, user, path=["response"]) assert cast(Any, response.is_closed) is True @@ -996,8 +1184,22 @@ async def test_method_retrieve_followers_you_know(self, async_client: AsyncXTwit async def test_method_retrieve_followers_you_know_with_all_params(self, async_client: AsyncXTwitterScraper) -> None: user = await async_client.x.users.retrieve_followers_you_know( id="id", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, user, path=["response"]) @@ -1041,7 +1243,7 @@ async def test_method_retrieve_following(self, async_client: AsyncXTwitterScrape user = await async_client.x.users.retrieve_following( id="id", ) - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowingResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1049,11 +1251,26 @@ async def test_method_retrieve_following_with_all_params(self, async_client: Asy user = await async_client.x.users.retrieve_following( id="id", after="after", + bio_contains="bioContains", cursor="cursor", - limit=0, + has_location=True, + has_website=True, + limit=1, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, + mode="standard", page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowingResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1065,7 +1282,7 @@ async def test_raw_response_retrieve_following(self, async_client: AsyncXTwitter assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" user = await response.parse() - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowingResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1077,7 +1294,7 @@ async def test_streaming_response_retrieve_following(self, async_client: AsyncXT assert response.http_request.headers.get("X-Stainless-Lang") == "python" user = await response.parse() - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveFollowingResponse, user, path=["response"]) assert cast(Any, response.is_closed) is True @@ -1103,32 +1320,51 @@ async def test_method_retrieve_likes_with_all_params(self, async_client: AsyncXT user = await async_client.x.users.retrieve_likes( id="id", any_words="anyWords", + blue_verified_only=True, + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", in_reply_to_tweet_id="inReplyToTweetId", language="language", + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, + min_views=0, + native_retweets=True, + near="near", + news=True, page_size=1, quotes="include", quotes_of_tweet_id="quotesOfTweetId", replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, since_date=parse_date("2019-12-27"), + since_id="sinceId", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), url="url", verified_only=True, + within="within", + within_time="withinTime", ) assert_matches_type(PaginatedTweets, user, path=["response"]) @@ -1180,32 +1416,51 @@ async def test_method_retrieve_media_with_all_params(self, async_client: AsyncXT user = await async_client.x.users.retrieve_media( id="id", any_words="anyWords", + blue_verified_only=True, + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", in_reply_to_tweet_id="inReplyToTweetId", language="language", + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, + min_views=0, + native_retweets=True, + near="near", + news=True, page_size=1, quotes="include", quotes_of_tweet_id="quotesOfTweetId", replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, since_date=parse_date("2019-12-27"), + since_id="sinceId", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), url="url", verified_only=True, + within="within", + within_time="withinTime", ) assert_matches_type(PaginatedTweets, user, path=["response"]) @@ -1257,34 +1512,53 @@ async def test_method_retrieve_mentions_with_all_params(self, async_client: Asyn user = await async_client.x.users.retrieve_mentions( id="id", any_words="anyWords", + blue_verified_only=True, + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", in_reply_to_tweet_id="inReplyToTweetId", language="language", + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, + min_views=0, + native_retweets=True, + near="near", + news=True, page_size=1, quotes="include", quotes_of_tweet_id="quotesOfTweetId", replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, since_date=parse_date("2019-12-27"), + since_id="sinceId", since_time="sinceTime", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), until_time="untilTime", url="url", verified_only=True, + within="within", + within_time="withinTime", ) assert_matches_type(PaginatedTweets, user, path=["response"]) @@ -1336,33 +1610,52 @@ async def test_method_retrieve_replies_with_all_params(self, async_client: Async user = await async_client.x.users.retrieve_replies( id="id", any_words="anyWords", + blue_verified_only=True, + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", include_parent_tweet=True, in_reply_to_tweet_id="inReplyToTweetId", language="language", + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, + min_views=0, + native_retweets=True, + near="near", + news=True, page_size=1, quotes="include", quotes_of_tweet_id="quotesOfTweetId", replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, since_date=parse_date("2019-12-27"), + since_id="sinceId", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), url="url", verified_only=True, + within="within", + within_time="withinTime", ) assert_matches_type(PaginatedTweets, user, path=["response"]) @@ -1413,7 +1706,21 @@ async def test_method_retrieve_search(self, async_client: AsyncXTwitterScraper) async def test_method_retrieve_search_with_all_params(self, async_client: AsyncXTwitterScraper) -> None: user = await async_client.x.users.retrieve_search( q="q", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) assert_matches_type(PaginatedUsers, user, path=["response"]) @@ -1457,34 +1764,53 @@ async def test_method_retrieve_tweets_with_all_params(self, async_client: AsyncX user = await async_client.x.users.retrieve_tweets( id="id", any_words="anyWords", + blue_verified_only=True, + card_name="cardName", cashtags="cashtags", conversation_id="conversationId", cursor="cursor", exact_phrase="exactPhrase", + exclude_source="excludeSource", exclude_words="excludeWords", from_user="fromUser", + geocode="geocode", hashtags="hashtags", include_parent_tweet=True, include_replies=True, in_reply_to_tweet_id="inReplyToTweetId", language="language", + max_faves=0, + max_id="maxId", + max_quotes=0, + max_replies=0, + max_retweets=0, media_type="images", mentioning="mentioning", + min_bookmarks=0, min_faves=0, min_quotes=0, min_replies=0, min_retweets=0, + min_views=0, + native_retweets=True, + near="near", + news=True, page_size=1, quotes="include", quotes_of_tweet_id="quotesOfTweetId", replies="include", retweets="include", retweets_of_tweet_id="retweetsOfTweetId", + safe=True, since_date=parse_date("2019-12-27"), + since_id="sinceId", + source="source", to_user="toUser", until_date=parse_date("2019-12-27"), url="url", verified_only=True, + within="within", + within_time="withinTime", ) assert_matches_type(PaginatedTweets, user, path=["response"]) @@ -1528,17 +1854,34 @@ async def test_method_retrieve_verified_followers(self, async_client: AsyncXTwit user = await async_client.x.users.retrieve_verified_followers( id="id", ) - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveVerifiedFollowersResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_retrieve_verified_followers_with_all_params(self, async_client: AsyncXTwitterScraper) -> None: user = await async_client.x.users.retrieve_verified_followers( id="id", + after="after", + bio_contains="bioContains", cursor="cursor", + has_location=True, + has_website=True, + limit=1, + location_contains="locationContains", + max_followers=0, + max_following=0, + max_statuses=0, + min_account_age_days=0, + min_followers=0, + min_following=0, + min_statuses=0, + mode="standard", page_size=20, + username_contains="usernameContains", + verified_only=True, + verified_type="verifiedType", ) - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveVerifiedFollowersResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1550,7 +1893,7 @@ async def test_raw_response_retrieve_verified_followers(self, async_client: Asyn assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" user = await response.parse() - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveVerifiedFollowersResponse, user, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1562,7 +1905,7 @@ async def test_streaming_response_retrieve_verified_followers(self, async_client assert response.http_request.headers.get("X-Stainless-Lang") == "python" user = await response.parse() - assert_matches_type(PaginatedUsers, user, path=["response"]) + assert_matches_type(UserRetrieveVerifiedFollowersResponse, user, path=["response"]) assert cast(Any, response.is_closed) is True From 99d4b97651b4e2d753f0ff33ecb912859e60d0da Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 21:01:55 +0000 Subject: [PATCH 2/3] release: 0.9.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 8 ++++++++ pyproject.toml | 2 +- src/x_twitter_scraper/_version.py | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 02f17d9..76d5538 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.8.1" + ".": "0.9.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 27ee6c4..00b3280 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.9.0 (2026-08-11) + +Full Changelog: [v0.8.1...v0.9.0](https://github.com/Xquik-dev/x-twitter-scraper-python/compare/v0.8.1...v0.9.0) + +### Features + +* **api:** api update ([6001ecb](https://github.com/Xquik-dev/x-twitter-scraper-python/commit/6001ecbc6504d11d83fbebe0a3cffd83713e71bd)) + ## 0.8.1 (2026-08-11) Full Changelog: [v0.8.0...v0.8.1](https://github.com/Xquik-dev/x-twitter-scraper-python/compare/v0.8.0...v0.8.1) diff --git a/pyproject.toml b/pyproject.toml index 05cf4a5..84d9b45 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "x_twitter_scraper" -version = "0.8.1" +version = "0.9.0" description = "Python library for the Xquik API. Not affiliated with X Corp." dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/x_twitter_scraper/_version.py b/src/x_twitter_scraper/_version.py index a286438..cf9d3c1 100644 --- a/src/x_twitter_scraper/_version.py +++ b/src/x_twitter_scraper/_version.py @@ -5,4 +5,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "x_twitter_scraper" -__version__ = "0.8.1" # x-release-please-version +__version__ = "0.9.0" # x-release-please-version From 79bc3d148c17bf0755219f02590313f30aac03c7 Mon Sep 17 00:00:00 2001 From: kriptoburak Date: Wed, 12 Aug 2026 00:16:11 +0300 Subject: [PATCH 3/3] fix: load search coverage responses --- requirements-dev.lock | 4 ++-- scripts/bootstrap | 10 +++------- src/x_twitter_scraper/types/x/tweet_search_response.py | 7 ++++--- uv.lock | 4 ++-- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index 1a87765..e1fa269 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -17,7 +17,7 @@ certifi==2026.6.17 # httpx colorama==0.4.6 ; sys_platform == 'win32' # via pytest -coverage==7.15.2 +coverage==7.15.3 dirty-equals==0.11 distro==1.9.0 # via x-twitter-scraper @@ -76,7 +76,7 @@ pytest-asyncio==1.4.0 pytest-xdist==3.8.0 respx==0.23.1 rich==15.0.0 -ruff==0.15.22 +ruff==0.16.1 sniffio==1.3.1 # via x-twitter-scraper time-machine==3.2.0 diff --git a/scripts/bootstrap b/scripts/bootstrap index 3f5de42..a50c91f 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -12,13 +12,9 @@ if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "${SKIP_BREW:-}" != "1 brew bundle check >/dev/null 2>&1 || { echo -n "==> Install Homebrew dependencies? (y/N): " read -r response - case "$response" in - [yY][eE][sS]|[yY]) - brew bundle - ;; - *) - ;; - esac + if [[ "$response" =~ ^[Yy]([Ee][Ss])?$ ]]; then + brew bundle + fi echo } fi diff --git a/src/x_twitter_scraper/types/x/tweet_search_response.py b/src/x_twitter_scraper/types/x/tweet_search_response.py index c3e4f1d..9811695 100644 --- a/src/x_twitter_scraper/types/x/tweet_search_response.py +++ b/src/x_twitter_scraper/types/x/tweet_search_response.py @@ -9,6 +9,7 @@ from pydantic import Field as FieldInfo from ..._models import BaseModel +from ..shared.search_tweet import SearchTweet from ..shared.paginated_tweets import PaginatedTweets __all__ = [ @@ -89,6 +90,8 @@ class TweetSearchCoverageResponse(PaginatedTweets): No-mode search, user Tweet, user reply, and direct reply reads use automatic coverage. Shape, filters, aliases, and billing stay compatible. Unprefixed cursors remain legacy. Follow next_cursor while has_next_page is true. An empty filtered page can still have has_next_page true. """ + tweets: List[SearchTweet] + diagnostic: TweetSearchCoverageResponseDiagnostic """Coverage evidence across parallel search strategies.""" @@ -97,6 +100,4 @@ class TweetSearchCoverageResponse(PaginatedTweets): next_cursor: Optional[Literal[""]] = None # type: ignore -TweetSearchResponse: TypeAlias = Union["PaginatedTweets", TweetSearchCoverageResponse] - -from ..shared.paginated_tweets import PaginatedTweets +TweetSearchResponse: TypeAlias = Union[PaginatedTweets, TweetSearchCoverageResponse] diff --git a/uv.lock b/uv.lock index b5eaaf3..38a4afe 100644 --- a/uv.lock +++ b/uv.lock @@ -16,7 +16,7 @@ conflicts = [[ ]] [options] -exclude-newer = "2026-08-04T14:49:36.499926Z" +exclude-newer = "2026-08-04T21:08:05.009269Z" exclude-newer-span = "P7D" [[package]] @@ -1571,7 +1571,7 @@ wheels = [ [[package]] name = "x-twitter-scraper" -version = "0.8.1" +version = "0.9.0" source = { editable = "." } dependencies = [ { name = "anyio" },