Module src.generatorEdited

Expand source code
import datetime
from pathlib import Path
import os

from fitz import fitz

import globals
from distutils.dir_util import copy_tree
import shutil
from bson import json_util, ObjectId
import io
import pymongo
import re
from flask_restful import Resource
from webargs.flaskparser import use_kwargs
from webargs import fields
from src import auth
from marshmallow import Schema
from fontTools import ttLib
from contextlib import redirect_stderr
from zipfile import ZipFile, ZIP_STORED

fileOutputFolder = ""
fileRedactedFolder = ""
fileOutputImageFolder = ""
fileOutputFontFolder = ""
fileOutputStylesFolder = ""
fileOutputTextFolder = ""
SAMPLEXHTML = ""
SAMPLECSS = ""
fileOutputOPFFile = ""
fileOutputTocNcxFile = ""
fileOutputTocFile = ""
SAMPLEXHTMLTEXT = ""
SAMPLECSSTEXT = ""
fileOutputBodtFile = ""
toc = ""

# COPY TEMPLATE TO STATIC FOLDER


def templateCopy(fileID):
    global fileOutputFolder
    global fileRedactedFolder
    global fileOutputImageFolder
    global fileOutputFontFolder
    global fileOutputStylesFolder
    global fileOutputTextFolder
    global SAMPLEXHTML
    global SAMPLECSS
    global fileOutputOPFFile
    global fileOutputTocNcxFile
    global fileOutputTocFile
    global SAMPLEXHTMLTEXT
    global SAMPLECSSTEXT
    global fileOutputBodtFile

    fileOutputFolder = os.path.join(globals.FILES_FOLDER, fileID, "output")
    fileRedactedFolder = os.path.join(globals.FILES_FOLDER, fileID, "redacted")
    fileOutputImageFolder = os.path.join(
        globals.FILES_FOLDER, fileID, "output", "OEBPS", "images")
    fileOutputFontFolder = os.path.join(
        globals.FILES_FOLDER, fileID, "output", "OEBPS", "Fonts")
    fileOutputStylesFolder = os.path.join(
        globals.FILES_FOLDER, fileID, "output", "OEBPS", "css")
    fileOutputTextFolder = os.path.join(
        globals.FILES_FOLDER, fileID, "output", "OEBPS")

    SAMPLEXHTML = os.path.join(fileOutputTextFolder, "SAMPLE.xhtml")
    SAMPLECSS = os.path.join(fileOutputStylesFolder, "style.css")

    fileOutputOPFFile = os.path.join(
        globals.FILES_FOLDER, fileID, "output", "OEBPS", "package.opf")
    fileOutputTocNcxFile = os.path.join(
        globals.FILES_FOLDER, fileID, "output", "OEBPS", "toc.ncx")
    fileOutputTocFile = os.path.join(
        globals.FILES_FOLDER, fileID, "output", "OEBPS", "TOC.xhtml")

    fileOutputBodtFile = os.path.join(fileOutputStylesFolder, "body.css")

    Path(fileOutputFolder).mkdir(parents=True, exist_ok=True)
    Path(fileOutputStylesFolder).mkdir(parents=True, exist_ok=True)
    Path(fileOutputTextFolder).mkdir(parents=True, exist_ok=True)

    copy_tree("template2", fileOutputFolder)

    # COPY REDACTED IMAGES
    copy_tree(os.path.join(globals.FILES_FOLDER,
              fileID, "images"), fileOutputImageFolder)


auth_args = {"Authorization": fields.Str(required=True)}


def valueReplacer(PageNum, pageCSS, pageImg, text, Properties, width, height, TotalPages):
    """
    It takes a string, finds all instances of {{KEY}} and replaces them with the value of the key in the
    Properties dictionary

    :param PageNum: The page number of the current page
    :param pageCSS: The path to the CSS file for the page
    :param pageImg: The path to the image file for the page
    :param text: the text to be replaced
    :param Properties: A list of dictionaries, each dictionary has a key and a value
    :param width: The width of the image
    :param height: The height of the page in pixels
    :param TotalPages: Total number of pages in the book
    :return: The text of the template with the values replaced.
    """
    matches = re.finditer(r"{{(\w+)}}", text, re.MULTILINE)
    for matchNum, match in enumerate(matches, start=1):
        for groups in match.groups():
            if groups == "WIDTH":
                value = width

            elif groups == "HEIGHT":
                value = height

            elif groups == "FILE_REL_CSS":
                value = re.sub(r"(.+)Styles", "./Styles",
                               pageCSS.replace("\\", "/"), 0, re.MULTILINE)

            elif groups == "TITLEPAGE_REL_PATH":
                titlepageList = list(
                    filter(lambda d: d['key'] in "TITLEPAGE_NO", Properties))
                titlepageNum = titlepageList[0]["value"] if len(
                    titlepageList) > 0 else ""
                value = f"page_{str(int(titlepageNum) - 1).zfill(3)}.xhtml"

            elif groups == "CHAPTER1_REL_PATH":
                chapter1List = list(
                    filter(lambda d: d['key'] in "CHAPTER1_NO", Properties))
                chapter1Num = chapter1List[0]["value"] if len(
                    chapter1List) > 0 else ""
                value = f"page_{str(int(chapter1Num) - 1).zfill(3)}.xhtml"

            elif groups == "COPYRIGHT_REL_PATH":
                copyrightList = list(
                    filter(lambda d: d['key'] in "COPYRIGHT_NO", Properties))
                copyrightNum = copyrightList[0]["value"] if len(
                    copyrightList) > 0 else ""
                value = f"page_{str(int(copyrightNum) - 1).zfill(3)}.xhtml"

            elif groups == "COVER_REL_PATH":
                value = "cover.xhtml"

            elif groups == "TOTALPAGES":
                value = TotalPages

            elif groups == "RESOLUTION":
                value = str(width) + "x" + str(height)

            elif groups == "IMAGE_URL":
                value = re.sub(r"(.+)Images", "./Images",
                               pageImg.replace("\\", "/"), 0, re.MULTILINE)

            elif groups == "PAGENUM":
                value = int(PageNum) - 1
                if value == 0:
                    value = "cover"
                else:
                    value = str(value).zfill(3)
            elif groups == "BODY_REL_CSS":
                value = "./Styles/body.css"
            else:
                valueList = list(
                    filter(lambda d: d['key'] in groups, Properties))
                value = valueList[-1]["value"] if len(valueList) > 0 else ""
            if value != "":
                text = text.replace("{{" + str(groups) + "}}", str(value))
    return text


def font_style(font_path):
    """
    It takes a font file path as an argument, opens the font file, reads the name table, and returns a
    dictionary of the name table entries

    :param font_path: The path to the font file
    :return: A dictionary of font details.
    """
    font = ttLib.TTFont(font_path, ignoreDecompileErrors=True)
    with redirect_stderr(None):
        names = font['name'].names

    details = {}
    for x in names:
        if x.langID == 0 or x.langID == 1033:
            try:
                details[x.nameID] = str.lower(x.toUnicode())
            except UnicodeDecodeError:
                details[x.nameID] = str.lower(x.string.decode(errors='ignore'))

    return details


def suportingFilesCreation(Properties, width, height, Fonts, TotalPages):
    """
    It creates the supporting files for the epub.

    :param Properties: A dictionary of the book's metadata
    :param width: the width of the page in pixels
    :param height: the height of the page
    :param Fonts: A list of dictionaries, each dictionary containing the following keys:
    :param TotalPages: The number of pages in the PDF
    """
    global fileOutputFolder
    global fileRedactedFolder
    global fileOutputImageFolder
    global fileOutputFontFolder
    global fileOutputStylesFolder
    global fileOutputTextFolder
    global SAMPLEXHTML
    global SAMPLECSS
    global fileOutputOPFFile
    global fileOutputTocNcxFile
    global fileOutputTocFile
    global SAMPLEXHTMLTEXT
    global SAMPLECSSTEXT
    global fileOutputBodtFile

    bookmarkChapterStart = - 1
    while str(toc[bookmarkChapterStart + 1][1]).lower() not in ["contents", "table of content"]:
        bookmarkChapterStart += 1
    if TotalPages - 2 >= bookmarkChapterStart:
        bookmarkChapterStart += 1
    else:
        bookmarkChapterStart = -1

    contentNavs = []
    navOrder = 3
    sampleNav = '<navPoint id="navPoint-{{navOrder}}" playOrder="{{navOrder}}"><navLabel><text>{{topic}}</text></navLabel><content src="{{pagexhtml}}"/></navPoint>'
    tocs = []
    sampleToc = '<li id="NavPoint-{{navOrder}}"><a href="{{pagexhtml}}">{{topic}}</a></li>'
    backmatter = '<li><a epub:type="backmatter" href="{{pagexhtml}}">{{topic}}</a></li>'
    for content in range(bookmarkChapterStart, len(toc)):
        if toc[content][1].lower() in ["contents", "table of content", "toc"]:
            navOrder += 1
            contentNavs.append(sampleNav.replace("{{navOrder}}", str(navOrder))
                               .replace("{{topic}}", "Table of Contents")
                               .replace("{{pagexhtml}}", f"page_{str(toc[content][2] - 1).zfill(3)}.xhtml"))
            tocs.append(sampleToc.replace("{{navOrder}}", str(navOrder).zfill(2))
                        .replace("{{topic}}", "Table of Contents")
                        .replace("{{pagexhtml}}", f"page_{str(toc[content][2] - 1).zfill(3)}.xhtml"))
        elif toc[content][1].lower() in ["back cover"]:
            continue
        else:
            navOrder += 1
            contentNavs.append(sampleNav.replace("{{navOrder}}", str(navOrder))
                               .replace("{{topic}}", toc[content][1])
                               .replace("{{pagexhtml}}", f"page_{str(toc[content][2] - 1).zfill(3)}.xhtml"))
            tocs.append(sampleToc.replace("{{navOrder}}", str(navOrder).zfill(2))
                        .replace("{{topic}}", toc[content][1])
                        .replace("{{pagexhtml}}", f"page_{str(toc[content][2] - 1).zfill(3)}.xhtml"))
            if content == len(toc) - 2:
                backmatter = backmatter.replace("{{topic}}", toc[content][1]) \
                    .replace("{{pagexhtml}}", f"page_{str(toc[content][2] - 1).zfill(3)}.xhtml")
    if "{{" in backmatter:
        backmatter = ""

    # TOC.ncx
    with io.open(fileOutputTocNcxFile, 'r', encoding='utf8') as f:
        tocNcxText = f.read()

    tocNcxText = valueReplacer(
        "", "", "", tocNcxText, Properties, width, height, TotalPages)

    with io.open(fileOutputTocNcxFile, 'w', encoding='utf8', newline='\n') as f:
        f.write(tocNcxText.replace(
            "./Text", "Text").replace("<contentNavs/>", "\n".join(contentNavs)))

    # TOC.xHTML
    with io.open(fileOutputTocFile, 'r', encoding='utf8') as f:
        tocXhtmlText = f.read()

    tocXhtmlText = valueReplacer(
        "", "", "", tocXhtmlText, Properties, width, height, TotalPages)

    with io.open(fileOutputTocFile, 'w', encoding='utf8', newline='\n') as f:
        f.write(tocXhtmlText.replace("./Text", "Text").replace("<toc/>",
                "\n".join(tocs)).replace("<backmatter/>", backmatter))

    # PACKAGE.OPF
    with io.open(fileOutputOPFFile, 'r', encoding='utf8') as f:
        opfFileText = f.read()

    imgsTemplate = '<item id="{{IMG_ID}}" href="{{IMG_REL_PATH}}" media-type="image/jpeg"/>'
    bodysTemplate = '<item id="{{ID}}" href="{{TEXT_REL_PATH}}" media-type="application/xhtml+xml"/>'
    fontsTemplate = '<item id="font{{FONT_ID}}" href="{{FONT_REL_PATH}}" media-type="application/vnd.ms-opentype"/>'
    bodyRefsTemplate = '<itemref idref="{{ID}}" linear="yes"/>'
    csssTemplate = '<item href="{{CSS_REL_PATH}}" id="{{CSS_FILENAME}}" media-type="text/css" />'

    csss = []
    bodys = []
    imgs = []
    bodyRefs = []
    fonts = []

    for i in range(1, TotalPages + 1):
        coverPage = "cover" if i == 1 else str(i).zfill(3)
        No_of_the_pages = str(i).zfill(3)
        if coverPage == "cover":
            imgs.append(imgsTemplate
                        .replace("{{IMG_ID}}", "cover-image")
                        .replace("{{IMG_REL_PATH}}", f"images/{coverPage}.jpg"))
            bodys.append(bodysTemplate
                         .replace("{{ID}}", f"cover")
                         .replace("{{TEXT_REL_PATH}}", f"{coverPage}.xhtml"))
            bodyRefs.append(bodyRefsTemplate
                            .replace("{{ID}}", f"{coverPage}"))
        else:
            imgs.append(imgsTemplate
                        .replace("{{IMG_ID}}", f"img{str(int(coverPage) - 1).zfill(3)}")
                        .replace("{{IMG_REL_PATH}}",
                                 f"images/page_{str(int(coverPage) - 1).zfill(3)}.jpg"))
            bodys.append(bodysTemplate
                         .replace("{{ID}}", f"page{str(int(coverPage) - 1).zfill(3)}")
                         .replace("{{TEXT_REL_PATH}}",
                                  f"page_{str(int(coverPage) - 1).zfill(3)}.xhtml"))
            bodyRefs.append(bodyRefsTemplate
                            .replace("{{ID}}", f"page{str(int(coverPage) - 1).zfill(3)}"))

    for i in range(0, len(Fonts)):
        fontName = str(Fonts[i]["fontPath"]).replace("\\", "/").split("/")[-1]
        fontOutputPath = os.path.join(fileOutputFontFolder, fontName)
        fontPath = os.path.join(globals.FONT_FOLDER, fontName)
        # shutil.copy2(fontPath, fontOutputPath)
        Fonts[i]["FONT_REL_PATH"] = fontOutputPath.replace(
            "\\", "/").split("output/OEBPS/")[-1]
        fonts.append(fontsTemplate
                     .replace("{{FONT_ID}}", str(i + 1))
                     .replace("{{FONT_REL_PATH}}", Fonts[i]["FONT_REL_PATH"]))

    opfFileText = opfFileText \
        .replace("<imgs/>", "\n".join(imgs)) \
        .replace("<bodys/>", "\n".join(bodys)) \
        .replace("<bodyrefs/>", "\n".join(bodyRefs)) \
        .replace("<fonts/>", "")\
        .replace("{{NOW}}", datetime.datetime.now(datetime.timezone.utc).isoformat().split(".")[0] + "Z")

    opfFileText = valueReplacer(
        "", "", "", opfFileText, Properties, width, height, TotalPages)

    with io.open(fileOutputOPFFile, 'w', encoding='utf8', newline='\n') as f:
        f.write(opfFileText.replace("./Text", "Text"))


def xhtmlAndCssCreation(Properties, Fonts, TotalPages, Pages, fileID):
    """
    It takes the data from the database and creates the xhtml and css files

    :param Properties: A dictionary of properties that are used to replace values in the XHTML and CSS
    files
    :param Fonts: A list of font names used in the document
    :param TotalPages: Total number of pages in the PDF
    :param Pages: A list of dictionaries, each dictionary representing a page
    :param fileID: The ID of the file being processed
    """
    global fileOutputFolder
    global fileRedactedFolder
    global fileOutputImageFolder
    global fileOutputFontFolder
    global fileOutputStylesFolder
    global fileOutputTextFolder
    global SAMPLEXHTML
    global SAMPLECSS
    global fileOutputOPFFile
    global fileOutputTocNcxFile
    global fileOutputTocFile
    global SAMPLEXHTMLTEXT
    global SAMPLECSSTEXT
    global fileOutputBodtFile

    # GENERATING TEXT AND CSS FILES
    with io.open(SAMPLEXHTML, 'r', encoding='utf8') as f:
        SAMPLEXHTMLTEXT = f.read()

    with io.open(SAMPLECSS, 'r', encoding='utf8') as f:
        SAMPLEXCSSTEXT = f.read()
    width = ""
    height = ""
    for page in Pages:
        height = page["Image"]["Height"]
        width = page["Image"]["Width"]
        pageNum = str(page['PageNum'] - 1).zfill(3)
        boxes = list(globals.boxesDB.find(
            {
                "pageId": page["PageID"]
            }
        ).sort([("boxIndex", pymongo.ASCENDING)])
        )
        pageImgTmp = os.path.join(
            fileOutputImageFolder, f"Page{page['PageNum']}.jpeg")
        pageImg = ""
        pageImgNum = ""
        if page["PageNum"] == 1:
            coverImg = pageImgTmp.replace(
                f"Page{page['PageNum']}.jpeg", "cover.jpg")
            pageImgNum = "cover.jpg"
            if not os.path.exists(coverImg):
                os.rename(pageImgTmp, coverImg)
            if os.path.exists(pageImgTmp):
                os.remove(pageImgTmp)
            pageImg = coverImg
            pageXhtml = os.path.join(fileOutputTextFolder, "cover.xhtml")
            pageCSS = os.path.join(fileOutputStylesFolder, "style.css")
            pageXhtmlText = SAMPLEXHTMLTEXT
            pageCSSText = SAMPLEXCSSTEXT
            # coverXhtmlText = coverXhtmlText.replace()
        else:
            pageImg = pageImgTmp.replace(
                f"Page{page['PageNum']}.jpeg", f"page_{pageNum}.jpg")
            if not os.path.exists(pageImg):
                os.rename(pageImgTmp, pageImg)
            if os.path.exists(pageImgTmp):
                os.remove(pageImgTmp)
            pageXhtml = os.path.join(
                fileOutputTextFolder, f"page_{pageNum}.xhtml")
            pageImgNum = f"page_{pageNum}.jpg"
            pageCSS = os.path.join(fileOutputStylesFolder, f"style.css")
            pageXhtmlText = SAMPLEXHTMLTEXT
            pageCSSText = SAMPLEXCSSTEXT

        bodyData = []
        cssData = []
        cssCounter = 0
        lineCssCounter = 0
        bookmarkChapterStart = - 1
        while str(toc[bookmarkChapterStart+1][1]).lower() not in ["contents", "table of content"]:
            bookmarkChapterStart += 1
        if len(Pages) - 2 >= bookmarkChapterStart:
            bookmarkChapterStart += 1
        else:
            bookmarkChapterStart = -1

        bodyData.append(
            f'<p style="background-repeat: no-repeat;"><img src="images/{pageImgNum}" alt=""/></p>')
        for box in boxes:
            pStyle = f'position: absolute;\n' \
                     f'top: {box["coordinates"][1]}px;\n' \
                     f'left: {box["coordinates"][0]}px;\n' \
                     f'width: {width - box["coordinates"][0]}px;\n' \
                     f'height: {box["coordinates"][3]}px;\n'
            lineCssCounter += 1
            lineCssSelector = "line" + str(lineCssCounter)
            cssData.append(f".{lineCssSelector}" + "{\n" + pStyle + "\n}")

            innerHtml = []
            for line in box["linesData"]:
                if "%" not in line["lineHeight"]:
                    line["lineHeight"] += "%"
                innerCssData = f'position: {line["position"]};\n' \
                    f'top: {line["top"]};\n'\
                    f'font-family: sans-serif;\n'\
                    f'left: {line["left"]};\n'\
                    f'font-size: {line["fontSize"]};\n'\
                    f'-ms-transform: rotate({line["textRotate"]}deg);\n'\
                    f'-webkit-transform: rotate({line["textRotate"]}deg);\n'\
                    f'transform: rotate({line["textRotate"]}deg);\n'\
                    f'font-weight: normal;\n'\
                    f'line-height: {line["lineHeight"].replace("normal%","normal")};\n'\
                    f'color: {line["color"]};\n'\
                    f'word-spacing: {line["wordSpacing"]};\n'\
                    f'letter-spacing: {line["letterSpacing"]};\n'\
                    f'font-style: normal;\n'\
                    f'text-decoration: {line["textDecoration"]};\n'\
                    f'white-space: pre;\n'
                cssCounter += 1
                innerCssSelector = "span" + str(cssCounter)
                data = line["text"].replace("\n", "<br>\n")
                line["text"] = re.sub(
                    r"\s{2,}", " ", line["text"], 0, re.MULTILINE)
                if line["text"].startswith(" "):
                    lastIndex = len(innerHtml) - 1
                    print(lastIndex)
                    if len(innerHtml) > 0:
                        lastElement = innerHtml[lastIndex]
                        lastElement = lastElement.replace(
                            "</span>", " </span>")
                        innerHtml[lastIndex] = lastElement
                innerHtml.append(
                    f'<span class="{innerCssSelector}">{data.lstrip()}</span>')
                if line["br"] is True and "<br>" not in data:
                    innerHtml.append("<br>")
                cssData.append(f".{innerCssSelector}" +
                               "{\n" + innerCssData + "\n}")

            bodyData.append(
                f'<{box["tagName"]} class="{lineCssSelector}"><a href="page_{str(toc[bookmarkChapterStart+lineCssCounter][2] - 1).zfill(3)}.xhtml">{"".join(innerHtml)}</a></{box["tagName"]}>')

        pageXhtmlText = pageXhtmlText.replace(
            "<bodyData/>", "\n".join(bodyData)).replace("<br>", "")
        cssDataFinal = "\n".join(cssData)
        # cssDataFinal = re.sub(r"font-family:(.*?);", "font-family:\"\\1\";", cssDataFinal, 0, re.MULTILINE)
        cssDataFinal = cssDataFinal.replace('" sans-serif"', "sans-serif")
        # pageCSSText = pageCSSText.replace("{{BODY_CSS}}", cssDataFinal)

        if len(boxes) == 0:
            pageXhtmlText = pageXhtmlText.replace(
                "<bodyData/>", "\n".join(bodyData)).replace("<br>", "")
            cssDataFinal = cssDataFinal.replace(
                "{{BODY_CSS}}", "").replace("{{FONTS_CSS}}", "")

        # REPLACING PROPERTIES IN CSS AND XHTML FILES
        if page['PageNum'] == 1:
            pageNum = "cover"
        pageXhtmlText = valueReplacer(page['PageNum'], pageCSS, pageImg, pageXhtmlText, Properties, width, height,
                                      TotalPages).\
            replace('<link href="./Styles/body.css" type="text/css" rel="stylesheet" />', "")\
            .replace(f"static/files/{fileID}/output/OEBPS", ".").replace(' class="page"', "")
        cssDataFinal = valueReplacer(page['PageNum'], pageCSS, pageImg, cssDataFinal, Properties, width, height,
                                     TotalPages)

        with io.open(pageXhtml, 'w', encoding='utf8', newline='\n') as f:
            f.write(re.sub(r"^\s+", "", pageXhtmlText, 0, re.MULTILINE))

        with io.open(pageCSS, 'a', encoding='utf8', newline='\n') as f:
            f.write(cssDataFinal)
    finalCss = ""
    fileCss = os.path.join(fileOutputStylesFolder, "style.css")
    with io.open(fileCss, 'r', encoding='utf8', newline='\n') as f:
        finalCss = f.read()

    with io.open(fileCss, 'w', encoding='utf8', newline='\n') as f:
        f.write(finalCss.replace("{{WIDTH}}", str(
            width)).replace("{{HEIGHT}}", str(height)))

    os.remove(SAMPLEXHTML)
    # os.remove(SAMPLECSS)


# It takes a fileID, verifies the user's token, and then creates an epub file from a pdf file.
class GenerateFile2(Resource):

    @use_kwargs(auth_args, location="headers")
    @use_kwargs({"fileID": fields.Str(required=True)}, location="query")
    def post(self, Authorization, fileID):
        """
        It takes a PDF file, converts it to an EPUB file, and returns the path to the EPUB file.

        :param Authorization: The token that is generated when the user logs in
        :param fileID: The ID of the file in the database
        :return: The path to the epub file.
        """
        if auth.verify(str(Authorization).split(" ")[1]):
            templateCopy(fileID)
            result = globals.filesDB.find_one(
                {
                    "_id": ObjectId(fileID)
                }
            )

            TotalPages = result["TotalPages"]
            Pages = result["Pages"]
            Fonts = result["Fonts"]
            Properties = result["Properties"]
            width = result["Pages"][0]["Image"]["Width"]
            height = result["Pages"][0]["Image"]["Height"]
            doc = fitz.open(os.path.join(
                globals.FILES_FOLDER, fileID, f"{fileID}.pdf"))
            global toc
            toc = doc.get_toc()
            suportingFilesCreation(
                Properties, width, height, Fonts, TotalPages)
            xhtmlAndCssCreation(Properties, Fonts, TotalPages, Pages, fileID)
            isbn = list(filter(lambda d: d['key'] in "ISBN", Properties))
            if len(isbn) > 0:
                isbn = isbn[0]["value"]
            else:
                isbn = "undefined"

            finalFile = os.path.join(fileOutputFolder, f'{isbn}.epub')
            if os.path.exists(finalFile):
                os.remove(finalFile)

            zipobj = ZipFile(finalFile, 'w', ZIP_STORED)
            rootlen = len(fileOutputFolder) + 1
            for base, dirs, files in os.walk(fileOutputFolder):
                for file in files:
                    if ".epub" not in file:
                        fn = os.path.join(base, file)
                        zipobj.write(fn, fn[rootlen:])

            return {"msg": finalFile.replace("\\", "/")}, 200
        else:
            return {"msg": "Unauthorized! Access Denied"}, 401

Functions

def font_style(font_path)

It takes a font file path as an argument, opens the font file, reads the name table, and returns a dictionary of the name table entries

:param font_path: The path to the font file :return: A dictionary of font details.

Expand source code
def font_style(font_path):
    """
    It takes a font file path as an argument, opens the font file, reads the name table, and returns a
    dictionary of the name table entries

    :param font_path: The path to the font file
    :return: A dictionary of font details.
    """
    font = ttLib.TTFont(font_path, ignoreDecompileErrors=True)
    with redirect_stderr(None):
        names = font['name'].names

    details = {}
    for x in names:
        if x.langID == 0 or x.langID == 1033:
            try:
                details[x.nameID] = str.lower(x.toUnicode())
            except UnicodeDecodeError:
                details[x.nameID] = str.lower(x.string.decode(errors='ignore'))

    return details
def suportingFilesCreation(Properties, width, height, Fonts, TotalPages)

It creates the supporting files for the epub.

:param Properties: A dictionary of the book's metadata :param width: the width of the page in pixels :param height: the height of the page :param Fonts: A list of dictionaries, each dictionary containing the following keys: :param TotalPages: The number of pages in the PDF

Expand source code
def suportingFilesCreation(Properties, width, height, Fonts, TotalPages):
    """
    It creates the supporting files for the epub.

    :param Properties: A dictionary of the book's metadata
    :param width: the width of the page in pixels
    :param height: the height of the page
    :param Fonts: A list of dictionaries, each dictionary containing the following keys:
    :param TotalPages: The number of pages in the PDF
    """
    global fileOutputFolder
    global fileRedactedFolder
    global fileOutputImageFolder
    global fileOutputFontFolder
    global fileOutputStylesFolder
    global fileOutputTextFolder
    global SAMPLEXHTML
    global SAMPLECSS
    global fileOutputOPFFile
    global fileOutputTocNcxFile
    global fileOutputTocFile
    global SAMPLEXHTMLTEXT
    global SAMPLECSSTEXT
    global fileOutputBodtFile

    bookmarkChapterStart = - 1
    while str(toc[bookmarkChapterStart + 1][1]).lower() not in ["contents", "table of content"]:
        bookmarkChapterStart += 1
    if TotalPages - 2 >= bookmarkChapterStart:
        bookmarkChapterStart += 1
    else:
        bookmarkChapterStart = -1

    contentNavs = []
    navOrder = 3
    sampleNav = '<navPoint id="navPoint-{{navOrder}}" playOrder="{{navOrder}}"><navLabel><text>{{topic}}</text></navLabel><content src="{{pagexhtml}}"/></navPoint>'
    tocs = []
    sampleToc = '<li id="NavPoint-{{navOrder}}"><a href="{{pagexhtml}}">{{topic}}</a></li>'
    backmatter = '<li><a epub:type="backmatter" href="{{pagexhtml}}">{{topic}}</a></li>'
    for content in range(bookmarkChapterStart, len(toc)):
        if toc[content][1].lower() in ["contents", "table of content", "toc"]:
            navOrder += 1
            contentNavs.append(sampleNav.replace("{{navOrder}}", str(navOrder))
                               .replace("{{topic}}", "Table of Contents")
                               .replace("{{pagexhtml}}", f"page_{str(toc[content][2] - 1).zfill(3)}.xhtml"))
            tocs.append(sampleToc.replace("{{navOrder}}", str(navOrder).zfill(2))
                        .replace("{{topic}}", "Table of Contents")
                        .replace("{{pagexhtml}}", f"page_{str(toc[content][2] - 1).zfill(3)}.xhtml"))
        elif toc[content][1].lower() in ["back cover"]:
            continue
        else:
            navOrder += 1
            contentNavs.append(sampleNav.replace("{{navOrder}}", str(navOrder))
                               .replace("{{topic}}", toc[content][1])
                               .replace("{{pagexhtml}}", f"page_{str(toc[content][2] - 1).zfill(3)}.xhtml"))
            tocs.append(sampleToc.replace("{{navOrder}}", str(navOrder).zfill(2))
                        .replace("{{topic}}", toc[content][1])
                        .replace("{{pagexhtml}}", f"page_{str(toc[content][2] - 1).zfill(3)}.xhtml"))
            if content == len(toc) - 2:
                backmatter = backmatter.replace("{{topic}}", toc[content][1]) \
                    .replace("{{pagexhtml}}", f"page_{str(toc[content][2] - 1).zfill(3)}.xhtml")
    if "{{" in backmatter:
        backmatter = ""

    # TOC.ncx
    with io.open(fileOutputTocNcxFile, 'r', encoding='utf8') as f:
        tocNcxText = f.read()

    tocNcxText = valueReplacer(
        "", "", "", tocNcxText, Properties, width, height, TotalPages)

    with io.open(fileOutputTocNcxFile, 'w', encoding='utf8', newline='\n') as f:
        f.write(tocNcxText.replace(
            "./Text", "Text").replace("<contentNavs/>", "\n".join(contentNavs)))

    # TOC.xHTML
    with io.open(fileOutputTocFile, 'r', encoding='utf8') as f:
        tocXhtmlText = f.read()

    tocXhtmlText = valueReplacer(
        "", "", "", tocXhtmlText, Properties, width, height, TotalPages)

    with io.open(fileOutputTocFile, 'w', encoding='utf8', newline='\n') as f:
        f.write(tocXhtmlText.replace("./Text", "Text").replace("<toc/>",
                "\n".join(tocs)).replace("<backmatter/>", backmatter))

    # PACKAGE.OPF
    with io.open(fileOutputOPFFile, 'r', encoding='utf8') as f:
        opfFileText = f.read()

    imgsTemplate = '<item id="{{IMG_ID}}" href="{{IMG_REL_PATH}}" media-type="image/jpeg"/>'
    bodysTemplate = '<item id="{{ID}}" href="{{TEXT_REL_PATH}}" media-type="application/xhtml+xml"/>'
    fontsTemplate = '<item id="font{{FONT_ID}}" href="{{FONT_REL_PATH}}" media-type="application/vnd.ms-opentype"/>'
    bodyRefsTemplate = '<itemref idref="{{ID}}" linear="yes"/>'
    csssTemplate = '<item href="{{CSS_REL_PATH}}" id="{{CSS_FILENAME}}" media-type="text/css" />'

    csss = []
    bodys = []
    imgs = []
    bodyRefs = []
    fonts = []

    for i in range(1, TotalPages + 1):
        coverPage = "cover" if i == 1 else str(i).zfill(3)
        No_of_the_pages = str(i).zfill(3)
        if coverPage == "cover":
            imgs.append(imgsTemplate
                        .replace("{{IMG_ID}}", "cover-image")
                        .replace("{{IMG_REL_PATH}}", f"images/{coverPage}.jpg"))
            bodys.append(bodysTemplate
                         .replace("{{ID}}", f"cover")
                         .replace("{{TEXT_REL_PATH}}", f"{coverPage}.xhtml"))
            bodyRefs.append(bodyRefsTemplate
                            .replace("{{ID}}", f"{coverPage}"))
        else:
            imgs.append(imgsTemplate
                        .replace("{{IMG_ID}}", f"img{str(int(coverPage) - 1).zfill(3)}")
                        .replace("{{IMG_REL_PATH}}",
                                 f"images/page_{str(int(coverPage) - 1).zfill(3)}.jpg"))
            bodys.append(bodysTemplate
                         .replace("{{ID}}", f"page{str(int(coverPage) - 1).zfill(3)}")
                         .replace("{{TEXT_REL_PATH}}",
                                  f"page_{str(int(coverPage) - 1).zfill(3)}.xhtml"))
            bodyRefs.append(bodyRefsTemplate
                            .replace("{{ID}}", f"page{str(int(coverPage) - 1).zfill(3)}"))

    for i in range(0, len(Fonts)):
        fontName = str(Fonts[i]["fontPath"]).replace("\\", "/").split("/")[-1]
        fontOutputPath = os.path.join(fileOutputFontFolder, fontName)
        fontPath = os.path.join(globals.FONT_FOLDER, fontName)
        # shutil.copy2(fontPath, fontOutputPath)
        Fonts[i]["FONT_REL_PATH"] = fontOutputPath.replace(
            "\\", "/").split("output/OEBPS/")[-1]
        fonts.append(fontsTemplate
                     .replace("{{FONT_ID}}", str(i + 1))
                     .replace("{{FONT_REL_PATH}}", Fonts[i]["FONT_REL_PATH"]))

    opfFileText = opfFileText \
        .replace("<imgs/>", "\n".join(imgs)) \
        .replace("<bodys/>", "\n".join(bodys)) \
        .replace("<bodyrefs/>", "\n".join(bodyRefs)) \
        .replace("<fonts/>", "")\
        .replace("{{NOW}}", datetime.datetime.now(datetime.timezone.utc).isoformat().split(".")[0] + "Z")

    opfFileText = valueReplacer(
        "", "", "", opfFileText, Properties, width, height, TotalPages)

    with io.open(fileOutputOPFFile, 'w', encoding='utf8', newline='\n') as f:
        f.write(opfFileText.replace("./Text", "Text"))
def templateCopy(fileID)
Expand source code
def templateCopy(fileID):
    global fileOutputFolder
    global fileRedactedFolder
    global fileOutputImageFolder
    global fileOutputFontFolder
    global fileOutputStylesFolder
    global fileOutputTextFolder
    global SAMPLEXHTML
    global SAMPLECSS
    global fileOutputOPFFile
    global fileOutputTocNcxFile
    global fileOutputTocFile
    global SAMPLEXHTMLTEXT
    global SAMPLECSSTEXT
    global fileOutputBodtFile

    fileOutputFolder = os.path.join(globals.FILES_FOLDER, fileID, "output")
    fileRedactedFolder = os.path.join(globals.FILES_FOLDER, fileID, "redacted")
    fileOutputImageFolder = os.path.join(
        globals.FILES_FOLDER, fileID, "output", "OEBPS", "images")
    fileOutputFontFolder = os.path.join(
        globals.FILES_FOLDER, fileID, "output", "OEBPS", "Fonts")
    fileOutputStylesFolder = os.path.join(
        globals.FILES_FOLDER, fileID, "output", "OEBPS", "css")
    fileOutputTextFolder = os.path.join(
        globals.FILES_FOLDER, fileID, "output", "OEBPS")

    SAMPLEXHTML = os.path.join(fileOutputTextFolder, "SAMPLE.xhtml")
    SAMPLECSS = os.path.join(fileOutputStylesFolder, "style.css")

    fileOutputOPFFile = os.path.join(
        globals.FILES_FOLDER, fileID, "output", "OEBPS", "package.opf")
    fileOutputTocNcxFile = os.path.join(
        globals.FILES_FOLDER, fileID, "output", "OEBPS", "toc.ncx")
    fileOutputTocFile = os.path.join(
        globals.FILES_FOLDER, fileID, "output", "OEBPS", "TOC.xhtml")

    fileOutputBodtFile = os.path.join(fileOutputStylesFolder, "body.css")

    Path(fileOutputFolder).mkdir(parents=True, exist_ok=True)
    Path(fileOutputStylesFolder).mkdir(parents=True, exist_ok=True)
    Path(fileOutputTextFolder).mkdir(parents=True, exist_ok=True)

    copy_tree("template2", fileOutputFolder)

    # COPY REDACTED IMAGES
    copy_tree(os.path.join(globals.FILES_FOLDER,
              fileID, "images"), fileOutputImageFolder)
def valueReplacer(PageNum, pageCSS, pageImg, text, Properties, width, height, TotalPages)

It takes a string, finds all instances of {{KEY}} and replaces them with the value of the key in the Properties dictionary

:param PageNum: The page number of the current page :param pageCSS: The path to the CSS file for the page :param pageImg: The path to the image file for the page :param text: the text to be replaced :param Properties: A list of dictionaries, each dictionary has a key and a value :param width: The width of the image :param height: The height of the page in pixels :param TotalPages: Total number of pages in the book :return: The text of the template with the values replaced.

Expand source code
def valueReplacer(PageNum, pageCSS, pageImg, text, Properties, width, height, TotalPages):
    """
    It takes a string, finds all instances of {{KEY}} and replaces them with the value of the key in the
    Properties dictionary

    :param PageNum: The page number of the current page
    :param pageCSS: The path to the CSS file for the page
    :param pageImg: The path to the image file for the page
    :param text: the text to be replaced
    :param Properties: A list of dictionaries, each dictionary has a key and a value
    :param width: The width of the image
    :param height: The height of the page in pixels
    :param TotalPages: Total number of pages in the book
    :return: The text of the template with the values replaced.
    """
    matches = re.finditer(r"{{(\w+)}}", text, re.MULTILINE)
    for matchNum, match in enumerate(matches, start=1):
        for groups in match.groups():
            if groups == "WIDTH":
                value = width

            elif groups == "HEIGHT":
                value = height

            elif groups == "FILE_REL_CSS":
                value = re.sub(r"(.+)Styles", "./Styles",
                               pageCSS.replace("\\", "/"), 0, re.MULTILINE)

            elif groups == "TITLEPAGE_REL_PATH":
                titlepageList = list(
                    filter(lambda d: d['key'] in "TITLEPAGE_NO", Properties))
                titlepageNum = titlepageList[0]["value"] if len(
                    titlepageList) > 0 else ""
                value = f"page_{str(int(titlepageNum) - 1).zfill(3)}.xhtml"

            elif groups == "CHAPTER1_REL_PATH":
                chapter1List = list(
                    filter(lambda d: d['key'] in "CHAPTER1_NO", Properties))
                chapter1Num = chapter1List[0]["value"] if len(
                    chapter1List) > 0 else ""
                value = f"page_{str(int(chapter1Num) - 1).zfill(3)}.xhtml"

            elif groups == "COPYRIGHT_REL_PATH":
                copyrightList = list(
                    filter(lambda d: d['key'] in "COPYRIGHT_NO", Properties))
                copyrightNum = copyrightList[0]["value"] if len(
                    copyrightList) > 0 else ""
                value = f"page_{str(int(copyrightNum) - 1).zfill(3)}.xhtml"

            elif groups == "COVER_REL_PATH":
                value = "cover.xhtml"

            elif groups == "TOTALPAGES":
                value = TotalPages

            elif groups == "RESOLUTION":
                value = str(width) + "x" + str(height)

            elif groups == "IMAGE_URL":
                value = re.sub(r"(.+)Images", "./Images",
                               pageImg.replace("\\", "/"), 0, re.MULTILINE)

            elif groups == "PAGENUM":
                value = int(PageNum) - 1
                if value == 0:
                    value = "cover"
                else:
                    value = str(value).zfill(3)
            elif groups == "BODY_REL_CSS":
                value = "./Styles/body.css"
            else:
                valueList = list(
                    filter(lambda d: d['key'] in groups, Properties))
                value = valueList[-1]["value"] if len(valueList) > 0 else ""
            if value != "":
                text = text.replace("{{" + str(groups) + "}}", str(value))
    return text
def xhtmlAndCssCreation(Properties, Fonts, TotalPages, Pages, fileID)

It takes the data from the database and creates the xhtml and css files

:param Properties: A dictionary of properties that are used to replace values in the XHTML and CSS files :param Fonts: A list of font names used in the document :param TotalPages: Total number of pages in the PDF :param Pages: A list of dictionaries, each dictionary representing a page :param fileID: The ID of the file being processed

Expand source code
def xhtmlAndCssCreation(Properties, Fonts, TotalPages, Pages, fileID):
    """
    It takes the data from the database and creates the xhtml and css files

    :param Properties: A dictionary of properties that are used to replace values in the XHTML and CSS
    files
    :param Fonts: A list of font names used in the document
    :param TotalPages: Total number of pages in the PDF
    :param Pages: A list of dictionaries, each dictionary representing a page
    :param fileID: The ID of the file being processed
    """
    global fileOutputFolder
    global fileRedactedFolder
    global fileOutputImageFolder
    global fileOutputFontFolder
    global fileOutputStylesFolder
    global fileOutputTextFolder
    global SAMPLEXHTML
    global SAMPLECSS
    global fileOutputOPFFile
    global fileOutputTocNcxFile
    global fileOutputTocFile
    global SAMPLEXHTMLTEXT
    global SAMPLECSSTEXT
    global fileOutputBodtFile

    # GENERATING TEXT AND CSS FILES
    with io.open(SAMPLEXHTML, 'r', encoding='utf8') as f:
        SAMPLEXHTMLTEXT = f.read()

    with io.open(SAMPLECSS, 'r', encoding='utf8') as f:
        SAMPLEXCSSTEXT = f.read()
    width = ""
    height = ""
    for page in Pages:
        height = page["Image"]["Height"]
        width = page["Image"]["Width"]
        pageNum = str(page['PageNum'] - 1).zfill(3)
        boxes = list(globals.boxesDB.find(
            {
                "pageId": page["PageID"]
            }
        ).sort([("boxIndex", pymongo.ASCENDING)])
        )
        pageImgTmp = os.path.join(
            fileOutputImageFolder, f"Page{page['PageNum']}.jpeg")
        pageImg = ""
        pageImgNum = ""
        if page["PageNum"] == 1:
            coverImg = pageImgTmp.replace(
                f"Page{page['PageNum']}.jpeg", "cover.jpg")
            pageImgNum = "cover.jpg"
            if not os.path.exists(coverImg):
                os.rename(pageImgTmp, coverImg)
            if os.path.exists(pageImgTmp):
                os.remove(pageImgTmp)
            pageImg = coverImg
            pageXhtml = os.path.join(fileOutputTextFolder, "cover.xhtml")
            pageCSS = os.path.join(fileOutputStylesFolder, "style.css")
            pageXhtmlText = SAMPLEXHTMLTEXT
            pageCSSText = SAMPLEXCSSTEXT
            # coverXhtmlText = coverXhtmlText.replace()
        else:
            pageImg = pageImgTmp.replace(
                f"Page{page['PageNum']}.jpeg", f"page_{pageNum}.jpg")
            if not os.path.exists(pageImg):
                os.rename(pageImgTmp, pageImg)
            if os.path.exists(pageImgTmp):
                os.remove(pageImgTmp)
            pageXhtml = os.path.join(
                fileOutputTextFolder, f"page_{pageNum}.xhtml")
            pageImgNum = f"page_{pageNum}.jpg"
            pageCSS = os.path.join(fileOutputStylesFolder, f"style.css")
            pageXhtmlText = SAMPLEXHTMLTEXT
            pageCSSText = SAMPLEXCSSTEXT

        bodyData = []
        cssData = []
        cssCounter = 0
        lineCssCounter = 0
        bookmarkChapterStart = - 1
        while str(toc[bookmarkChapterStart+1][1]).lower() not in ["contents", "table of content"]:
            bookmarkChapterStart += 1
        if len(Pages) - 2 >= bookmarkChapterStart:
            bookmarkChapterStart += 1
        else:
            bookmarkChapterStart = -1

        bodyData.append(
            f'<p style="background-repeat: no-repeat;"><img src="images/{pageImgNum}" alt=""/></p>')
        for box in boxes:
            pStyle = f'position: absolute;\n' \
                     f'top: {box["coordinates"][1]}px;\n' \
                     f'left: {box["coordinates"][0]}px;\n' \
                     f'width: {width - box["coordinates"][0]}px;\n' \
                     f'height: {box["coordinates"][3]}px;\n'
            lineCssCounter += 1
            lineCssSelector = "line" + str(lineCssCounter)
            cssData.append(f".{lineCssSelector}" + "{\n" + pStyle + "\n}")

            innerHtml = []
            for line in box["linesData"]:
                if "%" not in line["lineHeight"]:
                    line["lineHeight"] += "%"
                innerCssData = f'position: {line["position"]};\n' \
                    f'top: {line["top"]};\n'\
                    f'font-family: sans-serif;\n'\
                    f'left: {line["left"]};\n'\
                    f'font-size: {line["fontSize"]};\n'\
                    f'-ms-transform: rotate({line["textRotate"]}deg);\n'\
                    f'-webkit-transform: rotate({line["textRotate"]}deg);\n'\
                    f'transform: rotate({line["textRotate"]}deg);\n'\
                    f'font-weight: normal;\n'\
                    f'line-height: {line["lineHeight"].replace("normal%","normal")};\n'\
                    f'color: {line["color"]};\n'\
                    f'word-spacing: {line["wordSpacing"]};\n'\
                    f'letter-spacing: {line["letterSpacing"]};\n'\
                    f'font-style: normal;\n'\
                    f'text-decoration: {line["textDecoration"]};\n'\
                    f'white-space: pre;\n'
                cssCounter += 1
                innerCssSelector = "span" + str(cssCounter)
                data = line["text"].replace("\n", "<br>\n")
                line["text"] = re.sub(
                    r"\s{2,}", " ", line["text"], 0, re.MULTILINE)
                if line["text"].startswith(" "):
                    lastIndex = len(innerHtml) - 1
                    print(lastIndex)
                    if len(innerHtml) > 0:
                        lastElement = innerHtml[lastIndex]
                        lastElement = lastElement.replace(
                            "</span>", " </span>")
                        innerHtml[lastIndex] = lastElement
                innerHtml.append(
                    f'<span class="{innerCssSelector}">{data.lstrip()}</span>')
                if line["br"] is True and "<br>" not in data:
                    innerHtml.append("<br>")
                cssData.append(f".{innerCssSelector}" +
                               "{\n" + innerCssData + "\n}")

            bodyData.append(
                f'<{box["tagName"]} class="{lineCssSelector}"><a href="page_{str(toc[bookmarkChapterStart+lineCssCounter][2] - 1).zfill(3)}.xhtml">{"".join(innerHtml)}</a></{box["tagName"]}>')

        pageXhtmlText = pageXhtmlText.replace(
            "<bodyData/>", "\n".join(bodyData)).replace("<br>", "")
        cssDataFinal = "\n".join(cssData)
        # cssDataFinal = re.sub(r"font-family:(.*?);", "font-family:\"\\1\";", cssDataFinal, 0, re.MULTILINE)
        cssDataFinal = cssDataFinal.replace('" sans-serif"', "sans-serif")
        # pageCSSText = pageCSSText.replace("{{BODY_CSS}}", cssDataFinal)

        if len(boxes) == 0:
            pageXhtmlText = pageXhtmlText.replace(
                "<bodyData/>", "\n".join(bodyData)).replace("<br>", "")
            cssDataFinal = cssDataFinal.replace(
                "{{BODY_CSS}}", "").replace("{{FONTS_CSS}}", "")

        # REPLACING PROPERTIES IN CSS AND XHTML FILES
        if page['PageNum'] == 1:
            pageNum = "cover"
        pageXhtmlText = valueReplacer(page['PageNum'], pageCSS, pageImg, pageXhtmlText, Properties, width, height,
                                      TotalPages).\
            replace('<link href="./Styles/body.css" type="text/css" rel="stylesheet" />', "")\
            .replace(f"static/files/{fileID}/output/OEBPS", ".").replace(' class="page"', "")
        cssDataFinal = valueReplacer(page['PageNum'], pageCSS, pageImg, cssDataFinal, Properties, width, height,
                                     TotalPages)

        with io.open(pageXhtml, 'w', encoding='utf8', newline='\n') as f:
            f.write(re.sub(r"^\s+", "", pageXhtmlText, 0, re.MULTILINE))

        with io.open(pageCSS, 'a', encoding='utf8', newline='\n') as f:
            f.write(cssDataFinal)
    finalCss = ""
    fileCss = os.path.join(fileOutputStylesFolder, "style.css")
    with io.open(fileCss, 'r', encoding='utf8', newline='\n') as f:
        finalCss = f.read()

    with io.open(fileCss, 'w', encoding='utf8', newline='\n') as f:
        f.write(finalCss.replace("{{WIDTH}}", str(
            width)).replace("{{HEIGHT}}", str(height)))

    os.remove(SAMPLEXHTML)
    # os.remove(SAMPLECSS)

Classes

class GenerateFile2

Represents an abstract RESTful resource. Concrete resources should extend from this class and expose methods for each supported HTTP method. If a resource is invoked with an unsupported HTTP method, the API will return a response with status 405 Method Not Allowed. Otherwise the appropriate method is called and passed all arguments from the url rule used when adding the resource to an Api instance. See :meth:~flask_restful.Api.add_resource for details.

Expand source code
class GenerateFile2(Resource):

    @use_kwargs(auth_args, location="headers")
    @use_kwargs({"fileID": fields.Str(required=True)}, location="query")
    def post(self, Authorization, fileID):
        """
        It takes a PDF file, converts it to an EPUB file, and returns the path to the EPUB file.

        :param Authorization: The token that is generated when the user logs in
        :param fileID: The ID of the file in the database
        :return: The path to the epub file.
        """
        if auth.verify(str(Authorization).split(" ")[1]):
            templateCopy(fileID)
            result = globals.filesDB.find_one(
                {
                    "_id": ObjectId(fileID)
                }
            )

            TotalPages = result["TotalPages"]
            Pages = result["Pages"]
            Fonts = result["Fonts"]
            Properties = result["Properties"]
            width = result["Pages"][0]["Image"]["Width"]
            height = result["Pages"][0]["Image"]["Height"]
            doc = fitz.open(os.path.join(
                globals.FILES_FOLDER, fileID, f"{fileID}.pdf"))
            global toc
            toc = doc.get_toc()
            suportingFilesCreation(
                Properties, width, height, Fonts, TotalPages)
            xhtmlAndCssCreation(Properties, Fonts, TotalPages, Pages, fileID)
            isbn = list(filter(lambda d: d['key'] in "ISBN", Properties))
            if len(isbn) > 0:
                isbn = isbn[0]["value"]
            else:
                isbn = "undefined"

            finalFile = os.path.join(fileOutputFolder, f'{isbn}.epub')
            if os.path.exists(finalFile):
                os.remove(finalFile)

            zipobj = ZipFile(finalFile, 'w', ZIP_STORED)
            rootlen = len(fileOutputFolder) + 1
            for base, dirs, files in os.walk(fileOutputFolder):
                for file in files:
                    if ".epub" not in file:
                        fn = os.path.join(base, file)
                        zipobj.write(fn, fn[rootlen:])

            return {"msg": finalFile.replace("\\", "/")}, 200
        else:
            return {"msg": "Unauthorized! Access Denied"}, 401

Ancestors

  • flask_restful.Resource
  • flask.views.MethodView
  • flask.views.View

Class variables

var methods : Optional[List[str]]

Methods

def post(self, Authorization, fileID)

It takes a PDF file, converts it to an EPUB file, and returns the path to the EPUB file.

:param Authorization: The token that is generated when the user logs in :param fileID: The ID of the file in the database :return: The path to the epub file.

Expand source code
@use_kwargs(auth_args, location="headers")
@use_kwargs({"fileID": fields.Str(required=True)}, location="query")
def post(self, Authorization, fileID):
    """
    It takes a PDF file, converts it to an EPUB file, and returns the path to the EPUB file.

    :param Authorization: The token that is generated when the user logs in
    :param fileID: The ID of the file in the database
    :return: The path to the epub file.
    """
    if auth.verify(str(Authorization).split(" ")[1]):
        templateCopy(fileID)
        result = globals.filesDB.find_one(
            {
                "_id": ObjectId(fileID)
            }
        )

        TotalPages = result["TotalPages"]
        Pages = result["Pages"]
        Fonts = result["Fonts"]
        Properties = result["Properties"]
        width = result["Pages"][0]["Image"]["Width"]
        height = result["Pages"][0]["Image"]["Height"]
        doc = fitz.open(os.path.join(
            globals.FILES_FOLDER, fileID, f"{fileID}.pdf"))
        global toc
        toc = doc.get_toc()
        suportingFilesCreation(
            Properties, width, height, Fonts, TotalPages)
        xhtmlAndCssCreation(Properties, Fonts, TotalPages, Pages, fileID)
        isbn = list(filter(lambda d: d['key'] in "ISBN", Properties))
        if len(isbn) > 0:
            isbn = isbn[0]["value"]
        else:
            isbn = "undefined"

        finalFile = os.path.join(fileOutputFolder, f'{isbn}.epub')
        if os.path.exists(finalFile):
            os.remove(finalFile)

        zipobj = ZipFile(finalFile, 'w', ZIP_STORED)
        rootlen = len(fileOutputFolder) + 1
        for base, dirs, files in os.walk(fileOutputFolder):
            for file in files:
                if ".epub" not in file:
                    fn = os.path.join(base, file)
                    zipobj.write(fn, fn[rootlen:])

        return {"msg": finalFile.replace("\\", "/")}, 200
    else:
        return {"msg": "Unauthorized! Access Denied"}, 401