feat: add bot generated replies when it's being mentioned

This commit is contained in:
cătălin 2025-12-09 12:26:31 +01:00
commit d64c2398da
No known key found for this signature in database
9 changed files with 1670 additions and 963 deletions

149
tests/test_bot_mentions.py Normal file
View file

@ -0,0 +1,149 @@
import types
import pytest
from huesoporro.bot import SaveMessagesCog
class DummyDB:
def __init__(self, *args, **kwargs):
pass
class FakeChannel:
def __init__(self):
self.sent: list[str] = []
async def send(self, content: str):
self.sent.append(content)
class FakeAuthor:
def __init__(self, name: str):
self.name = name
class FakeMessage:
def __init__(self, content: str | None, author_name: str = "alice"):
self.content = content
self.author = FakeAuthor(author_name)
self.channel = FakeChannel()
class FakeBot:
def __init__(self, nick: str = "Junie", channel: str = "testchan"):
self.nick = nick
self.channel = channel
@pytest.fixture(autouse=True)
def patch_markov_and_svcs(monkeypatch):
monkeypatch.setattr("huesoporro.bot.MarkovDatabase", DummyDB)
class _DummyStoreSvc:
def __init__(self, db):
self.db = db
async def run(self, content: str | None):
return None
class _DummyGenSvc:
def __init__(self, db):
self.db = db
async def run(self, seed: str):
return None
monkeypatch.setattr("huesoporro.bot.SentenceStorerSvc", _DummyStoreSvc)
monkeypatch.setattr("huesoporro.bot.SentenceGeneratorSvc", _DummyGenSvc)
@pytest.fixture
def cog(monkeypatch) -> SaveMessagesCog:
bot = FakeBot()
return SaveMessagesCog(bot) # type: ignore[arg-type]
def make_async_fn(result=None, exc: Exception | None = None):
async def _fn(*args, **kwargs):
if exc:
raise exc
return result
return _fn
@pytest.mark.asyncio
async def test_handle_bot_mention_returns_none_on_empty_content(cog: SaveMessagesCog):
msg = FakeMessage(content=None)
res = await cog._handle_bot_mention(msg) # type: ignore[attr-defined]
assert res is None
assert msg.channel.sent == []
@pytest.mark.asyncio
async def test_handle_bot_mention_returns_none_when_no_mention(cog: SaveMessagesCog):
msg = FakeMessage(content="hello world")
res = await cog._handle_bot_mention(msg) # type: ignore[attr-defined]
assert res is None
assert msg.channel.sent == []
@pytest.mark.asyncio
async def test_handle_bot_mention_returns_none_when_only_mention(
cog: SaveMessagesCog, monkeypatch
):
msg = FakeMessage(content=cog.bot.nick) # type: ignore[attr-defined]
res = await cog._handle_bot_mention(msg) # type: ignore[attr-defined]
assert res is None
assert msg.channel.sent == []
@pytest.mark.asyncio
async def test_handle_bot_mention_generates_and_sends_reply(
cog: SaveMessagesCog, monkeypatch
):
msg = FakeMessage(content="juNie hello there")
monkeypatch.setattr(
cog, "generate_svc", types.SimpleNamespace(run=make_async_fn("foo bar"))
)
res = await cog._handle_bot_mention(msg) # type: ignore[attr-defined]
assert res == "foo bar"
assert len(msg.channel.sent) == 1
assert msg.channel.sent[0].startswith(f"@{msg.author.name} ")
assert msg.channel.sent[0].endswith("foo bar")
@pytest.mark.asyncio
async def test_handle_bot_mention_no_send_when_generator_returns_none(
cog: SaveMessagesCog, monkeypatch
):
msg = FakeMessage(content=f"{cog.bot.nick} hello") # type: ignore[attr-defined]
monkeypatch.setattr(
cog, "generate_svc", types.SimpleNamespace(run=make_async_fn(None))
)
res = await cog._handle_bot_mention(msg) # type: ignore[attr-defined]
assert res is None
assert msg.channel.sent == []
@pytest.mark.asyncio
async def test_handle_bot_mention_swallows_exceptions_and_returns_none(
cog: SaveMessagesCog, monkeypatch
):
msg = FakeMessage(content=f"{cog.bot.nick} hello") # type: ignore[attr-defined]
monkeypatch.setattr(
cog,
"generate_svc",
types.SimpleNamespace(run=make_async_fn(exc=RuntimeError("boom"))),
)
res = await cog._handle_bot_mention(msg) # type: ignore[attr-defined]
assert res is None
assert msg.channel.sent == []