diff --git a/bin/fix-submits b/bin/fix-submits new file mode 100755 index 0000000000000000000000000000000000000000..eb4476f3ae9056f9a3417b26dd099ba203c7f633 --- /dev/null +++ b/bin/fix-submits @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 + +import argparse +import datetime +import os +from sqlalchemy.orm import joinedload +import subprocess +import tempfile + +import mo.db as db +import mo.submit +import mo.util + +parser = argparse.ArgumentParser(description='Pokusí se opravit rozbitá PDF') +parser.add_argument(dest='id', type=int, nargs='?', help='ID papíru k opravení') +args = parser.parse_args() + +mo.util.init_standalone() +sess = db.get_session() + + +def fix_paper(id: int): + paper = (sess.query(db.Paper) + .options(joinedload(db.Paper.for_user_obj)) + .get(id)) + assert paper is not None + print(f"=== Paper #{id} ({paper.file_name})") + + sol = (sess.query(db.Solution) + .filter_by(task_id=paper.for_task, user_id=paper.for_user) + .one()) + if paper.paper_id not in [sol.final_submit, sol.final_feedback]: + print('--> not final\n') + sess.rollback() + return + + tmp_file = tempfile.NamedTemporaryFile(dir=mo.util.data_dir('tmp'), prefix='fix-') + + res = subprocess.run(['qpdf', os.path.join(mo.util.data_dir('submits'), paper.file_name), tmp_file.name]) + if res.returncode in [0, 3]: + sub = mo.submit.Submitter() + new_paper = db.Paper(task=paper.task, + for_user_obj=paper.for_user_obj, + type=paper.type, + uploaded_by_obj=paper.uploaded_by_obj, + uploaded_at=paper.uploaded_at + datetime.timedelta(seconds=1), + note='Automatická konverze rozbitého PDF') + sub.submit_paper(new_paper, tmp_file.name) + assert not new_paper.broken + + sess.add(new_paper) + if new_paper.type == db.PaperType.solution: + sol.final_submit_obj = new_paper + elif new_paper.type == db.PaperType.feedback: + sol.final_feedback_obj = new_paper + else: + assert False + + print('--> OK') + sess.commit() + else: + print(f'--> ERROR: qpdf failed with exit code {res.returncode}') + sess.rollback() + + print("") + + +if args.id is not None: + fix_paper(args.id) +else: + papers = sess.query(db.Paper).filter_by(broken=True).all() + sess.rollback() + for p in papers: + fix_paper(p.paper_id)