Token upload
This commit is contained in:
+44
-1
@@ -1,13 +1,16 @@
|
||||
import asyncio
|
||||
import io
|
||||
import re
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote
|
||||
|
||||
import httpx
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from fastapi import APIRouter, File, Form, HTTPException, UploadFile
|
||||
from fastapi.responses import FileResponse, StreamingResponse
|
||||
from PIL import Image
|
||||
|
||||
import db
|
||||
from worker import safe_filename
|
||||
from config import OUTPUTS
|
||||
|
||||
router = APIRouter()
|
||||
@@ -43,6 +46,46 @@ async def deck_cards(slug: str):
|
||||
]
|
||||
|
||||
|
||||
@router.post("/decks/{slug}/upload-image", status_code=201)
|
||||
async def upload_image(slug: str, name: str = Form(...), file: UploadFile = File(...)):
|
||||
slug = valid_slug(slug)
|
||||
deck = db.get_deck(slug)
|
||||
if not deck:
|
||||
raise HTTPException(404)
|
||||
name = name.strip()
|
||||
if not name:
|
||||
raise HTTPException(400, "name required")
|
||||
|
||||
raw = await file.read()
|
||||
try:
|
||||
img = Image.open(io.BytesIO(raw))
|
||||
img.load()
|
||||
except Exception:
|
||||
raise HTTPException(400, "unreadable image")
|
||||
if img.mode != "RGB":
|
||||
img = img.convert("RGB")
|
||||
|
||||
deck_dir = OUTPUTS / slug
|
||||
deck_dir.mkdir(exist_ok=True)
|
||||
|
||||
with db.conn() as c:
|
||||
max_pos = c.execute(
|
||||
"SELECT COALESCE(MAX(position), 0) FROM cards WHERE deck_slug=?", (slug,)
|
||||
).fetchone()[0]
|
||||
cur = c.execute(
|
||||
"INSERT INTO cards (deck_slug, name, position, fetch_status, price_usd) VALUES (?,?,?,?,0)",
|
||||
(slug, name, max_pos + 1, "done")
|
||||
)
|
||||
card_id = cur.lastrowid
|
||||
filename = f"{safe_filename(name)}_{card_id}.png"
|
||||
img.save(deck_dir / filename, "PNG")
|
||||
c.execute("UPDATE cards SET filename=? WHERE id=?", (filename, card_id))
|
||||
c.execute("INSERT INTO logs (deck_slug, line) VALUES (?,?)", (slug, f"[{max_pos + 1}] {name} — UPLOADED"))
|
||||
|
||||
db.recalc_done(slug)
|
||||
return {"id": card_id, "filename": filename}
|
||||
|
||||
|
||||
@router.get("/decks/{slug}/stream")
|
||||
async def stream(slug: str):
|
||||
slug = valid_slug(slug)
|
||||
|
||||
Reference in New Issue
Block a user