from typing import List, Dict, Union, Optional from dataclasses import dataclass, asdict Date = str Url = str ContentType = str TweetId = str UserId = str MediaKey = str Error = Dict @dataclass class User: id: UserId username: Optional[str] = None created_at: Optional[Date] = None name: Optional[str] = None verified: Optional[bool] = None profile_image_url: Optional[Url] = None description: Optional[str] = None url: Optional[str] = None @dataclass class PublicMetrics: retweet_count: Optional[int] = None reply_count: Optional[int] = None like_count: Optional[int] = None quote_count: Optional[int] = None # on video media (only?) view_count: Optional[int] = None @dataclass class NonPublicMetrics: impression_count: Optional[int] = None profile_clicks: Optional[int] = None url_link_clicks: Optional[int] = None user_profile_clicks: Optional[int] = None @dataclass class Media: media_key: MediaKey type: str width: int height: int @dataclass class PhotoMedia(Media): url: Url @dataclass class VideoMediaVariant: content_type: ContentType url: Url bit_rate: Optional[int] = None @dataclass class VideoMedia (Media): preview_image_url: Url duration_ms: int variants: List[VideoMediaVariant] public_metrics: Optional[PublicMetrics] = None non_public_metrics: Optional[NonPublicMetrics] = None @dataclass class GifMedia (Media): preview_image_url: Url variants: List[VideoMediaVariant] public_metrics: Optional[PublicMetrics] = None non_public_metrics: Optional[NonPublicMetrics] = None @dataclass class TweetAttachments: media_keys: Optional[List[MediaKey]] @dataclass class MentionEntity: start: int end: int id: UserId username: str @dataclass class UrlEntity: start: int end: int url: Url expanded_url: Optional[Url] = None display_url: Optional[str] = None media_key: Optional[MediaKey] = None description: Optional[str] = None title: Optional[str] = None unwound_url: Optional[Url] = None status: Optional[int] = None @dataclass class TweetEntities: urls: Optional[List[UrlEntity]] = None mentions: Optional[List[MentionEntity]] = None @dataclass class ReferencedTweet: id: TweetId type: str @dataclass class Tweet: id: TweetId created_at: Date text: str conversation_id: Optional[TweetId] = None in_reply_to_tweet_id: Optional[TweetId] = None author_id: Optional[UserId] = None referenced_tweets: Optional[List[ReferencedTweet]] = None entities: Optional[TweetEntities] = None public_metrics: Optional[PublicMetrics] = None non_public_metrics: Optional[NonPublicMetrics] = None attachments: Optional[TweetAttachments] = None edit_history_tweet_ids: Optional[List[TweetId]] = None @dataclass class TweetExpansions: users: Optional[List[User]] = None media: Optional[List[Union[VideoMedia, PhotoMedia, GifMedia]]] = None tweets: Optional[List[Tweet]] = None @dataclass class TweetSearchMeta: count: Optional[int] = None # is this an error? different endpoint type? result_count: Optional[int] = None next_token: Optional[str] = None newest_id: Optional[TweetId] = None oldest_id: Optional[TweetId] = None @dataclass class TweetSearchResponse: data: Optional[List[Tweet]] = None meta: Optional[TweetSearchMeta] = None includes: Optional[TweetExpansions] = None errors: Optional[List[Error]] = None @dataclass class DMEvent: id: str created_at: str event_type: str dm_conversation_id: str @dataclass class DMCMessageCreate(DMEvent): sender_id: UserId text: str attachments: Optional[TweetAttachments] = None @dataclass class DMParticpantsJoin (DMEvent): participant_ids: List[UserId] @dataclass class DMParticpantsLeave (DMEvent): participant_ids: List[UserId] @dataclass class DMEventsResponse: data: List[Union[DMCMessageCreate, DMParticpantsJoin, DMParticpantsLeave]] meta: Optional[TweetSearchMeta] = None # is SearchResultsMeta a general response format? includes: Optional[TweetExpansions] = None UserSearchMeta = Dict @dataclass class UserSearchResponse: data: Optional[List[User]] = None meta: Optional[UserSearchMeta] = None includes: Optional[TweetExpansions] = None errors: Optional[List[Error]] = None