feat(telegram,core): master topic instead of general in private chats

This commit is contained in:
hh
2026-08-28 18:12:58 +02:00
parent 5177392f46
commit 9663fbf956
3 changed files with 93 additions and 18 deletions
+32 -10
View File
@@ -20,6 +20,7 @@ from sqlmodel import select
from test_conversations import ScriptedClient, StubFrontend, World
USER = 42
GENERAL = f"{USER}/901"
class FakeBot:
@@ -234,10 +235,11 @@ async def stack() -> Stack:
async def test_general_is_master_and_reply_has_no_thread(stack: Stack) -> None:
stack.bot.message("hi")
reply = await stack.until(lambda: stack.sent_with("ok:hi"), what="reply")
assert reply["thread"] is None
assert reply["thread"] == 901
assert reply["parse_mode"] == "HTML"
assert stack.bot.topics == ["🦫 General"]
master = await stack.world.conversations.find_bound(
frontend="telegram", external_id=str(USER)
frontend="telegram", external_id=GENERAL
)
assert master is not None and master.kind == "master"
assert stack.bot.drafts and stack.bot.drafts[0]["chat_id"] == USER
@@ -258,7 +260,7 @@ async def test_new_topic_becomes_morning_branch_and_replies_in_thread(
assert branch is not None
assert branch.kind == "branch" and branch.title == "план"
master = await stack.world.conversations.find_bound(
frontend="telegram", external_id=str(USER)
frontend="telegram", external_id=GENERAL
)
assert branch.parent_id == master.id
prompts = [p for c in ScriptedClient.instances for p in c.prompts]
@@ -317,7 +319,7 @@ async def test_reply_from_another_window_is_mirrored_with_marker(stack: Stack) -
stack.bot.message("hi")
await stack.until(lambda: stack.sent_with("ok:hi"), what="reply")
master = await stack.world.conversations.find_bound(
frontend="telegram", external_id=str(USER)
frontend="telegram", external_id=GENERAL
)
await stack.world.conversations.post(master, "from panel", origin="user")
await stack.until(lambda: stack.sent_with("ok:from panel"), what="mirrored reply")
@@ -331,7 +333,7 @@ async def test_say_is_delivered_and_inject_turns_are_silent(stack: Stack) -> Non
stack.bot.message("hi")
await stack.until(lambda: stack.sent_with("ok:hi"), what="reply")
master = await stack.world.conversations.find_bound(
frontend="telegram", external_id=str(USER)
frontend="telegram", external_id=GENERAL
)
before = len(stack.bot.sent)
await stack.world.conversations.inject(
@@ -348,7 +350,7 @@ async def test_question_becomes_buttons_and_callback_answers(stack: Stack) -> No
stack.bot.message("hi")
await stack.until(lambda: stack.sent_with("ok:hi"), what="reply")
master = await stack.world.conversations.find_bound(
frontend="telegram", external_id=str(USER)
frontend="telegram", external_id=GENERAL
)
payload = {
"questions": [
@@ -393,7 +395,7 @@ async def test_question_timeout_renders_text_and_free_text_answers(
stack.bot.message("hi")
await stack.until(lambda: stack.sent_with("ok:hi"), what="reply")
master = await stack.world.conversations.find_bound(
frontend="telegram", external_id=str(USER)
frontend="telegram", external_id=GENERAL
)
stack.world.conversations._question_timeout = 0.3 # noqa: SLF001
payload = {"questions": [{"header": "Q", "question": "Сколько?", "options": []}]}
@@ -442,13 +444,33 @@ async def test_commands_status_merge_and_new(stack: Stack) -> None:
assert branch.status == "merged"
stack.bot.message("/new отчёт")
await stack.until(lambda: stack.sent_with("в новом топике"), what="new topic")
assert stack.bot.topics == ["отчёт"]
assert stack.bot.topics == ["🦫 General", "отчёт"]
child = await stack.world.conversations.find_bound(
frontend="telegram", external_id=f"{USER}/901"
frontend="telegram", external_id=f"{USER}/902"
)
assert child is not None and child.title == "отчёт"
assert await stack.tg.mark_topic(child)
assert stack.bot.topics[-1] == "edit:901:✅ отчёт"
assert stack.bot.topics[-1] == "edit:902:✅ отчёт"
async def test_master_topic_survives_rotation(stack: Stack) -> None:
stack.bot.message("hi")
await stack.until(lambda: stack.sent_with("ok:hi"), what="reply")
master = await stack.world.conversations.find_bound(
frontend="telegram", external_id=GENERAL
)
stack.bot.message("into general", thread=901)
await stack.until(lambda: stack.sent_with("ok:into general"), what="reply")
assert (await stack.world.conversations.find(kind="branch")) == []
await stack.world.conversations.set_status(master, "closed")
stack.bot.message("after rotation", thread=901)
await stack.until(lambda: stack.sent_with("ok:after rotation"), what="reply")
fresh = await stack.world.conversations.find_bound(
frontend="telegram", external_id=GENERAL
)
assert fresh.kind == "master" and fresh.id != master.id
assert stack.bot.topics == ["🦫 General"]
assert (await stack.world.conversations.find(kind="branch")) == []
async def test_inbox_stores_first_and_replays_after_restart(stack: Stack) -> None: