1
Fork 0
mirror of https://github.com/thegeneralist01/twitter-openapi synced 2026-01-11 23:50:26 +01:00
Signed-off-by: ふぁ <yuki@yuki0311.com>
This commit is contained in:
ふぁ 2023-05-05 21:11:19 +09:00
parent ca1fbb7815
commit cce687ba15
No known key found for this signature in database
GPG key ID: 83A8A5E74872A8AA
9 changed files with 268 additions and 95 deletions

View file

@ -436,7 +436,10 @@
},
"features": {}
},
"create.json": {
"=====v1.1====": {
"url": "https://twitter.com/i/api/1.1/"
},
"friendships/create.json": {
"include_profile_interstitial_type": 1,
"include_blocking": 1,
"include_blocked_by": 1,
@ -450,11 +453,91 @@
"include_ext_verified_type": 1,
"include_ext_profile_image_shape": 1,
"skip_status": 1,
"user_id": 1180389371481976833
"user_id": 44196397
},
"Template": {
"queryId": "",
"variables": {},
"features": {}
"friendships/destroy.json": {
"include_profile_interstitial_type": 1,
"include_blocking": 1,
"include_blocked_by": 1,
"include_followed_by": 1,
"include_want_retweets": 1,
"include_mute_edge": 1,
"include_can_dm": 1,
"include_can_media_tag": 1,
"include_ext_has_nft_avatar": 1,
"include_ext_is_blue_verified": 1,
"include_ext_verified_type": 1,
"include_ext_profile_image_shape": 1,
"skip_status": 1,
"user_id": 44196397
},
"friends/following/list.json": {
"include_profile_interstitial_type": 1,
"include_blocking": 1,
"include_blocked_by": 1,
"include_followed_by": 1,
"include_want_retweets": 1,
"include_mute_edge": 1,
"include_can_dm": 1,
"include_can_media_tag": 1,
"include_ext_has_nft_avatar": 1,
"include_ext_is_blue_verified": 1,
"include_ext_verified_type": 1,
"include_ext_profile_image_shape": 1,
"skip_status": 1,
"cursor": -1,
"user_id": 17152334,
"count": 3,
"with_total_count": true
},
"search/typeahead.json": {
"include_ext_is_blue_verified": 1,
"include_ext_verified_type": 1,
"include_ext_profile_image_shape": 1,
"q": "aaa",
"src": "search_box",
"result_type": "events,users,topics"
},
"=====v2====": {
"url": "https://twitter.com/i/api/2"
},
"search/adaptive.json": {
"include_profile_interstitial_type": 1,
"include_blocking": 1,
"include_blocked_by": 1,
"include_followed_by": 1,
"include_want_retweets": 1,
"include_mute_edge": 1,
"include_can_dm": 1,
"include_can_media_tag": 1,
"include_ext_has_nft_avatar": 1,
"include_ext_is_blue_verified": 1,
"include_ext_verified_type": 1,
"include_ext_profile_image_shape": 1,
"skip_status": 1,
"cards_platform": "Web-12",
"include_cards": 1,
"include_ext_alt_text": true,
"include_ext_limited_action_results": false,
"include_quote_count": true,
"include_reply_count": 1,
"tweet_mode": "extended",
"include_ext_views": true,
"include_entities": true,
"include_user_entities": true,
"include_ext_media_color": true,
"include_ext_media_availability": true,
"include_ext_sensitive_media_warning": true,
"include_ext_trusted_friends_metadata": true,
"send_error_codes": true,
"simple_quoted_tweet": true,
"q": "elon musk",
"query_source": "trend_click",
"count": 20,
"requestContext": "launch",
"pc": 1,
"spelling_corrections": 1,
"include_ext_edit_control": true,
"ext": "mediaStats,highlightedLabel,hasNftAvatar,voiceInfo,birdwatchPivot,enrichments,superFollowMetadata,unmentionInfo,editControl,vibe"
}
}

View file

@ -53,11 +53,17 @@ security:
tags:
- name: user
description: response User
- name: userList
- name: user-list
description: response User list
- name: tweet
description: response tweet
- name: post
description: post
- name: v1.1
description: legacy APIs
- name: v1.1-get
description: legacy APIs get
- name: v1.1-post
description: legacy APIs post
- name: v2-get
description: legacy APIs get
- name: v2-post
description: legacy APIs post

View file

@ -16,7 +16,7 @@ paths:
schema:
$ref: "#/components/schemas/FollowResponse"
tags:
- "userList"
- "user-list"
/graphql/{{queryId}}/Followers:
get:
@ -30,7 +30,7 @@ paths:
schema:
$ref: "#/components/schemas/FollowResponse"
tags:
- "userList"
- "user-list"
components:
schemas:

View file

@ -0,0 +1,25 @@
openapi: 3.0.3
info:
title: Twitter OpenAPI
version: 0.0.1
paths:
/1.1/friends/following/list.json:
get:
operationId: getFriendsFollowingList
description: get friends following list
responses:
"200":
description: Successful operation
tags:
- "v1.1-get"
/1.1/search/typeahead.json:
get:
operationId: getSearchTypeahead
description: get search typeahead
responses:
"200":
description: Successful operation
tags:
- "v1.1-get"

View file

@ -0,0 +1,25 @@
openapi: 3.0.3
info:
title: Twitter OpenAPI
version: 0.0.1
paths:
/1.1/friendships/create.json:
post:
operationId: postCreateFriendships
description: post create friendships
responses:
"200":
description: Successful operation
tags:
- "v1.1-post"
/1.1/friendships/destroy.json:
post:
operationId: postDestroyFriendships
description: post destroy friendships
responses:
"200":
description: Successful operation
tags:
- "v1.1-post"

View file

@ -4,12 +4,12 @@ info:
version: 0.0.1
paths:
/1.1/friendships/create.json:
post:
operationId: postCreateFriendships
description: post create friendships
/2/search/adaptive.json:
get:
operationId: getSearchAdaptive
description: get search adaptive
responses:
"200":
description: Successful operation
tags:
- "v1.1"
- "v2.0-get"

View file

@ -11,87 +11,106 @@ class Config:
"openapi": [AddSecuritySchemesOnSecuritySchemes()],
"request": {
key: [
ReplaceQueryIdPlaceholder(),
SetResponsesHeader(),
AddParametersOnContent(),
ReplaceQueryIdPlaceholder(split=-1),
SetResponsesHeader(suffix=None),
AddParametersOnContent(split=-1),
]
for key in ["default", "user", "userList", "tweet"]
for key in ["default", "user", "user-list", "tweet"]
}
| {
"post": [
ReplaceQueryIdPlaceholder(),
SetResponsesHeader(),
AddParametersOnParameters(),
],
"v1.1": [SetResponsesHeader("v1.1"), AddParametersOnParameters()],
key: [
ReplaceQueryIdPlaceholder(split=-1),
SetResponsesHeader(suffix=None),
AddParametersOnParameters(split=-1),
]
for key in ["post"]
}
| {
key: [
SetResponsesHeader("legacy"),
AddParametersOnParameters(split=2),
]
for key in ["v1.1-get", "v1.1-post", "v2.0-get", "v2.0-post"]
},
},
"dart": {
"openapi": [],
"request": {
key: [
ReplaceQueryIdPlaceholder(),
AddSecuritySchemesOnHeader(),
SetResponsesHeader(),
AddParametersOnParametersAsString(),
ReplaceQueryIdPlaceholder(split=-1),
AddSecuritySchemesOnHeader(split=-1),
SetResponsesHeader(suffix=None),
AddParametersOnParametersAsString(split=-1),
]
for key in ["default", "user", "userList", "tweet"]
for key in ["default", "user", "user-list", "tweet"]
}
| {
"post": [
ReplaceQueryIdPlaceholder(),
AddSecuritySchemesOnHeader(),
SetResponsesHeader(),
AddParametersOnParametersAsObject(),
],
"v1.1": [
SetResponsesHeader("v1.1"),
AddParametersOnParametersAsObject(),
],
key: [
ReplaceQueryIdPlaceholder(split=-1),
AddSecuritySchemesOnHeader(split=-1),
SetResponsesHeader(suffix=None),
AddParametersOnParametersAsObject(split=-1),
]
for key in ["post"]
}
| {
key: [
SetResponsesHeader(suffix="legacy"),
AddParametersOnParametersAsObject(split=2),
]
for key in ["v1.1-get", "v1.1-post", "v2.0-get", "v2.0-post"]
},
},
"typescript": {
"openapi": [AddSecuritySchemesOnSecuritySchemes()],
"request": {
key: [
ReplaceQueryIdPlaceholder(),
SetResponsesHeader(),
AddParametersOnParametersAsString(),
ReplaceQueryIdPlaceholder(split=-1),
SetResponsesHeader(suffix=None),
AddParametersOnParametersAsString(split=-1),
]
for key in ["default", "user", "userList", "tweet"]
for key in ["default", "user", "user-list", "tweet"]
}
| {
"post": [
ReplaceQueryIdPlaceholder(),
SetResponsesHeader(),
AddParametersOnParametersAsObject(),
],
"v1.1": [
SetResponsesHeader("v1.1"),
AddParametersOnParametersAsObject(),
],
key: [
ReplaceQueryIdPlaceholder(split=-1),
SetResponsesHeader(suffix=None),
AddParametersOnParametersAsObject(split=-1),
]
for key in ["post"]
}
| {
key: [
SetResponsesHeader(suffix="legacy"),
AddParametersOnParametersAsObject(split=2),
]
for key in ["v1.1-get", "v1.1-post", "v2.0-get", "v2.0-post"]
},
},
"test": {
"openapi": [AddSecuritySchemesOnSecuritySchemes()],
"request": {
key: [
ReplaceQueryIdPlaceholder(),
SetResponsesHeader(),
AddParametersOnParametersAsString(),
ReplaceQueryIdPlaceholder(split=-1),
SetResponsesHeader(suffix=None),
AddParametersOnParametersAsString(split=-1),
]
for key in ["default", "user", "userList", "tweet"]
for key in ["default", "user", "user-list", "tweet"]
}
| {
"post": [
ReplaceQueryIdPlaceholder(),
SetResponsesHeader(),
AddParametersOnParametersAsString(),
],
"v1.1": [
SetResponsesHeader("v1.1"),
AddParametersOnParametersAsString(),
],
key: [
ReplaceQueryIdPlaceholder(split=-1),
SetResponsesHeader(suffix=None),
AddParametersOnParametersAsString(split=-1),
]
for key in ["post"]
}
| {
key: [
SetResponsesHeader(suffix="legacy"),
AddParametersOnParametersAsObject(split=2),
]
for key in ["v1.1-get", "v1.1-post", "v2.0-get", "v2.0-post"]
},
},
}

View file

@ -15,9 +15,9 @@ class HookBase:
properties = {i: fn(obj[i]) for i in obj}
value = {
"type": "object",
"required": [i for i in obj],
"properties": properties,
}
value.update({"required": [i for i in obj]} if len(obj) > 0 else {})
value.update({"default": properties} if default else {})
value.update({"example": properties} if example else {})
return value
@ -50,27 +50,46 @@ class HookBase:
return yaml.safe_load(f)
# HookBase extends
class OpenapiHookBase(HookBase):
def hook(self, value: dict):
return value
class RequestHookBase(HookBase):
split: int
path_name: str
def __init__(self, split=1):
super().__init__()
self.split = split
def hook(self, path: str, value: dict):
value["parameters"] = value.get("parameters", [])
self.path_name = "/".join(path.split("/")[self.split :])
return path, value
class AddSecuritySchemesOnSecuritySchemes(HookBase):
# OpenapiHookBase extends
class AddSecuritySchemesOnSecuritySchemes(OpenapiHookBase):
def hook(self, value: dict):
value = super().hook(value)
component = self.load_component("security_schemes")
param = component["components"]["securitySchemes"]
value["components"]["securitySchemes"].extend(param)
return value
# RequestHookBase extends
class AddSecuritySchemesOnHeader(RequestHookBase):
def hook(self, path: str, value: dict):
value["parameters"] = value.get("parameters", [])
path, value = super().hook(path, value)
component = self.load_component("security_schemes")
param = component["paths"]["/parameters"]["get"]["parameters"]
value["parameters"].extend(param)
@ -79,30 +98,30 @@ class AddSecuritySchemesOnHeader(RequestHookBase):
class ReplaceQueryIdPlaceholder(RequestHookBase):
def hook(self, path: str, value: dict):
path_name = path.split("/")[-1]
new = self.PLACEHOLDER[path_name]["queryId"]
path, value = super().hook(path, value)
new = self.PLACEHOLDER[self.path_name]["queryId"]
return path.replace(r"{{queryId}}", new), value
class SetResponsesHeader(RequestHookBase):
prexix: str
suffix: str
def __init__(self, prexix: str = ""):
def __init__(self, suffix: str | None = None):
super().__init__()
self.prexix = prexix if prexix == "" else "_" + prexix
self.suffix = "" if suffix is None else "_" + suffix
def hook(self, path: str, value: dict):
component = self.load_component("response_header" + self.prexix)
path, value = super().hook(path, value)
component = self.load_component("response_header" + self.suffix)
value["responses"]["200"]["headers"] = component["components"]["headers"]
return path, value
class AddParametersOnParametersAsString(RequestHookBase):
def hook(self, path: str, value: dict):
value["parameters"] = value.get("parameters", [])
path_name = path.split("/")[-1]
for key in self.PLACEHOLDER[path_name].keys():
example = json.dumps(self.PLACEHOLDER[path_name][key])
path, value = super().hook(path, value)
for key in self.PLACEHOLDER[self.path_name].keys():
example = json.dumps(self.PLACEHOLDER[self.path_name][key])
value["parameters"].append(
{
"name": key,
@ -120,10 +139,9 @@ class AddParametersOnParametersAsString(RequestHookBase):
class AddParametersOnParametersAsObject(RequestHookBase):
def hook(self, path: str, value: dict):
value["parameters"] = value.get("parameters", [])
path_name = path.split("/")[-1]
for key in self.PLACEHOLDER[path_name].keys():
example = json.dumps(self.PLACEHOLDER[path_name][key])
path, value = super().hook(path, value)
for key in self.PLACEHOLDER[self.path_name].keys():
example = json.dumps(self.PLACEHOLDER[self.path_name][key])
value["parameters"].append(
{
"name": key,
@ -141,9 +159,8 @@ class AddParametersOnParametersAsObject(RequestHookBase):
class AddParametersOnContent(RequestHookBase):
def hook(self, path: str, value: dict):
value["parameters"] = value.get("parameters", [])
path_name = path.split("/")[-1]
for key in self.PLACEHOLDER[path_name].keys():
path, value = super().hook(path, value)
for key in self.PLACEHOLDER[self.path_name].keys():
value["parameters"].append(
{
"name": key,
@ -152,7 +169,7 @@ class AddParametersOnContent(RequestHookBase):
"content": {
"application/json": {
"schema": self.placeholder_to_yaml(
self.PLACEHOLDER[path_name][key]
self.PLACEHOLDER[self.path_name][key]
),
},
},
@ -163,16 +180,15 @@ class AddParametersOnContent(RequestHookBase):
class AddParametersOnParameters(RequestHookBase):
def hook(self, path: str, value: dict):
value["parameters"] = value.get("parameters", [])
path_name = path.split("/")[-1]
for key in self.PLACEHOLDER[path_name].keys():
path, value = super().hook(path, value)
for key in self.PLACEHOLDER[self.path_name].keys():
value["parameters"].append(
{
"name": key,
"in": "query",
"required": True,
"schema": self.placeholder_to_yaml(
self.PLACEHOLDER[path_name][key]
self.PLACEHOLDER[self.path_name][key]
),
}
)
@ -181,9 +197,8 @@ class AddParametersOnParameters(RequestHookBase):
class AddParametersOnBody(RequestHookBase):
def hook(self, path: str, value: dict):
value["parameters"] = value.get("parameters", [])
path_name = path.split("/")[-1]
data = self.PLACEHOLDER[path_name]
path, value = super().hook(path, value)
data = self.PLACEHOLDER[self.path_name]
schema = {i: self.placeholder_to_yaml(data[i]) for i in data.keys()}
value["requestBody"] = {
"description": "body",