feat: add extra Mumble bot instances and TTS greeting
Support [[mumble.extra]] config for additional Mumble identities that inherit connection settings from the main [mumble] section. Extra bots get their own state DB and do not run the voice trigger by default. Add TTS greeting on first connect via mumble.greet config option. Merlin joins as a second identity with his own client certificate. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -724,3 +724,75 @@ class TestTriggerMode:
|
||||
msg = _Msg(text="!listen")
|
||||
asyncio.run(_mod.cmd_listen(bot, msg))
|
||||
assert any("Trigger: claude" in r for r in bot.replied)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# TestGreeting
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestGreeting:
|
||||
def test_greet_on_first_connect(self):
|
||||
"""TTS greeting fires on first connect when configured."""
|
||||
bot = _FakeBot()
|
||||
bot.config = {"mumble": {"greet": "Hello there."}}
|
||||
bot._is_audio_ready = lambda: True
|
||||
|
||||
spawned = []
|
||||
|
||||
def fake_spawn(coro, *, name=None):
|
||||
spawned.append(name)
|
||||
coro.close()
|
||||
task = MagicMock()
|
||||
task.done.return_value = False
|
||||
return task
|
||||
|
||||
bot._spawn = fake_spawn
|
||||
asyncio.run(_mod.on_connected(bot))
|
||||
assert "voice-greet" in spawned
|
||||
|
||||
def test_greet_only_once(self):
|
||||
"""Greeting fires only on first connect, not on reconnect."""
|
||||
bot = _FakeBot()
|
||||
bot.config = {"mumble": {"greet": "Hello there."}}
|
||||
bot._is_audio_ready = lambda: True
|
||||
|
||||
spawned = []
|
||||
|
||||
def fake_spawn(coro, *, name=None):
|
||||
spawned.append(name)
|
||||
coro.close()
|
||||
task = MagicMock()
|
||||
task.done.return_value = False
|
||||
return task
|
||||
|
||||
bot._spawn = fake_spawn
|
||||
asyncio.run(_mod.on_connected(bot))
|
||||
assert spawned.count("voice-greet") == 1
|
||||
asyncio.run(_mod.on_connected(bot))
|
||||
assert spawned.count("voice-greet") == 1
|
||||
|
||||
def test_no_greet_without_config(self):
|
||||
"""No greeting when mumble.greet is not set."""
|
||||
bot = _FakeBot()
|
||||
bot.config = {}
|
||||
|
||||
spawned = []
|
||||
|
||||
def fake_spawn(coro, *, name=None):
|
||||
spawned.append(name)
|
||||
coro.close()
|
||||
task = MagicMock()
|
||||
task.done.return_value = False
|
||||
return task
|
||||
|
||||
bot._spawn = fake_spawn
|
||||
asyncio.run(_mod.on_connected(bot))
|
||||
assert "voice-greet" not in spawned
|
||||
|
||||
def test_no_greet_non_mumble(self):
|
||||
"""Greeting skipped for non-Mumble bots."""
|
||||
bot = _FakeBot(mumble=False)
|
||||
bot.config = {"mumble": {"greet": "Hello there."}}
|
||||
asyncio.run(_mod.on_connected(bot))
|
||||
# Should not raise or try to greet
|
||||
|
||||
Reference in New Issue
Block a user