118 lines
3.8 KiB
Python
118 lines
3.8 KiB
Python
"""
|
|
Cover-page generator for transcript and summary DOCX files.
|
|
|
|
Layout (all centered):
|
|
- 1 blank line
|
|
- Title in uppercase: "TRANSCRIPT" or "SUMMARY"
|
|
- Next line: "Transcript created on: [date]"
|
|
- Next line: "Transcribed by <COVER_PAGE_ORGANIZATION>"
|
|
- 2 blank lines
|
|
- Disclaimer (underlined)
|
|
- Disclaimer body
|
|
- Page break (ensures content starts on page 2)
|
|
|
|
Environment variables:
|
|
- COVER_PAGE_ENABLED: "true"/"false" (default: false)
|
|
- COVER_PAGE_ORGANIZATION: e.g., "A.P.Strom"
|
|
- SERVER_TIMEZONE: Timezone for document dates (e.g., "America/Toronto"). Defaults to "UTC".
|
|
"""
|
|
|
|
import os
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
|
from docx import Document
|
|
from docx.shared import Pt
|
|
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
|
from docx.oxml import OxmlElement
|
|
from docx.oxml.ns import qn
|
|
|
|
|
|
def _get_server_timezone():
|
|
tz_name = (os.getenv("SERVER_TIMEZONE") or "UTC").strip()
|
|
try:
|
|
return ZoneInfo(tz_name)
|
|
except (ZoneInfoNotFoundError, KeyError, ValueError):
|
|
return ZoneInfo("UTC")
|
|
|
|
|
|
def _add_centered_paragraph(doc: Document, text: str = "", font_size: Pt = Pt(12), bold: bool = False, underline: bool = False):
|
|
"""Add a centered paragraph with given text and style."""
|
|
p = doc.add_paragraph()
|
|
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
|
if text:
|
|
run = p.add_run(text)
|
|
run.font.name = "Courier"
|
|
run.font.size = font_size
|
|
run.bold = bold
|
|
run.underline = underline
|
|
return p
|
|
|
|
|
|
def _add_blank_lines(doc: Document, count: int):
|
|
"""Add specified number of blank lines (empty centered paragraphs)."""
|
|
for _ in range(count):
|
|
_add_centered_paragraph(doc)
|
|
|
|
|
|
def _add_page_break(doc: Document):
|
|
"""Insert a page break after the last paragraph (no extra blank line)."""
|
|
from docx.enum.text import WD_BREAK
|
|
last_p = doc.paragraphs[-1]
|
|
run = last_p.add_run()
|
|
run.add_break(WD_BREAK.PAGE)
|
|
|
|
|
|
def add_cover_page(
|
|
doc: Document,
|
|
title: str,
|
|
date_str: Optional[str] = None,
|
|
):
|
|
"""
|
|
Insert a cover page at the current cursor position.
|
|
|
|
- title: e.g., "TRANSCRIPT" or "SUMMARY"
|
|
- date_str: optional date string (e.g., "June 19, 2026");
|
|
if not provided, uses current server time in SERVER_TIMEZONE.
|
|
"""
|
|
|
|
# 1 blank line (removed two from top)
|
|
_add_blank_lines(doc, 1)
|
|
|
|
# Title in uppercase
|
|
_add_centered_paragraph(doc, text=title.upper().strip(), font_size=Pt(18), bold=True)
|
|
|
|
# Date of transcription (use provided or current server time)
|
|
if not date_str:
|
|
tz = _get_server_timezone()
|
|
now = datetime.now(tz)
|
|
date_str = now.strftime("%B %d, %Y")
|
|
_add_centered_paragraph(doc, text=f"Transcript created on: {date_str}", font_size=Pt(14))
|
|
|
|
# Transcribed by + organization
|
|
org = (os.getenv("COVER_PAGE_ORGANIZATION") or "").strip()
|
|
if org:
|
|
_add_centered_paragraph(doc, text=f"Transcribed by {org}", font_size=Pt(12))
|
|
|
|
# 2 blank lines
|
|
_add_blank_lines(doc, 2)
|
|
|
|
# Disclaimer: only the word "Disclaimer" is underlined
|
|
disclaimer_title = "Disclaimer"
|
|
disclaimer_body = (
|
|
"This transcription and any summary derived therefrom are created entirely by large language models. "
|
|
"Large language models are imperfect and may create errors or inaccuracies. "
|
|
"The following transcription and summary (if applicable) are designed to assist users. "
|
|
"They are not a conclusive record or summary of what transpired in an audio recording. "
|
|
"Use at your own risk."
|
|
)
|
|
|
|
# Underlined "Disclaimer" line
|
|
_add_centered_paragraph(doc, text=disclaimer_title, font_size=Pt(10), underline=True)
|
|
|
|
# Body text (not underlined)
|
|
_add_centered_paragraph(doc, text=disclaimer_body, font_size=Pt(10), underline=False)
|
|
|
|
# Page break after cover page so main content starts on page 2
|
|
_add_page_break(doc)
|