From e5ade4b81ed9aa9a72367e7f2feb4c7d35337cc9 Mon Sep 17 00:00:00 2001 From: dm1sh Date: Fri, 2 Jul 2021 03:58:12 +0500 Subject: [PATCH] Changed response format and added its schema, fixed some errors --- app/epub.py | 10 +++++++--- app/fb2.py | 42 ++++++++++++++++++++++++++++-------------- app/main.py | 12 ++++++------ app/utils.py | 12 ++++++++++-- 4 files changed, 51 insertions(+), 25 deletions(-) diff --git a/app/epub.py b/app/epub.py index ad7ec43..c9c6946 100644 --- a/app/epub.py +++ b/app/epub.py @@ -1,5 +1,6 @@ import aiofiles as aiof from base64 import b64encode +from fastapi import HTTPException import ebooklib from ebooklib import epub @@ -8,6 +9,7 @@ from tempfile import SpooledTemporaryFile from .utils import Document_Tokens + async def epub2html(file: SpooledTemporaryFile) -> str: """ @@ -22,10 +24,12 @@ async def epub2html(file: SpooledTemporaryFile) -> str: # TODO: join tokens to HTML html_content = "" ... - return html_content + return {**(tokens["metadata"]), "content": html_content} except Exception as e: - return "Error! Wrong epub file format: " + str(e) + raise HTTPException( + status_code=500, detail="Error! Wrong epub file format: " + str(e) + ) async def epub_to_tokens(file: SpooledTemporaryFile) -> Document_Tokens: @@ -89,4 +93,4 @@ def convert_list(titles_list: list[tuple[str, dict[str, str]]]): for title_obj in titles_list: res.append(title_obj[0]) - return "; ".join(res) \ No newline at end of file + return "; ".join(res) diff --git a/app/fb2.py b/app/fb2.py index 330711a..2a2e49f 100644 --- a/app/fb2.py +++ b/app/fb2.py @@ -1,7 +1,8 @@ from tempfile import SpooledTemporaryFile import xml.etree.ElementTree as ET from xml.etree.ElementTree import Element -from typing import Optional +from typing import Optional, Union +from fastapi import HTTPException from .utils import Document_Tokens @@ -13,21 +14,23 @@ namespaces = { HREF = f"{{{namespaces['xlink']}}}href" -async def fb22html(file: SpooledTemporaryFile) -> str: +async def fb22html(file: SpooledTemporaryFile) -> dict[str, str]: """ Splits fb2 to tokens and joins them to one html file """ try: - tokens = fb22tokens(file) + set_cover(tokens) html_content = fb2body2html(tokens) - return html_content + return {**(tokens["metadata"]), "content": html_content} except Exception as e: - return "Error! Wrong FB2 file format: " + str(e) + raise HTTPException( + status_code=500, detail="Error! Wrong fb2 file format: " + str(e) + ) def fb22tokens(file: SpooledTemporaryFile) -> Document_Tokens: @@ -46,7 +49,10 @@ def fb22tokens(file: SpooledTemporaryFile) -> Document_Tokens: """ tokens = { - "metadata": {}, + "metadata": { + "title": "", + "author": "", + }, "content": b"", } @@ -59,13 +65,13 @@ def fb22tokens(file: SpooledTemporaryFile) -> Document_Tokens: # Reading book metadata - book_info = description.find("title-info") + book_info = description.find("./title-info", namespaces) if book_info: metadata = {} - metadata["title"] = book_info.find("book-title", namespaces).text - metadata["author"] = get_author(book_info.find("author", namespaces)) - metadata["cover"] = get_cover(book_info.find("coverpage", namespaces)) - if metadata["cover"] is None: + metadata["title"] = book_info.find("./book-title", namespaces).text + metadata["author"] = get_author(book_info.find("./author", namespaces)) + metadata["cover"] = get_cover(book_info.find("./coverpage", namespaces)) + if not 'cover' in metadata.keys(): metadata.pop("cover") if len(metadata.keys()): @@ -101,11 +107,11 @@ def get_author(author: Element) -> str: "middle-name", "last-name", ): - el = author.find(tag_name, namespaces) + el = author.find("./" + tag_name, namespaces) if not el is None: res.append(el.text) if len(res) == 0: - res = author.find("nickname", namespaces).text + res = author.find("./nickname", namespaces).text else: res = " ".join(res) @@ -119,7 +125,15 @@ def get_cover(coverpage: Optional[Element]) -> Optional[str]: """ if coverpage: - return coverpage.find("image", namespaces).get(HREF) + return coverpage.find("./image", namespaces).get(HREF) + + +def set_cover(tokens: Document_Tokens) -> None: + cover = tokens["metadata"]["cover"] + if cover is None: + tokens["metadata"]["cover"] = "none" + elif cover[0] == "#": + tokens["metadata"]["cover"] = tokens[cover[1:]] def fb2body2html(tokens: Document_Tokens) -> str: diff --git a/app/main.py b/app/main.py index 98a6c1d..fb5382e 100644 --- a/app/main.py +++ b/app/main.py @@ -1,8 +1,10 @@ -from fastapi import FastAPI, File, UploadFile +from fastapi import FastAPI, File, UploadFile, HTTPException from fastapi.responses import HTMLResponse +from typing import Union from .epub import epub2html from .fb2 import fb22html +from .utils import HTMLBook app = FastAPI() @@ -12,14 +14,12 @@ def root(): return "Hello, World!" -@app.post( - "/uploadfile/", -) +@app.post("/uploadfile/", response_model=HTMLBook) async def create_upload_file(file: UploadFile = File(...)): if file.filename.endswith(".epub"): content = await epub2html(file.file) elif file.filename.endswith(".fb2"): content = await fb22html(file.file) else: - content = "Error! Unsupported file type" - return HTMLResponse(content=content) + raise HTTPException(status_code=415, detail="Error! Unsupported file type") + return content diff --git a/app/utils.py b/app/utils.py index 60a2a52..b277cca 100644 --- a/app/utils.py +++ b/app/utils.py @@ -1,3 +1,11 @@ -from typing import Union +from typing import Union, Optional +from pydantic import BaseModel -Document_Tokens = dict[str, Union[str, dict[str, str]]] \ No newline at end of file +Document_Tokens = dict[str, Union[str, dict[str, str]]] + + +class HTMLBook(BaseModel): + title: str + author: str + cover: Optional[str] + content: str