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 <noreply@anthropic.com>
This commit is contained in:
2026-02-03 22:54:07 +00:00
parent 67263e7ed9
commit 1239c4af2c
2 changed files with 85 additions and 0 deletions

View File

@@ -79,6 +79,13 @@ celery_app.conf.beat_schedule = {
"schedule": crontab(day_of_week=0, hour=5, minute=0), # Domingos 5 AM "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) # Reporte matutino por Telegram (8:00 AM Tijuana)
"telegram-morning-report": { "telegram-morning-report": {
"task": "worker.tasks.daily_reports.morning_report", "task": "worker.tasks.daily_reports.morning_report",

View File

@@ -549,6 +549,84 @@ def generate_service_post(
db.close() 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") @celery_app.task(name="worker.tasks.generate_content.generate_thread")
def generate_thread( def generate_thread(
topic: str, topic: str,