from datetime import datetime from typing import Any, Literal from pydantic import BaseModel, ConfigDict, Field ObjectType = Literal["point", "marker", "zone", "other"] class MapObjectCreate(BaseModel): name: str = Field(min_length=1, max_length=255) description: str = "" type: ObjectType latitude: float = Field(ge=-90, le=90) longitude: float = Field(ge=-180, le=180) created_at: datetime | None = None class MapObjectRead(BaseModel): model_config = ConfigDict(from_attributes=True) id: int name: str description: str type: ObjectType latitude: float longitude: float event_id: int | None = None created_at: datetime class MapObjectUpdate(BaseModel): name: str | None = Field(default=None, min_length=1, max_length=255) description: str | None = None type: ObjectType | None = None latitude: float | None = Field(default=None, ge=-90, le=90) longitude: float | None = Field(default=None, ge=-180, le=180) created_at: datetime | None = None class ObjectMediaRead(BaseModel): model_config = ConfigDict(from_attributes=True) id: int object_id: int original_name: str content_type: str size: int created_at: datetime url: str class EventRead(BaseModel): model_config = ConfigDict(from_attributes=True) id: int source_type: str source_url: str raw_text: str title: str description: str locality: str latitude: float | None longitude: float | None event_date: datetime | None ingested_at: datetime region: str | None topic: str | None tags: list[str] | None metadata: dict[str, Any] | None = Field(validation_alias="metadata_") class IngestEventItem(BaseModel): source_type: str = "telegram" source_url: str raw_text: str = "" title: str = "" description: str = "" locality: str = "" latitude: float | None = None longitude: float | None = None event_date: datetime | None = None region: str | None = None topic: str | None = None tags: list[str] | None = None metadata: dict[str, Any] | None = None class IngestRequest(BaseModel): job_id: int | None = None events: list[IngestEventItem] = Field(default_factory=list) class IngestResponse(BaseModel): ingested: int updated: int map_objects_synced: int class ParseJobCreate(BaseModel): source_type: str = "telegram" source_config: dict[str, Any] = Field(default_factory=dict) schedule: str | None = None class ParseJobRead(BaseModel): model_config = ConfigDict(from_attributes=True) id: int source_type: str source_config: dict[str, Any] schedule: str | None status: str last_run_at: datetime | None last_error: str | None created_at: datetime class ConsumerCreate(BaseModel): name: str regions: list[str] | None = None topics: list[str] | None = None date_from: datetime | None = None class ConsumerRead(BaseModel): model_config = ConfigDict(from_attributes=True) id: int name: str is_active: bool created_at: datetime api_key: str | None = None