""" Messenger API - Pydantic Models. Data models for contacts, conversations, messages, and groups. """ from typing import List, Optional from pydantic import BaseModel, Field # ========================================== # CONTACT MODELS # ========================================== class ContactBase(BaseModel): """Basis-Modell fuer Kontakte.""" name: str = Field(..., min_length=1, max_length=200) email: Optional[str] = None phone: Optional[str] = None role: str = Field(default="parent", description="parent, teacher, staff, student") student_name: Optional[str] = Field(None, description="Name des zugehoerigen Schuelers") class_name: Optional[str] = Field(None, description="Klasse z.B. 10a") notes: Optional[str] = None tags: List[str] = Field(default_factory=list) matrix_id: Optional[str] = Field(None, description="Matrix-ID z.B. @user:matrix.org") preferred_channel: str = Field(default="email", description="email, matrix, pwa") class ContactCreate(ContactBase): """Model fuer neuen Kontakt.""" pass class Contact(ContactBase): """Vollstaendiger Kontakt mit ID.""" id: str created_at: str updated_at: str online: bool = False last_seen: Optional[str] = None class ContactUpdate(BaseModel): """Update-Model fuer Kontakte.""" name: Optional[str] = None email: Optional[str] = None phone: Optional[str] = None role: Optional[str] = None student_name: Optional[str] = None class_name: Optional[str] = None notes: Optional[str] = None tags: Optional[List[str]] = None matrix_id: Optional[str] = None preferred_channel: Optional[str] = None # ========================================== # GROUP MODELS # ========================================== class GroupBase(BaseModel): """Basis-Modell fuer Gruppen.""" name: str = Field(..., min_length=1, max_length=100) description: Optional[str] = None group_type: str = Field(default="class", description="class, department, custom") class GroupCreate(GroupBase): """Model fuer neue Gruppe.""" member_ids: List[str] = Field(default_factory=list) class Group(GroupBase): """Vollstaendige Gruppe mit ID.""" id: str member_ids: List[str] = [] created_at: str updated_at: str # ========================================== # MESSAGE MODELS # ========================================== class MessageBase(BaseModel): """Basis-Modell fuer Nachrichten.""" content: str = Field(..., min_length=1) content_type: str = Field(default="text", description="text, file, image") file_url: Optional[str] = None send_email: bool = Field(default=False, description="Nachricht auch per Email senden") class MessageCreate(MessageBase): """Model fuer neue Nachricht.""" conversation_id: str class Message(MessageBase): """Vollstaendige Nachricht mit ID.""" id: str conversation_id: str sender_id: str # "self" fuer eigene Nachrichten timestamp: str read: bool = False read_at: Optional[str] = None email_sent: bool = False email_sent_at: Optional[str] = None email_error: Optional[str] = None # ========================================== # CONVERSATION MODELS # ========================================== class ConversationBase(BaseModel): """Basis-Modell fuer Konversationen.""" name: Optional[str] = None is_group: bool = False class Conversation(ConversationBase): """Vollstaendige Konversation mit ID.""" id: str participant_ids: List[str] = [] group_id: Optional[str] = None created_at: str updated_at: str last_message: Optional[str] = None last_message_time: Optional[str] = None unread_count: int = 0 class CSVImportResult(BaseModel): """Ergebnis eines CSV-Imports.""" imported: int skipped: int errors: List[str] contacts: List[Contact]