|
# retoor <retoor@molodetz.nl>
|
|
|
|
import logging
|
|
from datetime import datetime, timezone
|
|
from typing import Any, Optional
|
|
|
|
from devplacepy.attachments import get_attachments, link_attachments
|
|
from devplacepy.database import get_table, get_blocked_uids
|
|
from devplacepy.templating import clear_messages_cache
|
|
from devplacepy.utils import (
|
|
create_mention_notifications,
|
|
create_notification,
|
|
generate_uid,
|
|
time_ago,
|
|
track_action,
|
|
)
|
|
from devplacepy.services.audit import record as audit
|
|
from devplacepy.services.correction import schedule_correction
|
|
from devplacepy.services.ai_modifier import schedule_modification
|
|
|
|
logger = logging.getLogger("messaging.persist")
|
|
|
|
MAX_CONTENT_LENGTH = 2000
|
|
|
|
|
|
def _slim_attachment(attachment: dict[str, Any]) -> dict[str, Any]:
|
|
return {
|
|
"uid": attachment["uid"],
|
|
"url": attachment["url"],
|
|
"thumbnail_url": attachment.get("thumbnail_url"),
|
|
"is_image": bool(attachment.get("is_image")),
|
|
"is_video": bool(attachment.get("is_video")),
|
|
"original_filename": attachment.get("original_filename", ""),
|
|
"file_size": attachment.get("file_size", 0),
|
|
"mime_type": attachment.get("mime_type", ""),
|
|
}
|
|
|
|
|
|
def message_frame(
|
|
message: dict[str, Any], sender_username: str, client_id: Optional[str] = None,
|
|
sender_role: Optional[str] = None,
|
|
) -> dict[str, Any]:
|
|
attachments = get_attachments("message", message["uid"])
|
|
return {
|
|
"type": "message",
|
|
"uid": message["uid"],
|
|
"sender_uid": message["sender_uid"],
|
|
"sender_username": sender_username,
|
|
"sender_role": sender_role,
|
|
"receiver_uid": message["receiver_uid"],
|
|
"content": message["content"],
|
|
"created_at": message["created_at"],
|
|
"time_ago": time_ago(message["created_at"]),
|
|
"client_id": client_id,
|
|
"attachments": [_slim_attachment(a) for a in attachments],
|
|
}
|
|
|
|
|
|
def persist_message(
|
|
sender: dict[str, Any],
|
|
receiver_uid: str,
|
|
content: str,
|
|
attachment_uids: Optional[list[str]] = None,
|
|
*,
|
|
request: Any = None,
|
|
origin: str = "web",
|
|
) -> Optional[dict[str, Any]]:
|
|
content = (content or "").strip()[:MAX_CONTENT_LENGTH]
|
|
attachment_uids = attachment_uids or []
|
|
if not content and not attachment_uids:
|
|
return None
|
|
|
|
receiver = get_table("users").find_one(uid=receiver_uid)
|
|
if not receiver:
|
|
return None
|
|
|
|
if sender["uid"] in get_blocked_uids(receiver_uid):
|
|
return None
|
|
|
|
sender_uid = sender["uid"]
|
|
sender_username = sender.get("username", "")
|
|
messages_table = get_table("messages")
|
|
msg_uid = generate_uid()
|
|
created_at = datetime.now(timezone.utc).isoformat()
|
|
messages_table.insert(
|
|
{
|
|
"uid": msg_uid,
|
|
"sender_uid": sender_uid,
|
|
"receiver_uid": receiver_uid,
|
|
"content": content,
|
|
"read": False,
|
|
"created_at": created_at,
|
|
}
|
|
)
|
|
|
|
link_attachments(attachment_uids, "message", msg_uid)
|
|
schedule_correction(sender, "messages", msg_uid, request)
|
|
schedule_modification(sender, "messages", msg_uid, request)
|
|
|
|
if sender_uid != receiver_uid:
|
|
create_notification(
|
|
receiver_uid,
|
|
"message",
|
|
f"{sender_username} sent you a message",
|
|
sender_uid,
|
|
f"/messages?with_uid={sender_uid}",
|
|
)
|
|
clear_messages_cache(receiver_uid)
|
|
|
|
create_mention_notifications(
|
|
content, sender_uid, f"/messages?with_uid={receiver_uid}"
|
|
)
|
|
track_action(sender_uid, "message")
|
|
|
|
logger.info(
|
|
"Message %s sent from %s to %s via %s",
|
|
msg_uid,
|
|
sender_username,
|
|
receiver_uid,
|
|
origin,
|
|
)
|
|
logger.debug("message %s content length=%d", msg_uid, len(content))
|
|
|
|
summary = (
|
|
f"{sender_username} sent a message to "
|
|
f"{receiver.get('username') or receiver_uid}: {content}"
|
|
)
|
|
links = [
|
|
audit.target("message", msg_uid),
|
|
audit.recipient(receiver_uid, receiver.get("username")),
|
|
]
|
|
if request is not None:
|
|
audit.record(
|
|
request,
|
|
"message.send",
|
|
user=sender,
|
|
target_type="message",
|
|
target_uid=msg_uid,
|
|
summary=summary,
|
|
metadata={"origin": origin},
|
|
links=links,
|
|
)
|
|
else:
|
|
audit.record_system(
|
|
"message.send",
|
|
actor_kind="user",
|
|
actor_uid=sender_uid,
|
|
actor_username=sender_username,
|
|
actor_role="admin" if sender.get("role") == "Admin" else "member",
|
|
origin=origin,
|
|
target_type="message",
|
|
target_uid=msg_uid,
|
|
summary=summary,
|
|
metadata={"origin": origin},
|
|
links=links,
|
|
)
|
|
|
|
return {
|
|
"uid": msg_uid,
|
|
"sender_uid": sender_uid,
|
|
"receiver_uid": receiver_uid,
|
|
"content": content,
|
|
"read": False,
|
|
"created_at": created_at,
|
|
}
|