163 lines
4.6 KiB
Python
163 lines
4.6 KiB
Python
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
from nanobot.bus.events import OutboundMessage
|
|
from nanobot.bus.queue import MessageBus
|
|
from nanobot.channels.telegram import TelegramChannel
|
|
from nanobot.config.schema import TelegramConfig
|
|
|
|
|
|
class _FakeHTTPXRequest:
|
|
instances: list["_FakeHTTPXRequest"] = []
|
|
|
|
def __init__(self, **kwargs) -> None:
|
|
self.kwargs = kwargs
|
|
self.__class__.instances.append(self)
|
|
|
|
|
|
class _FakeUpdater:
|
|
def __init__(self, on_start_polling) -> None:
|
|
self._on_start_polling = on_start_polling
|
|
|
|
async def start_polling(self, **kwargs) -> None:
|
|
self._on_start_polling()
|
|
|
|
|
|
class _FakeBot:
|
|
def __init__(self) -> None:
|
|
self.sent_messages: list[dict] = []
|
|
|
|
async def get_me(self):
|
|
return SimpleNamespace(username="nanobot_test")
|
|
|
|
async def set_my_commands(self, commands) -> None:
|
|
self.commands = commands
|
|
|
|
async def send_message(self, **kwargs) -> None:
|
|
self.sent_messages.append(kwargs)
|
|
|
|
|
|
class _FakeApp:
|
|
def __init__(self, on_start_polling) -> None:
|
|
self.bot = _FakeBot()
|
|
self.updater = _FakeUpdater(on_start_polling)
|
|
self.handlers = []
|
|
self.error_handlers = []
|
|
|
|
def add_error_handler(self, handler) -> None:
|
|
self.error_handlers.append(handler)
|
|
|
|
def add_handler(self, handler) -> None:
|
|
self.handlers.append(handler)
|
|
|
|
async def initialize(self) -> None:
|
|
pass
|
|
|
|
async def start(self) -> None:
|
|
pass
|
|
|
|
|
|
class _FakeBuilder:
|
|
def __init__(self, app: _FakeApp) -> None:
|
|
self.app = app
|
|
self.token_value = None
|
|
self.request_value = None
|
|
self.get_updates_request_value = None
|
|
|
|
def token(self, token: str):
|
|
self.token_value = token
|
|
return self
|
|
|
|
def request(self, request):
|
|
self.request_value = request
|
|
return self
|
|
|
|
def get_updates_request(self, request):
|
|
self.get_updates_request_value = request
|
|
return self
|
|
|
|
def proxy(self, _proxy):
|
|
raise AssertionError("builder.proxy should not be called when request is set")
|
|
|
|
def get_updates_proxy(self, _proxy):
|
|
raise AssertionError("builder.get_updates_proxy should not be called when request is set")
|
|
|
|
def build(self):
|
|
return self.app
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_start_uses_request_proxy_without_builder_proxy(monkeypatch) -> None:
|
|
config = TelegramConfig(
|
|
enabled=True,
|
|
token="123:abc",
|
|
allow_from=["*"],
|
|
proxy="http://127.0.0.1:7890",
|
|
)
|
|
bus = MessageBus()
|
|
channel = TelegramChannel(config, bus)
|
|
app = _FakeApp(lambda: setattr(channel, "_running", False))
|
|
builder = _FakeBuilder(app)
|
|
|
|
monkeypatch.setattr("nanobot.channels.telegram.HTTPXRequest", _FakeHTTPXRequest)
|
|
monkeypatch.setattr(
|
|
"nanobot.channels.telegram.Application",
|
|
SimpleNamespace(builder=lambda: builder),
|
|
)
|
|
|
|
await channel.start()
|
|
|
|
assert len(_FakeHTTPXRequest.instances) == 1
|
|
assert _FakeHTTPXRequest.instances[0].kwargs["proxy"] == config.proxy
|
|
assert builder.request_value is _FakeHTTPXRequest.instances[0]
|
|
assert builder.get_updates_request_value is _FakeHTTPXRequest.instances[0]
|
|
|
|
|
|
def test_derive_topic_session_key_uses_thread_id() -> None:
|
|
message = SimpleNamespace(
|
|
chat=SimpleNamespace(type="supergroup"),
|
|
chat_id=-100123,
|
|
message_thread_id=42,
|
|
)
|
|
|
|
assert TelegramChannel._derive_topic_session_key(message) == "telegram:-100123:topic:42"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_send_progress_keeps_message_in_topic() -> None:
|
|
config = TelegramConfig(enabled=True, token="123:abc", allow_from=["*"])
|
|
channel = TelegramChannel(config, MessageBus())
|
|
channel._app = _FakeApp(lambda: None)
|
|
|
|
await channel.send(
|
|
OutboundMessage(
|
|
channel="telegram",
|
|
chat_id="123",
|
|
content="hello",
|
|
metadata={"_progress": True, "message_thread_id": 42},
|
|
)
|
|
)
|
|
|
|
assert channel._app.bot.sent_messages[0]["message_thread_id"] == 42
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_send_reply_infers_topic_from_message_id_cache() -> None:
|
|
config = TelegramConfig(enabled=True, token="123:abc", allow_from=["*"], reply_to_message=True)
|
|
channel = TelegramChannel(config, MessageBus())
|
|
channel._app = _FakeApp(lambda: None)
|
|
channel._message_threads[("123", 10)] = 42
|
|
|
|
await channel.send(
|
|
OutboundMessage(
|
|
channel="telegram",
|
|
chat_id="123",
|
|
content="hello",
|
|
metadata={"message_id": 10},
|
|
)
|
|
)
|
|
|
|
assert channel._app.bot.sent_messages[0]["message_thread_id"] == 42
|
|
assert channel._app.bot.sent_messages[0]["reply_parameters"].message_id == 10
|