refactor(pairing): move /pairing from BaseChannel to CommandRouter
/pairing is now a first-class built-in command dispatched through CommandRouter, just like /status, /model, /dream, etc. Benefits: - WebUI automatically shows /pairing in the slash command palette (because builtin_command_palette() feeds /api/commands). - All channels (Telegram, Discord, WebSocket, etc.) use the same dispatch path for /pairing; no more channel-level interception. - The command still only works for already-authorised users because is_allowed() gates message ingestion before the bus. Changes: - Add handle_pairing_command() to nanobot.pairing.store — pure function callable from CLI, CommandRouter, and tests. - Add cmd_pairing to nanobot.command.builtin and register in BUILTIN_COMMAND_SPECS + register_builtin_commands(). - Remove BaseChannel._handle_pairing_command() and the /pairing interception logic from _handle_message(). - Clean up unused pairing imports from base.py. - Add unit tests for handle_pairing_command and cmd_pairing dispatch.
This commit is contained in:
@@ -85,51 +85,3 @@ async def test_handle_message_group_ignores_unknown() -> None:
|
||||
|
||||
assert channel._sent == []
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_handle_pairing_command_list(monkeypatch) -> None:
|
||||
channel = _DummyChannel({"allowFrom": ["owner"]}, MessageBus())
|
||||
monkeypatch.setattr(
|
||||
"nanobot.channels.base.list_pending",
|
||||
lambda: [
|
||||
{
|
||||
"code": "ABCD-EFGH",
|
||||
"channel": "dummy",
|
||||
"sender_id": "123",
|
||||
"expires_at": 9999999999,
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
await channel._handle_pairing_command("owner", "chat1", "list")
|
||||
|
||||
assert len(channel._sent) == 1
|
||||
assert "ABCD-EFGH" in channel._sent[0].content
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_handle_pairing_command_approve(monkeypatch) -> None:
|
||||
channel = _DummyChannel({"allowFrom": ["owner"]}, MessageBus())
|
||||
monkeypatch.setattr(
|
||||
"nanobot.channels.base.approve_code",
|
||||
lambda code: ("dummy", "123") if code == "ABCD-EFGH" else None,
|
||||
)
|
||||
|
||||
await channel._handle_pairing_command("owner", "chat1", "approve ABCD-EFGH")
|
||||
|
||||
assert len(channel._sent) == 1
|
||||
assert "Approved" in channel._sent[0].content
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_handle_pairing_command_revoke(monkeypatch) -> None:
|
||||
channel = _DummyChannel({"allowFrom": ["owner"]}, MessageBus())
|
||||
monkeypatch.setattr(
|
||||
"nanobot.channels.base.revoke",
|
||||
lambda ch, sid: sid == "123",
|
||||
)
|
||||
|
||||
await channel._handle_pairing_command("owner", "chat1", "revoke 123")
|
||||
|
||||
assert len(channel._sent) == 1
|
||||
assert "Revoked" in channel._sent[0].content
|
||||
|
||||
Reference in New Issue
Block a user