#!/usr/bin/python3 import mailbox import email.header import email.utils import yaml import datetime import sys, os import argparse import quopri import json import subprocess import re from pprint import pprint from pathlib import Path import requests import pypandoc import jinja2 import util class Top: def __init__(self, title=None, sender=None, body=None, protostub=None, message=None): if message: subject = message["Subject"] needs_stripping = subject[:6] == "[top] " self.title = util.deEmojify(util.decode_header(subject[6:] if needs_stripping else subject)) real_name, address = email.utils.parseaddr(message["From"]) real_name = util.decode_header(real_name) self.sender = real_name or address payload = get_body_text(message) self.body = str(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") if self.body is None: self.body = "" def __repr__(self): return "" 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 util.WEEKDAYS[indate.weekday()] def prototop(top): result = "" if "protostub" in dir(top) and top.protostub: result = j2env.from_string(top.protostub).render(context, top=top) elif top.body: result = j2env.from_string(top.body).render(context) for search,replace in config["protoreplace"].items(): result = result.replace(search, replace) return result 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) if "command" in top: try: body = subprocess.run(top["command"], shell=True, text=True, capture_output=True, check=True).stdout except subprocess.CalledProcessError as e: print(f"Warning: Command for '{top['title']}' returned non-zero exit code, output not used") if "proto_command" in top: try: protostub = subprocess.run(top["proto_command"], shell=True, text=True, capture_output=True, check=True).stdout except subprocess.CalledProcessError as e: print(f"Warning: Protocommand for '{top['title']}' returned non-zero exit code, output not used") return Top(top["title"], sender, body, protostub) def main(rawargs=None): parser = argparse.ArgumentParser() parser.add_argument("--config", "-c", default=util.CONFIG_FILE) mode = parser.add_mutually_exclusive_group(required=True) mode.add_argument("--invite", action="store_true") mode.add_argument("--mm-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("--print-config", action="store_true", help=argparse.SUPPRESS) parser.add_argument("--write-mbox", action="store_true") parser.add_argument("--send-mm", action="store_true") parser.add_argument("--send-mail", action="store_true") parser.add_argument("--save", action="store_true") parser.add_argument("--time") parser.add_argument("--date") args = parser.parse_args(rawargs) config = util.get_config(util.get_normalized_config_path(args.config)) if args.print_config: pprint(config) sys.exit(0) if args.invite: template_file = config["invite_template_file"] elif args.presentation: template_file = config["presentation_template_file"] elif args.mm_invite: template_file = config["mminvite_template_file"] elif args.protocol: template_file = config["protocol_template_file"] else: raise Exception("Should never happen") global j2env j2env = jinja2.Environment() j2env.filters["wiki2latex"] = wiki2latex j2env.filters["j2replace"] = j2replace j2env.filters["date"] = date j2env.filters["time"] = time j2env.filters["weekday"] = weekday j2env.filters["prototop"] = prototop template = j2env.from_string(open(template_file).read()) mbox = mailbox.mbox(config["top_mbox_file"]) current_date = util.next_weekday(datetime.date.today(), config["default_weekday"]) if args.date: current_date = datetime.date.fromisoformat(args.date) #next_date = current_date + datetime.timedelta(days=7) next_date = util.next_weekday(current_date, config["default_weekday"]) last_date = util.last_weekday(current_date, config["default_weekday"]) actual_time = datetime.time.fromisoformat(args.time or 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 global context context = {"to": to, "redeleitung": config["redeleitung"], "protokoll": config["protokoll"], "date": current_date, "time": actual_time, "place": config["place"], "next_date": next_date, "last_date": last_date, "meeting_link": config["meeting_link"], "email_tops": email_tops, "WEEKDAYS": util.WEEKDAYS} if args.debug: for top in to: pprint(top.__dict__) pprint(context) elif args.save: if args.invite: filename = Path(config["invite_save_path"]) / Path("invite_"+datetime.date.today().isoformat()+".txt") elif args.presentation: filename = Path(config["presentation_save_path"]) / Path("presentation_"+datetime.date.today().isoformat()+".tex") elif args.protocol: filename = Path(config["protocol_save_path"]) / Path(datetime.date.today().isoformat()) else: raise Exception("Should never happen") with open(filename, "w") as file: file.write(template.render(context)) elif args.send_mail: 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"] subprocess.run([*config["sendmail"], config["invite_mail"]], input=str(msg), text=True, check=True) 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) elif args.send_mm: headers = {'Content-Type': 'application/json',} values = json.dumps({ "text": template.render(context), "username": "test"}) response = requests.post(config["mm_url"], headers=headers, data=values) else: print(template.render(context)) if __name__ == "__main__": main()