fix: add error handler and resilient reply to prevent crash on deleted messages

This commit is contained in:
Andre Kamarudin 2026-04-16 08:35:30 +08:00
parent b625ed237a
commit 3c6cafd62d

33
main.py
View file

@ -11,6 +11,7 @@ import subprocess
from openai import OpenAI from openai import OpenAI
from telegram import BotCommand, Update from telegram import BotCommand, Update
from telegram.error import BadRequest, TimedOut
from telegram.ext import ( from telegram.ext import (
ApplicationBuilder, ApplicationBuilder,
CommandHandler, CommandHandler,
@ -345,7 +346,7 @@ async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None
) )
except Exception as e: except Exception as e:
log.error("OpenAI API error: %s", e) log.error("OpenAI API error: %s", e)
await update.message.reply_text(f"Sorry, I hit an error: {e}") await _safe_reply(update, f"Sorry, I hit an error: {e}")
return return
choice = response.choices[0] choice = response.choices[0]
@ -381,14 +382,31 @@ async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None
if len(messages) > 60: if len(messages) > 60:
messages[:] = messages[:1] + messages[-40:] messages[:] = messages[:1] + messages[-40:]
await update.message.reply_text(msg.content) await _safe_reply(update, msg.content)
return return
await update.message.reply_text( await _safe_reply(
"I ran out of steps — please try again with a simpler request." update, "I ran out of steps — please try again with a simpler request."
) )
async def _safe_reply(update: Update, text: str, **kwargs) -> None:
"""Reply to a message, falling back to send_message if the original is gone."""
try:
await update.message.reply_text(text, **kwargs)
except BadRequest:
log.warning("Could not reply to message, sending without reply")
await update.effective_chat.send_message(text, **kwargs)
async def _error_handler(update: object, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Log errors and keep the bot running."""
if isinstance(context.error, TimedOut):
log.warning("Telegram request timed out")
return
log.error("Unhandled exception: %s", context.error, exc_info=context.error)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Main # Main
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@ -397,13 +415,16 @@ def main() -> None:
app.add_handler(CommandHandler("start", cmd_start)) app.add_handler(CommandHandler("start", cmd_start))
app.add_handler(CommandHandler("reset", cmd_reset)) app.add_handler(CommandHandler("reset", cmd_reset))
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message)) app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
app.add_error_handler(_error_handler)
# Register bot commands for the / menu # Register bot commands for the / menu
async def post_init(application) -> None: async def post_init(application) -> None:
await application.bot.set_my_commands([ await application.bot.set_my_commands(
[
BotCommand("start", "Show welcome message"), BotCommand("start", "Show welcome message"),
BotCommand("reset", "Reset conversation"), BotCommand("reset", "Reset conversation"),
]) ]
)
log.info("Bot commands registered") log.info("Bot commands registered")
app.post_init = post_init app.post_init = post_init