Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 27s
CI / test-go-edu-search (push) Successful in 40s
CI / test-python-klausur (push) Failing after 2m30s
CI / test-python-agent-core (push) Successful in 28s
CI / test-nodejs-website (push) Successful in 20s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
140 lines
3.8 KiB
Python
140 lines
3.8 KiB
Python
"""
|
|
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]
|