utils.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. from fastapi import APIRouter, UploadFile, File, Response
  2. from fastapi import Depends, HTTPException, status
  3. from peewee import SqliteDatabase
  4. from starlette.responses import StreamingResponse, FileResponse
  5. from pydantic import BaseModel
  6. from fpdf import FPDF
  7. import markdown
  8. from apps.web.internal.db import DB
  9. from utils.utils import get_admin_user
  10. from utils.misc import calculate_sha256, get_gravatar_url
  11. from config import OLLAMA_BASE_URLS, DATA_DIR, UPLOAD_DIR, ENABLE_ADMIN_EXPORT
  12. from constants import ERROR_MESSAGES
  13. from typing import List
  14. router = APIRouter()
  15. @router.get("/gravatar")
  16. async def get_gravatar(
  17. email: str,
  18. ):
  19. return get_gravatar_url(email)
  20. class MarkdownForm(BaseModel):
  21. md: str
  22. @router.post("/markdown")
  23. async def get_html_from_markdown(
  24. form_data: MarkdownForm,
  25. ):
  26. return {"html": markdown.markdown(form_data.md)}
  27. class ChatForm(BaseModel):
  28. title: str
  29. messages: List[dict]
  30. @router.post("/pdf")
  31. async def download_chat_as_pdf(
  32. form_data: ChatForm,
  33. ):
  34. pdf = FPDF()
  35. pdf.add_page()
  36. STATIC_DIR = "./static"
  37. FONTS_DIR = f"{STATIC_DIR}/fonts"
  38. pdf.add_font("NotoSans", "", f"{FONTS_DIR}/NotoSans-Regular.ttf")
  39. pdf.add_font("NotoSans", "b", f"{FONTS_DIR}/NotoSans-Bold.ttf")
  40. pdf.add_font("NotoSans", "i", f"{FONTS_DIR}/NotoSans-Italic.ttf")
  41. pdf.add_font("NotoSansKR", "", f"{FONTS_DIR}/NotoSansKR-Regular.ttf")
  42. pdf.add_font("NotoSansJP", "", f"{FONTS_DIR}/NotoSansJP-Regular.ttf")
  43. pdf.set_font("NotoSans", size=12)
  44. pdf.set_fallback_fonts(["NotoSansKR", "NotoSansJP"])
  45. pdf.set_auto_page_break(auto=True, margin=15)
  46. # Adjust the effective page width for multi_cell
  47. effective_page_width = (
  48. pdf.w - 2 * pdf.l_margin - 10
  49. ) # Subtracted an additional 10 for extra padding
  50. # Add chat messages
  51. for message in form_data.messages:
  52. role = message["role"]
  53. content = message["content"]
  54. pdf.set_font("NotoSans", "B", size=14) # Bold for the role
  55. pdf.multi_cell(effective_page_width, 10, f"{role.upper()}", 0, "L")
  56. pdf.ln(1) # Extra space between messages
  57. pdf.set_font("NotoSans", size=10) # Regular for content
  58. pdf.multi_cell(effective_page_width, 6, content, 0, "L")
  59. pdf.ln(1.5) # Extra space between messages
  60. # Save the pdf with name .pdf
  61. pdf_bytes = pdf.output()
  62. return Response(
  63. content=bytes(pdf_bytes),
  64. media_type="application/pdf",
  65. headers={"Content-Disposition": f"attachment;filename=chat.pdf"},
  66. )
  67. @router.get("/db/download")
  68. async def download_db(user=Depends(get_admin_user)):
  69. if not ENABLE_ADMIN_EXPORT:
  70. raise HTTPException(
  71. status_code=status.HTTP_401_UNAUTHORIZED,
  72. detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
  73. )
  74. if not isinstance(DB, SqliteDatabase):
  75. raise HTTPException(
  76. status_code=status.HTTP_400_BAD_REQUEST,
  77. detail=ERROR_MESSAGES.DB_NOT_SQLITE,
  78. )
  79. return FileResponse(
  80. DB.database,
  81. media_type="application/octet-stream",
  82. filename="webui.db",
  83. )