fix: watch diff — envío con fallback a texto plano y task no silencioso
Build & Deploy ResearchOwl / build-and-push (push) Successful in 7s

El resumen de diff generado por Claude se enviaba con parse_mode=MARKDOWN;
texto libre con entidades desbalanceadas provocaba BadRequest y el mensaje
no llegaba. Además el send_message estaba fuera del try/except de _task y el
task se retenía en _active_tasks sin await, así que la excepción se tragaba
sin log alguno.

- _safe_send(): intenta Markdown y reintenta en texto plano si falla
- _task: except de nivel superior que loguea cualquier fallo

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
ChemaVX
2026-06-09 18:39:55 +00:00
co-authored by Claude Opus 4.8
parent ca0eb059e8
commit fd9aaa193b
+27 -11
View File
@@ -816,6 +816,23 @@ async def _purge_on_startup(app: Application) -> None:
await db_conn.close() await db_conn.close()
async def _safe_send(bot, chat_id, text: str):
"""Envía un mensaje, con fallback a texto plano si falla el parseo Markdown.
Los resúmenes generados por Claude suelen contener entidades Markdown
desbalanceadas (*, _, [, `) que hacen que Telegram rechace el mensaje con
BadRequest. Sin este fallback, el envío fallaba en silencio.
"""
try:
await bot.send_message(chat_id, text, parse_mode=ParseMode.MARKDOWN)
except Exception as e:
logger.warning("Envío Markdown falló, reintentando en texto plano", error=str(e))
try:
await bot.send_message(chat_id, text)
except Exception as e2:
logger.error("Envío en texto plano también falló", chat_id=chat_id, error=str(e2))
async def _scheduler_loop(app: Application): async def _scheduler_loop(app: Application):
while True: while True:
db_conn = None db_conn = None
@@ -858,24 +875,23 @@ async def _scheduler_loop(app: Application):
) )
if summary: if summary:
await app.bot.send_message( await _safe_send(app.bot, c, summary)
c, summary, parse_mode=ParseMode.MARKDOWN
)
else: else:
await app.bot.send_message( await _safe_send(
c, app.bot, c,
f"🔄 *{t}* — sin novedades significativas esta vez.", f"🔄 *{t}* — sin novedades significativas esta vez."
parse_mode=ParseMode.MARKDOWN
) )
except Exception as e:
logger.error("Tarea programada falló",
topic=t, session_id=s, error=str(e))
finally: finally:
await inner_db_conn.close() await inner_db_conn.close()
task = asyncio.create_task(_task()) task = asyncio.create_task(_task())
_active_tasks[chat_id] = task _active_tasks[chat_id] = task
await app.bot.send_message( await _safe_send(
chat_id, app.bot, chat_id,
f"🔄 Investigación automática iniciada: `{topic}`", f"🔄 Investigación automática iniciada: `{topic}`"
parse_mode=ParseMode.MARKDOWN
) )
except Exception as e: except Exception as e:
logger.warning("Scheduler loop error", error=str(e)) logger.warning("Scheduler loop error", error=str(e))