"src/vscode:/vscode.git/clone" did not exist on "905dbf4969cc4f6919f5f18b76ec30c87a258390"
utils.py 2.8 KB
Newer Older
Timothy J. Baek's avatar
Timothy J. Baek committed
1
from fastapi import APIRouter, UploadFile, File, Response
Timothy J. Baek's avatar
Timothy J. Baek committed
2
from fastapi import Depends, HTTPException, status
3
from starlette.responses import StreamingResponse, FileResponse
Timothy J. Baek's avatar
Timothy J. Baek committed
4
5
from pydantic import BaseModel

Timothy J. Baek's avatar
Timothy J. Baek committed
6

Timothy J. Baek's avatar
Timothy J. Baek committed
7
from fpdf import FPDF
Timothy J. Baek's avatar
Timothy J. Baek committed
8
import markdown
9

10
11

from utils.utils import get_admin_user
12
from utils.misc import calculate_sha256, get_gravatar_url
13

14
from config import OLLAMA_BASE_URLS, DATA_DIR, UPLOAD_DIR
Timothy J. Baek's avatar
Timothy J. Baek committed
15
from constants import ERROR_MESSAGES
Timothy J. Baek's avatar
Timothy J. Baek committed
16
from typing import List
Timothy J. Baek's avatar
Timothy J. Baek committed
17
18
19
20

router = APIRouter()


21
22
23
24
25
@router.get("/gravatar")
async def get_gravatar(
    email: str,
):
    return get_gravatar_url(email)
26
27


Timothy J. Baek's avatar
Timothy J. Baek committed
28
29
30
31
32
33
34
35
36
37
38
class MarkdownForm(BaseModel):
    md: str


@router.post("/markdown")
async def get_html_from_markdown(
    form_data: MarkdownForm,
):
    return {"html": markdown.markdown(form_data.md)}


Timothy J. Baek's avatar
Timothy J. Baek committed
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
class ChatForm(BaseModel):
    title: str
    messages: List[dict]


@router.post("/pdf")
async def download_chat_as_pdf(
    form_data: ChatForm,
):
    pdf = FPDF()
    pdf.add_page()

    STATIC_DIR = "./static"
    FONTS_DIR = f"{STATIC_DIR}/fonts"

    pdf.add_font("NotoSans", "", f"{FONTS_DIR}/NotoSans-Regular.ttf")
    pdf.add_font("NotoSans", "b", f"{FONTS_DIR}/NotoSans-Bold.ttf")
    pdf.add_font("NotoSans", "i", f"{FONTS_DIR}/NotoSans-Italic.ttf")
    pdf.add_font("NotoSansKR", "", f"{FONTS_DIR}/NotoSansKR-Regular.ttf")
    pdf.add_font("NotoSansJP", "", f"{FONTS_DIR}/NotoSansJP-Regular.ttf")

    pdf.set_font("NotoSans", size=12)
    pdf.set_fallback_fonts(["NotoSansKR", "NotoSansJP"])

    pdf.set_auto_page_break(auto=True, margin=15)

    # Adjust the effective page width for multi_cell
    effective_page_width = (
        pdf.w - 2 * pdf.l_margin - 10
    )  # Subtracted an additional 10 for extra padding

    # Add chat messages
    for message in form_data.messages:
        role = message["role"]
        content = message["content"]
Timothy J. Baek's avatar
Timothy J. Baek committed
74
        pdf.set_font("NotoSans", "B", size=14)  # Bold for the role
Timothy J. Baek's avatar
Timothy J. Baek committed
75
76
77
78
        pdf.multi_cell(effective_page_width, 10, f"{role.upper()}", 0, "L")
        pdf.ln(1)  # Extra space between messages

        pdf.set_font("NotoSans", size=10)  # Regular for content
Timothy J. Baek's avatar
Timothy J. Baek committed
79
80
        pdf.multi_cell(effective_page_width, 6, content, 0, "L")
        pdf.ln(1.5)  # Extra space between messages
Timothy J. Baek's avatar
Timothy J. Baek committed
81
82
83
84
85
86
87
88
89
90
91

    # Save the pdf with name .pdf
    pdf_bytes = pdf.output()

    return Response(
        content=bytes(pdf_bytes),
        media_type="application/pdf",
        headers={"Content-Disposition": f"attachment;filename=chat.pdf"},
    )


92
93
@router.get("/db/download")
async def download_db(user=Depends(get_admin_user)):
94
    if not ENABLE_ADMIN_EXPORT:
95
96
97
98
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
        )
99
100
101
102
103
    return FileResponse(
        f"{DATA_DIR}/webui.db",
        media_type="application/octet-stream",
        filename="webui.db",
    )