mirror of
https://github.com/skoelle/icloud-contacts-sync.git
synced 2026-09-17 15:30:24 +00:00
related mapping
This commit is contained in:
+3
-3
@@ -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],
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -436,6 +436,20 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if contact.related_names %}
|
||||
<div class="section">
|
||||
<div class="section-title">Beziehungen</div>
|
||||
<div class="tiles-grid">
|
||||
{% for rn in contact.related_names %}
|
||||
<div class="tile">
|
||||
<div class="tile-label">{{ rn.type }}</div>
|
||||
<div class="tile-value">{{ rn.value }}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if contact.categories %}
|
||||
<div class="section">
|
||||
<div class="section-title">Kategorien</div>
|
||||
|
||||
+12
-1
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user