diff --git a/src/api/main.py b/src/api/main.py index 48fa74a..ad26e50 100644 --- a/src/api/main.py +++ b/src/api/main.py @@ -56,7 +56,7 @@ def _fmt_ts(dt) -> str | None: def _row_to_contact_out(row: dict, group_names: list[str] | None = None) -> dict: row = dict(row) - for field in ["emails", "phones", "addresses", "urls", "social_profiles", "categories"]: + for field in ["emails", "phones", "addresses", "urls", "social_profiles", "related_names", "categories"]: raw = row.get(field) row[field] = json.loads(raw) if raw else [] if not row.get("full_name"): @@ -134,7 +134,7 @@ def get_contact(contact_id: int, current_user: str = Depends(get_current_user)): with conn.cursor() as cur: cur.execute( f"""SELECT id, account, uid, full_name, prefix, given_name, middle_name, family_name, suffix, organization, - job_title, birthday, notes, photo_url, emails, phones, addresses, urls, social_profiles, categories, updated_at + job_title, birthday, notes, photo_url, emails, phones, addresses, urls, social_profiles, related_names, categories, updated_at FROM contacts {where_clause} {id_clause}""", params + [contact_id], ) @@ -625,7 +625,7 @@ def web_contact( with conn.cursor() as cur: cur.execute( f"""SELECT id, account, uid, full_name, prefix, given_name, middle_name, family_name, suffix, organization, - job_title, birthday, notes, photo_url, emails, phones, addresses, urls, social_profiles, categories, updated_at + job_title, birthday, notes, photo_url, emails, phones, addresses, urls, social_profiles, related_names, categories, updated_at FROM contacts {where_clause} {id_clause}""", params + [contact_id], ) diff --git a/src/api/schemas.py b/src/api/schemas.py index 2307458..b820150 100644 --- a/src/api/schemas.py +++ b/src/api/schemas.py @@ -25,6 +25,7 @@ class ContactOut(BaseModel): addresses: list urls: list social_profiles: list + related_names: list categories: list groups: list[str] = [] updated_at: str diff --git a/src/api/templates/contact.html b/src/api/templates/contact.html index ca4b3ee..a1b20e9 100644 --- a/src/api/templates/contact.html +++ b/src/api/templates/contact.html @@ -436,6 +436,20 @@ {% endif %} + {% if contact.related_names %} +
+
Beziehungen
+
+ {% for rn in contact.related_names %} +
+
{{ rn.type }}
+
{{ rn.value }}
+
+ {% endfor %} +
+
+ {% endif %} + {% if contact.categories %}
Kategorien
diff --git a/src/vcard_parser.py b/src/vcard_parser.py index 7842aad..69c888f 100644 --- a/src/vcard_parser.py +++ b/src/vcard_parser.py @@ -124,6 +124,17 @@ def parse_vcard(raw_text: str, account: str, etag: str | None = None) -> dict | categories = [c.strip() for c in vcard.categories.value] if hasattr(vcard, "categories") else [] + related_names = [] + for r in vcard.contents.get("related", []): + params = getattr(r, "params", {}) + type_val = params.get("TYPE") or params.get("type") or "other" + if isinstance(type_val, list): + type_val = type_val[0] if type_val else "other" + related_names.append({ + "type": type_val, + "value": r.value if r.value else "", + }) + photo_url = None photo_base64 = None if hasattr(vcard, "photo"): @@ -168,7 +179,7 @@ def parse_vcard(raw_text: str, account: str, etag: str | None = None) -> dict | "addresses": json.dumps(addresses, ensure_ascii=False), "urls": json.dumps(urls, ensure_ascii=False), "social_profiles": json.dumps(social_profiles, ensure_ascii=False), - "related_names": json.dumps([], ensure_ascii=False), + "related_names": json.dumps(related_names, ensure_ascii=False), "categories": json.dumps(categories, ensure_ascii=False), "raw_vcard": raw_text, "source": "icloud",