from fastapi import FastAPI, HTTPException from fastapi.responses import Response from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from playwright.async_api import async_playwright from typing import Optional import tempfile import os app = FastAPI() # Configura CORS para permitir requisições do frontend app.add_middleware( CORSMiddleware, allow_origins=["*"], # Em produção, especifique os domínios permitidos allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Modelo para criar posts (gerar imagem a partir de HTML) class PostRequest(BaseModel): html: str width: Optional[int] = 1080 # Largura padrão para posts (Instagram) height: Optional[int] = 1350 # Altura padrão para posts (Instagram) @app.get("/") def greet_json(): return {"Hello": "World!"} @app.post("/create-post") async def create_post(request: PostRequest): """ Cria uma imagem a partir de HTML para posts. Recebe HTML e retorna uma imagem PNG. Exemplo de uso: { "html": "
Conteúdo do post
", "width": 1080, "height": 1350 } """ html_file = None try: # Garantir que o HTML está completo html_content = request.html # Se o HTML não tiver estrutura completa, adicionar if " {html_content} """ # Criar arquivo temporário para o HTML with tempfile.NamedTemporaryFile(mode='w', suffix='.html', delete=False, encoding='utf-8') as f: f.write(html_content) html_file = f.name try: # Usar Playwright Async API para renderizar HTML e gerar screenshot async with async_playwright() as p: browser = await p.chromium.launch(headless=True) page = await browser.new_page(viewport={'width': request.width, 'height': request.height}) # Carrega o HTML do arquivo temporário await page.goto(f'file://{html_file}') # Espera o conteúdo carregar (especialmente imagens base64) await page.wait_for_timeout(2000) # Aguarda 2 segundos para garantir que imagens e fontes carreguem # Tira screenshot screenshot_bytes = await page.screenshot(full_page=True, type='png') await browser.close() # Remove arquivo temporário if os.path.exists(html_file): os.unlink(html_file) html_file = None # Retorna a imagem return Response( content=screenshot_bytes, media_type="image/png", headers={ "Content-Disposition": "attachment; filename=post.png" } ) except Exception as e: # Remove arquivo temporário em caso de erro if html_file and os.path.exists(html_file): os.unlink(html_file) raise e except Exception as e: # Garantir limpeza do arquivo temporário if html_file and os.path.exists(html_file): try: os.unlink(html_file) except: pass raise HTTPException(status_code=500, detail=f"Erro ao gerar imagem do post: {str(e)}")