# Copyright Sage Vaillancourt 2021 import os import subprocess from dataclasses import dataclass from flask import send_from_directory, Response proj_dir = os.getcwd() output_dir = proj_dir + '/outputs/' base_tex_text = open(proj_dir + '/letter_templates/base.tex', 'r').read() @dataclass class CLData: # Metadata: selectedLetter: int # Form Data: username: str company: str jobAndPronoun: str skillTypes: str mySkills: str body: str closingText: str def get_pairs(self) -> list[(str, str)]: return [ ('username', self.username), ('company', self.company), ('jobAndPronoun', self.jobAndPronoun), ('skillTypes', self.skillTypes), ('mySkills', self.mySkills), ('closingText', self.closingText), ('body', self.body), ] def generate_pdf(self) -> Response: """ :return: Response with the pdf attached as a download when successful :raise ValueError: e.args[0] is a list of error strings, if generation fails """ import threading unique_id = get_unique() unique_file = output_dir + unique_id + '.tex' f = open(unique_file, 'w') for pair in self.get_pairs(): f.write('\\def \\' + pair[0] + '{' + pair[1] + '}\n') f.write(base_tex_text) f.close() com = f'pdflatex -halt-on-error -jobname=outputs/{unique_id} {unique_file}' result = subprocess.run( ['bash', '-c', com], stdout=subprocess.PIPE, text=True ) build_text = f'[{get_datetime()}] Building for {unique_id} ' if result.returncode != 0: print(build_text + '[FAIL]') # Collect output but delete boilerplate text errors = list(map(str.strip, result.stdout.split('\n'))) del errors[:13] del errors[-2:] raise ValueError(errors) print(build_text + '[SUCCESS]') result = subprocess.run( [ 'gs', '-sDEVICE=pdfwrite', '-dCompatibilityLevel=1.5', '-dNOPAUSE', '-dQUIET', '-dBATCH', '-dPrinted=false', '-sOutputFile=outputs/' + unique_id + '.compressed.pdf', 'outputs/' + unique_id + '.pdf' ], stdout=subprocess.PIPE, text=True ) threading.Timer(60 * 5, cleanup, [output_dir + unique_id]).start() extension = 'compressed.pdf' if result.returncode == 0 else 'pdf' output_file = f'{unique_id}.{extension}' return send_from_directory( output_dir, output_file, download_name=self.username.replace(' ', '') + '_CoverLetter.pdf', as_attachment=True ) def cleanup(unique) -> None: subprocess.run(['bash', '-c', 'rm ' + unique + '.*']) def get_unique() -> str: import uuid unique = str(uuid.uuid1().hex) return unique def get_datetime() -> str: from datetime import datetime now = datetime.now() return now.strftime('%Y-%m-%d %H:%M:%S')