from __future__ import annotations from datetime import datetime from typing import Literal from pydantic import BaseModel, Field, field_validator INSTANCE_PATTERN = r'^[a-z0-9](?:[a-z0-9-]{0,38}[a-z0-9])?$' class Resources(BaseModel): storage: str = '1Gi' cpu_limit: str = '300m' memory_limit: str = '1536Mi' class AccountBase(BaseModel): instance_id: str = Field(pattern=INSTANCE_PATTERN, max_length=40) display_name: str = Field(min_length=1, max_length=80) api_id: int = Field(gt=0) api_hash: str = Field(min_length=16, max_length=128) resources: Resources = Field(default_factory=Resources) @field_validator('display_name', 'api_hash') @classmethod def strip_text(cls, value: str) -> str: return value.strip() class PhoneStart(AccountBase): phone: str = Field(min_length=7, max_length=32) @field_validator('phone') @classmethod def normalize_phone(cls, value: str) -> str: value = value.strip() if not value.startswith('+'): raise ValueError('phone must use international format') return value class StringSessionStart(AccountBase): session_string: str = Field(min_length=32) class CodeSubmit(BaseModel): code: str = Field(min_length=3, max_length=12) @field_validator('code') @classmethod def normalize_code(cls, value: str) -> str: return ''.join(value.split()) class PasswordSubmit(BaseModel): password: str = Field(min_length=1, max_length=256) class DeleteRequest(BaseModel): confirmation: str delete_data: bool = False class InstanceSummary(BaseModel): instance_id: str display_name: str namespace: str deployment: str pod: str | None = None status: Literal['running', 'stopped', 'pending', 'error'] reason: str | None = None ready: bool = False restarts: int = 0 pvc: str | None = None storage: str | None = None image: str cpu_limit: str | None = None memory_limit: str | None = None cpu_usage: str | None = None memory_usage: str | None = None updated_at: datetime | None = None legacy: bool = False deletable: bool = True class AuthResult(BaseModel): status: Literal['code_required', 'password_required', 'ready'] flow_id: str | None = None instance: InstanceSummary | None = None