mirror of
https://github.com/LifeArchiveProject/WeChatDataAnalysis.git
synced 2026-02-02 22:10:50 +08:00
improvement(chat): WCDB 回退补全昵称/头像
- contact.db 缺失(企业/开放平台/openim/群等)时,回退 WCDB realtime 查询 displayName/avatarUrl - 覆盖消息/会话:senderDisplayName/senderAvatar、link card from、quoteTitle、会话列表 name/avatar - realtime 场景尽量复用已建立的 WCDB 连接;best-effort,失败不影响主流程
This commit is contained in:
@@ -68,6 +68,8 @@ from ..session_last_message import (
|
|||||||
from ..wcdb_realtime import (
|
from ..wcdb_realtime import (
|
||||||
WCDBRealtimeError,
|
WCDBRealtimeError,
|
||||||
WCDB_REALTIME,
|
WCDB_REALTIME,
|
||||||
|
get_avatar_urls as _wcdb_get_avatar_urls,
|
||||||
|
get_display_names as _wcdb_get_display_names,
|
||||||
get_messages as _wcdb_get_messages,
|
get_messages as _wcdb_get_messages,
|
||||||
get_sessions as _wcdb_get_sessions,
|
get_sessions as _wcdb_get_sessions,
|
||||||
)
|
)
|
||||||
@@ -2231,6 +2233,35 @@ def _postprocess_full_messages(
|
|||||||
sender_contact_rows = _load_contact_rows(contact_db_path, uniq_senders)
|
sender_contact_rows = _load_contact_rows(contact_db_path, uniq_senders)
|
||||||
local_sender_avatars = _query_head_image_usernames(head_image_db_path, uniq_senders)
|
local_sender_avatars = _query_head_image_usernames(head_image_db_path, uniq_senders)
|
||||||
|
|
||||||
|
# contact.db may not include enterprise/openim contacts (or group chatroom records). WCDB has a more complete
|
||||||
|
# view of display names + avatar URLs, so we use it as a best-effort fallback.
|
||||||
|
wcdb_display_names: dict[str, str] = {}
|
||||||
|
wcdb_avatar_urls: dict[str, str] = {}
|
||||||
|
try:
|
||||||
|
need_display: list[str] = []
|
||||||
|
need_avatar: list[str] = []
|
||||||
|
for u in uniq_senders:
|
||||||
|
if not u:
|
||||||
|
continue
|
||||||
|
row = sender_contact_rows.get(u)
|
||||||
|
if _pick_display_name(row, u) == u:
|
||||||
|
need_display.append(u)
|
||||||
|
if (not _pick_avatar_url(row)) and (u not in local_sender_avatars):
|
||||||
|
need_avatar.append(u)
|
||||||
|
|
||||||
|
need_display = list(dict.fromkeys(need_display))
|
||||||
|
need_avatar = list(dict.fromkeys(need_avatar))
|
||||||
|
if need_display or need_avatar:
|
||||||
|
wcdb_conn = WCDB_REALTIME.ensure_connected(account_dir)
|
||||||
|
with wcdb_conn.lock:
|
||||||
|
if need_display:
|
||||||
|
wcdb_display_names = _wcdb_get_display_names(wcdb_conn.handle, need_display)
|
||||||
|
if need_avatar:
|
||||||
|
wcdb_avatar_urls = _wcdb_get_avatar_urls(wcdb_conn.handle, need_avatar)
|
||||||
|
except Exception:
|
||||||
|
wcdb_display_names = {}
|
||||||
|
wcdb_avatar_urls = {}
|
||||||
|
|
||||||
for m in merged:
|
for m in merged:
|
||||||
# If appmsg doesn't provide sourcedisplayname, try mapping sourceusername to display name.
|
# If appmsg doesn't provide sourcedisplayname, try mapping sourceusername to display name.
|
||||||
if (not str(m.get("from") or "").strip()) and str(m.get("fromUsername") or "").strip():
|
if (not str(m.get("from") or "").strip()) and str(m.get("fromUsername") or "").strip():
|
||||||
@@ -2238,15 +2269,28 @@ def _postprocess_full_messages(
|
|||||||
frow = sender_contact_rows.get(fu)
|
frow = sender_contact_rows.get(fu)
|
||||||
if frow is not None:
|
if frow is not None:
|
||||||
m["from"] = _pick_display_name(frow, fu)
|
m["from"] = _pick_display_name(frow, fu)
|
||||||
|
else:
|
||||||
|
wd = str(wcdb_display_names.get(fu) or "").strip()
|
||||||
|
if wd:
|
||||||
|
m["from"] = wd
|
||||||
|
|
||||||
su = str(m.get("senderUsername") or "")
|
su = str(m.get("senderUsername") or "")
|
||||||
if not su:
|
if not su:
|
||||||
continue
|
continue
|
||||||
row = sender_contact_rows.get(su)
|
row = sender_contact_rows.get(su)
|
||||||
m["senderDisplayName"] = _pick_display_name(row, su)
|
display_name = _pick_display_name(row, su)
|
||||||
|
if display_name == su:
|
||||||
|
wd = str(wcdb_display_names.get(su) or "").strip()
|
||||||
|
if wd and wd != su:
|
||||||
|
display_name = wd
|
||||||
|
m["senderDisplayName"] = display_name
|
||||||
avatar_url = _pick_avatar_url(row)
|
avatar_url = _pick_avatar_url(row)
|
||||||
if not avatar_url and su in local_sender_avatars:
|
if not avatar_url and su in local_sender_avatars:
|
||||||
avatar_url = base_url + _build_avatar_url(account_dir.name, su)
|
avatar_url = base_url + _build_avatar_url(account_dir.name, su)
|
||||||
|
if not avatar_url:
|
||||||
|
wa = str(wcdb_avatar_urls.get(su) or "").strip()
|
||||||
|
if wa.lower().startswith(("http://", "https://")):
|
||||||
|
avatar_url = wa
|
||||||
m["senderAvatar"] = avatar_url
|
m["senderAvatar"] = avatar_url
|
||||||
|
|
||||||
qu = str(m.get("quoteUsername") or "").strip()
|
qu = str(m.get("quoteUsername") or "").strip()
|
||||||
@@ -2262,9 +2306,15 @@ def _postprocess_full_messages(
|
|||||||
if remark:
|
if remark:
|
||||||
m["quoteTitle"] = remark
|
m["quoteTitle"] = remark
|
||||||
elif not qt:
|
elif not qt:
|
||||||
m["quoteTitle"] = _pick_display_name(qrow, qu)
|
title = _pick_display_name(qrow, qu)
|
||||||
|
if title == qu:
|
||||||
|
wd = str(wcdb_display_names.get(qu) or "").strip()
|
||||||
|
if wd and wd != qu:
|
||||||
|
title = wd
|
||||||
|
m["quoteTitle"] = title
|
||||||
elif not qt:
|
elif not qt:
|
||||||
m["quoteTitle"] = qu
|
wd = str(wcdb_display_names.get(qu) or "").strip()
|
||||||
|
m["quoteTitle"] = wd or qu
|
||||||
|
|
||||||
# Media URL fallback: if CDN URLs missing, use local media endpoints.
|
# Media URL fallback: if CDN URLs missing, use local media endpoints.
|
||||||
try:
|
try:
|
||||||
@@ -2401,6 +2451,7 @@ def list_chat_sessions(
|
|||||||
head_image_db_path = account_dir / "head_image.db"
|
head_image_db_path = account_dir / "head_image.db"
|
||||||
base_url = str(request.base_url).rstrip("/")
|
base_url = str(request.base_url).rstrip("/")
|
||||||
|
|
||||||
|
rt_conn = None
|
||||||
rows: list[Any]
|
rows: list[Any]
|
||||||
if source_norm == "realtime":
|
if source_norm == "realtime":
|
||||||
trace_id = f"rt-sessions-{int(time.time() * 1000)}-{threading.get_ident()}"
|
trace_id = f"rt-sessions-{int(time.time() * 1000)}-{threading.get_ident()}"
|
||||||
@@ -2416,6 +2467,7 @@ def list_chat_sessions(
|
|||||||
try:
|
try:
|
||||||
logger.info("[%s] ensure wcdb connected account=%s", trace_id, account_dir.name)
|
logger.info("[%s] ensure wcdb connected account=%s", trace_id, account_dir.name)
|
||||||
conn = WCDB_REALTIME.ensure_connected(account_dir)
|
conn = WCDB_REALTIME.ensure_connected(account_dir)
|
||||||
|
rt_conn = conn
|
||||||
logger.info("[%s] wcdb connected account=%s handle=%s", trace_id, account_dir.name, int(conn.handle))
|
logger.info("[%s] wcdb connected account=%s handle=%s", trace_id, account_dir.name, int(conn.handle))
|
||||||
logger.info("[%s] wcdb_get_sessions account=%s", trace_id, account_dir.name)
|
logger.info("[%s] wcdb_get_sessions account=%s", trace_id, account_dir.name)
|
||||||
wcdb_t0 = time.perf_counter()
|
wcdb_t0 = time.perf_counter()
|
||||||
@@ -2529,6 +2581,36 @@ def list_chat_sessions(
|
|||||||
contact_rows = _load_contact_rows(contact_db_path, usernames)
|
contact_rows = _load_contact_rows(contact_db_path, usernames)
|
||||||
local_avatar_usernames = _query_head_image_usernames(head_image_db_path, usernames)
|
local_avatar_usernames = _query_head_image_usernames(head_image_db_path, usernames)
|
||||||
|
|
||||||
|
# Some sessions (notably enterprise groups / openim-related IDs) may be missing from decrypted contact.db
|
||||||
|
# (or lack nickname/avatar columns). In that case, fall back to WCDB APIs (same as WeFlow) to resolve
|
||||||
|
# display names + avatar URLs.
|
||||||
|
wcdb_display_names: dict[str, str] = {}
|
||||||
|
wcdb_avatar_urls: dict[str, str] = {}
|
||||||
|
try:
|
||||||
|
need_display: list[str] = []
|
||||||
|
need_avatar: list[str] = []
|
||||||
|
for u in usernames:
|
||||||
|
if not u:
|
||||||
|
continue
|
||||||
|
row = contact_rows.get(u)
|
||||||
|
if _pick_display_name(row, u) == u:
|
||||||
|
need_display.append(u)
|
||||||
|
if (not _pick_avatar_url(row)) and (u not in local_avatar_usernames):
|
||||||
|
need_avatar.append(u)
|
||||||
|
|
||||||
|
need_display = list(dict.fromkeys(need_display))
|
||||||
|
need_avatar = list(dict.fromkeys(need_avatar))
|
||||||
|
if need_display or need_avatar:
|
||||||
|
wcdb_conn = rt_conn or WCDB_REALTIME.ensure_connected(account_dir)
|
||||||
|
with wcdb_conn.lock:
|
||||||
|
if need_display:
|
||||||
|
wcdb_display_names = _wcdb_get_display_names(wcdb_conn.handle, need_display)
|
||||||
|
if need_avatar:
|
||||||
|
wcdb_avatar_urls = _wcdb_get_avatar_urls(wcdb_conn.handle, need_avatar)
|
||||||
|
except Exception:
|
||||||
|
wcdb_display_names = {}
|
||||||
|
wcdb_avatar_urls = {}
|
||||||
|
|
||||||
preview_mode = str(preview or "").strip().lower()
|
preview_mode = str(preview or "").strip().lower()
|
||||||
if preview_mode not in {"latest", "index", "session", "db", "none"}:
|
if preview_mode not in {"latest", "index", "session", "db", "none"}:
|
||||||
preview_mode = "latest"
|
preview_mode = "latest"
|
||||||
@@ -2568,9 +2650,18 @@ def list_chat_sessions(
|
|||||||
c_row = contact_rows.get(username)
|
c_row = contact_rows.get(username)
|
||||||
|
|
||||||
display_name = _pick_display_name(c_row, username)
|
display_name = _pick_display_name(c_row, username)
|
||||||
|
if display_name == username:
|
||||||
|
wd = str(wcdb_display_names.get(username) or "").strip()
|
||||||
|
if wd and wd != username:
|
||||||
|
display_name = wd
|
||||||
|
|
||||||
avatar_url = _pick_avatar_url(c_row)
|
avatar_url = _pick_avatar_url(c_row)
|
||||||
if not avatar_url and username in local_avatar_usernames:
|
if not avatar_url and username in local_avatar_usernames:
|
||||||
avatar_url = base_url + _build_avatar_url(account_dir.name, username)
|
avatar_url = base_url + _build_avatar_url(account_dir.name, username)
|
||||||
|
if not avatar_url:
|
||||||
|
wa = str(wcdb_avatar_urls.get(username) or "").strip()
|
||||||
|
if wa.lower().startswith(("http://", "https://")):
|
||||||
|
avatar_url = wa
|
||||||
|
|
||||||
last_message = ""
|
last_message = ""
|
||||||
if preview_mode == "session":
|
if preview_mode == "session":
|
||||||
@@ -3896,6 +3987,35 @@ def list_chat_messages(
|
|||||||
sender_contact_rows = _load_contact_rows(contact_db_path, uniq_senders)
|
sender_contact_rows = _load_contact_rows(contact_db_path, uniq_senders)
|
||||||
local_sender_avatars = _query_head_image_usernames(head_image_db_path, uniq_senders)
|
local_sender_avatars = _query_head_image_usernames(head_image_db_path, uniq_senders)
|
||||||
|
|
||||||
|
# contact.db may not include enterprise/openim contacts (or group chatroom records). WCDB has a more complete
|
||||||
|
# view of display names + avatar URLs, so we use it as a best-effort fallback.
|
||||||
|
wcdb_display_names: dict[str, str] = {}
|
||||||
|
wcdb_avatar_urls: dict[str, str] = {}
|
||||||
|
try:
|
||||||
|
need_display: list[str] = []
|
||||||
|
need_avatar: list[str] = []
|
||||||
|
for u in uniq_senders:
|
||||||
|
if not u:
|
||||||
|
continue
|
||||||
|
row = sender_contact_rows.get(u)
|
||||||
|
if _pick_display_name(row, u) == u:
|
||||||
|
need_display.append(u)
|
||||||
|
if (not _pick_avatar_url(row)) and (u not in local_sender_avatars):
|
||||||
|
need_avatar.append(u)
|
||||||
|
|
||||||
|
need_display = list(dict.fromkeys(need_display))
|
||||||
|
need_avatar = list(dict.fromkeys(need_avatar))
|
||||||
|
if need_display or need_avatar:
|
||||||
|
wcdb_conn = WCDB_REALTIME.ensure_connected(account_dir)
|
||||||
|
with wcdb_conn.lock:
|
||||||
|
if need_display:
|
||||||
|
wcdb_display_names = _wcdb_get_display_names(wcdb_conn.handle, need_display)
|
||||||
|
if need_avatar:
|
||||||
|
wcdb_avatar_urls = _wcdb_get_avatar_urls(wcdb_conn.handle, need_avatar)
|
||||||
|
except Exception:
|
||||||
|
wcdb_display_names = {}
|
||||||
|
wcdb_avatar_urls = {}
|
||||||
|
|
||||||
for m in merged:
|
for m in merged:
|
||||||
# If appmsg doesn't provide sourcedisplayname, try mapping sourceusername to display name.
|
# If appmsg doesn't provide sourcedisplayname, try mapping sourceusername to display name.
|
||||||
if (not str(m.get("from") or "").strip()) and str(m.get("fromUsername") or "").strip():
|
if (not str(m.get("from") or "").strip()) and str(m.get("fromUsername") or "").strip():
|
||||||
@@ -3903,15 +4023,28 @@ def list_chat_messages(
|
|||||||
frow = sender_contact_rows.get(fu)
|
frow = sender_contact_rows.get(fu)
|
||||||
if frow is not None:
|
if frow is not None:
|
||||||
m["from"] = _pick_display_name(frow, fu)
|
m["from"] = _pick_display_name(frow, fu)
|
||||||
|
else:
|
||||||
|
wd = str(wcdb_display_names.get(fu) or "").strip()
|
||||||
|
if wd:
|
||||||
|
m["from"] = wd
|
||||||
|
|
||||||
su = str(m.get("senderUsername") or "")
|
su = str(m.get("senderUsername") or "")
|
||||||
if not su:
|
if not su:
|
||||||
continue
|
continue
|
||||||
row = sender_contact_rows.get(su)
|
row = sender_contact_rows.get(su)
|
||||||
m["senderDisplayName"] = _pick_display_name(row, su)
|
display_name = _pick_display_name(row, su)
|
||||||
|
if display_name == su:
|
||||||
|
wd = str(wcdb_display_names.get(su) or "").strip()
|
||||||
|
if wd and wd != su:
|
||||||
|
display_name = wd
|
||||||
|
m["senderDisplayName"] = display_name
|
||||||
avatar_url = _pick_avatar_url(row)
|
avatar_url = _pick_avatar_url(row)
|
||||||
if not avatar_url and su in local_sender_avatars:
|
if not avatar_url and su in local_sender_avatars:
|
||||||
avatar_url = base_url + _build_avatar_url(account_dir.name, su)
|
avatar_url = base_url + _build_avatar_url(account_dir.name, su)
|
||||||
|
if not avatar_url:
|
||||||
|
wa = str(wcdb_avatar_urls.get(su) or "").strip()
|
||||||
|
if wa.lower().startswith(("http://", "https://")):
|
||||||
|
avatar_url = wa
|
||||||
m["senderAvatar"] = avatar_url
|
m["senderAvatar"] = avatar_url
|
||||||
|
|
||||||
qu = str(m.get("quoteUsername") or "").strip()
|
qu = str(m.get("quoteUsername") or "").strip()
|
||||||
@@ -3927,9 +4060,15 @@ def list_chat_messages(
|
|||||||
if remark:
|
if remark:
|
||||||
m["quoteTitle"] = remark
|
m["quoteTitle"] = remark
|
||||||
elif not qt:
|
elif not qt:
|
||||||
m["quoteTitle"] = _pick_display_name(qrow, qu)
|
title = _pick_display_name(qrow, qu)
|
||||||
|
if title == qu:
|
||||||
|
wd = str(wcdb_display_names.get(qu) or "").strip()
|
||||||
|
if wd and wd != qu:
|
||||||
|
title = wd
|
||||||
|
m["quoteTitle"] = title
|
||||||
elif not qt:
|
elif not qt:
|
||||||
m["quoteTitle"] = qu
|
wd = str(wcdb_display_names.get(qu) or "").strip()
|
||||||
|
m["quoteTitle"] = wd or qu
|
||||||
|
|
||||||
# Media URL fallback: if CDN URLs missing, use local media endpoints.
|
# Media URL fallback: if CDN URLs missing, use local media endpoints.
|
||||||
try:
|
try:
|
||||||
@@ -4357,11 +4496,48 @@ async def _search_chat_messages_via_fts(
|
|||||||
uniq_usernames = list(dict.fromkeys([username] + [str(x.get("senderUsername") or "") for x in hits]))
|
uniq_usernames = list(dict.fromkeys([username] + [str(x.get("senderUsername") or "") for x in hits]))
|
||||||
contact_rows = _load_contact_rows(contact_db_path, uniq_usernames)
|
contact_rows = _load_contact_rows(contact_db_path, uniq_usernames)
|
||||||
local_avatar_usernames = _query_head_image_usernames(head_image_db_path, uniq_usernames)
|
local_avatar_usernames = _query_head_image_usernames(head_image_db_path, uniq_usernames)
|
||||||
|
|
||||||
|
wcdb_display_names: dict[str, str] = {}
|
||||||
|
wcdb_avatar_urls: dict[str, str] = {}
|
||||||
|
try:
|
||||||
|
need_display: list[str] = []
|
||||||
|
need_avatar: list[str] = []
|
||||||
|
for u in uniq_usernames:
|
||||||
|
uu = str(u or "").strip()
|
||||||
|
if not uu:
|
||||||
|
continue
|
||||||
|
row = contact_rows.get(uu)
|
||||||
|
if _pick_display_name(row, uu) == uu:
|
||||||
|
need_display.append(uu)
|
||||||
|
if (not _pick_avatar_url(row)) and (uu not in local_avatar_usernames):
|
||||||
|
need_avatar.append(uu)
|
||||||
|
|
||||||
|
need_display = list(dict.fromkeys(need_display))
|
||||||
|
need_avatar = list(dict.fromkeys(need_avatar))
|
||||||
|
if need_display or need_avatar:
|
||||||
|
wcdb_conn = WCDB_REALTIME.ensure_connected(account_dir)
|
||||||
|
with wcdb_conn.lock:
|
||||||
|
if need_display:
|
||||||
|
wcdb_display_names = _wcdb_get_display_names(wcdb_conn.handle, need_display)
|
||||||
|
if need_avatar:
|
||||||
|
wcdb_avatar_urls = _wcdb_get_avatar_urls(wcdb_conn.handle, need_avatar)
|
||||||
|
except Exception:
|
||||||
|
wcdb_display_names = {}
|
||||||
|
wcdb_avatar_urls = {}
|
||||||
|
|
||||||
conv_row = contact_rows.get(username)
|
conv_row = contact_rows.get(username)
|
||||||
conv_name = _pick_display_name(conv_row, username)
|
conv_name = _pick_display_name(conv_row, username)
|
||||||
|
if conv_name == username:
|
||||||
|
wd = str(wcdb_display_names.get(username) or "").strip()
|
||||||
|
if wd and wd != username:
|
||||||
|
conv_name = wd
|
||||||
conv_avatar = _pick_avatar_url(conv_row)
|
conv_avatar = _pick_avatar_url(conv_row)
|
||||||
if (not conv_avatar) and (username in local_avatar_usernames):
|
if (not conv_avatar) and (username in local_avatar_usernames):
|
||||||
conv_avatar = base_url + _build_avatar_url(account_dir.name, username)
|
conv_avatar = base_url + _build_avatar_url(account_dir.name, username)
|
||||||
|
if not conv_avatar:
|
||||||
|
wa = str(wcdb_avatar_urls.get(username) or "").strip()
|
||||||
|
if wa.lower().startswith(("http://", "https://")):
|
||||||
|
conv_avatar = wa
|
||||||
|
|
||||||
for h in hits:
|
for h in hits:
|
||||||
su = str(h.get("senderUsername") or "").strip()
|
su = str(h.get("senderUsername") or "").strip()
|
||||||
@@ -4369,14 +4545,19 @@ async def _search_chat_messages_via_fts(
|
|||||||
h["conversationAvatar"] = conv_avatar
|
h["conversationAvatar"] = conv_avatar
|
||||||
if su:
|
if su:
|
||||||
row = contact_rows.get(su)
|
row = contact_rows.get(su)
|
||||||
h["senderDisplayName"] = (
|
display_name = _pick_display_name(row, su) if row is not None else (conv_name if su == username else su)
|
||||||
_pick_display_name(row, su)
|
if display_name == su:
|
||||||
if row is not None
|
wd = str(wcdb_display_names.get(su) or "").strip()
|
||||||
else (conv_name if su == username else su)
|
if wd and wd != su:
|
||||||
)
|
display_name = wd
|
||||||
|
h["senderDisplayName"] = display_name
|
||||||
avatar_url = _pick_avatar_url(row)
|
avatar_url = _pick_avatar_url(row)
|
||||||
if (not avatar_url) and (su in local_avatar_usernames):
|
if (not avatar_url) and (su in local_avatar_usernames):
|
||||||
avatar_url = base_url + _build_avatar_url(account_dir.name, su)
|
avatar_url = base_url + _build_avatar_url(account_dir.name, su)
|
||||||
|
if not avatar_url:
|
||||||
|
wa = str(wcdb_avatar_urls.get(su) or "").strip()
|
||||||
|
if wa.lower().startswith(("http://", "https://")):
|
||||||
|
avatar_url = wa
|
||||||
h["senderAvatar"] = avatar_url
|
h["senderAvatar"] = avatar_url
|
||||||
else:
|
else:
|
||||||
uniq_contacts = list(
|
uniq_contacts = list(
|
||||||
@@ -4387,24 +4568,67 @@ async def _search_chat_messages_via_fts(
|
|||||||
contact_rows = _load_contact_rows(contact_db_path, uniq_contacts)
|
contact_rows = _load_contact_rows(contact_db_path, uniq_contacts)
|
||||||
local_avatar_usernames = _query_head_image_usernames(head_image_db_path, uniq_contacts)
|
local_avatar_usernames = _query_head_image_usernames(head_image_db_path, uniq_contacts)
|
||||||
|
|
||||||
|
wcdb_display_names: dict[str, str] = {}
|
||||||
|
wcdb_avatar_urls: dict[str, str] = {}
|
||||||
|
try:
|
||||||
|
need_display: list[str] = []
|
||||||
|
need_avatar: list[str] = []
|
||||||
|
for u in uniq_contacts:
|
||||||
|
uu = str(u or "").strip()
|
||||||
|
if not uu:
|
||||||
|
continue
|
||||||
|
row = contact_rows.get(uu)
|
||||||
|
if _pick_display_name(row, uu) == uu:
|
||||||
|
need_display.append(uu)
|
||||||
|
if (not _pick_avatar_url(row)) and (uu not in local_avatar_usernames):
|
||||||
|
need_avatar.append(uu)
|
||||||
|
|
||||||
|
need_display = list(dict.fromkeys(need_display))
|
||||||
|
need_avatar = list(dict.fromkeys(need_avatar))
|
||||||
|
if need_display or need_avatar:
|
||||||
|
wcdb_conn = WCDB_REALTIME.ensure_connected(account_dir)
|
||||||
|
with wcdb_conn.lock:
|
||||||
|
if need_display:
|
||||||
|
wcdb_display_names = _wcdb_get_display_names(wcdb_conn.handle, need_display)
|
||||||
|
if need_avatar:
|
||||||
|
wcdb_avatar_urls = _wcdb_get_avatar_urls(wcdb_conn.handle, need_avatar)
|
||||||
|
except Exception:
|
||||||
|
wcdb_display_names = {}
|
||||||
|
wcdb_avatar_urls = {}
|
||||||
|
|
||||||
for h in hits:
|
for h in hits:
|
||||||
cu = str(h.get("username") or "").strip()
|
cu = str(h.get("username") or "").strip()
|
||||||
su = str(h.get("senderUsername") or "").strip()
|
su = str(h.get("senderUsername") or "").strip()
|
||||||
crow = contact_rows.get(cu)
|
crow = contact_rows.get(cu)
|
||||||
conv_name = _pick_display_name(crow, cu) if cu else ""
|
conv_name = _pick_display_name(crow, cu) if cu else ""
|
||||||
|
if cu and (conv_name == cu):
|
||||||
|
wd = str(wcdb_display_names.get(cu) or "").strip()
|
||||||
|
if wd and wd != cu:
|
||||||
|
conv_name = wd
|
||||||
h["conversationName"] = conv_name or cu
|
h["conversationName"] = conv_name or cu
|
||||||
conv_avatar = _pick_avatar_url(crow)
|
conv_avatar = _pick_avatar_url(crow)
|
||||||
if (not conv_avatar) and cu and (cu in local_avatar_usernames):
|
if (not conv_avatar) and cu and (cu in local_avatar_usernames):
|
||||||
conv_avatar = base_url + _build_avatar_url(account_dir.name, cu)
|
conv_avatar = base_url + _build_avatar_url(account_dir.name, cu)
|
||||||
|
if not conv_avatar and cu:
|
||||||
|
wa = str(wcdb_avatar_urls.get(cu) or "").strip()
|
||||||
|
if wa.lower().startswith(("http://", "https://")):
|
||||||
|
conv_avatar = wa
|
||||||
h["conversationAvatar"] = conv_avatar
|
h["conversationAvatar"] = conv_avatar
|
||||||
if su:
|
if su:
|
||||||
row = contact_rows.get(su)
|
row = contact_rows.get(su)
|
||||||
h["senderDisplayName"] = (
|
display_name = _pick_display_name(row, su) if row is not None else (conv_name if su == cu else su)
|
||||||
_pick_display_name(row, su) if row is not None else (conv_name if su == cu else su)
|
if display_name == su:
|
||||||
)
|
wd = str(wcdb_display_names.get(su) or "").strip()
|
||||||
|
if wd and wd != su:
|
||||||
|
display_name = wd
|
||||||
|
h["senderDisplayName"] = display_name
|
||||||
avatar_url = _pick_avatar_url(row)
|
avatar_url = _pick_avatar_url(row)
|
||||||
if (not avatar_url) and (su in local_avatar_usernames):
|
if (not avatar_url) and (su in local_avatar_usernames):
|
||||||
avatar_url = base_url + _build_avatar_url(account_dir.name, su)
|
avatar_url = base_url + _build_avatar_url(account_dir.name, su)
|
||||||
|
if not avatar_url:
|
||||||
|
wa = str(wcdb_avatar_urls.get(su) or "").strip()
|
||||||
|
if wa.lower().startswith(("http://", "https://")):
|
||||||
|
avatar_url = wa
|
||||||
h["senderAvatar"] = avatar_url
|
h["senderAvatar"] = avatar_url
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user