from datetime import date, datetime from typing import Any from pydantic import BaseModel DEFAULT_LIMIT = 50 MAX_LIMIT = 500 class Page(BaseModel): limit: int = DEFAULT_LIMIT offset: int = 0 @property def capped_limit(self) -> int: return min(self.limit, MAX_LIMIT) class AccountView(BaseModel): account_id: int label: str | None phone: str | None tg_user_id: int | None is_active: bool is_bot: bool device_model: str | None class ChatListItem(BaseModel): chat_id: int title: str | None kind: str has_avatar: bool is_bot: bool is_contact: bool is_broadcast: bool message_count: int last_date: datetime | None last_text: str | None last_sender_id: int | None class DiscoverItem(BaseModel): chat_id: int title: str | None username: str | None kind: str is_bot: bool is_contact: bool has_avatar: bool message_count: int in_dialogs: bool tracked: bool class EntityView(BaseModel): type: str offset: int length: int url: str | None = None custom_emoji_id: str | None = None language: str | None = None class ReplyView(BaseModel): message_id: int | None = None sender_id: int | None = None sender_name: str | None = None text: str | None = None media_kind: str | None = None class ForwardView(BaseModel): kind: str from_id: int | None = None from_name: str | None = None chat_id: int | None = None chat_title: str | None = None message_id: int | None = None date: datetime | None = None signature: str | None = None class MediaRef(BaseModel): message_id: int id: int | None = None kind: str downloaded: bool = False width: int | None = None height: int | None = None duration: float | None = None mime: str | None = None file_size: int | None = None ttl_seconds: int | None = None extracted_text: str | None = None file_name: str | None = None class ReactionCount(BaseModel): emoji: str | None = None custom_emoji_id: str | None = None count: int chosen: bool = False class InlineButton(BaseModel): text: str kind: str url: str | None = None data: str | None = None class WebPageView(BaseModel): url: str display_url: str | None = None type: str | None = None site_name: str | None = None title: str | None = None description: str | None = None has_photo: bool = False class PollOption(BaseModel): text: str voter_count: int = 0 vote_percentage: int = 0 correct: bool | None = None class PollView(BaseModel): question: str options: list[PollOption] = [] total_voter_count: int = 0 quiz: bool = False closed: bool = False multiple: bool = False anonymous: bool = True class ContactView(BaseModel): user_id: int | None = None first_name: str | None = None last_name: str | None = None phone_number: str | None = None class LocationView(BaseModel): latitude: float | None = None longitude: float | None = None title: str | None = None address: str | None = None class ServiceView(BaseModel): kind: str member_ids: list[int] | None = None pinned_message_id: int | None = None duration: int | None = None class PinnedView(BaseModel): message_id: int text: str | None = None media_kind: str | None = None sender_name: str | None = None class StickerView(BaseModel): emoji: str | None = None set_name: str | None = None width: int | None = None height: int | None = None mime: str | None = None is_animated: bool = False is_video: bool = False class MessageView(BaseModel): chat_id: int message_id: int date: datetime sender_id: int | None text: str | None has_media: bool is_self_destruct: bool edited_at: datetime | None deleted_at: datetime | None entities: list[EntityView] = [] quote: str | None = None reply: ReplyView | None = None forward: ForwardView | None = None media_group_id: str | None = None media: list[MediaRef] = [] reactions: list[ReactionCount] = [] inline_buttons: list[list[InlineButton]] = [] web_page: WebPageView | None = None poll: PollView | None = None contact: ContactView | None = None location: LocationView | None = None service: ServiceView | None = None via_bot_id: int | None = None sticker: StickerView | None = None is_sticker: bool = False is_animated_emoji: bool = False read: bool = False read_at: datetime | None = None class MessageVersionView(BaseModel): observed_at: datetime edit_date: datetime | None text: str | None class MediaView(BaseModel): id: int account_id: int chat_id: int message_id: int kind: str storage_key: str | None file_size: int | None mime: str | None ttl_seconds: int | None downloaded: bool extracted_text: str | None created_at: datetime file_name: str | None = None class MediaVersionView(BaseModel): id: int kind: str storage_key: str file_size: int | None mime: str | None observed_at: datetime class StorageGroupView(BaseModel): group: str files: int bytes: int class StorageSummaryView(BaseModel): files: int bytes: int heavy_files: int heavy_bytes: int heavy_threshold: int trash_files: int trash_bytes: int groups: list[StorageGroupView] class StorageChatView(BaseModel): chat_id: int files: int bytes: int groups: list[StorageGroupView] class StorageFileView(BaseModel): media_id: int chat_id: int message_id: int kind: str mime: str | None file_name: str file_size: int date: datetime | None refs: int refetchable: bool class TrashItemView(BaseModel): storage_key: str chat_id: int message_id: int kind: str mime: str | None file_name: str file_size: int | None trashed_at: datetime purge_at: datetime refs: int refetchable: bool class TrashOutcome(BaseModel): files: int = 0 bytes: int = 0 keys: list[str] = [] blocked: list[int] = [] class StorageScopeView(BaseModel): chats: int files: int bytes: int kept: int gone: int class AvatarRef(BaseModel): unique_id: str storage_key: str | None downloaded: bool mime: str | None class AvatarHistoryView(BaseModel): unique_id: str first_seen_at: datetime downloaded: bool class CustomEmojiRef(BaseModel): storage_key: str | None downloaded: bool mime: str | None kind: str | None class CallbackView(BaseModel): position: int label: str | None data: str | None class ReactionView(BaseModel): peer_id: int reaction: str added_at: datetime removed_at: datetime | None class LinkView(BaseModel): position: int url: str kind: str web_url: str | None web_title: str | None web_description: str | None web_site_name: str | None class PresenceSample(BaseModel): peer_id: int ts: datetime status: str last_online_date: datetime | None next_offline_date: datetime | None class PresenceHourly(BaseModel): peer_id: int bucket: datetime samples: int online_samples: int last_seen: datetime | None class PresenceSession(BaseModel): started: datetime ended: datetime seconds: float online_seconds: float ongoing: bool class PresenceHour(BaseModel): weekday: int hour: int hours: int online_minutes: float | None covered_hours: float class PresenceDay(BaseModel): day: date online_seconds: float covered_seconds: float class CoverageGap(BaseModel): started: datetime ended: datetime class PresenceSummary(BaseModel): online_seconds: float daily_seconds: float | None covered_seconds: float session_count: int median_session_seconds: float | None first_online: int | None last_offline: int | None last_seen: datetime | None class PresenceStats(BaseModel): peer_id: int tz: str since: datetime until: datetime current: PresenceSample | None online: bool hidden: bool summary: PresenceSummary week: list[PresenceHour] days: list[PresenceDay] gaps: list[CoverageGap] sessions: list[PresenceSession] class VolumeBucket(BaseModel): bucket: date total: int outgoing: int incoming: int class ResponseStats(BaseModel): mine_median_seconds: float | None mine_count: int their_median_seconds: float | None their_count: int class PeerView(BaseModel): peer_id: int first_name: str | None last_name: str | None username: str | None phone: str | None photo_unique_id: str | None is_deleted_account: bool has_avatar: bool updated_at: datetime class ReaderView(BaseModel): peer_id: int read_at: datetime peer: PeerView | None class ReadInfoView(BaseModel): chat_id: int message_id: int chat_kind: str own: bool voice: bool observed_at: datetime | None listened_at: datetime | None exact_at: datetime | None readers: list[ReaderView] read: bool unread: bool outcome: str | None fetched_at: datetime | None can_fetch: bool class PeerHistoryView(BaseModel): observed_at: datetime first_name: str | None last_name: str | None username: str | None phone: str | None photo_unique_id: str | None is_deleted_account: bool class ChatLinkView(BaseModel): message_id: int date: datetime | None url: str kind: str web_url: str | None web_title: str | None web_site_name: str | None class DayCount(BaseModel): day: datetime count: int outgoing: int class MessageAt(BaseModel): message_id: int date: datetime class StoryView(BaseModel): peer_id: int story_id: int date: datetime | None expire_date: datetime | None caption: str | None media_kind: str | None storage_key: str | None downloaded: bool views: int | None pinned: bool deleted: bool class AnnotationView(BaseModel): id: int account_id: int chat_id: int message_id: int text: str created_at: datetime updated_at: datetime class WatchView(BaseModel): id: int account_id: int kind: str params: dict[str, Any] enabled: bool created_at: datetime updated_at: datetime class AlertView(BaseModel): id: int account_id: int watch_id: int ts: datetime payload: dict[str, Any] seen: bool created_at: datetime class FileShareView(BaseModel): id: int account_id: int token: str kind: str file_name: str url_name: str mime: str | None file_size: int | None title: str | None chat_id: int | None message_id: int | None peer_id: int | None story_id: int | None expires_at: datetime | None max_downloads: int | None download_count: int last_download_at: datetime | None revoked_at: datetime | None created_at: datetime class FileShareHitView(BaseModel): ts: datetime method: str ip: str | None user_agent: str | None counted: bool class BotView(BaseModel): bot_id: int account_id: int | None username: str | None title: str | None enabled: bool status: str status_detail: str | None backfilled_at: datetime | None checked_at: datetime | None added_at: datetime