from datetime import datetime from typing import Any, Optional from pydantic import BaseModel, Field class TestResult(BaseModel): success: bool message: str detail: Optional[str] = None class WebsiteCreate(BaseModel): name: str site_type: str = "sub2api" base_url: str api_prefix: str = "/api/v1/admin" auth_type: str = "api_key" auth_config: dict[str, Any] = {} groups_endpoint: str = "/groups" group_update_endpoint: str = "/groups/{id}" enabled: bool = True auto_sync_enabled: bool = True timeout_seconds: int = 30 class WebsiteUpdate(BaseModel): name: Optional[str] = None site_type: Optional[str] = None base_url: Optional[str] = None api_prefix: Optional[str] = None auth_type: Optional[str] = None auth_config: Optional[dict[str, Any]] = None groups_endpoint: Optional[str] = None group_update_endpoint: Optional[str] = None enabled: Optional[bool] = None auto_sync_enabled: Optional[bool] = None timeout_seconds: Optional[int] = None class WebsiteResponse(BaseModel): id: int name: str site_type: str base_url: str api_prefix: str auth_type: str auth_config_masked: dict[str, Any] groups_endpoint: str group_update_endpoint: str enabled: bool auto_sync_enabled: bool timeout_seconds: int last_status: str last_checked_at: Optional[datetime] last_error: Optional[str] created_at: datetime updated_at: datetime model_config = {"from_attributes": True} class WebsiteGroupResponse(BaseModel): id: str name: str rate_multiplier: Optional[str] = None raw: dict[str, Any] = {} class BindingSourceGroup(BaseModel): upstream_id: int group_id: str upstream_name: str = "" group_name: str = "" class BindingCreate(BaseModel): website_id: int target_group_id: str target_group_name: str = "" source_groups: list[BindingSourceGroup] = Field(default_factory=list) percent: float = Field(default=0, ge=0) algorithm: str = "max_plus_percent" enabled: bool = True class BindingUpdate(BaseModel): website_id: Optional[int] = None target_group_id: Optional[str] = None target_group_name: Optional[str] = None source_groups: Optional[list[BindingSourceGroup]] = None percent: Optional[float] = Field(default=None, ge=0) algorithm: Optional[str] = None enabled: Optional[bool] = None class BindingResponse(BaseModel): id: int website_id: int website_name: str target_group_id: str target_group_name: str source_groups: list[BindingSourceGroup] percent: float algorithm: str enabled: bool created_at: datetime updated_at: datetime class WebsiteSyncLogResponse(BaseModel): id: int website_id: int binding_id: Optional[int] target_group_id: str target_group_name: str algorithm: str percent: float source_rates: list[dict[str, Any]] old_rate: Optional[str] new_rate: Optional[str] status: str message: str created_at: datetime class ImportGroupsRequest(BaseModel): group_ids: list[str] = Field(default_factory=list) name_prefix: str = "" class ImportGroupItem(BaseModel): source_group_id: str source_group_name: str target_group_id: Optional[str] = None target_group_name: str = "" status: str message: str = "" raw: dict[str, Any] = {} class ImportGroupsResponse(BaseModel): success: bool message: str items: list[ImportGroupItem] class SyncImportStatusRequest(BaseModel): upstream_id: int = Field(default=0) class ImportAccountsRequest(BaseModel): upstream_key_ids: list[int] = Field(default_factory=list) target_group_map: dict[str, str] = Field(default_factory=dict) account_name_prefix: str = "SmartUp" default_platform: str = "openai" platform_mode: str = "auto" # "auto" | "manual" concurrency: int = Field(default=10, ge=1) priority: int = Field(default=1, ge=0) auto_priority_by_rate: bool = True class ImportAccountItem(BaseModel): upstream_key_id: int source_group_id: str source_group_name: str target_group_id: Optional[str] = None account_id: Optional[str] = None account_name: str = "" platform: str = "" upstream_base_url: str = "" status: str message: str = "" raw: dict[str, Any] = {} class ImportAccountsResponse(BaseModel): success: bool message: str items: list[ImportAccountItem] class WebsiteBatchSyncResponse(BaseModel): total: int success: int failed: int skipped: int message: str logs: list[WebsiteSyncLogResponse]