Implement contact matching

This commit is contained in:
2026-02-15 23:48:32 +00:00
parent 1e83c800f8
commit d9491ae817
12 changed files with 667 additions and 46 deletions

View File

@@ -262,8 +262,13 @@ class WhatsAppClient(ClientBase):
)
if connected_value:
self._connected = True
account = await self._resolve_account_identifier()
account_list = [account] if account else list(self._accounts or [])
if not account_list:
account_list = [self.client_name]
self._publish_state(
connected=True,
accounts=account_list,
pair_status="connected",
last_event="connected_probe",
connected_at=now_ts,
@@ -442,6 +447,12 @@ class WhatsAppClient(ClientBase):
async def on_connected(client, event: connected_ev):
self._connected = True
account = await self._resolve_account_identifier()
if account:
self._remember_contact(
account,
jid=account,
name="Linked Account",
)
self._publish_state(
connected=True,
warning="",
@@ -502,6 +513,12 @@ class WhatsAppClient(ClientBase):
status_text = str(status_raw or "").strip().lower()
if status_text in {"2", "success"}:
account = await self._resolve_account_identifier()
if account:
self._remember_contact(
account,
jid=account,
name="Linked Account",
)
self._connected = True
self._publish_state(
connected=True,
@@ -640,6 +657,35 @@ class WhatsAppClient(ClientBase):
out.add(f"+{digits}")
return out
def _remember_contact(self, identifier, *, jid="", name="", chat=""):
cleaned = str(identifier or "").strip()
if not cleaned:
return
state = transport.get_runtime_state(self.service)
existing = state.get("contacts") or []
rows = [item for item in existing if isinstance(item, dict)]
merged = []
seen = set()
now_ts = int(time.time())
row = {
"identifier": cleaned,
"jid": str(jid or "").strip(),
"name": str(name or "").strip(),
"chat": str(chat or "").strip(),
"seen_at": now_ts,
}
merged.append(row)
seen.add(cleaned)
for item in rows:
candidate = str(item.get("identifier") or item.get("jid") or "").strip()
if not candidate or candidate in seen:
continue
seen.add(candidate)
merged.append(item)
if len(merged) >= 500:
break
self._publish_state(contacts=merged, last_contact_seen_at=now_ts)
def _jid_to_identifier(self, value):
raw = str(value or "").strip()
if not raw:
@@ -761,6 +807,11 @@ class WhatsAppClient(ClientBase):
or self._pluck(event, "timestamp")
)
ts = self._normalize_timestamp(raw_ts)
self._remember_contact(
sender or chat,
jid=sender,
chat=chat,
)
identifier_values = self._normalize_identifier_candidates(sender, chat)
if not identifier_values:
@@ -853,6 +904,11 @@ class WhatsAppClient(ClientBase):
or int(time.time() * 1000)
)
receipt_type = str(self._pluck(event, "Type") or "").strip()
self._remember_contact(
sender or chat,
jid=sender,
chat=chat,
)
for candidate in self._normalize_identifier_candidates(sender, chat):
await self.ur.message_read(
@@ -885,6 +941,11 @@ class WhatsAppClient(ClientBase):
state = self._pluck(event, "State") or self._pluck(event, "state")
state_text = str(state or "").strip().lower()
is_typing = state_text in {"1", "composing", "chat_presence_composing"}
self._remember_contact(
sender or chat,
jid=sender,
chat=chat,
)
for candidate in self._normalize_identifier_candidates(sender, chat):
if is_typing:
@@ -908,6 +969,7 @@ class WhatsAppClient(ClientBase):
is_unavailable = bool(
self._pluck(event, "Unavailable") or self._pluck(event, "unavailable")
)
self._remember_contact(sender, jid=sender)
for candidate in self._normalize_identifier_candidates(sender):
if is_unavailable: