- Estructura completa del proyecto con FastAPI - Modelos de base de datos (productos, servicios, posts, calendario, interacciones) - Publishers para X, Threads, Instagram, Facebook - Generador de contenido con DeepSeek API - Worker de Celery con tareas programadas - Dashboard básico con templates HTML - Docker Compose para despliegue - Documentación completa Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
87 lines
2.6 KiB
Python
87 lines
2.6 KiB
Python
"""
|
|
Tareas de limpieza y mantenimiento.
|
|
"""
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
from worker.celery_app import celery_app
|
|
from app.core.database import SessionLocal
|
|
from app.models.post import Post
|
|
from app.models.interaction import Interaction
|
|
|
|
|
|
@celery_app.task(name="worker.tasks.cleanup.daily_cleanup")
|
|
def daily_cleanup():
|
|
"""
|
|
Limpieza diaria del sistema.
|
|
Se ejecuta a las 3 AM.
|
|
"""
|
|
db = SessionLocal()
|
|
|
|
try:
|
|
results = []
|
|
|
|
# 1. Eliminar posts fallidos de más de 7 días
|
|
cutoff_failed = datetime.utcnow() - timedelta(days=7)
|
|
deleted_failed = db.query(Post).filter(
|
|
Post.status == "failed",
|
|
Post.created_at < cutoff_failed
|
|
).delete()
|
|
results.append(f"Posts fallidos eliminados: {deleted_failed}")
|
|
|
|
# 2. Archivar interacciones respondidas de más de 30 días
|
|
cutoff_interactions = datetime.utcnow() - timedelta(days=30)
|
|
archived = db.query(Interaction).filter(
|
|
Interaction.responded == True,
|
|
Interaction.responded_at < cutoff_interactions,
|
|
Interaction.is_archived == False
|
|
).update({"is_archived": True})
|
|
results.append(f"Interacciones archivadas: {archived}")
|
|
|
|
# 3. Eliminar posts cancelados de más de 14 días
|
|
cutoff_cancelled = datetime.utcnow() - timedelta(days=14)
|
|
deleted_cancelled = db.query(Post).filter(
|
|
Post.status == "cancelled",
|
|
Post.created_at < cutoff_cancelled
|
|
).delete()
|
|
results.append(f"Posts cancelados eliminados: {deleted_cancelled}")
|
|
|
|
# 4. Resetear contadores de tips (mensualmente, si es día 1)
|
|
if datetime.utcnow().day == 1:
|
|
from app.models.tip_template import TipTemplate
|
|
db.query(TipTemplate).update({"used_count": 0})
|
|
results.append("Contadores de tips reseteados")
|
|
|
|
db.commit()
|
|
|
|
return results
|
|
|
|
except Exception as e:
|
|
db.rollback()
|
|
return f"Error en limpieza: {e}"
|
|
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
@celery_app.task(name="worker.tasks.cleanup.cleanup_old_images")
|
|
def cleanup_old_images():
|
|
"""Limpiar imágenes generadas antiguas."""
|
|
import os
|
|
from pathlib import Path
|
|
|
|
upload_dir = Path("uploads/generated")
|
|
if not upload_dir.exists():
|
|
return "Directorio de uploads no existe"
|
|
|
|
cutoff = datetime.utcnow() - timedelta(days=7)
|
|
deleted = 0
|
|
|
|
for file in upload_dir.glob("*.png"):
|
|
file_time = datetime.fromtimestamp(file.stat().st_mtime)
|
|
if file_time < cutoff:
|
|
file.unlink()
|
|
deleted += 1
|
|
|
|
return f"Imágenes eliminadas: {deleted}"
|