- Remove old title-only style. - New layout (centered): - 5 blank lines - Logo from COVER_PAGE_LOGO_URL - 3 blank lines - Title (TRANSCRIPT or SUMMARY) - Date of transcription - Created by + COVER_PAGE_ORGANIZATION - 3 blank lines - Disclaimer - Insert page break after cover page; content starts on page 2.
134 lines
3.9 KiB
Python
134 lines
3.9 KiB
Python
"""
|
|
Cover-page generator for transcript and summary DOCX files.
|
|
|
|
Layout (all centered):
|
|
- 5 blank lines
|
|
- Logo from COVER_PAGE_LOGO_URL (if set)
|
|
- 3 blank lines
|
|
- Title in uppercase: "TRANSCRIPT" or "SUMMARY"
|
|
- Next line: date of transcription (e.g. "June 19, 2026")
|
|
- Next line: "Created by <COVER_PAGE_ORGANIZATION>"
|
|
- 3 blank lines
|
|
- Disclaimer text
|
|
|
|
A page break is inserted after the cover page so the main content starts on page 2.
|
|
|
|
Environment variables:
|
|
- COVER_PAGE_ENABLED: "true"/"false" (default: false)
|
|
- COVER_PAGE_ORGANIZATION: e.g., "A.P.Strom"
|
|
- COVER_PAGE_LOGO_URL: URL of logo image to include on the cover page
|
|
"""
|
|
|
|
import os
|
|
import io
|
|
import requests
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
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 _add_centered_paragraph(doc: Document, text: str = "", font_size: Pt = Pt(12), bold: 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
|
|
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 paragraph."""
|
|
p = doc.add_paragraph()
|
|
pPr = p._p.get_or_add_pPr()
|
|
for child in list(pPr):
|
|
tag = child.tag.split("}")[-1] if "}" in child.tag else child.tag
|
|
if tag in ("tabs", "spacing", "ind"):
|
|
pPr.remove(child)
|
|
page_break = OxmlElement("w:pageBreak")
|
|
page_break.set("{http://schemas.openxmlformats.org/wordprocessingml/2006/main}val", "1")
|
|
pPr.append(page_break)
|
|
|
|
|
|
def _download_image_bytes(url: str) -> Optional[bytes]:
|
|
"""Download image from URL and return bytes, or None on failure."""
|
|
try:
|
|
r = requests.get(url, timeout=10)
|
|
if r.status_code == 200:
|
|
return r.content
|
|
except Exception:
|
|
pass
|
|
return None
|
|
|
|
|
|
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 today's date.
|
|
"""
|
|
|
|
# 5 blank lines
|
|
_add_blank_lines(doc, 5)
|
|
|
|
# Logo (if COVER_PAGE_LOGO_URL is set)
|
|
logo_url = (os.getenv("COVER_PAGE_LOGO_URL") or "").strip()
|
|
if logo_url:
|
|
img_bytes = _download_image_bytes(logo_url)
|
|
if img_bytes:
|
|
p = doc.add_paragraph()
|
|
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
|
try:
|
|
# Add image centered
|
|
p.add_run().add_picture(io.BytesIO(img_bytes), width=None)
|
|
except Exception:
|
|
# Fallback: do nothing if image fails
|
|
pass
|
|
|
|
# 3 blank lines
|
|
_add_blank_lines(doc, 3)
|
|
|
|
# Title in uppercase
|
|
_add_centered_paragraph(doc, text=title.upper().strip(), font_size=Pt(18), bold=True)
|
|
|
|
# Date of transcription
|
|
if not date_str:
|
|
date_str = datetime.utcnow().strftime("%B %d, %Y")
|
|
_add_centered_paragraph(doc, text=date_str, font_size=Pt(14))
|
|
|
|
# Created by + organization
|
|
org = (os.getenv("COVER_PAGE_ORGANIZATION") or "").strip()
|
|
if org:
|
|
_add_centered_paragraph(doc, text=f"Created by {org}", font_size=Pt(12))
|
|
|
|
# 3 blank lines
|
|
_add_blank_lines(doc, 3)
|
|
|
|
# Disclaimer
|
|
disclaimer = (
|
|
"Disclaimer\n"
|
|
"This transcription and any summary derived therefrom may contain errors or inaccuracies."
|
|
)
|
|
_add_centered_paragraph(doc, text=disclaimer, font_size=Pt(10))
|
|
|
|
# Page break after cover page so main content starts on page 2
|
|
_add_page_break(doc)
|