#!/usr/bin/python3 import mailbox import jinja2 import email.header import email.utils import yaml import datetime import sys, os import pypandoc import argparse import quopri from pprint import pprint CONFIG_FILE = "generator.conf" WEEKDAYS = { 0: "Montag", 1: "Dienstag", 2: "Mittwoch", 3: "Donnerstag", 4: "Freitag", 5: "Samstag", 6: "Sonntag" } def decode_header(header): return "".join([ x[0].decode(x[1] or "ascii") if isinstance(x[0], bytes) else x[0] for x in email.header.decode_header(header) ]) class Top: def __init__(self, title=None, sender=None, body=None, protostub=None, message=None): if message: self.title = decode_header(message["Subject"])[6:] real_name, address = email.utils.parseaddr(message["From"]) self.sender = real_name or address payload = message.get_payload() if message["Content-Transfer-Encoding"] == "quoted-printable": payload = quopri.decodestring(payload.encode("ascii")).decode("utf8") self.body = payload.rpartition("\n--")[0] if "\n--" in payload else payload elif title: self.title = title self.sender = sender self.body = body self.protostub = protostub else: raise ValueError("One of title or message is needed") def __repr__(self): return "" # from https://stackoverflow.com/questions/6558535/find-the-date-for-the-first-monday-after-a-given-a-date def next_weekday(d, weekday): days_ahead = weekday - d.weekday() if days_ahead < 0: # Target day already happened this week days_ahead += 7 return d + datetime.timedelta(days_ahead) def last_weekday(d, weekday): days_ahead = weekday - d.weekday() if days_ahead >= 0: # Target day already happened this week days_ahead -= 7 return d + datetime.timedelta(days_ahead) def wiki2latex(intext): intext = intext.replace(":\n", ":\n\n") return pypandoc.convert_text(intext, 'latex', format='md') def j2replace(intext): return j2env.from_string(intext).render(context) def date(indate): return indate.strftime("%d.%m.%Y") def time(intime): return intime.strftime("%H:%M") def weekday(indate): return WEEKDAYS[indate.weekday()] def conf2top(top): sender = None body = None protostub = None try: sender = top["sender"] except KeyError: pass try: body = top["body"] except KeyError: pass try: protostub = top["protostub"] except KeyError: pass if "file" in top: try: body = open(top["file"]).read() except OSError as e: print("Warning: Error opening", top["file"], file=sys.stderr) return Top(top["title"], sender, body, protostub) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--config", default=CONFIG_FILE) mode = parser.add_mutually_exclusive_group(required=True) mode.add_argument("--invite", action="store_true") mode.add_argument("--presentation", action="store_true") mode.add_argument("--protocol", action="store_true") parser.add_argument("--debug", action="store_true", help=argparse.SUPPRESS) parser.add_argument("--write-mbox", action="store_true") args = parser.parse_args() config = yaml.full_load(open(args.config)) if args.invite: template_file = config["invite_template_file"] elif args.presentation: template_file = config["presentation_template_file"] elif args.protocol: template_file = config["protocol_template_file"] else: raise Exception("Should never happen") j2env = jinja2.Environment() j2env.filters["wiki2latex"] = wiki2latex j2env.filters["j2replace"] = j2replace j2env.filters["date"] = date j2env.filters["time"] = time j2env.filters["weekday"] = weekday template = j2env.from_string(open(template_file).read()) mbox = mailbox.mbox(config["top_mbox_file"]) current_date = next_weekday(datetime.date.today(), config["default_weekday"]) next_date = current_date + datetime.timedelta(days=7) last_date = last_weekday(current_date, config["default_weekday"]) time = datetime.time.fromisoformat(config["default_time"]) pre_tops = [] post_tops = [] for top in config["pre_tops"]: pre_tops.append(conf2top(top)) for top in config["post_tops"]: post_tops.append(conf2top(top)) email_tops = [] for message in mbox: if args.debug: print(message.get_payload()) top = Top(message=message) email_tops.append(top) to = pre_tops + email_tops + post_tops context = {"to": to, "redeleitung": config["redeleitung"], "protokoll": config["protokoll"], "date": current_date, "time": time, "place": config["place"], "next_date": next_date, "last_date": last_date, "meeting_link": config["meeting_link"], "email_tops": email_tops, "WEEKDAYS": WEEKDAYS} if args.debug: for top in to: pprint(top.__dict__) pprint(context) elif args.write_mbox: msg = email.message.EmailMessage() msg.set_content(template.render(context)) msg["Subject"] = j2env.from_string(config["invite_subject"]).render(context) msg["From"] = email.utils.formataddr((config["redeleitung"]["name"], config["redeleitung"]["email"])) msg["To"] = config["invite_mail"] mbox = mailbox.mbox(config["mbox_out"]) mbox.add(msg) mbox.close() print(mbox) else: print(template.render(context))