UnderCover/app/pdf_builder.py

120 lines
3.1 KiB
Python

# 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')