Files
monorepo/band/band_contacts_to_google_contacts.py
T

126 lines
5.2 KiB
Python

import csv
import argparse
import datetime
import re
def get_category(instrument):
"""Categorize the instrument into Woodwinds, Brass, Percussion, or Colorguard."""
inst_lower = instrument.lower()
if any(x in inst_lower for x in ['flute', 'clarinet', 'sax', 'oboe', 'bassoon', 'piccolo']):
return 'Woodwinds'
if any(x in inst_lower for x in ['trumpet', 'mellophone', 'horn', 'trombone', 'baritone', 'euphonium', 'tuba', 'sousaphone']):
return 'Brass'
if any(x in inst_lower for x in ['percussion', 'snare', 'tenor', 'drum', 'cymbal', 'marimba', 'vibraphone', 'timpani', 'bells', 'electronics']):
return 'Percussion'
if 'guard' in inst_lower or 'color' in inst_lower:
return 'Colorguard'
return 'Leadership' # Fallback for generic roles like Drum Major
def format_phone(phone_str):
"""Clean and standardize the phone numbers."""
phone = str(phone_str).strip()
if not phone:
return ""
# Leave non-US international codes as they are
if phone.startswith('+') and not phone.startswith('+1'):
return phone
# Standardize US numbers to XXX-XXX-XXXX
digits = re.sub(r'\D', '', phone)
if len(digits) == 10:
return f"{digits[:3]}-{digits[3:6]}-{digits[6:]}"
elif len(digits) == 11 and digits.startswith('1'):
return f"{digits[1:4]}-{digits[4:7]}-{digits[7:]}"
return phone
def main():
parser = argparse.ArgumentParser(description="Convert Band Leadership CSV to Google Contacts format.")
parser.add_argument("input_file", help="Path to the input CSV file")
parser.add_argument("-y", "--year", type=int, default=datetime.datetime.now().year,
help="Target year for labels and grade calculation (defaults to current year)")
parser.add_argument("-o", "--output", default="google_contacts_import.csv",
help="Output file name")
args = parser.parse_args()
target_year = args.year
# Google Contacts Headers matching your expected output
google_headers = [
"First Name", "Middle Name", "Last Name", "Phonetic First Name", "Phonetic Middle Name",
"Phonetic Last Name", "Name Prefix", "Name Suffix", "Nickname", "File As",
"Organization Name", "Organization Title", "Organization Department", "Birthday", "Notes",
"Photo", "Labels", "E-mail 1 - Label", "E-mail 1 - Value", "Phone 1 - Label",
"Phone 1 - Value", "Phone 2 - Label", "Phone 2 - Value", "Phone 3 - Label", "Phone 3 - Value",
"Address 1 - Label", "Address 1 - Formatted", "Address 1 - Street", "Address 1 - City",
"Address 1 - PO Box", "Address 1 - Region", "Address 1 - Postal Code", "Address 1 - Country",
"Address 1 - Extended Address"
]
with open(args.input_file, mode='r', encoding='utf-8') as infile, \
open(args.output, mode='w', encoding='utf-8', newline='') as outfile:
reader = csv.DictReader(infile)
writer = csv.DictWriter(outfile, fieldnames=google_headers)
writer.writeheader()
for row in reader:
# Skip empty rows or the trailing blank commas in the source file
name_field = row.get('NAME', '').strip()
if not name_field or name_field == ',':
continue
# Parse Name ("Last, First")
name_parts = name_field.split(',')
last_name = name_parts[0].strip() if len(name_parts) > 0 else ""
first_name = name_parts[1].strip() if len(name_parts) > 1 else ""
# Parse Instrument (e.g., "04 - Tenor Sax" -> "Tenor Sax")
section_raw = row.get('SECTION', '').strip()
instrument = section_raw.split('-', 1)[-1].strip() if '-' in section_raw else section_raw
if not instrument:
instrument = "Unknown"
# Parse Grade and formulate Notes
grade_raw = row.get('GRADE', '').strip()
grade_match = re.match(r"(\d{4})\s*\((.*?)\)", grade_raw)
if grade_match:
grad_year = grade_match.group(1)
grade_level = grade_match.group(2).capitalize()
notes = f"Class of {grad_year}. A {grade_level} in {target_year}"
else:
notes = grade_raw
# Determine Label
category = get_category(instrument)
label = f"{target_year} {category} ::: Marching Band ::: * myContacts"
# Build the output row
out_row = {key: "" for key in google_headers}
out_row["First Name"] = first_name
out_row["Last Name"] = f"{last_name} ({instrument})"
out_row["Notes"] = notes
out_row["Labels"] = label
# Map Email
email = row.get('EMAIL', '').strip()
if email:
out_row["E-mail 1 - Label"] = "Home"
out_row["E-mail 1 - Value"] = email
# Map Phone
phone = row.get('PHONE', '').strip()
if phone:
out_row["Phone 1 - Label"] = "Mobile"
out_row["Phone 1 - Value"] = format_phone(phone)
writer.writerow(out_row)
print(f"Success! Formatted contacts saved to {args.output}")
if __name__ == '__main__':
main()