|
|
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() |
|
|
|
|
|
|
|
|
app.add_middleware( |
|
|
CORSMiddleware, |
|
|
allow_origins=["*"], |
|
|
allow_credentials=True, |
|
|
allow_methods=["*"], |
|
|
allow_headers=["*"], |
|
|
) |
|
|
|
|
|
|
|
|
class PostRequest(BaseModel): |
|
|
html: str |
|
|
width: Optional[int] = 1080 |
|
|
height: Optional[int] = 1350 |
|
|
|
|
|
@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": "<div>Conteúdo do post</div>", |
|
|
"width": 1080, |
|
|
"height": 1350 |
|
|
} |
|
|
""" |
|
|
html_file = None |
|
|
try: |
|
|
|
|
|
html_content = request.html |
|
|
|
|
|
|
|
|
if "<!DOCTYPE" not in html_content and "<html" not in html_content: |
|
|
html_content = f"""<!DOCTYPE html> |
|
|
<html lang="pt-BR"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
</head> |
|
|
<body> |
|
|
{html_content} |
|
|
</body> |
|
|
</html>""" |
|
|
|
|
|
|
|
|
with tempfile.NamedTemporaryFile(mode='w', suffix='.html', delete=False, encoding='utf-8') as f: |
|
|
f.write(html_content) |
|
|
html_file = f.name |
|
|
|
|
|
try: |
|
|
|
|
|
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}) |
|
|
|
|
|
|
|
|
await page.goto(f'file://{html_file}') |
|
|
|
|
|
|
|
|
await page.wait_for_timeout(2000) |
|
|
|
|
|
|
|
|
screenshot_bytes = await page.screenshot(full_page=True, type='png') |
|
|
|
|
|
await browser.close() |
|
|
|
|
|
|
|
|
if os.path.exists(html_file): |
|
|
os.unlink(html_file) |
|
|
html_file = None |
|
|
|
|
|
|
|
|
return Response( |
|
|
content=screenshot_bytes, |
|
|
media_type="image/png", |
|
|
headers={ |
|
|
"Content-Disposition": "attachment; filename=post.png" |
|
|
} |
|
|
) |
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
if html_file and os.path.exists(html_file): |
|
|
os.unlink(html_file) |
|
|
raise e |
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
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)}") |