fix: prefer FN for WhatsApp contact cards (#622) (thanks @mahmoudashraf93)
This commit is contained in:
@@ -41,7 +41,7 @@
|
|||||||
- WhatsApp: improve "no active web listener" errors (include account + relink hint). (#612) — thanks @YuriNachos
|
- WhatsApp: improve "no active web listener" errors (include account + relink hint). (#612) — thanks @YuriNachos
|
||||||
- WhatsApp: add broadcast groups for multi-agent replies. (#547) — thanks @pasogott
|
- WhatsApp: add broadcast groups for multi-agent replies. (#547) — thanks @pasogott
|
||||||
- WhatsApp: resolve @lid inbound senders via auth-dir mapping fallback + shared resolver. (#365)
|
- WhatsApp: resolve @lid inbound senders via auth-dir mapping fallback + shared resolver. (#365)
|
||||||
- WhatsApp: treat shared contact cards as inbound messages. (#622) — thanks @mahmoudashraf93
|
- WhatsApp: treat shared contact cards as inbound messages (prefer vCard FN). (#622) — thanks @mahmoudashraf93
|
||||||
- iMessage: isolate group-ish threads by chat_id. (#535) — thanks @mdahmann
|
- iMessage: isolate group-ish threads by chat_id. (#535) — thanks @mdahmann
|
||||||
- Models: add OAuth expiry checks in doctor, expanded `models status` auth output (missing auth + `--check` exit codes). (#538) — thanks @latitudeki5223
|
- Models: add OAuth expiry checks in doctor, expanded `models status` auth output (missing auth + `--check` exit codes). (#538) — thanks @latitudeki5223
|
||||||
- Deps: bump Pi to 0.40.0 and drop pi-ai patch (upstream 429 fix). (#543) — thanks @mcinteerj
|
- Deps: bump Pi to 0.40.0 and drop pi-ai patch (upstream 429 fix). (#543) — thanks @mcinteerj
|
||||||
|
|||||||
@@ -44,6 +44,22 @@ describe("web inbound helpers", () => {
|
|||||||
expect(body).toBe("<contact: Ada Lovelace, +15555550123>");
|
expect(body).toBe("<contact: Ada Lovelace, +15555550123>");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("prefers FN over N in WhatsApp vcards", () => {
|
||||||
|
const body = extractText({
|
||||||
|
contactMessage: {
|
||||||
|
vcard: [
|
||||||
|
"BEGIN:VCARD",
|
||||||
|
"VERSION:3.0",
|
||||||
|
"N:Lovelace;Ada;;;",
|
||||||
|
"FN:Ada Lovelace",
|
||||||
|
"TEL;TYPE=CELL:+15555550123",
|
||||||
|
"END:VCARD",
|
||||||
|
].join("\n"),
|
||||||
|
},
|
||||||
|
} as unknown as import("@whiskeysockets/baileys").proto.IMessage);
|
||||||
|
expect(body).toBe("<contact: Ada Lovelace, +15555550123>");
|
||||||
|
});
|
||||||
|
|
||||||
it("extracts multiple WhatsApp contact cards", () => {
|
it("extracts multiple WhatsApp contact cards", () => {
|
||||||
const body = extractText({
|
const body = extractText({
|
||||||
contactsArrayMessage: {
|
contactsArrayMessage: {
|
||||||
|
|||||||
@@ -735,9 +735,7 @@ export function extractText(
|
|||||||
const contactPlaceholder =
|
const contactPlaceholder =
|
||||||
extractContactPlaceholder(message) ??
|
extractContactPlaceholder(message) ??
|
||||||
(extracted && extracted !== message
|
(extracted && extracted !== message
|
||||||
? extractContactPlaceholder(
|
? extractContactPlaceholder(extracted as proto.IMessage | undefined)
|
||||||
extracted as proto.IMessage | undefined,
|
|
||||||
)
|
|
||||||
: undefined);
|
: undefined);
|
||||||
if (contactPlaceholder) return contactPlaceholder;
|
if (contactPlaceholder) return contactPlaceholder;
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -791,12 +789,11 @@ function describeContact(input: {
|
|||||||
return { name, phone };
|
return { name, phone };
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseVcard(
|
function parseVcard(vcard?: string): { name?: string; phones: string[] } {
|
||||||
vcard?: string,
|
|
||||||
): { name?: string; phones: string[] } {
|
|
||||||
if (!vcard) return { phones: [] };
|
if (!vcard) return { phones: [] };
|
||||||
const lines = vcard.split(/\r?\n/);
|
const lines = vcard.split(/\r?\n/);
|
||||||
let name: string | undefined;
|
let nameFromN: string | undefined;
|
||||||
|
let nameFromFn: string | undefined;
|
||||||
const phones: string[] = [];
|
const phones: string[] = [];
|
||||||
for (const rawLine of lines) {
|
for (const rawLine of lines) {
|
||||||
const line = rawLine.trim();
|
const line = rawLine.trim();
|
||||||
@@ -808,15 +805,19 @@ function parseVcard(
|
|||||||
if (!rawValue) continue;
|
if (!rawValue) continue;
|
||||||
const value = cleanVcardValue(rawValue);
|
const value = cleanVcardValue(rawValue);
|
||||||
if (!value) continue;
|
if (!value) continue;
|
||||||
if ((key === "FN" || key === "N") && !name) {
|
if (key === "FN" && !nameFromFn) {
|
||||||
name = normalizeVcardName(value);
|
nameFromFn = normalizeVcardName(value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (key === "N" && !nameFromN) {
|
||||||
|
nameFromN = normalizeVcardName(value);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (key.startsWith("TEL") || key.includes(".TEL")) {
|
if (key.startsWith("TEL") || key.includes(".TEL")) {
|
||||||
phones.push(value);
|
phones.push(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { name, phones };
|
return { name: nameFromFn ?? nameFromN, phones };
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanVcardValue(value: string): string {
|
function cleanVcardValue(value: string): string {
|
||||||
@@ -832,8 +833,8 @@ function normalizeVcardName(value: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formatContactPlaceholder(name?: string, phone?: string): string {
|
function formatContactPlaceholder(name?: string, phone?: string): string {
|
||||||
const parts = [name, phone].filter(
|
const parts = [name, phone].filter((value): value is string =>
|
||||||
(value): value is string => Boolean(value),
|
Boolean(value),
|
||||||
);
|
);
|
||||||
if (parts.length === 0) return "<contact>";
|
if (parts.length === 0) return "<contact>";
|
||||||
return `<contact: ${parts.join(", ")}>`;
|
return `<contact: ${parts.join(", ")}>`;
|
||||||
|
|||||||
Reference in New Issue
Block a user