diff --git a/app/api/routes/posts.py b/app/api/routes/posts.py index 6703aa6..1d51f1e 100644 --- a/app/api/routes/posts.py +++ b/app/api/routes/posts.py @@ -220,6 +220,62 @@ async def reject_post(post_id: int, db: Session = Depends(get_db)): return {"message": "Post rechazado", "post_id": post_id} +@router.post("/{post_id}/publish") +async def publish_post_now(post_id: int, db: Session = Depends(get_db)): + """Publicar un post inmediatamente.""" + from worker.tasks.publish_post import publish_to_platform + + post = db.query(Post).filter(Post.id == post_id).first() + if not post: + raise HTTPException(status_code=404, detail="Post no encontrado") + + if post.status not in ["draft", "pending_approval", "scheduled", "failed"]: + raise HTTPException( + status_code=400, + detail=f"No se puede publicar un post con status '{post.status}'" + ) + + # Cambiar estado a publishing + post.status = "publishing" + db.commit() + + # Encolar tarea de publicación para cada plataforma + for platform in post.platforms: + publish_to_platform.delay(post.id, platform) + + return { + "success": True, + "message": "Post enviado a publicación", + "post_id": post_id, + "platforms": post.platforms + } + + +@router.post("/{post_id}/mark-published") +async def mark_post_as_published(post_id: int, db: Session = Depends(get_db)): + """Marcar un post como publicado manualmente (sin usar API).""" + post = db.query(Post).filter(Post.id == post_id).first() + if not post: + raise HTTPException(status_code=404, detail="Post no encontrado") + + if post.status not in ["draft", "pending_approval", "scheduled", "failed"]: + raise HTTPException( + status_code=400, + detail=f"No se puede marcar un post con status '{post.status}'" + ) + + post.status = "published" + post.published_at = datetime.utcnow() + post.error_message = None + db.commit() + + return { + "success": True, + "message": "Post marcado como publicado", + "post_id": post_id + } + + @router.post("/{post_id}/regenerate") async def regenerate_post(post_id: int, db: Session = Depends(get_db)): """Regenerar contenido de un post con IA.""" diff --git a/app/worker/tasks.py b/app/worker/tasks.py index c3f45f9..060ba2a 100644 --- a/app/worker/tasks.py +++ b/app/worker/tasks.py @@ -60,10 +60,32 @@ def publish_post(self, post_id: int): for platform_name in post.platforms: try: platform = Platform(platform_name) + + # Get platform-specific content + platform_content = post.get_content_for_platform(platform_name) + + # Pre-validate content length with descriptive error + publisher = publisher_manager.get_publisher(platform) + if publisher and hasattr(publisher, 'char_limit'): + content_length = len(platform_content) + if content_length > publisher.char_limit: + error_msg = ( + f"Contenido excede límite: {content_length}/{publisher.char_limit} " + f"caracteres (sobra {content_length - publisher.char_limit})" + ) + logger.error(f"Validation failed for {platform_name}: {error_msg}") + results[platform_name] = { + "success": False, + "post_id": None, + "url": None, + "error": error_msg + } + continue + result = run_async( publisher_manager.publish( platform=platform, - content=post.content, + content=platform_content, image_path=post.image_url ) ) @@ -90,10 +112,14 @@ def publish_post(self, post_id: int): if any_success: post.status = "published" post.published_at = datetime.utcnow() - post.publish_results = results + post.platform_post_ids = { + k: v.get("post_id") for k, v in results.items() if v.get("success") + } else: post.status = "failed" - post.publish_results = results + # Collect all error messages + errors = [f"{k}: {v.get('error')}" for k, v in results.items() if v.get("error")] + post.error_message = "\n".join(errors) if errors else "Unknown error" db.commit() diff --git a/dashboard/templates/posts.html b/dashboard/templates/posts.html index 59a4617..506faef 100644 --- a/dashboard/templates/posts.html +++ b/dashboard/templates/posts.html @@ -184,10 +184,13 @@ ${platformContents} -