diff --git a/src/api/create_book.py b/src/api/create_book.py index e2354dd..f4ab035 100644 --- a/src/api/create_book.py +++ b/src/api/create_book.py @@ -1,16 +1,22 @@ -import aiohttp, asyncio +import asyncio from ebooklib import epub import unicodedata import re +from aiohttp_client_cache import CachedSession, FileBackend headers = { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" } +cache = FileBackend( + use_temp=True, + expire_after=43200, # 12 hours +) + async def retrieve_story(story_id: int, retry=True) -> dict: """Taking a story_id, return its information from the Wattpad API.""" - async with aiohttp.ClientSession(headers=headers) as session: + async with CachedSession(headers=headers, cache=cache) as session: try: async with session.get( f"https://www.wattpad.com/api/v3/stories/{story_id}?fields=tags,id,title,createDate,modifyDate,language(name),description,completed,mature,url,isPaywalled,user(username),parts(id,title),cover" @@ -31,7 +37,7 @@ async def retrieve_story(story_id: int, retry=True) -> dict: async def fetch_part_content(part_id: int) -> str: """Return the HTML Content of a Part.""" - async with aiohttp.ClientSession(headers=headers) as session: + async with CachedSession(headers=headers, cache=cache) as session: try: async with session.get( f"https://www.wattpad.com/apiv2/?m=storytext&id={part_id}" @@ -52,7 +58,7 @@ async def fetch_part_content(part_id: int) -> str: async def fetch_cover(url: str) -> bytes: """Fetch image bytes.""" - async with aiohttp.ClientSession(headers=headers) as session: + async with CachedSession(headers=headers, cache=cache) as session: try: async with session.get(url) as response: if not response.ok: diff --git a/src/api/main.py b/src/api/main.py index b9b7fa9..da28dc9 100644 --- a/src/api/main.py +++ b/src/api/main.py @@ -1,11 +1,19 @@ +from pathlib import Path from fastapi import FastAPI -from fastapi.responses import StreamingResponse +from fastapi.responses import FileResponse, StreamingResponse from ebooklib import epub -from create_book import retrieve_story, set_cover, set_metadata, add_chapters +from create_book import retrieve_story, set_cover, set_metadata, add_chapters, slugify import tempfile from io import BytesIO +from fastapi.staticfiles import StaticFiles app = FastAPI() +BUILD_PATH = Path(__file__).parent / "build" + + +@app.get("/") +def home(): + return FileResponse(BUILD_PATH / "index.html") @app.get("/download/{story_id}") @@ -37,11 +45,16 @@ async def download_book(story_id: int): return StreamingResponse( BytesIO(book_data), media_type="application/epub+zip", - headers={"Content-Disposition": f'attachment; filename="book_{story_id}.epub"'}, + headers={ + "Content-Disposition": f'attachment; filename="{slugify(data["title"])}_{story_id}.epub"' # Thanks https://stackoverflow.com/a/72729058 + }, ) +app.mount("/", StaticFiles(directory=BUILD_PATH), "static") + + if __name__ == "__main__": import uvicorn - uvicorn.run(app, host="0.0.0.0", port=80) + uvicorn.run(app, host="0.0.0.0", port=8084)