From 1239c4af2ca7962805857324959a9e97b3c7f4cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Consultor=C3=ADa=20AS?= Date: Tue, 3 Feb 2026 22:54:07 +0000 Subject: [PATCH] feat: Add daily Threads content generation for manual publishing - Add generate_threads_manual_posts() task that creates 2 posts daily - Posts are saved with status 'draft' for manual copy/paste to Threads - Uses tip_tech template with rotating categories (productividad, ia, etc.) - Scheduled to run daily at 7:00 AM (Tijuana timezone) - Posts appear in dashboard for easy access This is a workaround while waiting for Threads API approval. Co-Authored-By: Claude Opus 4.5 --- worker/celery_app.py | 7 +++ worker/tasks/generate_content.py | 78 ++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/worker/celery_app.py b/worker/celery_app.py index 002970a..8a93929 100644 --- a/worker/celery_app.py +++ b/worker/celery_app.py @@ -79,6 +79,13 @@ celery_app.conf.beat_schedule = { "schedule": crontab(day_of_week=0, hour=5, minute=0), # Domingos 5 AM }, + # Generar posts para Threads (publicación manual) - 7:00 AM + "generate-threads-manual": { + "task": "worker.tasks.generate_content.generate_threads_manual_posts", + "schedule": crontab(hour=7, minute=0), + "args": [2], # 2 posts diarios + }, + # Reporte matutino por Telegram (8:00 AM Tijuana) "telegram-morning-report": { "task": "worker.tasks.daily_reports.morning_report", diff --git a/worker/tasks/generate_content.py b/worker/tasks/generate_content.py index 5cb7687..7a05cfa 100644 --- a/worker/tasks/generate_content.py +++ b/worker/tasks/generate_content.py @@ -549,6 +549,84 @@ def generate_service_post( db.close() +@celery_app.task(name="worker.tasks.generate_content.generate_threads_manual_posts") +def generate_threads_manual_posts(count: int = 2): + """ + Generar posts para Threads que se publicarán manualmente. + + Genera tips de tecnología variados optimizados para Threads + y los guarda con status 'draft' para copiar y publicar manualmente. + + Args: + count: Número de posts a generar (default 2) + """ + db = SessionLocal() + + try: + created = [] + # Categorías para variar el contenido + categories = ["productividad", "ia", "seguridad", "automatización", "python", "negocios"] + + for i in range(count): + # Seleccionar categoría diferente para cada post + category = categories[i % len(categories)] + + # Generar contenido con IA usando el template tip_tech + result = run_async( + content_generator.generate_with_quality_check( + template_name="tip_tech", + variables={ + "category": category, + "difficulty_level": "principiante", + "target_audience": "profesionales y emprendedores" + }, + platform="threads", + db=db, + max_attempts=2 + ) + ) + + content = result.get("content", "") + + if not content: + logger.warning(f"No se pudo generar contenido para Threads (categoria: {category})") + continue + + # Crear post con status draft (para publicación manual) + post = Post( + content=content, + content_threads=content, + content_type="tip_tech", + platforms=["threads"], + status="draft", # Para publicación manual + approval_required=False, + quality_score=result.get("quality_score"), + score_breakdown=result.get("score_breakdown"), + generation_attempts=result.get("attempts", 1) + ) + + db.add(post) + created.append(category) + + db.commit() + + logger.info(f"Generados {len(created)} posts para Threads (manual): categorías={created}") + + return { + "status": "success", + "generated": len(created), + "categories": created + } + + except Exception as e: + logger.error(f"Error generando posts para Threads: {e}") + db.rollback() + return {"status": "error", "error": str(e)} + + finally: + db.close() + + @celery_app.task(name="worker.tasks.generate_content.generate_thread") def generate_thread( topic: str,