diff --git a/contacts_to_remind.py b/contacts_to_remind.py new file mode 100644 index 0000000..b59c698 --- /dev/null +++ b/contacts_to_remind.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Dieses Script exportiert Geburtstage aus Apple Contacts und erstellt eine +Remind-Datei (geburtstage.rem) für Geburtstagserinnerungen. +""" + +import os +import sys +import datetime +import argparse +from pathlib import Path + +try: + # Statt 'contacts' verwenden wir pyobjc-framework-Contacts + from Contacts import CNContactStore, CNContactFetchRequest, CNContactBirthdayKey, CNContactGivenNameKey, CNContactFamilyNameKey + import objc +except ImportError: + print("Die 'pyobjc-framework-Contacts' Bibliothek wird benötigt. Bitte installieren Sie sie mit:") + print("uv pip install pyobjc-framework-Contacts") + sys.exit(1) + +def get_birthdays_from_contacts(): + """Ruft alle Kontakte mit Geburtstagsinformationen aus Apple Contacts ab.""" + store = CNContactStore.alloc().init() + + # Anfrage für Kontakte mit Geburtstagsinformationen erstellen + keys_to_fetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactBirthdayKey] + request = CNContactFetchRequest.alloc().initWithKeysToFetch_(keys_to_fetch) + + birthdays = [] + + # Callback-Funktion für jeden gefundenen Kontakt + def handle_contact(contact, stop): + birthday = contact.birthday() + if birthday: + given_name = contact.givenName() or "" + family_name = contact.familyName() or "" + name = f"{given_name} {family_name}".strip() + + # Sicherstellen, dass wir tatsächlich Integer-Werte haben + try: + month = birthday.month() + day = birthday.day() + + # Prüfen, ob ein Jahr existiert + try: + year = birthday.year() + # In Apple Contacts ist 1604 oft ein Platzhalter für "kein Jahr" + if year == 1604: + year = None + except: + year = None + + # Nur hinzufügen, wenn gültige Monat- und Tagwerte vorhanden sind + if isinstance(month, int) and isinstance(day, int): + birthdays.append({ + 'name': name, + 'month': month, + 'day': day, + 'year': year if isinstance(year, int) and year != 1604 else None + }) + except: + # Fehler beim Extrahieren der Datumsinformationen + pass + + # Anfrage ausführen mit der Callback-Funktion + error = objc.nil + store.enumerateContactsWithFetchRequest_error_usingBlock_(request, error, handle_contact) + + return birthdays + +def create_remind_file(birthdays, output_file='geburtstage.rem'): + """Erstellt eine Remind-Datei mit den Geburtstagsinformationen.""" + current_year = datetime.datetime.now().year + + with open(output_file, 'w', encoding='utf-8') as f: + f.write("# Geburtstage aus Apple Contacts\n") + f.write("# Erstellt am: {}\n".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) + f.write("# Enthält Erinnerungen am Geburtstag und 7 Tage vorher\n\n") + + for person in sorted(birthdays, key=lambda x: (x['month'], x['day'])): + name = person['name'] + month = person['month'] + day = person['day'] + birth_year = person['year'] + + # Alterstext erstellen, falls Geburtsjahr vorhanden und gültig + age_text = "" + if birth_year and isinstance(birth_year, int) and birth_year > 1900 and birth_year < current_year: + age = current_year - birth_year + age_text = f"({age} Jahre alt)" + + # Remind-Eintrag für den Geburtstag selbst + remind_entry = f'REM {day} {month_to_abbr(month)} MSG {name}: Geburtstag {age_text} %b\n' + f.write(remind_entry) + + # Remind-Eintrag für die Vorwarnung 7 Tage vorher + remind_entry_advance = f'REM {day} {month_to_abbr(month)} +7 MSG Vorwarnung: {name} hat in 7 Tagen Geburtstag {age_text} %b\n' + f.write(remind_entry_advance) + +def month_to_abbr(month_num): + """Konvertiert eine Monatsnummer (1-12) in die dreistellige Abkürzung für Remind.""" + months = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", + "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"] + return months[month_num - 1] + +def main(): + """Hauptfunktion des Scripts.""" + parser = argparse.ArgumentParser(description='Exportiert Geburtstage aus Apple Contacts in eine Remind-Datei.') + parser.add_argument('-o', '--output', default='geburtstage.rem', + help='Ausgabedatei (Standard: geburtstage.rem)') + parser.add_argument('-v', '--verbose', action='store_true', + help='Ausführliche Ausgabe') + + args = parser.parse_args() + + try: + if args.verbose: + print("Lese Kontakte aus Apple Contacts...") + + birthdays = get_birthdays_from_contacts() + + if args.verbose: + print(f"{len(birthdays)} Kontakte mit Geburtstagsinformationen gefunden.") + + create_remind_file(birthdays, args.output) + + print(f"Remind-Datei erfolgreich erstellt: {args.output}") + print(f"Insgesamt {len(birthdays)} Geburtstage exportiert.") + + except Exception as e: + print(f"Fehler: {e}") + import traceback + traceback.print_exc() + sys.exit(1) + +if __name__ == "__main__": + main()