ソースを参照

Say out loud that require_mention gates channels only

The room-kind check read like an arbitrary narrowing: whether someone
addresses the bot seems orthogonal to where they do it. It is not — a DM
is already addressed at the bot, so gating it on a mention would mute it
entirely. Name that reason at the condition and pin it with a DM test.
Paul Klumpp 1 週間 前
コミット
37772f42c9
2 ファイル変更43 行追加2 行削除
  1. 3 2
      adapter.py
  2. 40 0
      test_adapter.py

+ 3 - 2
adapter.py

@@ -629,8 +629,6 @@ class ChattoAdapter(BasePlatformAdapter):
         if not self._check_auth(user):
             return
         
-        # For DMs, always respond. For rooms with require_mention, only respond when mentioned.
-        # Strip the mention from the text for the agent
         # Todo: use a function that either reads from cache or gets room kind again.
         if self._room_kinds.get(message.room_id) is None:
             room_viewer_state = await client.get_room(message.room_id) 
@@ -644,6 +642,9 @@ class ChattoAdapter(BasePlatformAdapter):
 
         logger.info("message_body: %s room_kind: %s", message_body, room_kind)
 
+        # require_mention deliberately gates channels only: in a channel the bot
+        # is one of many listeners and must be addressed, whereas a DM is already
+        # addressed at it — so DMs are always answered, mention or not.
         mentioned = False
         if (room_kind == RoomKind.CHANNEL and self.chatto_config.require_mention.value and self.me):
             if self.me.login and not mentioned:

+ 40 - 0
test_adapter.py

@@ -713,6 +713,46 @@ class TestChatTypeMapping:
         assert event.source.chat_type == "channel"
 
 
+# -- require_mention --
+
+class TestRequireMention:
+    """require_mention gates channels only — a DM is already addressed at the bot."""
+
+    def _adapter(self):
+        adapter = _make_adapter()
+        adapter.chatto_config.allow_all_users.value = True
+        adapter.chatto_config.require_mention.value = True
+        adapter.me = _make_user("bot-user-id", "hermes_bot")
+        adapter._user_cache["user-1"] = _make_user("user-1", "alice")
+        adapter.handle_message = AsyncMock()
+        return adapter
+
+    async def _dispatch(self, adapter, room_id, body):
+        payload = _make_posted_payload(room_id=room_id)
+        payload.fetch_message = AsyncMock(
+            return_value=_make_message(body=body, room_id=room_id))
+        await adapter._dispatch_message_posted(payload)
+
+    async def test_channel_without_mention_is_discarded(self):
+        adapter = self._adapter()
+        adapter._room_kinds["room-1"] = RoomKind.CHANNEL
+        await self._dispatch(adapter, "room-1", "hi there")
+        adapter.handle_message.assert_not_called()
+
+    async def test_channel_with_mention_is_answered(self):
+        adapter = self._adapter()
+        adapter._room_kinds["room-1"] = RoomKind.CHANNEL
+        await self._dispatch(adapter, "room-1", "@hermes_bot hi there")
+        adapter.handle_message.assert_called_once()
+
+    async def test_dm_is_answered_without_a_mention(self):
+        """The point of the room_kind check: require_mention must not mute DMs."""
+        adapter = self._adapter()
+        adapter._room_kinds["dm-1"] = RoomKind.DM
+        await self._dispatch(adapter, "dm-1", "hi there")
+        adapter.handle_message.assert_called_once()
+
+
 # -- Inbound attachments --
 
 class TestInboundAttachments: