mirror of
https://github.com/skoelle/icloud-contacts-sync.git
synced 2026-09-17 23:40: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
|
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]:
|
def _account_filter_clause(account_name: str | None) -> tuple[str, list]:
|
||||||
if account_name is None:
|
if account_name is None:
|
||||||
return "", []
|
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"])
|
groups = db.get_groups_for_contact(conn, row["account"], row["uid"])
|
||||||
group_names = [g["name"] for g in groups if g.get("name")]
|
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])
|
@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"])
|
groups = db.get_groups_for_contact(conn, row["account"], row["uid"])
|
||||||
group_names = [g["name"] for g in groups if g.get("name")]
|
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 = ""
|
homecity = ""
|
||||||
workcity = ""
|
workcity = ""
|
||||||
|
|||||||
@@ -443,7 +443,9 @@
|
|||||||
{% for rn in contact.related_names %}
|
{% for rn in contact.related_names %}
|
||||||
<div class="tile">
|
<div class="tile">
|
||||||
<div class="tile-label">{{ rn.type }}</div>
|
<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>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -383,6 +383,18 @@ def get_groups_for_contact(conn, account: str, member_uid: str) -> list[dict]:
|
|||||||
return cur.fetchall()
|
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:
|
def get_group_count(conn, account: str | None) -> int:
|
||||||
where_clause, params = _account_filter_clause(account)
|
where_clause, params = _account_filter_clause(account)
|
||||||
with conn.cursor() as cur:
|
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"
|
type_val = params.get("TYPE") or params.get("type") or "other"
|
||||||
if isinstance(type_val, list):
|
if isinstance(type_val, list):
|
||||||
type_val = type_val[0] if type_val else "other"
|
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({
|
related_names.append({
|
||||||
"type": type_val,
|
"type": type_val,
|
||||||
"value": r.value if r.value else "",
|
"value": value,
|
||||||
})
|
})
|
||||||
|
|
||||||
photo_url = None
|
photo_url = None
|
||||||
|
|||||||
Reference in New Issue
Block a user