mirror of
https://github.com/flibusta-apps/fb2converter_server.git
synced 2025-12-06 06:55:36 +01:00
119 lines
2.8 KiB
Python
119 lines
2.8 KiB
Python
import asyncio
|
|
import os
|
|
import os.path
|
|
import shutil
|
|
import time
|
|
from typing import AsyncIterator
|
|
import uuid
|
|
|
|
from fastapi import FastAPI, APIRouter, File, UploadFile, Form, HTTPException, status
|
|
from fastapi.responses import StreamingResponse
|
|
|
|
import aiofiles
|
|
import aiofiles.os
|
|
import aiofiles.ospath
|
|
from fastapi_utils.tasks import repeat_every
|
|
import sentry_sdk
|
|
|
|
from config import env_config
|
|
|
|
|
|
sentry_sdk.init(
|
|
env_config.SENTRY_DSN,
|
|
)
|
|
|
|
|
|
router = APIRouter(tags=["converter"])
|
|
|
|
|
|
@router.post("/")
|
|
async def convert(
|
|
file: UploadFile = File({}),
|
|
format: str = Form({}),
|
|
):
|
|
format_lower = format.lower()
|
|
if format_lower not in ["epub", "mobi"]:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST, detail="Wrong format!"
|
|
)
|
|
|
|
temp_uuid = uuid.uuid1()
|
|
|
|
temp_filename = str(temp_uuid) + ".fb2"
|
|
converted_temp_filename = str(temp_uuid) + "." + format_lower
|
|
|
|
try:
|
|
async with aiofiles.open(temp_filename, "wb") as f:
|
|
while content := await file.read(1024):
|
|
if isinstance(content, str):
|
|
content = content.encode()
|
|
|
|
await f.write(content)
|
|
|
|
proc = await asyncio.create_subprocess_exec(
|
|
"./bin/fb2c",
|
|
"convert",
|
|
"--to",
|
|
format,
|
|
temp_filename,
|
|
stdout=asyncio.subprocess.PIPE,
|
|
stderr=asyncio.subprocess.PIPE,
|
|
)
|
|
|
|
_, stderr = await proc.communicate()
|
|
finally:
|
|
await aiofiles.os.remove(temp_filename)
|
|
|
|
if proc.returncode != 0 or len(stderr) != 0:
|
|
try:
|
|
await aiofiles.os.remove(converted_temp_filename)
|
|
except FileNotFoundError:
|
|
pass
|
|
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST, detail="Can't convert!"
|
|
)
|
|
|
|
async def result_iterator() -> AsyncIterator[bytes]:
|
|
try:
|
|
async with aiofiles.open(converted_temp_filename, "rb") as f:
|
|
while data := await f.read(2048):
|
|
yield data
|
|
finally:
|
|
await aiofiles.os.remove(converted_temp_filename)
|
|
|
|
return StreamingResponse(result_iterator())
|
|
|
|
|
|
@router.get("/healthcheck")
|
|
async def healthcheck():
|
|
return "Ok!"
|
|
|
|
|
|
app = FastAPI()
|
|
|
|
app.include_router(router)
|
|
|
|
|
|
@app.on_event("startup")
|
|
@repeat_every(seconds=60, raise_exceptions=True)
|
|
def remove_temp_files():
|
|
current_time = time.time()
|
|
|
|
try:
|
|
os.remove("./conversion.log")
|
|
except IOError:
|
|
pass
|
|
|
|
for f in os.listdir("/tmp/"):
|
|
target_path = f"/tmp/{f}"
|
|
|
|
is_file = os.path.isfile(target_path)
|
|
|
|
creation_time = os.path.getctime(target_path)
|
|
if (current_time - creation_time) // 3600 >= 3:
|
|
if is_file:
|
|
os.remove(target_path)
|
|
else:
|
|
shutil.rmtree(target_path)
|