139 lines
5.4 KiB
Python
139 lines
5.4 KiB
Python
#!/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 Geburstag {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()
|