Spaces:
Paused
Paused
| import os | |
| import httpx | |
| from typing import Optional | |
| from fastapi import APIRouter, HTTPException | |
| from pydantic import BaseModel | |
| router = APIRouter() | |
| # 🔧 Configuração do WordPress | |
| WP_URL = os.getenv("WP_URL") | |
| WP_USER = os.getenv("WP_USER") | |
| WP_PASS = os.getenv("WP_PASS") | |
| if not WP_URL or not WP_USER or not WP_PASS: | |
| raise ValueError("❌ WP_URL, WP_USER ou WP_PASS não configurados!") | |
| AUTH = (WP_USER, WP_PASS) | |
| class WPPost(BaseModel): | |
| title: str | |
| content: str | |
| subhead: Optional[str] = None # 👈 campo ACF mapeado para "subtitulo" | |
| image_url: Optional[str] = None | |
| author_username: Optional[str] = None # 👈 novo campo para o username do author | |
| status: str = "publish" | |
| async def get_user_id_by_username(client: httpx.AsyncClient, username: str) -> Optional[int]: | |
| """Busca o ID do usuário pelo username""" | |
| try: | |
| response = await client.get(f"{WP_URL}/users?search={username}", auth=AUTH) | |
| if response.status_code == 200: | |
| users = response.json() | |
| for user in users: | |
| if user.get("slug") == username or user.get("name") == username: | |
| return user.get("id") | |
| return None | |
| except Exception: | |
| return None | |
| async def create_wordpress_post(post: WPPost): | |
| async with httpx.AsyncClient(timeout=20.0) as client: | |
| featured_media_id = None | |
| author_id = None | |
| # 👤 Buscar ID do author se username fornecido | |
| if post.author_username: | |
| author_id = await get_user_id_by_username(client, post.author_username) | |
| if not author_id: | |
| raise HTTPException( | |
| status_code=404, | |
| detail=f"Usuário '{post.author_username}' não encontrado" | |
| ) | |
| # Upload de imagem se fornecida | |
| if post.image_url: | |
| try: | |
| img_resp = await client.get(post.image_url, timeout=15.0) | |
| if img_resp.status_code == 200: | |
| filename = post.image_url.split("/")[-1].split("?")[0] | |
| media_headers = { | |
| "Content-Disposition": f"attachment; filename={filename}", | |
| "Content-Type": img_resp.headers.get("content-type", "image/jpeg") | |
| } | |
| upload = await client.post( | |
| f"{WP_URL}/media", | |
| auth=AUTH, | |
| headers=media_headers, | |
| content=img_resp.content | |
| ) | |
| if upload.status_code in [200, 201]: | |
| featured_media_id = upload.json().get("id") | |
| except Exception: | |
| pass # Ignora erro de imagem para não quebrar o post | |
| # Dados do post | |
| post_data = { | |
| "title": post.title, | |
| "content": post.content, | |
| "status": post.status | |
| } | |
| if featured_media_id: | |
| post_data["featured_media"] = featured_media_id | |
| # 👤 Adicionar author se encontrado | |
| if author_id: | |
| post_data["author"] = author_id | |
| # Campo ACF: subhead → subtitulo | |
| if post.subhead: | |
| post_data["subtitulo"] = post.subhead | |
| # Criar post | |
| response = await client.post(f"{WP_URL}/posts", auth=AUTH, json=post_data) | |
| if response.status_code not in [200, 201]: | |
| raise HTTPException(status_code=response.status_code, detail=response.text) | |
| result = response.json() | |
| # 🔄 Fallback: Se ACF não foi salvo, tentar novamente | |
| if post.subhead and not result.get("acf", {}).get("subtitulo"): | |
| post_id = result.get("id") | |
| if post_id: | |
| acf_data = {"acf": {"subtitulo": post.subhead}} | |
| update_resp = await client.post(f"{WP_URL}/posts/{post_id}", auth=AUTH, json=acf_data) | |
| if update_resp.status_code in [200, 201]: | |
| result = update_resp.json() | |
| return result |