web1 / app.py
iq7se2's picture
Upload 9 files
d043a72 verified
import io
import os
from fastapi import FastAPI, HTTPException, Query
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import StreamingResponse
import uvicorn
from config import logger, validate_web_env
from database import init_db
from scraper import (
download_images_as_pdf_async,
download_images_as_zip_async,
fetch_chapter_images_api,
get_genres_list,
get_manga_chapters_api,
)
validate_web_env()
init_db()
app = FastAPI(title="Utoon Web API", version="1.0.0")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
async def home():
return {"status": "online"}
@app.get("/health")
async def health():
return {"ok": True}
@app.get("/manga/chapters")
async def manga_chapters(url: str = Query(..., description="Utoon manga URL")):
chapters = await get_manga_chapters_api(url)
if not chapters:
raise HTTPException(status_code=404, detail="No chapters found for this URL")
return {"url": url, "count": len(chapters), "chapters": chapters}
@app.get("/genres")
async def genres():
return {"genres": get_genres_list()}
@app.get("/chapter/download")
async def chapter_download(
chapter_id: str = Query(..., description="Chapter ID"),
manga_slug: str = Query("manga", description="Slug used in output filename"),
chapter_slug: str = Query("chapter", description="Chapter slug used in output filename"),
file_format: str = Query("pdf", pattern="^(pdf|zip)$"),
):
images = await fetch_chapter_images_api(chapter_id)
if not images:
raise HTTPException(status_code=404, detail="Could not fetch chapter images")
try:
if file_format == "pdf":
content = await download_images_as_pdf_async(images, manga_slug, chapter_id)
filename = f"{manga_slug}_chapter-{chapter_slug}.pdf"
media_type = "application/pdf"
else:
content = await download_images_as_zip_async(images, manga_slug, chapter_id)
filename = f"{manga_slug}_chapter-{chapter_slug}.zip"
media_type = "application/zip"
except Exception as exc:
logger.error("Failed to build %s for chapter %s: %s", file_format, chapter_id, exc)
raise HTTPException(status_code=500, detail="Failed to generate chapter file") from exc
return StreamingResponse(
io.BytesIO(content),
media_type=media_type,
headers={"Content-Disposition": f'attachment; filename="{filename}"'},
)
if __name__ == "__main__":
port = int(os.getenv("PORT", "7860"))
uvicorn.run("app:app", host="0.0.0.0", port=port)