#!/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 %b {age_text}\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()