feat(seo): wire autofill into publish path behind SEO_AUTOFILL (default off, dry-run support)
Build & Deploy ResearchOwl / build-and-push (push) Successful in 7s

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ChemaVX
2026-06-25 14:14:39 +00:00
co-authored by Claude Opus 4.8
parent 89aa8d6030
commit 7a995da88f
4 changed files with 870 additions and 52 deletions
+19 -2
View File
@@ -278,7 +278,11 @@ async def cmd_generate(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
chat_id = update.effective_chat.id
output_arg = ctx.args[0].lower() if ctx.args else ""
lang = "en" if len(ctx.args) > 1 and ctx.args[1].lower() == "en" else "es"
rest = [a.lower() for a in ctx.args[1:]]
lang = "en" if "en" in rest else "es"
# `/generate blog en dry` forces SEO dry-run for this one call (proposes SEO to
# Telegram, writes a bare draft). Global default still comes from SEO_AUTOFILL.
seo_override = "dryrun" if ("dry" in rest or "dryrun" in rest) else None
type_map = {
"podcast": OutputType.PODCAST,
@@ -347,7 +351,8 @@ async def cmd_generate(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
processor = ContentProcessor(db, ollama)
generator = OutputGenerator(db, ollama, processor)
output = await generator.generate(session_id, output_type, gen_progress, lang=lang)
output = await generator.generate(session_id, output_type, gen_progress,
lang=lang, seo_override=seo_override)
# Send as file if very long
if len(output) > 8000:
@@ -384,6 +389,18 @@ async def cmd_generate(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
else:
await send_chunked(update.message, output)
# SEO autofill / dry-run summary — a SEPARATE short message so it is never
# buried inside the long .md document. None on the flag-off path.
if getattr(generator, "last_publish_notice", None):
try:
await update.message.reply_text(
generator.last_publish_notice,
parse_mode=ParseMode.MARKDOWN,
disable_web_page_preview=True,
)
except Exception as e:
logger.warning("Failed to send SEO summary message", error=str(e))
try:
stats = await db.get_usage_stats(session_id)
total_cost = sum(s.get("total_cost", 0) for s in stats)