import argparse from collections.abc import Mapping from dataclasses import dataclass from pyexcel_odsr import get_data COLUMN_HEADER = { "firstname": "Vorname", "lastname": "Nachname", "email": "Email", "status": "Status", } @dataclass class Person: firstname: str lastname: str email: str status: str row_number: int member_of: list[str] @dataclass class Mailinglist: name: str members: list[Person] extra_recipients: list[str] def pretty_print(self, include_names: bool = False): print(f"{self.name}allmende-gufi.de:\n") for member in sorted(self.members, key=lambda x: x.email): printout = member.email.strip() if include_names: printout = f"{printout:<30} ({member.firstname} {member.lastname})" print(printout) for extra_recipient in self.extra_recipients: print(extra_recipient) def read_member_file(data: list[list]) -> list[Person]: """ Reads the memeber ODS file and returns a List of all the people in the project. """ header_row = data["Tabelle1"][0] result = [] for index, row in enumerate(data["Tabelle1"][2:], start=1): if len(row) == 0: continue person = Person( firstname=row[header_row.index(COLUMN_HEADER["firstname"])], lastname=row[header_row.index(COLUMN_HEADER["lastname"])], email=row[header_row.index(COLUMN_HEADER["email"])], status=row[header_row.index(COLUMN_HEADER["status"])], row_number=index, member_of=[], ) for h_index, header in enumerate(header_row): if header.endswith("@") and len(row) > h_index and row[h_index] == "x": person.member_of.append(header) if person.status != "Ehemalig": result.append(person) return result def compute_mailing_lists(people: list[Person]) -> list[Mailinglist]: """ Takes the list of people in the projects and returns a list of all Mailinglists. """ result: dict[str, Mailinglist] = {} for person in people: for l in person.member_of: if l not in result: result[l] = Mailinglist(name=l, members=[], extra_recipients=[]) result[l].members.append(person) return list(sorted(result.values(), key=lambda x: x.name)) def create_wiki_article( mailing_lists: list[Mailinglist], omit: list[str] = ["alle@", "mitglieder@"] ) -> str: """ Creates a DokuWiki article source listing the mailing lists in a table with their address and first names of the persons on it. """ wiki = "===== Mailing Lists =====\n\n" wiki += "^ Mail-Adresse ^ Mitglieder*innen ^\n" for ml in sorted(mailing_lists, key=lambda x: x.name): if ml.name in omit: continue address = ml.name + "allmende-gufi.de" first_names = ", ".join( [p.firstname for p in sorted(ml.members, key=lambda x: x.firstname)] ) wiki += f"| {address} | {first_names} |\n" return wiki if __name__ == "__main__": parser = argparse.ArgumentParser( prog="Mail list manager", description="Generate Allmende mailing lists from an .ods file", ) parser.add_argument( "input_file", type=str, help="Path to the .ods file containing the member data. It's usually located at 05_Organisation/allmende_menschen.ods", ) parser.add_argument( "--names", action="store_true", help="If given, peoples full names will be included in the printout", ) parser.add_argument( "--wiki", action="store_true", help="Output as DokuWiki article instead of pretty print", ) args = parser.parse_args() data = get_data(args.input_file) header_row = data["Tabelle1"][0] extra_recipients_row = data["Tabelle1"][1] people = read_member_file(data) mailing_lists = compute_mailing_lists(people) # add extra recipients to mailing_lists for l in mailing_lists: index = header_row.index(l.name) if len(extra_recipients_row) > index: extra_recipients = extra_recipients_row[header_row.index(l.name)] l.extra_recipients = extra_recipients.split(",") if args.wiki: print(create_wiki_article(mailing_lists)) else: for l in mailing_lists: l.pretty_print(include_names=args.names) print("\n=======\n")