Last active
October 26, 2023 08:06
-
-
Save Epicpkmn11/df4623f79c0d4aefb6b0b2506d71f614 to your computer and use it in GitHub Desktop.
concom.py - Creates a vCard from a CSV
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# SPDX-License-Identifier: CC0-1.0 | |
# SPDX-FileContributer: Pk11, 2023 | |
# Source: https://gist.github.com/Epicpkmn11/df4623f79c0d4aefb6b0b2506d71f614 | |
from argparse import ArgumentParser, FileType | |
from datetime import datetime | |
import csv | |
import re | |
class vcard: | |
first_name = "" | |
last_name = "" | |
address = None | |
email = None | |
cell_phone = None | |
home_phone = None | |
discord = None | |
role = None | |
note = None | |
def set_name(self, first, last): | |
self.first_name = first | |
self.last_name = last | |
def set_email(self, email): | |
if email: | |
self.email = email | |
def set_address(self, address): | |
# Parse address in format: | |
# [STREET], [CITY] [STATE (2 letter)] [ZIP(+4)] | |
addresses = re.findall(r"(.*) *, +(.*?),? +([A-Z]{2}) +(\d{5}(?:-\d{4})?)", address) | |
if len(addresses): | |
addr = addresses[0] | |
self.address = f";;{addr[0]};{addr[1]};{addr[2]};{addr[3]};United States" | |
def set_phone(self, phone): | |
# Parse phone number in format: | |
# XXX-XXX-XXXX (type) | |
# If type left out, assume cell | |
phones = re.findall(r"(\d{3}-\d{3}-\d{4})(?: \((\w+)\))?", phone) | |
for phone in phones: | |
if phone[1] == "home": | |
self.home_phone = phone[0] | |
else: | |
self.cell_phone = phone[0] | |
def set_discord(self, discord): | |
# This column is set up as a yes/no with the | |
# username sometimes in parenthesis. | |
# Discord usernames are no more than 32 chars long | |
# and either a-z 0-9 . and _ or anything followed by #XXXX. | |
usernames = re.findall(r"Yes \(([a-z0-9._]{1,32}|.{1,32}#\d{4})\)", discord) | |
if len(usernames): | |
self.discord = usernames[0].replace("#", "%23") | |
def set_role(self, role): | |
if role: | |
self.role = role | |
def set_notes(self, notes): | |
# Remove any empty string notes, join together with double newlines, | |
# then escape all newlines | |
self.note = "\n\n".join([note for note in notes if note]).replace("\n", "\\n") | |
def to_string(self): | |
out = [ | |
"BEGIN:VCARD", | |
"VERSION:2.1", | |
"ORG:MNStF;Concom", | |
"REV:" + datetime.utcnow().strftime("%Y%m%dT%H%M%SZ"), | |
f"N:{self.last_name};{self.first_name};;;", | |
"FN:" + f"{self.first_name} {self.last_name}".strip() | |
] | |
if self.address: | |
out.append("ADR;HOME:" + self.address) | |
if self.email: | |
out.append("EMAIL:" + self.email) | |
if self.cell_phone: | |
out.append("TEL;CELL:" + self.cell_phone) | |
if self.home_phone: | |
out.append("TEL;HOME:" + self.home_phone) | |
if self.discord: | |
out.append("IMPP:discord:" + self.discord) | |
if self.role: | |
out.append("ROLE:" + self.role) | |
if self.note: | |
out.append("NOTE:" + self.note) | |
out.append("END:VCARD") | |
return "\n".join(out) | |
def main(): | |
parser = ArgumentParser(description="Creates a vCard from a CSV") | |
parser.add_argument("input", metavar="input.csv", type=FileType("r"), help="CSV file") | |
parser.add_argument("output", metavar="output.vcf", type=str, help="vCard file") | |
args = parser.parse_args() | |
people = [] | |
reader = csv.DictReader(args.input, delimiter=",", quotechar="\"") | |
for row in reader: | |
person = vcard() | |
person.set_name(row["First name"], row["Last name"]) | |
person.set_email(row["E-mail"]) | |
person.set_address(row["Postal"]) | |
person.set_phone(row["Phone"]) | |
person.set_discord(row["Discord?"]) | |
person.set_role(row["Role(s)"]) | |
person.set_notes([row["Phone comments"], row["Additional"]]) | |
people.append(person) | |
with open(args.output, "w") as outfile: | |
outfile.write("\n\n".join([person.to_string() for person in people])) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment