Files
leocrm/app/plugins/builtins/kommunikation/serializers.py
T

130 lines
4.0 KiB
Python

"""Row/response serialization helpers for the kommunikation plugin."""
from __future__ import annotations
import logging
import re
from typing import Any
from app.plugins.builtins.kommunikation.models import (
CommConversation,
CommMessage,
CommMessageAttachment,
CommMessageBlock,
CommMessageReaction,
CommParticipant,
)
logger = logging.getLogger(__name__)
MAX_TRIGGER_DEPTH = 3
# ─── serializers ───
# ─── Mention Parsing ───
MENTION_PATTERN = re.compile(r"@(\w+)")
def parse_mentions(content: str) -> list[str]:
"""Parse @mentions from message content. Returns list of mentioned types/names."""
return MENTION_PATTERN.findall(content)
# ─── Conversation Helpers ───
def conversation_to_response(
conv: CommConversation,
participants: list[CommParticipant],
unread_count: int = 0,
is_pinned_by_user: bool = False,
) -> dict[str, Any]:
"""Convert a CommConversation to a response dict."""
return {
"id": str(conv.id),
"title": conv.title,
"is_locked": conv.is_locked,
"locked_by": conv.locked_by,
"is_direct": conv.is_direct,
"is_archived": conv.is_archived,
"is_pinned": is_pinned_by_user,
"created_by": str(conv.created_by) if conv.created_by else None,
"created_by_type": conv.created_by_type,
"last_msg_at": conv.last_msg_at.isoformat() if conv.last_msg_at else None,
"last_msg_preview": conv.last_msg_preview,
"last_msg_sender_type": conv.last_msg_sender_type,
"participants": [participant_to_response(p) for p in participants],
"unread_count": unread_count,
"metadata": conv.metadata_ or {},
}
def participant_to_response(p: CommParticipant) -> dict[str, Any]:
"""Convert a CommParticipant to a response dict."""
return {
"id": str(p.id),
"conversation_id": str(p.conversation_id),
"participant_id": str(p.participant_id) if p.participant_id else None,
"participant_type": p.participant_type,
"display_name": p.display_name,
"role": p.role,
"joined_at": p.joined_at.isoformat() if p.joined_at else None,
}
def message_to_response(
msg: CommMessage,
blocks: list[CommMessageBlock] | None = None,
attachments: list[CommMessageAttachment] | None = None,
reactions: list[CommMessageReaction] | None = None,
) -> dict[str, Any]:
"""Convert a CommMessage to a response dict."""
return {
"id": str(msg.id),
"conversation_id": str(msg.conversation_id),
"sender_id": str(msg.sender_id) if msg.sender_id else None,
"sender_type": msg.sender_type,
"content": msg.content,
"content_format": msg.content_format,
"metadata": msg.metadata_ or {},
"reply_to_id": str(msg.reply_to_id) if msg.reply_to_id else None,
"is_pinned": msg.is_pinned,
"created_at": msg.created_at.isoformat() if msg.created_at else None,
"edited_at": msg.edited_at.isoformat() if msg.edited_at else None,
"blocks": [
{
"id": str(b.id),
"block_type": b.block_type,
"block_data": b.block_data,
"sort_order": b.sort_order,
}
for b in (blocks or [])
],
"attachments": [
{
"id": str(a.id),
"file_id": str(a.file_id) if a.file_id else None,
"file_source": a.file_source,
"file_name": a.file_name,
"file_type": a.file_type,
"file_size": a.file_size,
"thumbnail_path": a.thumbnail_path,
}
for a in (attachments or [])
],
"reactions": [
{
"id": str(r.id),
"message_id": str(r.message_id),
"user_id": str(r.user_id),
"emoji": r.emoji,
}
for r in (reactions or [])
],
}
# ─── Conversation CRUD ───