""" Watermark module for Free-tier output files. Strategy: Add a subtle, professional footer/header that: - Clearly marks the file as "Free plan" output - Doesn't destroy the document's usability - Motivates upgrade without frustrating the user DOCX: Footer with light-gray text + link PPTX: Small text box bottom-right on each slide XLSX: Footer text on each sheet """ from pathlib import Path from typing import Optional from docx import Document from docx.oxml import OxmlElement from docx.oxml.ns import qn from docx.enum.text import WD_ALIGN_PARAGRAPH from core.logging import get_logger logger = get_logger(__name__) WATERMARK_TEXT = "Translated with Office Translator — Free Plan" WATERMARK_URL = "wordly.art" WATERMARK_COLOR = "B0B0B0" # Light gray def add_watermark_docx(output_path: Path) -> None: """Add a subtle footer watermark to a DOCX file.""" try: document = Document(str(output_path)) for section in document.sections: # Enable footer footer = section.footer footer.is_linked_to_previous = False if not footer.paragraphs: footer.add_paragraph() para = footer.paragraphs[0] para.alignment = WD_ALIGN_PARAGRAPH.CENTER # Clear existing content for run in para.runs: run.clear() # Add watermark run run = para.add_run(WATERMARK_TEXT) run.font.size = 8 # Pt — small run.font.color.rgb = None # Will set via XML # Set color via XML (more reliable) rPr = run._r.get_or_add_rPr() color_elem = OxmlElement("w:color") color_elem.set(qn("w:val"), WATERMARK_COLOR) rPr.append(color_elem) document.save(str(output_path)) logger.info("watermark_added", file=str(output_path)) except Exception as e: logger.error("watermark_docx_error", error=str(e)) # Don't fail the whole translation if watermark fails def add_watermark_pptx(output_path: Path) -> None: """Add a small watermark text box to each slide.""" try: from pptx import Presentation from pptx.util import Inches, Pt, Emu from pptx.dml.color import RGBColor from pptx.enum.text import PP_ALIGN prs = Presentation(str(output_path)) for slide in prs.slides: # Add text box at bottom-right left = Inches(5.5) top = Inches(7.0) width = Inches(3.5) height = Inches(0.4) txBox = slide.shapes.add_textbox(left, top, width, height) tf = txBox.text_frame tf.word_wrap = True p = tf.paragraphs[0] p.alignment = PP_ALIGN.RIGHT run = p.add_run() run.text = WATERMARK_TEXT run.font.size = Pt(7) run.font.color.rgb = RGBColor(0xB0, 0xB0, 0xB0) prs.save(str(output_path)) logger.info("watermark_added_pptx", file=str(output_path)) except Exception as e: logger.error("watermark_pptx_error", error=str(e)) def add_watermark_xlsx(output_path: Path) -> None: """Add a footer watermark to each sheet.""" try: from openpyxl import load_workbook from openpyxl.worksheet.header_footer import HeaderFooter wb = load_workbook(str(output_path)) for ws in wb.worksheets: if ws.sheet_properties.pageSetUpPr is None: from openpyxl.worksheet.properties import PageSetupProperties ws.sheet_properties.pageSetUpPr = PageSetupProperties() ws.oddFooter.center.text = WATERMARK_TEXT ws.oddFooter.center.font = "Arial,Regular" ws.oddFooter.center.size = 8 wb.save(str(output_path)) wb.close() logger.info("watermark_added_xlsx", file=str(output_path)) except Exception as e: logger.error("watermark_xlsx_error", error=str(e)) def add_watermark_pdf(output_path: Path) -> None: """Add a subtle footer watermark on every page of a PDF using PyMuPDF.""" try: import fitz doc = fitz.open(str(output_path)) for page in doc: rect = page.rect # Position at bottom center text_point = fitz.Point( rect.width / 2 - 100, rect.height - 15 ) page.insert_text( text_point, WATERMARK_TEXT, fontsize=7, color=(0.69, 0.69, 0.69), # #B0B0B0 fontname="helv", ) doc.save(str(output_path), incremental=True, encryption=0) doc.close() logger.info("watermark_added_pdf", file=str(output_path)) except Exception as e: logger.error("watermark_pdf_error", error=str(e)) def add_watermark(output_path: Path, file_extension: str) -> None: """Apply watermark based on file type.""" ext = file_extension.lower() if ext == ".docx": add_watermark_docx(output_path) elif ext == ".pptx": add_watermark_pptx(output_path) elif ext == ".xlsx": add_watermark_xlsx(output_path) elif ext == ".pdf": add_watermark_pdf(output_path) else: logger.info("watermark_skipped", extension=ext)