fix(whatsapp): resolve lid mappings for inbound

This commit is contained in:
Peter Steinberger
2026-01-09 21:46:11 +01:00
parent 5fa26bfec7
commit a5065b354e
5 changed files with 208 additions and 38 deletions

View File

@@ -30,6 +30,7 @@ import {
isSelfChatMode,
jidToE164,
normalizeE164,
resolveJidToE164,
toWhatsappJid,
} from "../utils.js";
import { resolveWhatsAppAccount } from "./accounts.js";
@@ -123,23 +124,10 @@ export async function monitorWebInbox(options: {
const GROUP_META_TTL_MS = 5 * 60 * 1000; // 5 minutes
const lidLookup = sock.signalRepository?.lidMapping;
const resolveJidToE164 = async (
const resolveInboundJid = async (
jid: string | null | undefined,
): Promise<string | null> => {
if (!jid) return null;
const direct = jidToE164(jid);
if (direct) return direct;
if (!/(@lid|@hosted\.lid)$/.test(jid)) return null;
if (!lidLookup?.getPNForLID) return null;
try {
const pnJid = await lidLookup.getPNForLID(jid);
if (!pnJid) return null;
return jidToE164(pnJid);
} catch (err) {
logVerbose(`LID mapping lookup failed for ${jid}: ${String(err)}`);
return null;
}
};
): Promise<string | null> =>
resolveJidToE164(jid, { authDir: options.authDir, lidLookup });
const getGroupMeta = async (jid: string) => {
const cached = groupMetaCache.get(jid);
@@ -150,7 +138,7 @@ export async function monitorWebInbox(options: {
(
await Promise.all(
meta.participants?.map(async (p) => {
const mapped = await resolveJidToE164(p.id);
const mapped = await resolveInboundJid(p.id);
return mapped ?? p.id;
}) ?? [],
)
@@ -191,12 +179,12 @@ export async function monitorWebInbox(options: {
continue;
const group = isJidGroup(remoteJid);
const participantJid = msg.key?.participant ?? undefined;
const from = group ? remoteJid : await resolveJidToE164(remoteJid);
const from = group ? remoteJid : await resolveInboundJid(remoteJid);
// Skip if we still can't resolve an id to key conversation
if (!from) continue;
const senderE164 = group
? participantJid
? await resolveJidToE164(participantJid)
? await resolveInboundJid(participantJid)
: null
: from;
let groupSubject: string | undefined;

View File

@@ -78,6 +78,9 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { resetLogger, setLoggerOverride } from "../logging.js";
import { monitorWebInbox } from "./inbound.js";
const ACCOUNT_ID = "default";
let authDir: string;
describe("web monitor inbox", () => {
beforeEach(() => {
vi.clearAllMocks();
@@ -86,12 +89,14 @@ describe("web monitor inbox", () => {
code: "PAIRCODE",
created: true,
});
authDir = fsSync.mkdtempSync(path.join(os.tmpdir(), "clawdbot-auth-"));
});
afterEach(() => {
resetLogger();
setLoggerOverride(null);
vi.useRealTimers();
fsSync.rmSync(authDir, { recursive: true, force: true });
});
it("streams inbound messages", async () => {
@@ -100,7 +105,12 @@ describe("web monitor inbox", () => {
await msg.reply("pong");
});
const listener = await monitorWebInbox({ verbose: false, onMessage });
const listener = await monitorWebInbox({
verbose: false,
onMessage,
accountId: ACCOUNT_ID,
authDir,
});
const sock = await createWaSocket();
expect(sock.sendPresenceUpdate).toHaveBeenCalledWith("available");
const upsert = {
@@ -146,7 +156,12 @@ describe("web monitor inbox", () => {
return;
});
const listener = await monitorWebInbox({ verbose: false, onMessage });
const listener = await monitorWebInbox({
verbose: false,
onMessage,
accountId: ACCOUNT_ID,
authDir,
});
const sock = await createWaSocket();
const getPNForLID = vi.spyOn(
sock.signalRepository.lidMapping,
@@ -178,12 +193,60 @@ describe("web monitor inbox", () => {
await listener.close();
});
it("resolves LID JIDs via authDir mapping files", async () => {
const onMessage = vi.fn(async () => {
return;
});
fsSync.writeFileSync(
path.join(authDir, "lid-mapping-555_reverse.json"),
JSON.stringify("1555"),
);
const listener = await monitorWebInbox({
verbose: false,
onMessage,
accountId: ACCOUNT_ID,
authDir,
});
const sock = await createWaSocket();
const getPNForLID = vi.spyOn(
sock.signalRepository.lidMapping,
"getPNForLID",
);
const upsert = {
type: "notify",
messages: [
{
key: { id: "abc", fromMe: false, remoteJid: "555@lid" },
message: { conversation: "ping" },
messageTimestamp: 1_700_000_000,
pushName: "Tester",
},
],
};
sock.ev.emit("messages.upsert", upsert);
await new Promise((resolve) => setImmediate(resolve));
expect(onMessage).toHaveBeenCalledWith(
expect.objectContaining({ body: "ping", from: "+1555", to: "+123" }),
);
expect(getPNForLID).not.toHaveBeenCalled();
await listener.close();
});
it("resolves group participant LID JIDs via Baileys mapping", async () => {
const onMessage = vi.fn(async () => {
return;
});
const listener = await monitorWebInbox({ verbose: false, onMessage });
const listener = await monitorWebInbox({
verbose: false,
onMessage,
accountId: ACCOUNT_ID,
authDir,
});
const sock = await createWaSocket();
const getPNForLID = vi.spyOn(
sock.signalRepository.lidMapping,
@@ -234,7 +297,12 @@ describe("web monitor inbox", () => {
}
});
const listener = await monitorWebInbox({ verbose: false, onMessage });
const listener = await monitorWebInbox({
verbose: false,
onMessage,
accountId: ACCOUNT_ID,
authDir,
});
const sock = await createWaSocket();
const upsert = {
type: "notify",