admin_bot: add emergency pause, manual fallback configuration, and admin management UI
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
"""Channel lists render as one button menu, and each button opens that channel's card."""
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, "/app")
|
||||
|
||||
from db.database import init_db, close_db_pool
|
||||
from db.repository import Repository
|
||||
from services.admin_bot import AdminBotService
|
||||
|
||||
SRC = -1009999000030
|
||||
TRG = -1009999000031
|
||||
|
||||
|
||||
async def _cleanup(repo):
|
||||
pool = await repo._get_pool()
|
||||
async with pool.acquire() as conn:
|
||||
await conn.execute("DELETE FROM posts WHERE source_channel_id = $1;", SRC)
|
||||
await conn.execute("DELETE FROM sources WHERE channel_id = $1;", SRC)
|
||||
await conn.execute("DELETE FROM targets WHERE channel_id = $1;", TRG)
|
||||
|
||||
|
||||
def button_data(rows):
|
||||
return [b.data.decode() for row in rows for b in row]
|
||||
|
||||
|
||||
async def run_tests():
|
||||
await init_db()
|
||||
repo = Repository()
|
||||
await _cleanup(repo)
|
||||
try:
|
||||
await _run_assertions(repo)
|
||||
finally:
|
||||
await _cleanup(repo)
|
||||
await close_db_pool()
|
||||
print("All admin menu tests passed successfully!")
|
||||
|
||||
|
||||
async def _run_assertions(repo):
|
||||
bot = AdminBotService(repo=repo, review_channel_id=0, admin_user_ids=[1])
|
||||
|
||||
src_id = await repo.add_source(SRC, "Menu Source", "menusrc")
|
||||
target_id = await repo.add_target(TRG, "Menu Target", None)
|
||||
await repo.create_raw_post(SRC, 1, "a post", content_hash="menu_1")
|
||||
|
||||
# Source list: one button per source, pointing at its detail view.
|
||||
text, buttons = await bot._render_source_list()
|
||||
assert "Menu Source" not in text, "the list message itself should stay a header, not a card dump"
|
||||
data = button_data(buttons)
|
||||
assert f"src_view:{src_id}" in data, f"source button missing: {data}"
|
||||
|
||||
# Target list likewise, and it flags auto-routing.
|
||||
text, buttons = await bot._render_target_list()
|
||||
data = button_data(buttons)
|
||||
assert f"trg_view:{target_id}" in data, f"target button missing: {data}"
|
||||
def label_for(rows, want):
|
||||
for row in rows:
|
||||
for b in row:
|
||||
if b.data.decode() == want:
|
||||
return b.text
|
||||
raise AssertionError(f"button {want} not found")
|
||||
|
||||
assert "🤖" not in label_for(buttons, f"trg_view:{target_id}"), "no auto-route configured yet"
|
||||
await repo.set_target_auto_sources(target_id, [SRC])
|
||||
_, buttons = await bot._render_target_list()
|
||||
assert "🤖" in label_for(buttons, f"trg_view:{target_id}"), "auto-routed target should be flagged"
|
||||
|
||||
# Source detail card carries fetch buttons and a way back.
|
||||
card, buttons = await bot._render_source_config(src_id)
|
||||
assert "Menu Source" in card and str(SRC) in card
|
||||
assert "<b>1</b>" in card, f"collected count missing from card: {card}"
|
||||
assert "Menu Target" in card, "auto-routed target should be listed on the source card"
|
||||
data = button_data(buttons)
|
||||
assert f"hist:{SRC}:20" in data and f"histn:{SRC}" in data, f"fetch buttons missing: {data}"
|
||||
assert "list_src" in data, f"back button missing: {data}"
|
||||
|
||||
# Target detail card can get back to its list too.
|
||||
card, buttons = await bot._render_target_config(target_id)
|
||||
data = button_data(buttons)
|
||||
assert f"auto_src:{target_id}" in data, f"auto-route button missing: {data}"
|
||||
assert "list_trg" in data, f"back button missing: {data}"
|
||||
|
||||
# Missing ids degrade gracefully instead of raising.
|
||||
card, buttons = await bot._render_source_config(999999)
|
||||
assert "یافت نشد" in card and buttons == []
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(run_tests())
|
||||
Reference in New Issue
Block a user