From cce687ba158bcaa590cae37eb87f39e70217e926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=B5=E3=81=81?= Date: Fri, 5 May 2023 21:11:19 +0900 Subject: [PATCH] add MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: ふぁ --- ..._v1.1.yaml => response_header_legacy.yaml} | 0 src/config/placeholder.json | 95 +++++++++++++- src/openapi/openapi-3.0.yaml | 12 +- src/openapi/paths/follow.yaml | 4 +- src/openapi/paths/v1.1-get.yaml | 25 ++++ src/openapi/paths/v1.1-post.yaml | 25 ++++ .../paths/{v1.1.yaml => v2.0-get.yaml} | 10 +- tools/build_config.py | 121 ++++++++++-------- tools/hooks.py | 71 ++++++---- 9 files changed, 268 insertions(+), 95 deletions(-) rename src/config/component/{response_header_v1.1.yaml => response_header_legacy.yaml} (100%) create mode 100644 src/openapi/paths/v1.1-get.yaml create mode 100644 src/openapi/paths/v1.1-post.yaml rename src/openapi/paths/{v1.1.yaml => v2.0-get.yaml} (52%) diff --git a/src/config/component/response_header_v1.1.yaml b/src/config/component/response_header_legacy.yaml similarity index 100% rename from src/config/component/response_header_v1.1.yaml rename to src/config/component/response_header_legacy.yaml diff --git a/src/config/placeholder.json b/src/config/placeholder.json index 072d3c7..2089057 100644 --- a/src/config/placeholder.json +++ b/src/config/placeholder.json @@ -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" } } \ No newline at end of file diff --git a/src/openapi/openapi-3.0.yaml b/src/openapi/openapi-3.0.yaml index 4f32d0b..403f3ba 100644 --- a/src/openapi/openapi-3.0.yaml +++ b/src/openapi/openapi-3.0.yaml @@ -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 diff --git a/src/openapi/paths/follow.yaml b/src/openapi/paths/follow.yaml index c0f6eeb..305922f 100644 --- a/src/openapi/paths/follow.yaml +++ b/src/openapi/paths/follow.yaml @@ -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: diff --git a/src/openapi/paths/v1.1-get.yaml b/src/openapi/paths/v1.1-get.yaml new file mode 100644 index 0000000..16d5493 --- /dev/null +++ b/src/openapi/paths/v1.1-get.yaml @@ -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" diff --git a/src/openapi/paths/v1.1-post.yaml b/src/openapi/paths/v1.1-post.yaml new file mode 100644 index 0000000..35104d0 --- /dev/null +++ b/src/openapi/paths/v1.1-post.yaml @@ -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" diff --git a/src/openapi/paths/v1.1.yaml b/src/openapi/paths/v2.0-get.yaml similarity index 52% rename from src/openapi/paths/v1.1.yaml rename to src/openapi/paths/v2.0-get.yaml index 56d1398..2b2b374 100644 --- a/src/openapi/paths/v1.1.yaml +++ b/src/openapi/paths/v2.0-get.yaml @@ -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" diff --git a/tools/build_config.py b/tools/build_config.py index 77d0243..d1821d3 100644 --- a/tools/build_config.py +++ b/tools/build_config.py @@ -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"] }, }, } diff --git a/tools/hooks.py b/tools/hooks.py index dcdff9b..08c51a7 100644 --- a/tools/hooks.py +++ b/tools/hooks.py @@ -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",