from __future__ import annotations import logging import re logger = logging.getLogger(__name__) class MattermostGating: def __init__(self, account: dict): self.chatmode = account.get("chatmode", "oncall") self.onchar_prefixes = account.get("onchar_prefixes", [">", "!"]) self.require_mention = account.get("require_mention", True) def should_respond( self, chat_type: str, message_text: str, was_mentioned: bool, ) -> tuple[bool, str]: if chat_type == "direct": return True, "dm_always" if self.chatmode == "onmessage": return True, "onmessage" if self.chatmode == "onchar": return self._check_onchar(message_text) if self.chatmode == "oncall": if was_mentioned: return True, "mentioned" return self._check_onchar_fallback(message_text) return False, "unknown_chatmode" def _check_onchar(self, text: str) -> tuple[bool, str]: stripped = text.strip() for prefix in self.onchar_prefixes: if stripped.startswith(prefix): return True, "onchar_triggered" return False, "onchar_not_triggered" def _check_onchar_fallback(self, text: str) -> tuple[bool, str]: if not self.require_mention: return True, "mention_not_required" for prefix in self.onchar_prefixes: if text.strip().startswith(prefix): return True, "onchar_fallback" return False, "missing_mention" def was_mentioned(self, text: str, bot_user_id: str, bot_username: str | None = None) -> bool: mentions = self.extract_mentions(text) if bot_user_id in mentions: return True if bot_username: return bot_username in text or f"@{bot_username}" in text return False def extract_mentions(self, text: str) -> list[str]: user_ids = re.findall(r"@([a-z0-9]{26})", text, re.IGNORECASE) usernames = re.findall(r"@(\w+)", text) return user_ids + usernames def strip_onchar_prefix(self, text: str) -> str: stripped = text.strip() for prefix in self.onchar_prefixes: if stripped.startswith(prefix): return stripped[len(prefix):].strip() return text