from __future__ import annotations from datetime import datetime from enum import Enum from typing import Optional from pydantic import BaseModel, Field # ── Enums ────────────────────────────────────────────────────────────────────── class ChannelType(str, Enum): telegram = "telegram" whatsapp = "whatsapp" sms = "sms" class MessageStatus(str, Enum): pending = "pending" sent = "sent" delivered = "delivered" read = "read" failed = "failed" class MessageDirection(str, Enum): inbound = "inbound" outbound = "outbound" # ── Contact ──────────────────────────────────────────────────────────────────── class ContactCreate(BaseModel): name: str = Field(..., min_length=1, max_length=255) phone: Optional[str] = None email: Optional[str] = None telegram_id: Optional[str] = None telegram_username: Optional[str] = None whatsapp_phone: Optional[str] = None notes: Optional[str] = None class ContactUpdate(BaseModel): name: Optional[str] = Field(None, min_length=1, max_length=255) phone: Optional[str] = None email: Optional[str] = None telegram_id: Optional[str] = None telegram_username: Optional[str] = None whatsapp_phone: Optional[str] = None notes: Optional[str] = None class ContactResponse(BaseModel): model_config = {"from_attributes": True} id: str name: str phone: Optional[str] = None email: Optional[str] = None telegram_id: Optional[str] = None telegram_username: Optional[str] = None whatsapp_phone: Optional[str] = None notes: Optional[str] = None created_at: datetime updated_at: Optional[datetime] = None # ── Message ──────────────────────────────────────────────────────────────────── class SendMessageRequest(BaseModel): channel: ChannelType # Empfänger – je nach Kanal eines der Felder befüllen recipient_phone: Optional[str] = Field(None, description="Telefonnummer für WhatsApp/SMS (E.164: +49…)") recipient_telegram_id: Optional[str] = Field(None, description="Telegram Chat-ID") # Optional: Kontakt-ID aus der DB contact_id: Optional[str] = None text: str = Field(..., min_length=1, max_length=4096) reply_to_id: Optional[str] = None class MessageResponse(BaseModel): model_config = {"from_attributes": True} id: str conversation_id: str sender_id: Optional[str] = None channel: ChannelType channel_message_id: Optional[str] = None direction: MessageDirection text: str status: MessageStatus error_message: Optional[str] = None created_at: datetime sent_at: Optional[datetime] = None delivered_at: Optional[datetime] = None read_at: Optional[datetime] = None # ── Conversation ─────────────────────────────────────────────────────────────── class ConversationResponse(BaseModel): model_config = {"from_attributes": True} id: str channel: ChannelType channel_conversation_id: Optional[str] = None title: Optional[str] = None is_group: bool is_archived: bool last_message_at: Optional[datetime] = None created_at: datetime last_message: Optional[MessageResponse] = None unread_count: int = 0 contact_id: Optional[str] = None # ── Channel Status ───────────────────────────────────────────────────────────── class ChannelStatusResponse(BaseModel): channel: ChannelType enabled: bool connected: bool detail: Optional[str] = None class SystemStatusResponse(BaseModel): channels: list[ChannelStatusResponse] database: bool timestamp: datetime # ── Auth / User ───────────────────────────────────────────────────────────── class UserRole(str, Enum): admin = "admin" user = "user" class LoginRequest(BaseModel): username: str = Field(..., min_length=1, max_length=64) password: str = Field(..., min_length=1) class TokenResponse(BaseModel): access_token: str token_type: str = "bearer" username: str role: UserRole class UserCreate(BaseModel): username: str = Field(..., min_length=1, max_length=64) password: str = Field(..., min_length=6) role: UserRole = UserRole.user class UserUpdate(BaseModel): password: Optional[str] = Field(None, min_length=6) role: Optional[UserRole] = None is_active: Optional[bool] = None class UserResponse(BaseModel): model_config = {"from_attributes": True} id: str username: str role: UserRole is_active: bool created_at: datetime