1
Fork 0
mirror of https://github.com/thegeneralist01/twitter-openapi synced 2026-01-11 07:30:37 +01:00

Merge branch 'dev'

Signed-off-by: ふぁ <yuki@yuki0311.com>
This commit is contained in:
ふぁ 2024-09-29 23:18:51 +09:00
commit fb626cc2ff
No known key found for this signature in database
GPG key ID: 83A8A5E74872A8AA
23 changed files with 1707 additions and 1352 deletions

3
.gitignore vendored
View file

@ -3,4 +3,5 @@ __pycache__/
cookie.json
*_generated
*.jar
cache/
cache/
tools/input.js

17
.vscode/settings.json vendored
View file

@ -6,14 +6,23 @@
"yaml.schemas": {
"https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.0/schema.json": "src/**/*.yaml"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[yaml]": {
"editor.defaultFormatter": "redhat.vscode-yaml"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
// "python.analysis.typeCheckingMode": "basic",
"[python]": {
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit",
"source.fixAll": "explicit",
},
"source.fixAll": "explicit"
}
}
}
}

7
.vscode/tasks.json vendored
View file

@ -16,7 +16,6 @@
"command": [
".venv/Scripts/activate;",
"python tools/build.py;",
"scoop reset temurin11-jdk;",
"java -jar openapi-generator-cli.jar generate -c test/python/openapi-generator-config.yaml -g python;",
"python -m pip install ./python_generated;"
]
@ -32,16 +31,16 @@
"command": [
"python3 -m venv .venv;",
".venv/bin/python3 -m pip install -r requirements.txt;",
"wget https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/7.4.0/openapi-generator-cli-7.4.0.jar -O openapi-generator-cli.jar;"
"wget https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/7.8.0/openapi-generator-cli-7.8.0.jar -O openapi-generator-cli.jar;"
]
},
"windows": {
"command": [
"python -m venv .venv;",
".venv/Scripts/python -m pip install -r requirements.txt;",
"Invoke-WebRequest https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/7.4.0/openapi-generator-cli-7.4.0.jar -OutFile openapi-generator-cli.jar;"
"Invoke-WebRequest https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/7.8.0/openapi-generator-cli-7.8.0.jar -OutFile openapi-generator-cli.jar;"
]
}
}
]
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,31 @@
{
"errors": [
{
"message": "_Missing: No status found with that ID.",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": ["threaded_conversation_with_injections_v2"],
"extensions": {
"name": "GenericError",
"source": "Server",
"code": 144,
"kind": "NonFatal",
"tracing": {
"trace_id": "e6de8b2b694ae128"
}
},
"code": 144,
"kind": "NonFatal",
"name": "GenericError",
"source": "Server",
"tracing": {
"trace_id": "e6de8b2b694ae128"
}
}
],
"data": {}
}

Binary file not shown.

View file

@ -11,7 +11,7 @@ paths:
required: true
schema:
type: string
default: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
default: "Not Implemented"
description: "UserAgent, some APIs may be rejected if changed."
- name: authorization
in: header
@ -118,8 +118,8 @@ paths:
required: true
schema:
type: string
default: "https://twitter.com/home"
description: "https://twitter.com/home"
default: "https://x.com/home"
description: "https://x.com/home"
- name: Priority
in: header
required: true
@ -135,7 +135,7 @@ paths:
components:
securitySchemes:
UserAgent:
description: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
description: "Not Implemented"
in: header
name: user-agent
type: apiKey
@ -211,7 +211,7 @@ components:
name: Sec-Fetch-Site
type: apiKey
Referer:
description: "https://twitter.com/home"
description: "https://x.com/home"
in: header
name: Referer
type: apiKey

View file

@ -1,15 +1,13 @@
{
"HomeTimeline": {
"queryId": "q1x0puFIVMzsbx2Yoh-usA",
"queryId": "HJFjzBgCs16TqxewQOeLNg",
"variables": {
"count": 20,
"includePromotedContent": true,
"latestControlAvailable": true,
"requestContext": "launch",
"withCommunity": true,
"seenTweetIds": [
"1349129669258448897"
]
"seenTweetIds": ["1349129669258448897"]
},
"features": {
"rweb_tipjar_consumption_enabled": true,
@ -21,7 +19,6 @@
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"articles_preview_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
@ -32,7 +29,6 @@
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"tweet_with_visibility_results_prefer_gql_media_interstitial_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
@ -40,15 +36,13 @@
}
},
"HomeLatestTimeline": {
"queryId": "eL8vHLgEw2ZL9X9dKdakLQ",
"queryId": "DiTkXJgLqBBxCs7zaYsbtA",
"variables": {
"count": 20,
"includePromotedContent": true,
"latestControlAvailable": true,
"requestContext": "launch",
"seenTweetIds": [
"1349129669258448897"
]
"seenTweetIds": ["1349129669258448897"]
},
"features": {
"rweb_tipjar_consumption_enabled": true,
@ -60,7 +54,6 @@
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"articles_preview_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
@ -71,7 +64,6 @@
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"tweet_with_visibility_results_prefer_gql_media_interstitial_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
@ -79,7 +71,7 @@
}
},
"ListLatestTweetsTimeline": {
"queryId": "GX5ovLTwyoN1Td13GHvhIg",
"queryId": "Pa45JvqZuKcW1plybfgBlQ",
"variables": {
"listId": "1539453138322673664",
"count": 20
@ -94,7 +86,6 @@
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"articles_preview_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
@ -105,7 +96,6 @@
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"tweet_with_visibility_results_prefer_gql_media_interstitial_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
@ -113,20 +103,21 @@
}
},
"UserByScreenName": {
"queryId": "k5XapwcSikNsEsILW5FvgA",
"queryId": "Yka-W8dz7RaEuQNkroPkYw",
"variables": {
"screen_name": "elonmusk",
"withSafetyModeUserFields": true
},
"features": {
"hidden_profile_likes_enabled": true,
"hidden_profile_subscriptions_enabled": true,
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"subscriptions_verification_info_is_identity_verified_enabled": true,
"subscriptions_verification_info_verified_since_enabled": true,
"highlights_tweets_tab_ui_enabled": true,
"responsive_web_twitter_article_notes_tab_enabled": true,
"subscriptions_feature_can_gift_premium": true,
"creator_subscriptions_tweet_preview_api_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"responsive_web_graphql_timeline_navigation_enabled": true
@ -154,13 +145,12 @@
}
},
"UsersByRestIds": {
"queryId": "itEhGywpgX9b3GJCzOtSrA",
"queryId": "GYBpHkmyXjeuX9IeNJmweA",
"variables": {
"userIds": [
"44196397"
]
"userIds": ["44196397"]
},
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
@ -168,14 +158,14 @@
}
},
"ProfileSpotlightsQuery": {
"queryId": "X-Sw7rvhcUhof35mh5ObKw",
"queryId": "-0XdHI-mrHWBQd8-oLo1aA",
"variables": {
"screen_name": "elonmusk"
},
"features": {}
},
"UserTweets": {
"queryId": "5ICa5d9-AitXZrIA3H-4MQ",
"queryId": "E3opETHurmVJflFsUBVuUQ",
"variables": {
"userId": "44196397",
"count": 40,
@ -185,31 +175,33 @@
"withV2Timeline": true
},
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_media_download_video_enabled": false,
"responsive_web_enhance_cards_enabled": false
}
},
"UserTweetsAndReplies": {
"queryId": "UtLStR_BnYUGD7Q453UXQg",
"queryId": "bt4TKuFz4T7Ckk-VvQVSow",
"variables": {
"userId": "44196397",
"count": 40,
@ -219,31 +211,33 @@
"withV2Timeline": true
},
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_media_download_video_enabled": false,
"responsive_web_enhance_cards_enabled": false
}
},
"UserHighlightsTweets": {
"queryId": "ZRU-YBvpJ5c-SOS-nb_Lhg",
"queryId": "Z-XscDcWUuMO5HalgHf57A",
"variables": {
"userId": "44196397",
"count": 40,
@ -251,31 +245,33 @@
"withVoice": true
},
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_media_download_video_enabled": false,
"responsive_web_enhance_cards_enabled": false
}
},
"UserMedia": {
"queryId": "tO4LMUYAZbR4T0SqQ85aAw",
"queryId": "dexO_2tohK86JDudXXG3Yw",
"variables": {
"userId": "44196397",
"count": 40,
@ -286,31 +282,33 @@
"withV2Timeline": true
},
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_media_download_video_enabled": false,
"responsive_web_enhance_cards_enabled": false
}
},
"Likes": {
"queryId": "9s8V6sUI8fZLDiN-REkAxA",
"queryId": "aeJWz--kknVBOl7wQ7gh7Q",
"variables": {
"userId": "44196397",
"count": 20,
@ -321,62 +319,66 @@
"withV2Timeline": true
},
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_media_download_video_enabled": false,
"responsive_web_enhance_cards_enabled": false
}
},
"Bookmarks": {
"queryId": "cQxQgX8MJYjWwC0dxpyfYg",
"queryId": "QUjXply7fA7fk05FRyajEg",
"variables": {
"count": 20,
"includePromotedContent": true
},
"features": {
"graphql_timeline_v2_bookmark_timeline": true,
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_media_download_video_enabled": false,
"responsive_web_enhance_cards_enabled": false
}
},
"TweetDetail": {
"queryId": "zJvfJs3gSbrVhC0MKjt_OQ",
"queryId": "QuBlQ6SxNAQCt6-kBiCXCQ",
"variables": {
"focalTweetId": "1349129669258448897",
"referrer": "home",
@ -398,7 +400,6 @@
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"articles_preview_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
@ -409,7 +410,6 @@
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"tweet_with_visibility_results_prefer_gql_media_interstitial_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
@ -461,7 +461,7 @@
}
},
"SearchTimeline": {
"queryId": "fZK7JipRHWtiZsTodhsTfQ",
"queryId": "UN1i3zUiCWa-6r-Uaho4fw",
"variables": {
"rawQuery": "elonmusk",
"count": 20,
@ -469,26 +469,28 @@
"product": "Top"
},
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_media_download_video_enabled": false,
"responsive_web_enhance_cards_enabled": false
}
},
@ -524,162 +526,172 @@
}
},
"Retweeters": {
"queryId": "X-XEqG5qHQSAwmvy00xfyQ",
"queryId": "8019obfgnveiPiJuS2Rtow",
"variables": {
"tweetId": "1349129669258448897",
"count": 20,
"includePromotedContent": true
},
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_media_download_video_enabled": false,
"responsive_web_enhance_cards_enabled": false
}
},
"Followers": {
"queryId": "ZG1BQPaRSg04qo55kKaW2g",
"queryId": "OSXFkKmGvfw_6pGgGtkWFg",
"variables": {
"userId": "44196397",
"count": 20,
"includePromotedContent": false
},
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_media_download_video_enabled": false,
"responsive_web_enhance_cards_enabled": false
}
},
"Following": {
"queryId": "PAnE9toEjRfE-4tozRcsfw",
"queryId": "7oQrdmth4zE3EtD42ZxgOA",
"variables": {
"userId": "44196397",
"count": 20,
"includePromotedContent": false
},
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_media_download_video_enabled": false,
"responsive_web_enhance_cards_enabled": false
}
},
"BlueVerifiedFollowers": {
"queryId": "mg4dFO4kMIKt6tpqPMmFeg",
"queryId": "cpPRJUmSz2Fiu1PpIYmEsw",
"variables": {
"userId": "1347135745706708993",
"count": 20,
"includePromotedContent": false
},
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_media_download_video_enabled": false,
"responsive_web_enhance_cards_enabled": false
}
},
"FollowersYouKnow": {
"queryId": "citX7s5IAb1C6AVCqUO68g",
"queryId": "52sUpz5G7XvESPWgKW9i9Q",
"variables": {
"userId": "44196397",
"count": 20,
"includePromotedContent": false
},
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_media_download_video_enabled": false,
"responsive_web_enhance_cards_enabled": false
}
},
"CreateTweet": {
"queryId": "8ED1SMuUGkOZVBEjiYUTfw",
"queryId": "xT36w0XM3A8jDynpkram2A",
"variables": {
"tweet_text": "test",
"media": {
@ -696,26 +708,29 @@
"in_reply_to_tweet_id": "1111111111111111111",
"exclude_reply_user_ids": []
},
"dark_request": false
"dark_request": false,
"disallowed_reply_options": false
},
"features": {
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"tweetypie_unmention_optimization_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"articles_preview_enabled": true,
"rweb_video_timestamps_enabled": true,
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"responsive_web_media_download_video_enabled": false,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_enhance_cards_enabled": false
@ -724,8 +739,7 @@
"FavoriteTweet": {
"queryId": "lI07N6Otwv1PhnEgXILM7A",
"variables": {
"tweet_id": "1349129669258448897",
"dark_request": false
"tweet_id": "1349129669258448897"
}
},
"UnfavoriteTweet": {
@ -769,7 +783,7 @@
}
},
"#=====v1.1====": {
"url": "https://twitter.com/i/api/1.1/"
"url": "https://x.com/i/api/1.1/"
},
"friendships/create.json": {
"include_profile_interstitial_type": 1,
@ -831,7 +845,7 @@
"result_type": "events,users,topics"
},
"#=====v2====": {
"url": "https://twitter.com/i/api/2"
"url": "https://x.com/i/api/2"
},
"search/adaptive.json": {
"include_profile_interstitial_type": 1,
@ -871,5 +885,166 @@
"spelling_corrections": 1,
"include_ext_edit_control": true,
"ext": "mediaStats,highlightedLabel,hasNftAvatar,voiceInfo,birdwatchPivot,enrichments,superFollowMetadata,unmentionInfo,editControl,vibe"
},
"#=====NotImplemented====": {},
"DataSaverMode": {
"queryId": "xF6sXnKJfS2AOylzxRjf6A"
},
"PinnedTimelines": {
"queryId": "xUjP0kS7EE05CLp3KUD-Eg",
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"responsive_web_graphql_timeline_navigation_enabled": true
}
},
"getAltTextPromptPreference": {
"queryId": "PFIxTk8owMoZgiMccP0r4g"
},
"ExploreSidebar": {
"queryId": "rqiZoeu9EBUhOqZdKY139g",
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_enhance_cards_enabled": false
}
},
"useFetchProfileBlocks_profileExistsQuery": {
"queryId": "Z2BA99jFw6TxaJM5v7Irmg"
},
"ExplorePage": {
"queryId": "IK_dxB178qS4T8cvA2G_UA",
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_enhance_cards_enabled": false
}
},
"CommunitiesCreateButtonQuery": {
"queryId": "ScODPHsG2d28Xr-rDSBThg"
},
"CarouselQuery": {
"queryId": "xfgycRkhqXy90CmTQZ7Kig"
},
"CommunitiesRankedTimeline": {
"queryId": "ruTkdk9a7c2U99VzD4MtMw",
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_enhance_cards_enabled": false
}
},
"BirdwatchFetchGlobalTimeline": {
"queryId": "Hu5em3YzOCFtiBOxT3qvEQ",
"features": {
"rweb_tipjar_consumption_enabled": true,
"responsive_web_graphql_exclude_directive_enabled": true,
"verified_phone_label_enabled": false,
"responsive_web_graphql_timeline_navigation_enabled": true,
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
"creator_subscriptions_tweet_preview_api_enabled": true,
"communities_web_enable_tweet_community_results_fetch": true,
"c9s_tweet_anatomy_moderator_badge_enabled": true,
"articles_preview_enabled": true,
"responsive_web_edit_tweet_api_enabled": true,
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
"view_counts_everywhere_api_enabled": true,
"longform_notetweets_consumption_enabled": true,
"responsive_web_twitter_article_tweet_consumption_enabled": true,
"tweet_awards_web_tipping_enabled": false,
"creator_subscriptions_quote_tweet_preview_enabled": false,
"freedom_of_speech_not_reach_fetch_enabled": true,
"standardized_nudges_misinfo": true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
"rweb_video_timestamps_enabled": true,
"longform_notetweets_rich_text_read_enabled": true,
"longform_notetweets_inline_media_enabled": true,
"responsive_web_enhance_cards_enabled": false
}
},
"BirdwatchFetchAuthenticatedUserProfile": {
"queryId": "hkYn13HnxM_eVCEGGl-Fdw",
"features": {
"responsive_web_birdwatch_top_contributor_enabled": true,
"responsive_web_birdwatch_mobile_nav_setting_enabled": false,
"responsive_web_birdwatch_note_limit_enabled": true
}
},
"useRelayDelegateDataPendingQuery": {
"queryId": "0d3YLrCrAvgiPrMFGc33SA"
},
"DelegatedAccountListQuery": {
"queryId": "R0L__TguknNYVKUvNwmBpA",
"features": {
"responsive_web_graphql_timeline_navigation_enabled": true
}
},
"UsersVerifiedAvatars": {
"queryId": "aLfvAoX6xy2ojqzOnkbrIA",
"features": {
"responsive_web_graphql_timeline_navigation_enabled": true
}
}
}
}

View file

@ -14,8 +14,7 @@ paths:
content:
application/json:
schema:
oneOf:
- $ref: "#/components/schemas/OtherResponse"
$ref: "#/components/schemas/OtherResponse"
tags:
- "other"

View file

@ -4,22 +4,26 @@ info:
version: 0.0.1
paths: {}
components:
schemas:
ErrorResponse:
Errors:
type: object
required:
- errors
- data
properties:
errors:
$ref: "#/components/schemas/Errors"
type: array
items:
$ref: "#/components/schemas/Error"
data:
$ref: "#/components/schemas/ErrorsData"
Errors:
type: array
items:
$ref: "#/components/schemas/Error"
ErrorsData:
type: object
properties:
user:
type: string # always null
pattern: "dummy"
Error:
type: object
@ -32,7 +36,6 @@ components:
- kind
- name
- source
- retry_after
- tracing
properties:
message:
@ -46,7 +49,7 @@ components:
items:
type: string
extensions:
$ref: "#/components/schemas/Extensions"
$ref: "#/components/schemas/ErrorExtensions"
code:
type: integer
kind:
@ -71,7 +74,7 @@ components:
column:
type: integer
Extensions:
ErrorExtensions:
type: object
required:
- name
@ -84,6 +87,8 @@ components:
type: string
source:
type: string
retry_after:
type: integer
code:
type: integer
kind:
@ -98,3 +103,4 @@ components:
properties:
trace_id:
type: string
pattern: "^[0-9a-f]{16}$"

View file

@ -84,7 +84,6 @@ components:
- "__typename"
- "cursorType"
- "value"
- "stopOnEmptyResponse"
properties:
__typename:
$ref: "./typename.yaml#/components/schemas/TypeName" # TimelineTimelineCursor
@ -98,7 +97,6 @@ components:
type: string
stopOnEmptyResponse:
type: boolean
default: false
displayTreatment:
$ref: "#/components/schemas/DisplayTreatment"
@ -230,7 +228,7 @@ components:
ItemResult:
properties:
__typename:
$ref: "./typename.yaml#/components/schemas/TypeName" # null | TimelineTweet
$ref: "./typename.yaml#/components/schemas/TypeName" # null | TimelineTweet | TweetUnavailable
result:
$ref: "./tweet.yaml#/components/schemas/TweetUnion"

View file

@ -1,99 +0,0 @@
openapi: 3.0.3
info:
title: Twitter OpenAPI
version: 0.0.1
paths: {}
components:
schemas:
Errors:
type: object
required:
- errors
properties:
errors:
type: array
items:
$ref: "#/components/schemas/Error"
Error:
type: object
required:
- message
- locations
- path
- extensions
- code
- kind
- name
- source
- retry_after
- tracing
properties:
message:
type: string
locations:
type: array
items:
$ref: "#/components/schemas/Location"
path:
type: array
items:
type: string
extensions:
$ref: "#/components/schemas/ErrorExtensions"
code:
type: integer
kind:
type: string
name:
type: string
source:
type: string
retry_after:
type: integer
tracing:
$ref: "#/components/schemas/Tracing"
Location:
type: object
required:
- line
- column
properties:
line:
type: integer
column:
type: integer
ErrorExtensions:
type: object
required:
- name
- source
- retry_after
- code
- kind
- tracing
properties:
name:
type: string
source:
type: string
retry_after:
type: integer
code:
type: integer
kind:
type: string
tracing:
$ref: "#/components/schemas/Tracing"
Tracing:
type: object
required:
- trace_id
properties:
trace_id:
type: string
pattern: "^[0-9a-f]{16}$"

View file

@ -277,7 +277,21 @@ components:
properties:
type:
type: string
enum: [TimelineCoverBehaviorDismiss]
enum: [TimelineCoverBehaviorDismiss, TimelineCoverBehaviorNavigate]
url:
type: TimelineCoverBehaviorUrl
TimelineCoverBehaviorUrl:
required:
- "url"
- "url_type"
properties:
url:
type: string
format: uri
url_type:
type: string
enum: ["ExternalUrl"]
Callback:
required:

View file

@ -7,8 +7,6 @@ paths: {}
components:
schemas:
TimelineV2:
required:
- "timeline"
properties:
timeline:
$ref: "#/components/schemas/Timeline"

View file

@ -12,12 +12,14 @@ components:
- $ref: "#/components/schemas/Tweet"
- $ref: "#/components/schemas/TweetWithVisibilityResults"
- $ref: "#/components/schemas/TweetTombstone"
- $ref: "#/components/schemas/TweetUnavailable"
discriminator:
propertyName: __typename
mapping": # deprecated
Tweet: "#/components/schemas/Tweet"
TweetWithVisibilityResults: "#/components/schemas/TweetWithVisibilityResults"
TweetTombstone: "#/components/schemas/TweetTombstone"
TweetUnavailable: "#/components/schemas/TweetUnavailable"
TweetWithVisibilityResults:
required:
@ -138,6 +140,13 @@ components:
$ref: "./typename.yaml#/components/schemas/TypeName" # TweetWithVisibilityResults
additionalProperties: true # todo
TweetUnavailable: # nsfw tweet
properties:
__typename:
$ref: "./typename.yaml#/components/schemas/TypeName" # TweetUnavailable
reason:
type: string
Tweet:
required:
- "rest_id"
@ -162,7 +171,6 @@ components:
$ref: "#/components/schemas/TweetEditPrespective"
is_translatable:
type: boolean
default: false
source:
type: string # html (<a href="http://twitter.com/download/android" rel="nofollow">Twitter for Android</a>)
legacy:
@ -189,6 +197,8 @@ components:
$ref: "#/components/schemas/AuthorCommunityRelationship"
article:
$ref: "#/components/schemas/Article"
community_results:
$ref: "#/components/schemas/Community"
TweetEditControl:
properties:
@ -884,10 +894,8 @@ components:
type: string # enum
possibly_sensitive:
type: boolean
default: false
possibly_sensitive_editable:
type: boolean
default: false
quote_count:
type: integer
reply_count:
@ -1289,13 +1297,10 @@ components:
properties:
adult_content:
type: boolean
default: false
graphic_violence:
type: boolean
default: false
other:
type: boolean
default: false
MediaSizes:
required:
@ -1464,8 +1469,6 @@ components:
type: integer
AllowDownloadStatus:
required:
- "allow_download"
properties:
allow_download:
type: boolean

View file

@ -35,9 +35,6 @@ components:
- "is_blue_verified"
- "legacy"
- "rest_id"
- "super_follow_eligible"
- "super_followed_by"
- "super_following"
- "profile_image_shape"
properties:
@ -50,13 +47,11 @@ components:
type: boolean
has_nft_avatar:
type: boolean
default: false
id:
type: string
pattern: "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$" # base64
is_blue_verified:
type: boolean
default: false
legacy:
$ref: "#/components/schemas/UserLegacy"
rest_id:
@ -67,13 +62,10 @@ components:
additionalProperties: true # todo
super_follow_eligible:
type: boolean
default: false
super_followed_by:
type: boolean
default: false
super_following:
type: boolean
default: false
profile_image_shape:
type: string
enum:
@ -96,6 +88,10 @@ components:
$ref: "#/components/schemas/UserTipJarSettings"
legacy_extended_profile:
$ref: "#/components/schemas/UserLegacyExtendedProfile"
has_hidden_likes_on_profile:
type: boolean
premium_gifting_eligible:
type: boolean
UserProfessional:
required:
@ -143,7 +139,6 @@ components:
properties:
is_identity_verified:
type: boolean
default: false
reason:
$ref: "#/components/schemas/UserVerificationInfoReason"
@ -214,6 +209,8 @@ components:
type: string
gofundme_handle:
type: string # uri
bandcamp_handle:
type: string # uri
UserLegacyExtendedProfile:
properties:
@ -243,10 +240,6 @@ components:
UserLegacy:
required:
- "blocked_by"
- "blocking"
- "can_dm"
- "can_media_tag"
- "created_at"
- "default_profile"
- "default_profile_image"
@ -254,52 +247,39 @@ components:
- "entities"
- "fast_followers_count"
- "favourites_count"
# 31 # - "follow_request_sent"
# 31 # - "followed_by"
- "followers_count"
# 31 # - "following"
- "friends_count"
- "has_custom_timelines"
- "is_translator"
- "listed_count"
- "location"
- "media_count"
- "muting"
- "name"
- "normal_followers_count"
# 31 # - "notifications"
- "pinned_tweet_ids_str"
- "possibly_sensitive"
- "profile_image_url_https"
- "profile_interstitial_type"
# 31 # - "protected"
- "screen_name"
- "status"
- "statuses_count"
- "translator_type"
- "verified"
- "want_retweets"
properties:
blocked_by:
type: boolean
default: false
blocking:
type: boolean
default: false
can_dm:
type: boolean
default: false
can_media_tag:
type: boolean
default: false
created_at:
$ref: "./general.yaml#/components/schemas/TwitterTimeFormat"
default_profile:
type: boolean
default: false
default_profile_image:
type: boolean
default: false
description:
type: string
entities:
@ -309,54 +289,40 @@ components:
type: integer
favourites_count:
type: integer
default: 0
follow_request_sent:
type: boolean
default: false
followed_by:
type: boolean
default: false
followers_count:
type: integer
default: 0
following:
type: boolean
default: false
friends_count:
type: integer
default: 0
has_custom_timelines:
type: boolean
default: false
is_translator:
type: boolean
default: false
listed_count:
type: integer
default: 0
location:
type: string
media_count:
type: integer
default: 0
muting:
type: boolean
default: false
name:
type: string
normal_followers_count:
type: integer
default: 0
notifications:
type: boolean
default: false
pinned_tweet_ids_str:
type: array
items:
type: string
possibly_sensitive:
type: boolean
default: false
profile_banner_extensions:
type: object
profile_banner_url:
@ -371,12 +337,10 @@ components:
type: string
protected:
type: boolean
default: false
screen_name:
type: string
statuses_count:
type: integer
default: 0
translator_type:
type: string
url:
@ -385,7 +349,6 @@ components:
type: boolean
want_retweets:
type: boolean
default: false
verified_type:
type: string
enum: ["Business", "Government"]

View file

@ -1,6 +1,7 @@
import base64
import concurrent.futures
import glob
import inspect
import json
import logging
import os
@ -180,6 +181,8 @@ if __name__ == "__main__":
f'cookie.json not found. Please run `{"; ".join(commands)}` first.'
)
if isinstance(cookies, list):
cookies = {k["name"]: k["value"] for k in cookies}
cookies_str = "; ".join([f"{k}={v}" for k, v in cookies.items()])
with open("src/config/placeholder.json", "r") as f:
@ -208,6 +211,15 @@ if __name__ == "__main__":
task_callback(file, thread=False)
logger.info(f"Match rate: {rate}")
for file in glob.glob("other/**/*.json", recursive=True):
with open(file, "r") as f:
data = json.load(f)
try:
_ = pt.Errors.from_dict(data)
except Exception as e:
error_dump(e)
api_conf = pt.Configuration(
api_key={
"ClientLanguage": "en",
@ -231,7 +243,7 @@ if __name__ == "__main__":
error_count = 0
for x in [pt.DefaultApi, pt.TweetApi, pt.UserApi, pt.UsersApi, pt.UserListApi]:
for props, fn in x.__dict__.items():
for props, fn in inspect.getmembers(x):
if not callable(fn):
continue
if props.startswith("__") or not props.endswith("_with_http_info"):
@ -284,7 +296,7 @@ if __name__ == "__main__":
try:
logger.info("Try: Self UserByScreenName Test")
kwargs = get_kwargs("UserByScreenName", {"screen_name": "NxWDOyLMd483329"})
kwargs = get_kwargs("UserByScreenName", {"screen_name": "ptcpz3"})
res = pt.UserApi(api_client).get_user_by_screen_name_with_http_info(**kwargs)
data = res.data.to_dict()
@ -295,7 +307,7 @@ if __name__ == "__main__":
)
logger.info(f"Match rate: {rate}")
screen_name = data["data"]["user"]["result"]["legacy"]["screen_name"]
if not screen_name == "NxWDOyLMd483329":
if not screen_name == "ptcpz3":
raise Exception("UserByScreenName failed")
except Exception as e:
error_dump(e)
@ -330,10 +342,12 @@ if __name__ == "__main__":
"1720975693524377759",
"1721006592303251551",
"1739194269477331076",
"1697450269259522256",
"1697450278742884799",
# "1697450269259522256",
# "1697450278742884799",
"1749500209061663043",
"1759056048764469303",
"1349129669258448897",
"1810188416812019999",
]
for id in ids:
try:
@ -342,6 +356,13 @@ if __name__ == "__main__":
res = pt.TweetApi(api_client).get_tweet_detail_with_http_info(**kwargs)
data = res.data.to_dict()
save_cache(
{
"raw": res.raw_data.decode("utf-8"),
"type": res.data.__class__.__name__,
}
)
rate = match_rate(
data,
json.loads(res.raw_data),

View file

@ -2,6 +2,7 @@ import json
from pathlib import Path
import openapi_client as pt
import urllib3
def get_kwargs(key, additional):
@ -19,6 +20,8 @@ if __name__ == "__main__":
if Path("cookie.json").exists():
with open("cookie.json", "r") as f:
cookies = json.load(f)
if isinstance(cookies, list):
cookies = {k["name"]: k["value"] for k in cookies}
cookies_str = "; ".join([f"{k}={v}" for k, v in cookies.items()])
with open("src/config/placeholder.json", "r") as f:
@ -31,9 +34,17 @@ if __name__ == "__main__":
"GuestToken": cookies["gt"],
},
)
latest_user_agent_res = urllib3.PoolManager().request(
"GET",
"https://raw.githubusercontent.com/fa0311/latest-user-agent/main/output.json",
)
latest_user_agent = json.loads(latest_user_agent_res.data.decode("utf-8"))
api_conf.access_token = "AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA"
api_client = pt.ApiClient(configuration=api_conf, cookie=cookies_str)
api_client.user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
api_client.user_agent = latest_user_agent["chrome-fetch"]
pt.TweetApi(api_client).get_user_tweets_with_http_info(
**get_kwargs("UserTweets", {}),

View file

@ -6,6 +6,7 @@ from hooks import (
AddSecuritySchemesOnSecuritySchemes,
RemoveErrorHandle,
SetResponsesHeader,
SetUserAgentOnSecuritySchemes,
)
@ -40,7 +41,10 @@ class Config:
additionalHooks.append(RemoveErrorHandle())
return {
"openapi": [AddSecuritySchemesOnSecuritySchemes()],
"openapi": [
AddSecuritySchemesOnSecuritySchemes(),
SetUserAgentOnSecuritySchemes(),
],
"schemas": [],
"other": [],
"request": {

130
tools/generater.py Normal file
View file

@ -0,0 +1,130 @@
# https://github.com/tsukumijima/KonomiTV/blob/master/server/misc/TwitterAPIQueryGenerator.py
# https://github.com/tsukumijima/KonomiTV/blob/master/License.txt
#!/usr/bin/env python3
# Usage: poetry run python -m misc.TwitterAPIQueryGenerator
import json
import re
import urllib.parse
from rich import print
from rich.rule import Rule
def main():
print(Rule(characters="="))
print(
"Chrome DevTools の Network タブで「表示されているものをすべてfetch としてコピー」したコードを`input.js`に貼り付けてください。"
)
print("Enter を押すと続行します。")
print(Rule(characters="="))
input()
with open("./tools/input.js", "r") as f:
fetch_code_raw = f.read()
print(Rule(characters="="))
splited = fetch_code_raw.split("\n")
fetch_code_list = []
code = ""
for line in splited:
if line.startswith("fetch("):
if code:
fetch_code_list.append(code)
code = line
else:
code += line + "\n"
fetch_code_list.append(code)
for fetch_code in fetch_code_list:
# query_idとendpointを抽出
query_id_match = re.search(r'/i/api/graphql/([^/]+)/([^"?]+)', fetch_code)
if not query_id_match:
print("query_id と endpoint の抽出に失敗しました。")
print(Rule(characters="="))
return
query_id = query_id_match.group(1)
endpoint = query_id_match.group(2)
# リクエストメソッドを判定
method_match = re.search(r'"method"\s*:\s*"(GET|POST)"', fetch_code)
if not method_match:
print("リクエストメソッドの判定に失敗しました。")
print(Rule(characters="="))
return
method = method_match.group(1)
if method == "POST":
# POST リクエストの場合、fetch() コードの第二引数にある {} で囲まれたオブジェクトを正規表現で抽出したものを JSON としてパース
body_match = re.search(r'"body"\s*:\s*"({.*})"', fetch_code, re.DOTALL)
if not body_match:
print("body の抽出に失敗しました。")
print(Rule(characters="="))
return
body_json_str = body_match.group(1).replace("\\", "")
body_json = json.loads(body_json_str)
features = body_json.get("features", None)
variables = body_json.get("variables", None)
else:
# GET リクエストの場合、まず URL を抽出
url_match = re.search(r'"(https?://[^"]+)"', fetch_code)
if not url_match:
print("URL の抽出に失敗しました。")
print(Rule(characters="="))
return
url = url_match.group(1)
# URL をパースして query string を取得
parsed_url = urllib.parse.urlparse(url)
query_string = parsed_url.query
# query string を dict 形式にパース
query_dict = urllib.parse.parse_qs(query_string)
# features を取得
features_json_str = query_dict.get("features", [None])[0]
if features_json_str is None:
features = None
variables = None
else:
try:
features = json.loads(features_json_str)
except json.JSONDecodeError:
print(
"features の JSON パースに失敗しました。features は None として続行します。"
)
features = None
variables = None
with open("./src/config/placeholder.json", "r") as f:
placeholder = json.load(f)
def check(a, b, msg):
if isinstance(a, dict) and isinstance(b, dict):
for k in {*a.keys(), *b.keys()}:
if k not in b:
print(f"{msg} key: {k} が存在しません。")
elif k not in a:
print(f"{msg} key: {k} が存在しません。")
else:
check(a[k], b[k], msg)
check(
variables,
placeholder.get(endpoint, {}).get("variables", {}),
f"{endpoint} の variables が不一致です。",
)
with open("./src/config/placeholder.json", "w") as f:
placeholder[endpoint] = placeholder.get(endpoint, {})
placeholder[endpoint]["queryId"] = query_id
if features:
placeholder[endpoint]["features"] = features
json.dump(placeholder, f, indent=4)
if __name__ == "__main__":
main()

View file

@ -1,5 +1,6 @@
import json
import urllib3
import yaml
@ -60,6 +61,13 @@ class HookBase:
with open("src/config/placeholder.json", mode="r", encoding="utf-8") as f:
return yaml.safe_load(f)
def load_user_agent(self) -> str:
user_agent = urllib3.PoolManager().request(
"GET",
"https://raw.githubusercontent.com/fa0311/latest-user-agent/main/output.json",
)
return json.loads(user_agent.data)["chrome-fetch"]
# HookBase extends
@ -106,6 +114,14 @@ class AddSecuritySchemesOnSecuritySchemes(OpenapiHookBase):
return value
class SetUserAgentOnSecuritySchemes(OpenapiHookBase):
def hook(self, value: dict):
value = super().hook(value)
param = value["components"]["securitySchemes"]
param["UserAgent"]["description"] = self.load_user_agent()
return value
# SchemasHookBase extends
@ -151,6 +167,15 @@ class AddSecuritySchemesOnHeader(RequestHookBase):
return path, value
class SetUserAgentOnHeader(RequestHookBase):
def hook(self, path: str, value: dict):
path, value = super().hook(path, value)
component = self.load_component("security_schemes")
param = component["paths"]["/parameters"]["get"]["parameters"]
value["parameters"].extend(param)
return path, value
class ReplaceQueryIdPlaceholder(RequestHookBase):
def hook(self, path: str, value: dict):
path, value = super().hook(path, value)