From 4fc22a6c99c5f27d0158f1fe2cd634f12790696f Mon Sep 17 00:00:00 2001 From: EQ maintenance for AliZakaee <62015010+AliZakaee@users.noreply.github.com> Date: Fri, 7 Aug 2026 20:42:48 +0330 Subject: [PATCH] fix: report failed automatic deliveries --- handlers/business_updates.py | 38 ++++++++++++++++++-- tests/unit/handlers/test_business_updates.py | 34 ++++++++++++++++++ 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/handlers/business_updates.py b/handlers/business_updates.py index c1d4a8e..4a5f8ee 100644 --- a/handlers/business_updates.py +++ b/handlers/business_updates.py @@ -207,9 +207,41 @@ def _deliver_auto(conn, message, customer_text: str, reply_text: str) -> None: "reply permission. Check Telegram Business → Chatbots." ) return - telegram_api.send_reply(handlers.bot, customer_chat_id, reply_text, - business_connection_id=bcid, - reply_to_message_id=message.message_id) + try: + telegram_api.send_reply( + handlers.bot, + customer_chat_id, + reply_text, + business_connection_id=bcid, + reply_to_message_id=message.message_id, + ) + except telegram_api.TelegramPartialSendError as exc: + log.error( + "auto-reply partially delivered chat=%s chunks=%d/%d", + utils.mask_id(customer_chat_id), + exc.sent_count, + exc.total_count, + ) + name = business_service.customer_display_name(bcid, customer_chat_id) + handlers.notify_owner( + f"⚠️ An automatic reply to {utils.escape(name)} was only " + f"partially delivered ({exc.sent_count}/{exc.total_count} parts). " + "Check the customer chat before sending anything else." + ) + return + except Exception as exc: + log.warning( + "auto-reply delivery unconfirmed chat=%s error=%s", + utils.mask_id(customer_chat_id), + type(exc).__name__, + ) + name = business_service.customer_display_name(bcid, customer_chat_id) + handlers.notify_owner( + f"⚠️ Delivery of an automatic reply to {utils.escape(name)} " + "could not be confirmed. No outbound history was recorded; check " + "the customer chat before retrying." + ) + return database.insert_message(bcid, customer_chat_id, None, "out", "assistant", reply_text) memory_service.append_exchange(bcid, customer_chat_id, customer_text, reply_text) log.info("auto-replied chat=%s len=%d", utils.mask_id(customer_chat_id), len(reply_text)) diff --git a/tests/unit/handlers/test_business_updates.py b/tests/unit/handlers/test_business_updates.py index 4e33adb..8f35d0f 100644 --- a/tests/unit/handlers/test_business_updates.py +++ b/tests/unit/handlers/test_business_updates.py @@ -162,6 +162,40 @@ def test_deliver_auto_records_outbound(db, stub_bot, make_message, mocker): assert _out_count(db) == 1 +def test_deliver_auto_warns_on_partial_delivery(db, stub_bot, make_message, mocker): + mocker.patch( + "telegram_api.send_reply", + side_effect=bu.telegram_api.TelegramPartialSendError(1, 2), + ) + notify = mocker.patch("handlers.notify_owner") + db.upsert_business_connection("bc1", 999, True, True) + conn = db.get_business_connection("bc1") + + bu._deliver_auto(conn, make_message(chat_id=5), "ctext", "reply text") + + assert "partially delivered (1/2 parts)" in notify.call_args.args[0] + assert _out_count(db) == 0 + assert db.get_recent_memory("bc1", 5, 10) == [] + + +def test_deliver_auto_warns_when_delivery_is_unconfirmed( + db, stub_bot, make_message, mocker +): + mocker.patch( + "telegram_api.send_reply", + side_effect=bu.telegram_api.TelegramAPIError("unavailable"), + ) + notify = mocker.patch("handlers.notify_owner") + db.upsert_business_connection("bc1", 999, True, True) + conn = db.get_business_connection("bc1") + + bu._deliver_auto(conn, make_message(chat_id=5), "ctext", "reply text") + + assert "could not be confirmed" in notify.call_args.args[0] + assert _out_count(db) == 0 + assert db.get_recent_memory("bc1", 5, 10) == [] + + # --- deleted messages -------------------------------------------------------- def test_deleted_invalidates_approval(penv): aid = penv.db.insert_pending_approval("bc1", 5, 22, "c", "r")