fix(telegram): recreate stale topics (#127)

This commit is contained in:
banteg
2026-01-13 22:55:26 +04:00
committed by GitHub
parent 43fd594061
commit b2834da232
4 changed files with 127 additions and 7 deletions
+87
View File
@@ -8,6 +8,7 @@ import pytest
from takopi import commands, plugins
from takopi.telegram.commands.executor import _CaptureTransport, _run_engine
from takopi.telegram.commands.file_transfer import _handle_file_get, _handle_file_put
from takopi.telegram.commands.topics import _handle_topic_command
import takopi.telegram.loop as telegram_loop
import takopi.telegram.topics as telegram_topics
from takopi.directives import parse_directives
@@ -1149,6 +1150,92 @@ async def test_maybe_rename_topic_skips_when_title_matches(tmp_path: Path) -> No
assert bot.edit_topic_calls == []
@pytest.mark.anyio
async def test_topic_command_recreates_stale_topic(tmp_path: Path) -> None:
class _StaleTopicBot(_FakeBot):
def __init__(self) -> None:
super().__init__()
self.create_topic_calls: list[dict[str, Any]] = []
async def create_forum_topic(
self, chat_id: int, name: str
) -> ForumTopic | None:
self.create_topic_calls.append({"chat_id": chat_id, "name": name})
return ForumTopic(message_thread_id=55)
async def edit_forum_topic(
self, chat_id: int, message_thread_id: int, name: str
) -> bool:
self.edit_topic_calls.append(
{
"chat_id": chat_id,
"message_thread_id": message_thread_id,
"name": name,
}
)
return False
transport = _FakeTransport()
bot = _StaleTopicBot()
runner = ScriptRunner([Return(answer="ok")], engine=CODEX_ENGINE)
projects = ProjectsConfig(
projects={
"takopi": ProjectConfig(
alias="takopi",
path=tmp_path,
worktrees_dir=Path(".worktrees"),
)
},
default_project=None,
)
runtime = TransportRuntime(router=_make_router(runner), projects=projects)
exec_cfg = ExecBridgeConfig(
transport=transport,
presenter=MarkdownPresenter(),
final_notify=True,
)
cfg = TelegramBridgeConfig(
bot=bot,
runtime=runtime,
chat_id=123,
startup_msg="",
exec_cfg=exec_cfg,
topics=TelegramTopicsSettings(enabled=True, scope="main"),
)
store = TopicStateStore(tmp_path / "telegram_topics_state.json")
await store.set_context(
123,
77,
RunContext(project="takopi", branch="master"),
topic_title="takopi @master",
)
msg = TelegramIncomingMessage(
transport="telegram",
chat_id=123,
message_id=10,
text="/topic takopi @master",
reply_to_message_id=None,
reply_to_text=None,
sender_id=123,
)
await _handle_topic_command(
cfg,
msg,
"takopi @master",
store,
resolved_scope="main",
scope_chat_ids=frozenset({123}),
)
assert bot.edit_topic_calls
assert bot.create_topic_calls
assert await store.get_thread(123, 77) is None
snapshot = await store.get_thread(123, 55)
assert snapshot is not None
assert snapshot.context == RunContext(project="takopi", branch="master")
@pytest.mark.anyio
async def test_send_with_resume_waits_for_token() -> None:
transport = _FakeTransport()
+14
View File
@@ -54,3 +54,17 @@ async def test_topic_state_store_clear_and_find(tmp_path) -> None:
snapshot = await store.get_thread(2, 20)
assert snapshot is not None
assert snapshot.default_engine is None
@pytest.mark.anyio
async def test_topic_state_store_delete_thread(tmp_path) -> None:
path = tmp_path / "telegram_topics_state.json"
store = TopicStateStore(path)
context = RunContext(project="proj", branch="main")
await store.set_context(1, 10, context)
await store.set_session_resume(1, 10, ResumeToken(engine="codex", value="abc123"))
await store.delete_thread(1, 10)
assert await store.get_thread(1, 10) is None
assert await store.find_thread_for_context(1, context) is None