Жалоба Alex: «реплаю на сообщения Коди — не реагирует». Триаж реплай на
бота распознавал (07:57, rule=reply_to_bot, ответ через 25 с), но:
- set_reaction слал reaction_type одиночным объектом вместо reaction —
массива ReactionType: Telegram видел пустую реакцию — в личке молча
«снимал реакции» (ok → MessageSeen, 596/нед, 👀 не было видно), в
группе 400 REACTION_EMPTY. Тест test_seen_indication закреплял баг —
исправлен под Bot API;
- ответ в группе уходил отдельным сообщением: теперь reply на сообщение
(батч — на последнее, досылка --followup — на исходный вопрос) с
allow_sending_without_reply; личка — как было;
- edited_message уже принятого сообщения писался новым входящим
(m-516174914/915 — исправленная опечатка дала дубль в батче) — пропуск.
Тест: test_tg_group_ux 10 PASS; полный набор — без регрессий.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
76 lines
3.6 KiB
Python
76 lines
3.6 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""TG в группах (аудит 2026-10-17, «реплаю Коди — не реагирует»). Hermetic.
|
||
|
||
Запуск: ./venv/bin/python tests/test_tg_group_ux.py
|
||
|
||
Проверяет: setMessageReaction шлёт reaction МАССИВОМ (было reaction_type
|
||
одиночным объектом → REACTION_EMPTY в группе, пустая реакция в личке);
|
||
ответ в группе — reply на сообщение (батч — на последнее), с
|
||
allow_sending_without_reply; в личке — без цитаты; досылка итога в группе —
|
||
тоже reply; правка уже принятого сообщения распознаётся как не новое.
|
||
"""
|
||
import json
|
||
import os
|
||
import sys
|
||
import tempfile
|
||
|
||
sys.path.insert(0, "/root/simbiot-harness")
|
||
os.environ["SIMBIOT_DB"] = os.path.join(tempfile.mkdtemp(prefix="simbiot_grpux_"), "harness.db")
|
||
|
||
from harness import es, tg_inbox
|
||
|
||
es.init_db()
|
||
fails = []
|
||
|
||
|
||
def check(name, cond, extra=""):
|
||
print(("PASS" if cond else "FAIL"), name, ("| " + str(extra)) if not cond else "")
|
||
if not cond:
|
||
fails.append(name)
|
||
|
||
|
||
API = []
|
||
tg_inbox._load_env = lambda: None
|
||
tg_inbox._api = lambda method, params, timeout=35: API.append((method, dict(params))) or {"ok": True, "result": True}
|
||
|
||
tg_inbox.set_reaction(-100, 7)
|
||
meth, prm = API[-1]
|
||
check("реакция: метод setMessageReaction", meth == "setMessageReaction")
|
||
check("реакция: параметр reaction — массив ReactionType",
|
||
json.loads(prm.get("reaction", "null")) == [{"type": "emoji", "emoji": "👀"}], prm)
|
||
check("реакция: нет мусорного reaction_type", "reaction_type" not in prm, prm)
|
||
|
||
G, P = -1004402779881, 7569223131
|
||
for uid, chat, ct, mid, ts in ((1, G, "supergroup", 2420, "2026-10-17T07:57:30"),
|
||
(2, G, "supergroup", 2428, "2026-10-17T07:57:31"),
|
||
(3, P, "private", 4950, "2026-10-17T07:57:32"),
|
||
(4, G, "supergroup", 2500, "2026-10-17T08:00:00")):
|
||
es.append_event("inbox", f"m-{uid}", "MessageReceived", {
|
||
"update_id": uid, "chat_id": chat, "chat_type": ct, "message_id": mid,
|
||
"text": "вопрос", "kind": "text", "first_name": "Alex"})
|
||
|
||
|
||
def sent():
|
||
return [p for m, p in API if m == "sendMessage"][-1]
|
||
|
||
|
||
API.clear()
|
||
tg_inbox.send_batch_reply(["m-1", "m-2"], "сводный ответ")
|
||
s = sent()
|
||
check("батч в группе: reply на последнее сообщение", s.get("reply_to_message_id") == 2428, s)
|
||
check("reply не теряется, если цель удалена", s.get("allow_sending_without_reply") == "true", s)
|
||
tg_inbox.send_reply("m-3", "ответ в личку")
|
||
check("личка: без цитаты", "reply_to_message_id" not in sent(), sent())
|
||
tg_inbox.send_reply("m-4", "ответ в группу")
|
||
check("одиночный ответ в группе: reply", sent().get("reply_to_message_id") == 2500, sent())
|
||
tg_inbox.send_followup("m-4", "итог работы")
|
||
check("досылка в группе: reply на исходный вопрос", sent().get("reply_to_message_id") == 2500
|
||
and sent().get("text") == "итог работы", sent())
|
||
|
||
check("правка принятого сообщения — не новое",
|
||
tg_inbox._already_received({"chat": {"id": G}, "message_id": 2428}))
|
||
check("новое сообщение — новое",
|
||
not tg_inbox._already_received({"chat": {"id": G}, "message_id": 9999}))
|
||
|
||
print(f"\n{'OK' if not fails else 'FAILED'}: {len(fails)} fail(s)")
|
||
sys.exit(1 if fails else 0)
|