ForcePilot/backend/package/yuxi/channels/adapters/mattermost/reply.py

68 lines
1.9 KiB
Python
Raw Normal View History

from __future__ import annotations
from dataclasses import dataclass
ReplyToMode = str
REPLY_OFF: ReplyToMode = "off"
REPLY_FIRST: ReplyToMode = "first"
REPLY_ALL: ReplyToMode = "all"
REPLY_BATCHED: ReplyToMode = "batched"
REPLY_MODES = frozenset({REPLY_OFF, REPLY_FIRST, REPLY_ALL, REPLY_BATCHED})
@dataclass
class ReplyConfig:
mode: ReplyToMode = REPLY_OFF
thread_only: bool = False
@classmethod
def from_config(cls, config: dict) -> ReplyConfig:
mode = config.get("reply_to_mode", REPLY_OFF)
if mode not in REPLY_MODES:
mode = REPLY_OFF
thread_only = bool(config.get("reply_thread_only", False))
return cls(mode=mode, thread_only=thread_only)
class ReplyManager:
def __init__(self, config: dict | None = None):
self._config = ReplyConfig.from_config(config or {})
@property
def mode(self) -> ReplyToMode:
return self._config.mode
@property
def thread_only(self) -> bool:
return self._config.thread_only
def should_reply(self, chat_type: str, has_thread: bool = False) -> bool:
if chat_type == "direct":
return False
mode = self._config.mode
if mode == REPLY_OFF:
return False
if mode == REPLY_FIRST and chat_type == "direct":
return True
if mode == REPLY_ALL:
return True
if mode == REPLY_BATCHED:
return True
return False
def resolve_reply_target(self, chat_id: str, root_id: str | None) -> str | None:
"""返回应该回复到的消息 ID用作 root_idNone 表示不绑定线程。"""
if self._config.mode == REPLY_OFF:
return None
if self._config.thread_only and root_id:
return root_id
if self._config.mode in (REPLY_ALL, REPLY_BATCHED) and root_id:
return root_id
return None