beh-11: addressed-only channels — silent unless mentioned, replied to, or named; scheduled tasks skip them

This commit is contained in:
Oleksandr Kozachuk
2026-07-23 15:26:06 +02:00
parent f3c25de310
commit 1cdd240d98
3 changed files with 112 additions and 2 deletions
+24
View File
@@ -203,6 +203,10 @@ class FjerkroaBot(commands.Bot):
async def _execute_task(self, channel_name: str, prompt: str) -> None:
"""Run a due task through the normal responder path (TSK-02)."""
# Never post unprompted into addressed-only channels (BEH-11)
if self.channel_addressed_only(channel_name):
logging.info(f"task for addressed-only channel {channel_name!r} skipped (BEH-11)")
return
channel = self.channel_by_name(channel_name, getattr(self, "chat_channel", None), no_ignore=True)
if channel is None:
raise RuntimeError(f"task channel {channel_name!r} not resolvable")
@@ -501,6 +505,21 @@ class FjerkroaBot(commands.Bot):
"""fnmatch patterns; plain names match exactly as before (BEH-09)."""
return any(fnmatch.fnmatchcase(str(channel_name), pattern) for pattern in self.config.get("ignore-channels", []))
def channel_addressed_only(self, channel_name) -> bool:
"""fnmatch patterns like ignore-channels (BEH-11)."""
return any(fnmatch.fnmatchcase(str(channel_name), pattern) for pattern in self.config.get("addressed-only-channels", []))
def _addressed(self, message, msg: AIMessage) -> bool:
"""Mention/DM, reply to the bot, or the bot's name in the text (BEH-11)."""
if msg.direct:
return True
reference = getattr(message, "reference", None)
resolved = getattr(reference, "resolved", None) if reference else None
if resolved is not None and getattr(resolved, "author", None) == self.user:
return True
name = str(getattr(self.user, "name", "") or "")
return bool(name) and name.lower() in msg.message.lower()
def ignore_message(self, channel_name, message):
return self.channel_ignored(channel_name) and not message.direct
@@ -554,6 +573,11 @@ class FjerkroaBot(commands.Bot):
if attachment_urls:
msg.urls = attachment_urls
# Addressed-only channels: silent unless spoken to (BEH-11)
if self.channel_addressed_only(channel_name) and not self._addressed(message, msg):
self.log_message_action("addressed-only-skip", msg, channel_name)
return
# Reply/ignore classifier gate — direct messages bypass (BEH-01/02/03/07)
handled, factual = await self._classifier_gate(message, msg, airesponder, channel_name)
if handled: