abbe7a18fc
- P0: hooks.py 3-tuple fix, trigger_dispatcher Contract, contacts/plugin unregister_actions_by_owner - P0: 5 test files — check_permission mocks removed, hardcoded DB credential → env var - P1: attachment_service DmsFile via Contract helper, restore_registry/history_hooks dedup - P1: mail/plugin restore unregister, mcp_client datetime.now(UTC), saved_views/filters patterns - P1: ProtectedRoute fail-closed, 13 test assertion fixes (bcrypt, DB-URLs, SECRET_KEYs) - P2: deprecated notifications → post_system_message (3 files), forgejo Base, report_generator lazy import - P2: webhooks permissions, deps.py/roles.py plugin perms removed, import_export default - P2: address/tags/entity_links patterns removed, worker.py Contract-Umgehungen fixed - P2: 28 frontend TODOs (hardcoded constants, deprecated notification API) - P3: dead code, duplicates, deprecated imports, private attr, __import__ inline - P3: 8 frontend TODOs (LucideIcons, inline styles, XSS, i18n) - ruff: 838 → 0 (612 auto-fix + 246 manual + 27 F821 regression fix) - F821: 30 → 0 (AutomationDefinition, DmsFile, user_id, Path, Any, String) - Contract-Umgehungen: 2 neue gefunden (worker.py:169, worker.py:280) und gefixt
175 lines
4.1 KiB
Python
175 lines
4.1 KiB
Python
"""Pydantic schemas for the kommunikation plugin API."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
# ─── Conversation Schemas ───
|
|
|
|
class ParticipantResponse(BaseModel):
|
|
id: str
|
|
conversation_id: str
|
|
participant_id: str | None = None
|
|
participant_type: str
|
|
display_name: str | None = None
|
|
role: str
|
|
joined_at: str | None = None
|
|
|
|
|
|
class ConversationCreate(BaseModel):
|
|
title: str | None = None
|
|
participant_ids: list[str] = Field(default_factory=list)
|
|
participant_types: list[str] = Field(default_factory=lambda: ["user"])
|
|
initial_message: str | None = None
|
|
is_direct: bool = False
|
|
|
|
|
|
class ConversationUpdate(BaseModel):
|
|
title: str | None = None
|
|
is_archived: bool | None = None
|
|
|
|
|
|
class ConversationResponse(BaseModel):
|
|
id: str
|
|
title: str | None = None
|
|
is_locked: bool = False
|
|
locked_by: str | None = None
|
|
is_direct: bool = False
|
|
is_archived: bool = False
|
|
is_pinned: bool = False
|
|
created_by: str | None = None
|
|
created_by_type: str = "user"
|
|
last_msg_at: str | None = None
|
|
last_msg_preview: str | None = None
|
|
last_msg_sender_type: str | None = None
|
|
participants: list[ParticipantResponse] = Field(default_factory=list)
|
|
unread_count: int = 0
|
|
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
|
|
|
|
class ConversationListResponse(BaseModel):
|
|
items: list[ConversationResponse]
|
|
total: int
|
|
|
|
|
|
# ─── Participant Management ───
|
|
|
|
class ParticipantAdd(BaseModel):
|
|
participant_id: str
|
|
participant_type: str = "user"
|
|
role: str = "member"
|
|
|
|
|
|
class ParticipantRoleUpdate(BaseModel):
|
|
role: str = Field(..., pattern="^(admin|member|reader)$")
|
|
|
|
|
|
# ─── Message Schemas ───
|
|
|
|
class MessageBlockCreate(BaseModel):
|
|
block_type: str
|
|
block_data: dict[str, Any]
|
|
|
|
|
|
class MessageBlockResponse(BaseModel):
|
|
id: str
|
|
block_type: str
|
|
block_data: dict[str, Any]
|
|
sort_order: int = 0
|
|
|
|
|
|
class AttachmentCreate(BaseModel):
|
|
file_id: str | None = None
|
|
file_source: str = "comm"
|
|
|
|
|
|
class AttachmentResponse(BaseModel):
|
|
id: str
|
|
file_id: str | None = None
|
|
file_source: str = "comm"
|
|
file_name: str
|
|
file_type: str
|
|
file_size: int | None = None
|
|
thumbnail_path: str | None = None
|
|
|
|
|
|
class MessageCreate(BaseModel):
|
|
content: str = ""
|
|
content_format: str = "text"
|
|
blocks: list[MessageBlockCreate] = Field(default_factory=list)
|
|
reply_to_id: str | None = None
|
|
attachments: list[AttachmentCreate] = Field(default_factory=list)
|
|
|
|
|
|
class MessageUpdate(BaseModel):
|
|
content: str | None = None
|
|
read: bool | None = None
|
|
|
|
|
|
class MessageResponse(BaseModel):
|
|
id: str
|
|
conversation_id: str
|
|
sender_id: str | None = None
|
|
sender_type: str
|
|
content: str = ""
|
|
content_format: str = "text"
|
|
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
reply_to_id: str | None = None
|
|
is_pinned: bool = False
|
|
created_at: str | None = None
|
|
edited_at: str | None = None
|
|
blocks: list[MessageBlockResponse] = Field(default_factory=list)
|
|
attachments: list[AttachmentResponse] = Field(default_factory=list)
|
|
reactions: list[dict[str, Any]] = Field(default_factory=list)
|
|
|
|
|
|
class MessageListResponse(BaseModel):
|
|
items: list[MessageResponse]
|
|
total: int
|
|
page: int = 1
|
|
has_more: bool = False
|
|
|
|
|
|
# ─── Reaction Schemas ───
|
|
|
|
class ReactionCreate(BaseModel):
|
|
emoji: str
|
|
|
|
|
|
class ReactionResponse(BaseModel):
|
|
id: str
|
|
message_id: str
|
|
user_id: str
|
|
emoji: str
|
|
|
|
|
|
# ─── Read State ───
|
|
|
|
class ReadStateUpdate(BaseModel):
|
|
last_read_msg_id: str | None = None
|
|
|
|
|
|
# ─── Mini-App Schemas ───
|
|
|
|
class MiniAppResponse(BaseModel):
|
|
app_id: str
|
|
name: str
|
|
icon: str
|
|
description: str
|
|
plugin_name: str
|
|
render_schema: dict[str, Any] = Field(default_factory=dict)
|
|
|
|
|
|
class MiniAppStartRequest(BaseModel):
|
|
app_id: str
|
|
config: dict[str, Any] = Field(default_factory=dict)
|
|
|
|
|
|
# ─── WebSocket Message Schemas ───
|
|
|
|
class WSMessage(BaseModel):
|
|
type: str
|
|
data: dict[str, Any] = Field(default_factory=dict)
|