1
Fork 0
mirror of https://github.com/thegeneralist01/twitter-openapi synced 2026-01-11 23:50:26 +01:00

Merge pull request #36 from fa0311/dev

Dev
This commit is contained in:
ふぁ 2023-09-17 03:35:27 +09:00 committed by GitHub
commit 5ed23cce61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 1258 additions and 383 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@ __pycache__/
cookie.json cookie.json
*_generated *_generated
*.jar *.jar
cache/

3
.vscode/tasks.json vendored
View file

@ -6,8 +6,10 @@
"type": "shell", "type": "shell",
"linux": { "linux": {
"command": [ "command": [
"source .venv/bin/activate;",
"python3 tools/build.py;", "python3 tools/build.py;",
"java -jar openapi-generator-cli.jar generate -c test/python/openapi-generator-config.yaml -g python;", "java -jar openapi-generator-cli.jar generate -c test/python/openapi-generator-config.yaml -g python;",
"python3 test/python/replace.py;",
"python3 -m pip install ./python_generated;" "python3 -m pip install ./python_generated;"
] ]
}, },
@ -16,6 +18,7 @@
".venv/Scripts/activate;", ".venv/Scripts/activate;",
"python tools/build.py;", "python tools/build.py;",
"java -jar openapi-generator-cli.jar generate -c test/python/openapi-generator-config.yaml -g python;", "java -jar openapi-generator-cli.jar generate -c test/python/openapi-generator-config.yaml -g python;",
"python test/python/replace.py;",
"python -m pip install ./python_generated;" "python -m pip install ./python_generated;"
] ]
} }

View file

@ -47,6 +47,8 @@ components:
superFollowersCount: superFollowersCount:
type: integer type: integer
superFollowsApplicationStatus: superFollowsApplicationStatus:
enum:
- NotStarted
type: string type: string
userFeatures: userFeatures:
$ref: '#/components/schemas/UserFeatures' $ref: '#/components/schemas/UserFeatures'

View file

@ -138,6 +138,9 @@ components:
additionalProperties: true additionalProperties: true
type: object type: object
displayType: displayType:
enum:
- Vertical
- VerticalConversation
type: string type: string
entryType: entryType:
$ref: '#/components/schemas/ContentEntryType' $ref: '#/components/schemas/ContentEntryType'
@ -185,6 +188,10 @@ components:
itemType: itemType:
$ref: '#/components/schemas/ContentItemType' $ref: '#/components/schemas/ContentItemType'
userDisplayType: userDisplayType:
enum:
- User
- UserDetailed
- SubscribableUser
type: string type: string
user_results: user_results:
$ref: ./user.yaml#/components/schemas/UserResults $ref: ./user.yaml#/components/schemas/UserResults

View file

@ -1,5 +1,11 @@
components: components:
schemas: schemas:
AdditionalMediaInfo:
properties:
monetizable:
type: boolean
required:
- monetizable
Entities: Entities:
properties: properties:
hashtags: hashtags:
@ -31,7 +37,7 @@ components:
properties: properties:
media: media:
items: items:
$ref: '#/components/schemas/Media' $ref: '#/components/schemas/MediaExtended'
type: array type: array
required: required:
- media - media
@ -46,8 +52,7 @@ components:
expanded_url: expanded_url:
format: uri format: uri
type: string type: string
ext_media_availability: features:
additionalProperties: true
type: object type: object
id_str: id_str:
pattern: ^[0-9]+$ pattern: ^[0-9]+$
@ -56,42 +61,180 @@ components:
items: items:
type: integer type: integer
type: array type: array
media_key:
pattern: ^[0-9]+_[0-9]+$
type: string
media_url_https: media_url_https:
format: uri format: uri
type: string type: string
original_info: original_info:
properties: $ref: '#/components/schemas/MediaOriginalInfo'
focus_rects:
items:
additionalProperties: true
type: object
type: array
height:
type: integer
width:
type: integer
type: object
sizes: sizes:
additionalProperties: true $ref: '#/components/schemas/MediaSizes'
type: object
type: type:
enum:
- photo
- video
- animated_gif
type: string type: string
url: url:
format: uri format: uri
type: string type: string
required: required:
- display_url
- expanded_url
- id_str - id_str
- indices - indices
- media_url_https - media_url_https
- url
- display_url
- expanded_url
- type - type
- url
- sizes - sizes
- original_info - original_info
MediaExtended:
properties:
additional_media_info:
$ref: '#/components/schemas/AdditionalMediaInfo'
display_url:
format: uri
type: string
expanded_url:
format: uri
type: string
ext_media_availability:
$ref: '#/components/schemas/extMediaAvailability'
features:
type: object
id_str:
pattern: ^[0-9]+$
type: string
indices:
items:
type: integer
type: array
mediaStats:
$ref: '#/components/schemas/mediaStats'
media_key:
type: string
media_url_https:
format: uri
type: string
original_info:
$ref: '#/components/schemas/MediaOriginalInfo'
sizes:
$ref: '#/components/schemas/MediaSizes'
type:
enum:
- photo
- video
- animated_gif
type: string
url:
format: uri
type: string
video_info:
$ref: '#/components/schemas/MediaVideoInfo'
required:
- display_url
- expanded_url
- id_str
- indices
- media_key
- media_url_https
- type
- url
- ext_media_availability
- sizes
- original_info
MediaOriginalInfo:
properties:
focus_rects:
items:
$ref: '#/components/schemas/MediaOriginalInfoFocusRect'
type: array
height:
type: integer
width:
type: integer
required:
- height
- width
MediaOriginalInfoFocusRect:
properties:
h:
type: integer
w:
type: integer
x:
type: integer
y:
type: integer
required:
- x
- y
- w
- h
type: object
MediaSize:
properties:
h:
type: integer
resize:
enum:
- crop
- fit
type: string
w:
type: integer
required:
- w
- h
- resize
MediaSizes:
properties:
large:
$ref: '#/components/schemas/MediaSize'
medium:
$ref: '#/components/schemas/MediaSize'
small:
$ref: '#/components/schemas/MediaSize'
thumb:
$ref: '#/components/schemas/MediaSize'
required:
- large
- medium
- small
- thumb
MediaVideoInfo:
properties:
aspect_ratio:
items:
type: integer
type: array
duration_millis:
type: integer
variants:
items:
$ref: '#/components/schemas/MediaVideoInfoVariant'
type: array
required:
- aspect_ratio
- variants
MediaVideoInfoVariant:
properties:
bitrate:
type: integer
content_type:
type: string
url:
format: uri
type: string
required:
- content_type
- url
SelfThread:
properties:
id_str:
pattern: ^[0-9]+$
type: string
required:
- id_str
Symbol: Symbol:
additionalProperties: true additionalProperties: true
type: object type: object
@ -100,15 +243,68 @@ components:
__typename: __typename:
$ref: ./typename.yaml#/components/schemas/TypeName $ref: ./typename.yaml#/components/schemas/TypeName
card: card:
$ref: '#/components/schemas/TweetCard'
core:
$ref: ./user.yaml#/components/schemas/UserResultCore
edit_control:
$ref: '#/components/schemas/TweetEditControl'
edit_prespective:
$ref: '#/components/schemas/TweetEditPrespective'
is_translatable:
default: false
type: boolean
legacy:
$ref: '#/components/schemas/TweetLegacy'
quoted_status_result:
$ref: ./content.yaml#/components/schemas/ItemResult
rest_id:
pattern: ^[0-9]+$
type: string
source:
type: string
unmention_data:
additionalProperties: true
type: object
views:
$ref: '#/components/schemas/TweetView'
required:
- rest_id
- core
- edit_control
- is_translatable
- source
- legacy
- views
TweetCard:
properties: properties:
legacy: legacy:
$ref: '#/components/schemas/TweetCardLegacy'
rest_id:
type: string
TweetCardLegacy:
properties: properties:
binding_values: binding_values:
items: items:
$ref: '#/components/schemas/TweetCardLegacyBindingValue'
type: array
name:
type: string
url:
type: string
required:
- binding_values
- name
- url
TweetCardLegacyBindingValue:
properties: properties:
key: key:
type: string type: string
value: value:
$ref: '#/components/schemas/TweetCardLegacyBindingValueData'
required:
- key
- value
TweetCardLegacyBindingValueData:
properties: properties:
boolean_value: boolean_value:
type: boolean type: boolean
@ -120,27 +316,27 @@ components:
type: string type: string
required: required:
- type - type
type: object TweetEditControl:
required: properties:
- key edit_control_initial:
- value $ref: '#/components/schemas/TweetEditControlInitial'
type: object edit_tweet_ids:
items:
pattern: ^[0-9]+$
type: string
type: array type: array
name: editable_until_msecs:
pattern: ^[0-9]+$
type: string type: string
url: edits_remaining:
pattern: ^[0-9]+$
type: string type: string
required: initial_tweet_id:
- binding_values pattern: ^[0-9]+$
- name
- url
type: object
rest_id:
type: string type: string
type: object is_edit_eligible:
core: type: boolean
$ref: ./user.yaml#/components/schemas/UserResultCore TweetEditControlInitial:
edit_control:
properties: properties:
edit_tweet_ids: edit_tweet_ids:
items: items:
@ -155,42 +351,17 @@ components:
type: string type: string
is_edit_eligible: is_edit_eligible:
type: boolean type: boolean
type: object required:
edit_prespective: - edit_tweet_ids
- editable_until_msecs
- is_edit_eligible
- edits_remaining
TweetEditPrespective:
properties: properties:
favorited: favorited:
type: boolean type: boolean
retweeted: retweeted:
type: boolean type: boolean
type: object
is_translatable:
default: false
type: boolean
legacy:
$ref: '#/components/schemas/TweetLegacy'
quoted_status_result:
$ref: ./content.yaml#/components/schemas/ItemResult
rest_id:
pattern: ^[0-9]+$
type: string
unmention_data:
additionalProperties: true
type: object
views:
properties:
count:
pattern: ^[0-9]+$
type: string
state:
type: string
type: object
required:
- rest_id
- core
- edit_control
- is_translatable
- legacy
- views
TweetLegacy: TweetLegacy:
properties: properties:
bookmark_count: bookmark_count:
@ -240,13 +411,7 @@ components:
retweeted_status_result: retweeted_status_result:
$ref: ./content.yaml#/components/schemas/ItemResult $ref: ./content.yaml#/components/schemas/ItemResult
self_thread: self_thread:
properties: $ref: '#/components/schemas/SelfThread'
id_str:
pattern: ^[0-9]+$
type: string
required:
- id_str
type: object
user_id_str: user_id_str:
pattern: ^[0-9]+$ pattern: ^[0-9]+$
type: string type: string
@ -284,6 +449,17 @@ components:
- $ref: '#/components/schemas/Tweet' - $ref: '#/components/schemas/Tweet'
- $ref: '#/components/schemas/TweetWithVisibilityResults' - $ref: '#/components/schemas/TweetWithVisibilityResults'
- $ref: '#/components/schemas/TweetTombstone' - $ref: '#/components/schemas/TweetTombstone'
TweetView:
properties:
count:
pattern: ^[0-9]+$
type: string
state:
enum:
- EnabledWithCount
type: string
required:
- state
TweetWithVisibilityResults: TweetWithVisibilityResults:
properties: properties:
__typename: __typename:
@ -316,6 +492,20 @@ components:
UserMention: UserMention:
additionalProperties: true additionalProperties: true
type: object type: object
extMediaAvailability:
properties:
status:
enum:
- Available
type: string
required:
- status
mediaStats:
properties:
viewCount:
type: integer
required:
- viewCount
info: info:
title: Twitter OpenAPI title: Twitter OpenAPI
version: 0.0.1 version: 0.0.1

View file

@ -11,6 +11,7 @@ components:
- TweetTombstone - TweetTombstone
- TimelinePrompt - TimelinePrompt
- TimelineMessagePrompt - TimelineMessagePrompt
- TweetUnavailable
- Tweet - Tweet
- User - User
- UserUnavailable - UserUnavailable

View file

@ -47,6 +47,8 @@ components:
superFollowersCount: superFollowersCount:
type: integer type: integer
superFollowsApplicationStatus: superFollowsApplicationStatus:
enum:
- NotStarted
type: string type: string
userFeatures: userFeatures:
$ref: '#/components/schemas/UserFeatures' $ref: '#/components/schemas/UserFeatures'

View file

@ -138,6 +138,9 @@ components:
additionalProperties: true additionalProperties: true
type: object type: object
displayType: displayType:
enum:
- Vertical
- VerticalConversation
type: string type: string
entryType: entryType:
$ref: '#/components/schemas/ContentEntryType' $ref: '#/components/schemas/ContentEntryType'
@ -185,6 +188,10 @@ components:
itemType: itemType:
$ref: '#/components/schemas/ContentItemType' $ref: '#/components/schemas/ContentItemType'
userDisplayType: userDisplayType:
enum:
- User
- UserDetailed
- SubscribableUser
type: string type: string
user_results: user_results:
$ref: ./user.yaml#/components/schemas/UserResults $ref: ./user.yaml#/components/schemas/UserResults

View file

@ -1,5 +1,11 @@
components: components:
schemas: schemas:
AdditionalMediaInfo:
properties:
monetizable:
type: boolean
required:
- monetizable
Entities: Entities:
properties: properties:
hashtags: hashtags:
@ -31,7 +37,7 @@ components:
properties: properties:
media: media:
items: items:
$ref: '#/components/schemas/Media' $ref: '#/components/schemas/MediaExtended'
type: array type: array
required: required:
- media - media
@ -46,8 +52,7 @@ components:
expanded_url: expanded_url:
format: uri format: uri
type: string type: string
ext_media_availability: features:
additionalProperties: true
type: object type: object
id_str: id_str:
pattern: ^[0-9]+$ pattern: ^[0-9]+$
@ -56,42 +61,180 @@ components:
items: items:
type: integer type: integer
type: array type: array
media_key:
pattern: ^[0-9]+_[0-9]+$
type: string
media_url_https: media_url_https:
format: uri format: uri
type: string type: string
original_info: original_info:
properties: $ref: '#/components/schemas/MediaOriginalInfo'
focus_rects:
items:
additionalProperties: true
type: object
type: array
height:
type: integer
width:
type: integer
type: object
sizes: sizes:
additionalProperties: true $ref: '#/components/schemas/MediaSizes'
type: object
type: type:
enum:
- photo
- video
- animated_gif
type: string type: string
url: url:
format: uri format: uri
type: string type: string
required: required:
- display_url
- expanded_url
- id_str - id_str
- indices - indices
- media_url_https - media_url_https
- url
- display_url
- expanded_url
- type - type
- url
- sizes - sizes
- original_info - original_info
MediaExtended:
properties:
additional_media_info:
$ref: '#/components/schemas/AdditionalMediaInfo'
display_url:
format: uri
type: string
expanded_url:
format: uri
type: string
ext_media_availability:
$ref: '#/components/schemas/extMediaAvailability'
features:
type: object
id_str:
pattern: ^[0-9]+$
type: string
indices:
items:
type: integer
type: array
mediaStats:
$ref: '#/components/schemas/mediaStats'
media_key:
type: string
media_url_https:
format: uri
type: string
original_info:
$ref: '#/components/schemas/MediaOriginalInfo'
sizes:
$ref: '#/components/schemas/MediaSizes'
type:
enum:
- photo
- video
- animated_gif
type: string
url:
format: uri
type: string
video_info:
$ref: '#/components/schemas/MediaVideoInfo'
required:
- display_url
- expanded_url
- id_str
- indices
- media_key
- media_url_https
- type
- url
- ext_media_availability
- sizes
- original_info
MediaOriginalInfo:
properties:
focus_rects:
items:
$ref: '#/components/schemas/MediaOriginalInfoFocusRect'
type: array
height:
type: integer
width:
type: integer
required:
- height
- width
MediaOriginalInfoFocusRect:
properties:
h:
type: integer
w:
type: integer
x:
type: integer
y:
type: integer
required:
- x
- y
- w
- h
type: object
MediaSize:
properties:
h:
type: integer
resize:
enum:
- crop
- fit
type: string
w:
type: integer
required:
- w
- h
- resize
MediaSizes:
properties:
large:
$ref: '#/components/schemas/MediaSize'
medium:
$ref: '#/components/schemas/MediaSize'
small:
$ref: '#/components/schemas/MediaSize'
thumb:
$ref: '#/components/schemas/MediaSize'
required:
- large
- medium
- small
- thumb
MediaVideoInfo:
properties:
aspect_ratio:
items:
type: integer
type: array
duration_millis:
type: integer
variants:
items:
$ref: '#/components/schemas/MediaVideoInfoVariant'
type: array
required:
- aspect_ratio
- variants
MediaVideoInfoVariant:
properties:
bitrate:
type: integer
content_type:
type: string
url:
format: uri
type: string
required:
- content_type
- url
SelfThread:
properties:
id_str:
pattern: ^[0-9]+$
type: string
required:
- id_str
Symbol: Symbol:
additionalProperties: true additionalProperties: true
type: object type: object
@ -100,15 +243,68 @@ components:
__typename: __typename:
$ref: ./typename.yaml#/components/schemas/TypeName $ref: ./typename.yaml#/components/schemas/TypeName
card: card:
$ref: '#/components/schemas/TweetCard'
core:
$ref: ./user.yaml#/components/schemas/UserResultCore
edit_control:
$ref: '#/components/schemas/TweetEditControl'
edit_prespective:
$ref: '#/components/schemas/TweetEditPrespective'
is_translatable:
default: false
type: boolean
legacy:
$ref: '#/components/schemas/TweetLegacy'
quoted_status_result:
$ref: ./content.yaml#/components/schemas/ItemResult
rest_id:
pattern: ^[0-9]+$
type: string
source:
type: string
unmention_data:
additionalProperties: true
type: object
views:
$ref: '#/components/schemas/TweetView'
required:
- rest_id
- core
- edit_control
- is_translatable
- source
- legacy
- views
TweetCard:
properties: properties:
legacy: legacy:
$ref: '#/components/schemas/TweetCardLegacy'
rest_id:
type: string
TweetCardLegacy:
properties: properties:
binding_values: binding_values:
items: items:
$ref: '#/components/schemas/TweetCardLegacyBindingValue'
type: array
name:
type: string
url:
type: string
required:
- binding_values
- name
- url
TweetCardLegacyBindingValue:
properties: properties:
key: key:
type: string type: string
value: value:
$ref: '#/components/schemas/TweetCardLegacyBindingValueData'
required:
- key
- value
TweetCardLegacyBindingValueData:
properties: properties:
boolean_value: boolean_value:
type: boolean type: boolean
@ -120,27 +316,27 @@ components:
type: string type: string
required: required:
- type - type
type: object TweetEditControl:
required: properties:
- key edit_control_initial:
- value $ref: '#/components/schemas/TweetEditControlInitial'
type: object edit_tweet_ids:
items:
pattern: ^[0-9]+$
type: string
type: array type: array
name: editable_until_msecs:
pattern: ^[0-9]+$
type: string type: string
url: edits_remaining:
pattern: ^[0-9]+$
type: string type: string
required: initial_tweet_id:
- binding_values pattern: ^[0-9]+$
- name
- url
type: object
rest_id:
type: string type: string
type: object is_edit_eligible:
core: type: boolean
$ref: ./user.yaml#/components/schemas/UserResultCore TweetEditControlInitial:
edit_control:
properties: properties:
edit_tweet_ids: edit_tweet_ids:
items: items:
@ -155,42 +351,17 @@ components:
type: string type: string
is_edit_eligible: is_edit_eligible:
type: boolean type: boolean
type: object required:
edit_prespective: - edit_tweet_ids
- editable_until_msecs
- is_edit_eligible
- edits_remaining
TweetEditPrespective:
properties: properties:
favorited: favorited:
type: boolean type: boolean
retweeted: retweeted:
type: boolean type: boolean
type: object
is_translatable:
default: false
type: boolean
legacy:
$ref: '#/components/schemas/TweetLegacy'
quoted_status_result:
$ref: ./content.yaml#/components/schemas/ItemResult
rest_id:
pattern: ^[0-9]+$
type: string
unmention_data:
additionalProperties: true
type: object
views:
properties:
count:
pattern: ^[0-9]+$
type: string
state:
type: string
type: object
required:
- rest_id
- core
- edit_control
- is_translatable
- legacy
- views
TweetLegacy: TweetLegacy:
properties: properties:
bookmark_count: bookmark_count:
@ -240,13 +411,7 @@ components:
retweeted_status_result: retweeted_status_result:
$ref: ./content.yaml#/components/schemas/ItemResult $ref: ./content.yaml#/components/schemas/ItemResult
self_thread: self_thread:
properties: $ref: '#/components/schemas/SelfThread'
id_str:
pattern: ^[0-9]+$
type: string
required:
- id_str
type: object
user_id_str: user_id_str:
pattern: ^[0-9]+$ pattern: ^[0-9]+$
type: string type: string
@ -284,6 +449,17 @@ components:
- $ref: '#/components/schemas/Tweet' - $ref: '#/components/schemas/Tweet'
- $ref: '#/components/schemas/TweetWithVisibilityResults' - $ref: '#/components/schemas/TweetWithVisibilityResults'
- $ref: '#/components/schemas/TweetTombstone' - $ref: '#/components/schemas/TweetTombstone'
TweetView:
properties:
count:
pattern: ^[0-9]+$
type: string
state:
enum:
- EnabledWithCount
type: string
required:
- state
TweetWithVisibilityResults: TweetWithVisibilityResults:
properties: properties:
__typename: __typename:
@ -316,6 +492,20 @@ components:
UserMention: UserMention:
additionalProperties: true additionalProperties: true
type: object type: object
extMediaAvailability:
properties:
status:
enum:
- Available
type: string
required:
- status
mediaStats:
properties:
viewCount:
type: integer
required:
- viewCount
info: info:
title: Twitter OpenAPI title: Twitter OpenAPI
version: 0.0.1 version: 0.0.1

View file

@ -11,6 +11,7 @@ components:
- TweetTombstone - TweetTombstone
- TimelinePrompt - TimelinePrompt
- TimelineMessagePrompt - TimelineMessagePrompt
- TweetUnavailable
- Tweet - Tweet
- User - User
- UserUnavailable - UserUnavailable

View file

@ -68,7 +68,8 @@ components:
superFollowersCount: superFollowersCount:
type: integer type: integer
superFollowsApplicationStatus: superFollowsApplicationStatus:
type: string # enum: NotStarted type: string
enum: [NotStarted]
user_id: user_id:
type: string type: string
pattern: "^[0-9]+$" pattern: "^[0-9]+$"

View file

@ -40,8 +40,7 @@ components:
itemContent: itemContent:
$ref: "#/components/schemas/ItemContentUnion" $ref: "#/components/schemas/ItemContentUnion"
clientEventInfo: clientEventInfo:
type: object $ref: "#/components/schemas/ClientEventInfo"
additionalProperties: true # todo
feedbackInfo: feedbackInfo:
type: object type: object
additionalProperties: true # todo additionalProperties: true # todo
@ -60,7 +59,8 @@ components:
entryType: entryType:
$ref: "#/components/schemas/ContentEntryType" # TimelineTimelineCursor $ref: "#/components/schemas/ContentEntryType" # TimelineTimelineCursor
displayType: displayType:
type: string # enum type: string
enum: [Vertical, VerticalConversation]
items: items:
type: array type: array
items: items:
@ -112,8 +112,7 @@ components:
- "itemContent" - "itemContent"
properties: properties:
clientEventInfo: clientEventInfo:
type: object $ref: "#/components/schemas/ClientEventInfo"
additionalProperties: true # todo
itemContent: itemContent:
$ref: "#/components/schemas/ItemContentUnion" $ref: "#/components/schemas/ItemContentUnion"
@ -183,13 +182,13 @@ components:
SocialContext: SocialContext:
$ref: "#/components/schemas/SocialContext" $ref: "#/components/schemas/SocialContext"
userDisplayType: userDisplayType:
type: string # enum type: string
enum: [User, UserDetailed, SubscribableUser]
user_results: user_results:
$ref: "./user.yaml#/components/schemas/UserResults" $ref: "./user.yaml#/components/schemas/UserResults"
ItemResult: ItemResult:
required: required:
- "result"
properties: properties:
__typename: __typename:
$ref: "./typename.yaml#/components/schemas/TypeName" # null | TimelineTweet $ref: "./typename.yaml#/components/schemas/TypeName" # null | TimelineTweet
@ -217,3 +216,17 @@ components:
__typename: __typename:
$ref: "./typename.yaml#/components/schemas/TypeName" # TimelineMessagePrompt $ref: "./typename.yaml#/components/schemas/TypeName" # TimelineMessagePrompt
additionalProperties: true # todo additionalProperties: true # todo
ClientEventInfo:
properties:
component:
# enum half_cover
type: string
element:
type: string
# august-2023-privacy-prompt-candidate
# pattern: "(([a-z]+|[0-9]+|[0-9a-f]+)(-|$))+"
# pattern: "^(january|february|march|april|may|june|july|august|september|october|november|december)-[0-9]{4}-([a-z]-)+[a-z]+$"
details:
type: object
additionalProperties: true # todo

View file

@ -15,6 +15,8 @@ components:
- $ref: "#/components/schemas/TimelineReplaceEntry" - $ref: "#/components/schemas/TimelineReplaceEntry"
- $ref: "#/components/schemas/TimelineShowAlert" - $ref: "#/components/schemas/TimelineShowAlert"
- $ref: "#/components/schemas/TimelineTerminateTimeline" - $ref: "#/components/schemas/TimelineTerminateTimeline"
- $ref: "#/components/schemas/TimelineShowCover"
discriminator: discriminator:
propertyName: type propertyName: type
mapping": # deprecated mapping": # deprecated
@ -25,6 +27,7 @@ components:
TimelineReplaceEntry: "#/components/schemas/TimelineReplaceEntry" TimelineReplaceEntry: "#/components/schemas/TimelineReplaceEntry"
TimelineShowAlert: "#/components/schemas/TimelineShowAlert" TimelineShowAlert: "#/components/schemas/TimelineShowAlert"
TimelineTerminateTimeline: "#/components/schemas/TimelineTerminateTimeline" TimelineTerminateTimeline: "#/components/schemas/TimelineTerminateTimeline"
TimelineShowCover: "#/components/schemas/TimelineShowCover"
InstructionType: InstructionType:
type: string type: string
@ -37,6 +40,7 @@ components:
TimelineReplaceEntry, TimelineReplaceEntry,
TimelineShowAlert, TimelineShowAlert,
TimelineTerminateTimeline, TimelineTerminateTimeline,
TimelineShowCover,
] ]
TimelineAddEntries: TimelineAddEntries:
@ -162,3 +166,133 @@ components:
sortIndex: sortIndex:
type: string type: string
pattern: "[0-9]+$" pattern: "[0-9]+$"
TimelineShowCover:
required:
- type
- clientEventInfo
- cover
properties:
type:
$ref: "#/components/schemas/InstructionType" # TimelineShowCover
clientEventInfo:
$ref: "./content.yaml#/components/schemas/ClientEventInfo"
cover:
$ref: "#/components/schemas/TimelineHalfCover"
TimelineHalfCover:
required:
- type
- halfCoverDisplayType
- primaryText
- primaryCoverCta
- secondaryText
- impressionCallbacks
- dismissible
properties:
type:
type: string
enum: [TimelineHalfCover]
halfCoverDisplayType:
type: string
enum: [Cover]
primaryText:
$ref: "#/components/schemas/Text"
secondaryText:
$ref: "#/components/schemas/Text"
primaryCoverCta:
$ref: "#/components/schemas/CoverCta"
impressionCallbacks:
type: array
items:
$ref: "#/components/schemas/Callback"
dismissible:
type: boolean
Text:
required:
- text
- entities
properties:
text:
type: string
entities:
type: array
items:
$ref: "#/components/schemas/TextEntity"
TextEntity:
required:
- fromIndex
- toIndex
- ref
properties:
fromIndex:
type: integer
toIndex:
type: integer
ref:
$ref: "#/components/schemas/TextEntityRef"
TextEntityRef:
required:
- type
- url
- urlType
properties:
type:
type: string
enum: [TimelineUrl]
url:
type: string
format: uri
urlType:
type: string
enum: [ExternalUrl]
CoverCta:
required:
- text
- ctaBehavior
- callbacks
- clientEventInfo
- buttonStyle
properties:
Text:
type: string
ctaBehavior:
$ref: "#/components/schemas/TimelineCoverBehavior"
callbacks:
type: array
items:
$ref: "#/components/schemas/Callback"
clientEventInfo:
$ref: "#/components/schemas/CtaClientEventInfo"
buttonStyle:
type: string
enum: ["Primary"]
TimelineCoverBehavior:
required:
- type
properties:
type:
type: string
enum: [TimelineCoverBehaviorDismiss]
Callback:
required:
- endpoint
properties:
endpoint:
type: string
format: uri
# pattern: '^/1\.1/[a-z]+/[a-z]+\.json\?[a-z_]+=[a-z0-9-]+(&[a-z_]+=[a-z0-9-]+)+?$' #/1.1/onboarding/fatigue.json?{params}
CtaClientEventInfo:
required:
- action
properties:
action:
type: string
enum: [primary_cta]

View file

@ -38,11 +38,12 @@ components:
Tweet: Tweet:
required: required:
- "rest_id" - "rest_id"
- "core" # If the tweet has been edited, this property does not exist.
# - "core"
- "edit_control" - "edit_control"
# - "edit_prespective"
- "is_translatable" - "is_translatable"
- "legacy" # - "source"
# - "legacy"
- "views" - "views"
properties: properties:
@ -54,49 +55,27 @@ components:
core: core:
$ref: "./user.yaml#/components/schemas/UserResultCore" $ref: "./user.yaml#/components/schemas/UserResultCore"
card: card:
type: object $ref: "#/components/schemas/TweetCard"
properties:
rest_id:
type: string
legacy:
type: object
required:
- "binding_values"
- "name"
- "url"
properties:
name:
type: string
url:
type: string
binding_values:
type: array
items:
type: object
required:
- "key"
- "value"
properties:
key:
type: string
value:
type: object
required:
- "type"
properties:
string_value:
type: string
boolean_value:
type: boolean
scribe_key:
type: string
type:
type: string
unmention_data: unmention_data:
type: object type: object
additionalProperties: true # todo additionalProperties: true # todo
edit_control: edit_control:
type: object $ref: "#/components/schemas/TweetEditControl"
edit_prespective:
$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:
$ref: "#/components/schemas/TweetLegacy"
views:
$ref: "#/components/schemas/TweetView"
quoted_status_result:
$ref: "./content.yaml#/components/schemas/ItemResult"
TweetEditControl:
properties: properties:
edit_tweet_ids: edit_tweet_ids:
type: array type: array
@ -111,28 +90,94 @@ components:
edits_remaining: edits_remaining:
type: string type: string
pattern: "^[0-9]+$" pattern: "^[0-9]+$"
edit_prespective: initial_tweet_id:
type: object type: string
pattern: "^[0-9]+$"
edit_control_initial:
$ref: "#/components/schemas/TweetEditControlInitial"
TweetEditControlInitial:
required:
- "edit_tweet_ids"
- "editable_until_msecs"
- "is_edit_eligible"
- "edits_remaining"
properties:
edit_tweet_ids:
type: array
items:
type: string
pattern: "^[0-9]+$"
editable_until_msecs:
type: string
pattern: "^[0-9]+$"
is_edit_eligible:
type: boolean
edits_remaining:
type: string
pattern: "^[0-9]+$"
TweetEditPrespective:
properties: properties:
favorited: favorited:
type: boolean type: boolean
retweeted: retweeted:
type: boolean type: boolean
is_translatable: TweetView:
type: boolean required:
default: false - "state"
legacy:
$ref: "#/components/schemas/TweetLegacy"
views:
type: object
properties: properties:
count: count:
type: string type: string
pattern: "^[0-9]+$" pattern: "^[0-9]+$"
state: state:
type: string # enum type: string
quoted_status_result: enum: [EnabledWithCount]
$ref: "./content.yaml#/components/schemas/ItemResult"
TweetCard:
properties:
rest_id:
type: string
legacy:
$ref: "#/components/schemas/TweetCardLegacy"
TweetCardLegacy:
required:
- "binding_values"
- "name"
- "url"
properties:
name:
type: string
url:
type: string
binding_values:
type: array
items:
$ref: "#/components/schemas/TweetCardLegacyBindingValue"
TweetCardLegacyBindingValue:
required:
- "key"
- "value"
properties:
key:
type: string
value:
$ref: "#/components/schemas/TweetCardLegacyBindingValueData"
TweetCardLegacyBindingValueData:
required:
- "type"
properties:
string_value:
type: string
boolean_value:
type: boolean
scribe_key:
type: string
type:
type: string
TweetLegacy: TweetLegacy:
required: required:
@ -202,15 +247,17 @@ components:
type: string type: string
pattern: "^[0-9]+$" pattern: "^[0-9]+$"
self_thread: self_thread:
type: object $ref: "#/components/schemas/SelfThread"
extended_entities:
$ref: "#/components/schemas/ExtendedEntities"
SelfThread:
required: required:
- "id_str" - "id_str"
properties: properties:
id_str: id_str:
type: string type: string
pattern: "^[0-9]+$" pattern: "^[0-9]+$"
extended_entities:
$ref: "#/components/schemas/ExtendedEntities"
Entities: Entities:
required: required:
@ -218,7 +265,6 @@ components:
- "symbols" - "symbols"
- "user_mentions" - "user_mentions"
- "urls" - "urls"
# - "media"
properties: properties:
hashtags: hashtags:
type: array type: array
@ -271,27 +317,25 @@ components:
items: items:
type: integer type: integer
ExtendedEntities:
required:
- "media"
properties:
media:
type: array
items:
$ref: "#/components/schemas/Media"
Media: Media:
required: required:
- "display_url"
- "expanded_url"
- "id_str" - "id_str"
- "indices" - "indices"
- "media_url_https" - "media_url_https"
- "url"
- "display_url"
- "expanded_url"
- "type" - "type"
- "url"
# - "features"
- "sizes" - "sizes"
- "original_info" - "original_info"
properties: properties:
display_url:
type: string
format: uri
expanded_url:
type: string
format: uri
id_str: id_str:
type: string type: string
pattern: "^[0-9]+$" pattern: "^[0-9]+$"
@ -302,22 +346,86 @@ components:
media_url_https: media_url_https:
type: string type: string
format: uri format: uri
type:
type: string
enum: [photo, video, animated_gif]
url: url:
type: string type: string
format: uri format: uri
features:
type: object
sizes:
$ref: "#/components/schemas/MediaSizes"
original_info:
$ref: "#/components/schemas/MediaOriginalInfo"
ExtendedEntities:
required:
- "media"
properties:
media:
type: array
items:
$ref: "#/components/schemas/MediaExtended"
MediaExtended:
required:
- "display_url"
- "expanded_url"
- "id_str"
- "indices"
- "media_key"
- "media_url_https"
- "type"
- "url"
- "ext_media_availability"
# - "features"
- "sizes"
- "original_info"
properties:
display_url: display_url:
type: string type: string
format: uri format: uri
expanded_url: expanded_url:
type: string type: string
format: uri format: uri
id_str:
type: string
pattern: "^[0-9]+$"
indices:
type: array
items:
type: integer
media_key:
type: string
media_url_https:
type: string
format: uri
type: type:
type: string # enum type: string
enum: [photo, video, animated_gif]
url:
type: string
format: uri
additional_media_info:
$ref: "#/components/schemas/AdditionalMediaInfo"
mediaStats:
$ref: "#/components/schemas/mediaStats"
ext_media_availability:
$ref: "#/components/schemas/extMediaAvailability"
features:
type: object
sizes: sizes:
type: object $ref: "#/components/schemas/MediaSizes"
additionalProperties: true # todo
original_info: original_info:
type: object $ref: "#/components/schemas/MediaOriginalInfo"
video_info:
$ref: "#/components/schemas/MediaVideoInfo"
MediaOriginalInfo:
required:
- "height"
- "width"
properties: properties:
height: height:
type: integer type: integer
@ -326,11 +434,102 @@ components:
focus_rects: focus_rects:
type: array type: array
items: items:
$ref: "#/components/schemas/MediaOriginalInfoFocusRect"
MediaOriginalInfoFocusRect:
type: object type: object
additionalProperties: true # todo required:
media_key: - "x"
- "y"
- "w"
- "h"
properties:
x:
type: integer
y:
type: integer
w:
type: integer
h:
type: integer
MediaVideoInfo:
required:
- "aspect_ratio"
- "variants"
properties:
aspect_ratio:
type: array
items:
type: integer
duration_millis:
type: integer
variants:
type: array
items:
$ref: "#/components/schemas/MediaVideoInfoVariant"
MediaVideoInfoVariant:
required:
- "content_type"
- "url"
properties:
bitrate:
type: integer
content_type:
type: string type: string
pattern: "^[0-9]+_[0-9]+$" url:
ext_media_availability: type: string
type: object format: uri
additionalProperties: true # todo
AdditionalMediaInfo:
required:
- "monetizable"
properties:
monetizable:
type: boolean
mediaStats:
required:
- "viewCount"
properties:
viewCount:
type: integer
extMediaAvailability:
# required:
# - "status"
properties:
status:
type: string
enum: [Available]
MediaSizes:
required:
- "large"
- "medium"
- "small"
- "thumb"
properties:
large:
$ref: "#/components/schemas/MediaSize"
medium:
$ref: "#/components/schemas/MediaSize"
small:
$ref: "#/components/schemas/MediaSize"
thumb:
$ref: "#/components/schemas/MediaSize"
MediaSize:
required:
- "w"
- "h"
- "resize"
properties:
w:
type: integer
h:
type: integer
resize:
type: string
enum: [crop, fit]

View file

@ -18,6 +18,7 @@ components:
TweetTombstone, TweetTombstone,
TimelinePrompt, TimelinePrompt,
TimelineMessagePrompt, TimelineMessagePrompt,
TweetUnavailable,
Tweet, Tweet,
User, User,
UserUnavailable, UserUnavailable,

23
test/python/replace.py Normal file
View file

@ -0,0 +1,23 @@
import glob
for file in glob.glob("python_generated/openapi_client/models/*.py"):
with open(file, "r") as f:
text = f.read()
indent = " "
text = text.replace(
f"{indent}{indent}try:",
f"{indent}{indent}if match == 0:",
)
text = text.replace(
f"{indent}{indent}except (ValidationError, ValueError) as e:",
f"{indent}{indent}else:",
)
text = text.replace(
f"{indent}{indent}{indent}error_messages.append(str(e))",
f"{indent}{indent}{indent}pass",
)
with open(file, "w") as f:
f.write(text)

View file

@ -5,6 +5,10 @@ import base64
import openapi_client as pt import openapi_client as pt
from pathlib import Path from pathlib import Path
import time import time
import glob
import aenum
import concurrent.futures
import traceback
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s %(levelname)s %(message)s") logging.basicConfig(level=logging.DEBUG, format="%(asctime)s %(levelname)s %(message)s")
@ -14,23 +18,7 @@ TWITTER_SESSION = os.environ.get("TWITTER_SESSION", None)
ERROR_UNCATCHED = os.environ.get("ERROR_UNCATCHED", "false").lower() == "true" ERROR_UNCATCHED = os.environ.get("ERROR_UNCATCHED", "false").lower() == "true"
SLEEP_TIME = float(os.environ.get("SLEEP", "0")) SLEEP_TIME = float(os.environ.get("SLEEP", "0"))
CUESOR_TEST_COUNT = int(os.environ.get("CUESOR_TEST_COUNT", "3")) CUESOR_TEST_COUNT = int(os.environ.get("CUESOR_TEST_COUNT", "3"))
STRICT_MODE = os.environ.get("STRICT_MODE", "false").lower() == "true"
if Path("cookie.json").exists():
with open("cookie.json", "r") as f:
cookies = json.load(f)
elif TWITTER_SESSION is not None:
data = base64.b64decode(TWITTER_SESSION).decode("utf-8")
cookies = json.loads(data)
else:
commands = ["python -m pip install tweepy_authlib", "python tools/login.py"]
raise Exception(f'cookie.json not found. Please run `{"; ".join(commands)}` first.')
cookies_str = "; ".join([f"{k}={v}" for k, v in cookies.items()])
with open("src/config/placeholder.json", "r") as f:
placeholder = json.load(f)
def get_key(snake_str): def get_key(snake_str):
@ -74,10 +62,68 @@ def get_kwargs(key, additional):
return kwargs return kwargs
def match_rate_zero(key):
if STRICT_MODE:
raise Exception(f"Strict mode: {key}")
return 0
def match_rate(a, b, key=""):
if isinstance(a, aenum.Enum):
a = a.value
if isinstance(b, aenum.Enum):
b = b.value
if a is None and b is False:
return 1
if a is False and b is None:
return 1
if type(a) != type(b):
return match_rate_zero(key)
if type(a) == dict and type(b) == dict:
if len(a) == 0 and len(b) == 0:
return 1
if len(a) == 0 or len(b) == 0:
return match_rate_zero(key)
data = [match_rate(a.get(k), b.get(k), key=f"{key}.{k}") for k in a.keys()]
return sum(data) / len(a)
if type(a) == list and type(b) == list:
if len(a) == 0 and len(b) == 0:
return 1
if len(a) != len(b):
return match_rate_zero(a, b, key=key)
data = [match_rate(a[i], b[i], key=f"{key}[{i}]") for i in range(len(a))]
return sum(data) / len(a)
if a == b:
return 1
return match_rate_zero(a, b, key=key)
def save_cache(data):
rand = time.time_ns()
os.makedirs("cache", exist_ok=True)
with open(f"cache/{rand}.json", "w+") as f:
json.dump(data, f, indent=4)
def task_callback(file, thread=True):
try:
with open(file, "r") as f:
cache = json.load(f)
data = pt.__dict__[cache["type"]].from_json(cache["raw"])
rate = match_rate(data.to_dict(), json.loads(cache["raw"]))
return rate, file
except Exception as e:
if thread:
return 0, file
else:
raise
def error_dump(e): def error_dump(e):
if ERROR_UNCATCHED: if ERROR_UNCATCHED:
raise raise
import traceback
logger.error("==========[STACK TRACE]==========") logger.error("==========[STACK TRACE]==========")
for trace in traceback.format_exc().split("\n"): for trace in traceback.format_exc().split("\n"):
@ -85,30 +131,63 @@ def error_dump(e):
logger.info("================================") logger.info("================================")
api_conf = pt.Configuration( if __name__ == "__main__":
if Path("cookie.json").exists():
with open("cookie.json", "r") as f:
cookies = json.load(f)
elif TWITTER_SESSION is not None:
data = base64.b64decode(TWITTER_SESSION).decode("utf-8")
cookies = json.loads(data)
else:
commands = ["python -m pip install tweepy_authlib", "python tools/login.py"]
raise Exception(
f'cookie.json not found. Please run `{"; ".join(commands)}` first.'
)
cookies_str = "; ".join([f"{k}={v}" for k, v in cookies.items()])
with open("src/config/placeholder.json", "r") as f:
placeholder = json.load(f)
fail = []
with concurrent.futures.ProcessPoolExecutor() as executor:
tasks = [executor.submit(task_callback, x) for x in glob.glob("cache/*.json")]
for task in concurrent.futures.as_completed(tasks):
rate, file = task.result()
if rate < 1:
fail.append(file)
logger.info(f"Match rate: {rate}")
logger.info(f"Fail: {len(fail)} / {len(glob.glob('cache/*.json'))}")
for file in fail:
task_callback(file, thread=False)
logger.info(f"Match rate: {rate}")
api_conf = pt.Configuration(
api_key={ api_key={
"ClientLanguage": "en", "ClientLanguage": "en",
"ActiveUser": "yes", "ActiveUser": "yes",
"AuthType": "OAuth2Session", "AuthType": "OAuth2Session",
"CsrfToken": cookies["ct0"], "CsrfToken": cookies["ct0"],
}, },
) )
api_conf.access_token = "AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA" api_conf.access_token = "AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA"
api_client = pt.ApiClient(configuration=api_conf, cookie=cookies_str) 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/112.0.0.0 Safari/537.36" api_client.user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"
error_count = 0 error_count = 0
for x in [pt.DefaultApi, pt.TweetApi, pt.UserApi, pt.UsersApi, pt.UserListApi]: for x in [pt.DefaultApi, pt.TweetApi, pt.UserApi, pt.UsersApi, pt.UserListApi]:
for props, fn in x.__dict__.items(): for props, fn in x.__dict__.items():
if not callable(fn): if not callable(fn):
continue continue
if props.startswith("__") or props.endswith("_with_http_info"): if props.startswith("__") or not props.endswith("_with_http_info"):
continue continue
key = get_key(props) key = get_key(props[:-15])
cursor_list = set([None]) cursor_list = set([None])
cursor_history = set() cursor_history = set()
@ -118,15 +197,27 @@ for x in [pt.DefaultApi, pt.TweetApi, pt.UserApi, pt.UsersApi, pt.UserListApi]:
cursor_history.add(cursor) cursor_history.add(cursor)
logger.info(f"Try: {key} {cursor}") logger.info(f"Try: {key} {cursor}")
kwargs = get_kwargs(key, {} if cursor is None else {"cursor": cursor}) kwargs = get_kwargs(
res: dict = getattr(x(api_client), props)(**kwargs).to_dict() key, {} if cursor is None else {"cursor": cursor}
)
res: pt.ApiResponse = getattr(x(api_client), props)(**kwargs)
data = res.data.to_dict()
new_cursor = set(get_cursor(res, find_cursor)) - cursor_history save_cache(
{
"raw": res.raw_data,
"type": res.data.__class__.__name__,
}
)
new_cursor = set(get_cursor(data, find_cursor)) - cursor_history
cursor_list.update(new_cursor) cursor_list.update(new_cursor)
# logger.info(f"Find cursor: {len(new_cursor)}")
if res.get("errors") is not None: rate = match_rate(data, json.loads(res.raw_data))
logger.error(res) logger.info(f"Match rate: {rate}")
if data.get("errors") is not None:
logger.error(data)
error_count += 1 error_count += 1
if len(cursor_list) == 0: if len(cursor_list) == 0:
@ -137,24 +228,33 @@ for x in [pt.DefaultApi, pt.TweetApi, pt.UserApi, pt.UsersApi, pt.UserListApi]:
error_dump(e) error_dump(e)
error_count += 1 error_count += 1
try:
try:
logger.info(f"Try: Self UserByScreenName Test") logger.info(f"Try: Self UserByScreenName Test")
kwargs = get_kwargs("UserByScreenName", {"screen_name": "a810810931931"}) kwargs = get_kwargs("UserByScreenName", {"screen_name": "a810810931931"})
res = pt.UserApi(api_client).get_user_by_screen_name(**kwargs).to_dict() res = pt.UserApi(api_client).get_user_by_screen_name_with_http_info(**kwargs)
if not res["data"]["user"]["result"]["legacy"]["screen_name"] == "a810810931931": data = res.data.to_dict()
rate = match_rate(data, json.loads(res.raw_data))
logger.info(f"Match rate: {rate}")
screen_name = data["data"]["user"]["result"]["legacy"]["screen_name"]
if not screen_name == "a810810931931":
raise Exception("UserByScreenName failed") raise Exception("UserByScreenName failed")
except Exception as e: except Exception as e:
error_dump(e) error_dump(e)
error_count += 1 error_count += 1
try: try:
logger.info(f"Try: Self UserTweets Test") logger.info(f"Try: Self UserTweets Test")
kwargs = get_kwargs("UserTweets", {"userId": "1180389371481976833"}) kwargs = get_kwargs("UserTweets", {"userId": "1180389371481976833"})
pt.TweetApi(api_client).get_user_tweets(**kwargs) res = pt.TweetApi(api_client).get_user_tweets_with_http_info(**kwargs)
except Exception as e: data = res.data.to_dict()
rate = match_rate(data, json.loads(res.raw_data))
logger.info(f"Match rate: {rate}")
except Exception as e:
error_dump(e) error_dump(e)
error_count += 1 error_count += 1
if error_count > 0: if error_count > 0:
exit(1) exit(1)