mirror of
https://github.com/skoelle/icloud-contacts-sync.git
synced 2026-09-17 15:30:24 +00:00
related contact details
This commit is contained in:
+24
-2
@@ -66,6 +66,25 @@ def _row_to_contact_out(row: dict, group_names: list[str] | None = None) -> dict
|
||||
return row
|
||||
|
||||
|
||||
def _enrich_related_names(conn, contact: dict) -> None:
|
||||
related = contact.get("related_names", [])
|
||||
if not related:
|
||||
return
|
||||
uids = [r["value"] for r in related if r.get("value")]
|
||||
if not uids:
|
||||
return
|
||||
resolved = db.resolve_related_names(conn, contact["account"], uids)
|
||||
for r in related:
|
||||
uid = r.get("value", "")
|
||||
info = resolved.get(uid)
|
||||
if info:
|
||||
r["id"] = info["id"]
|
||||
r["name"] = info["name"]
|
||||
else:
|
||||
r["id"] = None
|
||||
r["name"] = uid
|
||||
|
||||
|
||||
def _account_filter_clause(account_name: str | None) -> tuple[str, list]:
|
||||
if account_name is None:
|
||||
return "", []
|
||||
@@ -146,7 +165,9 @@ def get_contact(contact_id: int, current_user: str = Depends(get_current_user)):
|
||||
groups = db.get_groups_for_contact(conn, row["account"], row["uid"])
|
||||
group_names = [g["name"] for g in groups if g.get("name")]
|
||||
|
||||
return _row_to_contact_out(row, group_names=group_names)
|
||||
contact = _row_to_contact_out(row, group_names=group_names)
|
||||
_enrich_related_names(conn, contact)
|
||||
return contact
|
||||
|
||||
|
||||
@app.get("/api/contacts/birthdays/today", response_model=list[ContactOut])
|
||||
@@ -638,7 +659,8 @@ def web_contact(
|
||||
groups = db.get_groups_for_contact(conn, row["account"], row["uid"])
|
||||
group_names = [g["name"] for g in groups if g.get("name")]
|
||||
|
||||
contact = _row_to_contact_out(row, group_names=group_names)
|
||||
contact = _row_to_contact_out(row, group_names=group_names)
|
||||
_enrich_related_names(conn, contact)
|
||||
|
||||
homecity = ""
|
||||
workcity = ""
|
||||
|
||||
@@ -443,7 +443,9 @@
|
||||
{% for rn in contact.related_names %}
|
||||
<div class="tile">
|
||||
<div class="tile-label">{{ rn.type }}</div>
|
||||
<div class="tile-value">{{ rn.value }}</div>
|
||||
<div class="tile-value">
|
||||
{% if rn.id %}<a href="/contacts/{{ rn.id }}">{{ rn.name }}</a>{% else %}{{ rn.name }}{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
@@ -383,6 +383,18 @@ def get_groups_for_contact(conn, account: str, member_uid: str) -> list[dict]:
|
||||
return cur.fetchall()
|
||||
|
||||
|
||||
def resolve_related_names(conn, account: str, uids: list[str]) -> dict[str, dict]:
|
||||
if not uids:
|
||||
return {}
|
||||
placeholders = ", ".join(["%s"] * len(uids))
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
f"SELECT uid, id, full_name FROM contacts WHERE account = %s AND uid IN ({placeholders})",
|
||||
[account] + uids,
|
||||
)
|
||||
return {row["uid"]: {"id": row["id"], "name": row["full_name"]} for row in cur.fetchall()}
|
||||
|
||||
|
||||
def get_group_count(conn, account: str | None) -> int:
|
||||
where_clause, params = _account_filter_clause(account)
|
||||
with conn.cursor() as cur:
|
||||
|
||||
+4
-1
@@ -130,9 +130,12 @@ def parse_vcard(raw_text: str, account: str, etag: str | None = None) -> dict |
|
||||
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"
|
||||
value = r.value if r.value else ""
|
||||
if value.startswith(_MEMBER_PREFIX):
|
||||
value = value[len(_MEMBER_PREFIX):]
|
||||
related_names.append({
|
||||
"type": type_val,
|
||||
"value": r.value if r.value else "",
|
||||
"value": value,
|
||||
})
|
||||
|
||||
photo_url = None
|
||||
|
||||
Reference in New Issue
Block a user