diff --git a/extensions/whatsapp/src/inbound/outbound-mentions.test.ts b/extensions/whatsapp/src/inbound/outbound-mentions.test.ts index 88d0b31a01bd..57746827df81 100644 --- a/extensions/whatsapp/src/inbound/outbound-mentions.test.ts +++ b/extensions/whatsapp/src/inbound/outbound-mentions.test.ts @@ -16,11 +16,25 @@ describe("resolveWhatsAppOutboundMentions", () => { }); }); - it("rewrites phone-number tokens to LID mention text without device suffixes", () => { + it.each([ + { text: "ping @+5511976136970", expected: "ping @277038292303944" }, + { + text: "literal \\` ping @+5511976136970", + expected: "literal \\` ping @277038292303944", + }, + { + text: "literal \\\\\\` ping @+5511976136970", + expected: "literal \\\\\\` ping @277038292303944", + }, + { + text: "inside ``notify ` @+5511976136970`` then @+5511976136970", + expected: "inside ``notify ` @+5511976136970`` then @277038292303944", + }, + ])("rewrites visible phone-number mentions to LIDs: $text", ({ text, expected }) => { expect( resolveWhatsAppOutboundMentions({ chatJid: "120363000000000000@g.us", - text: "ping @+5511976136970", + text, participants: [ { id: "277038292303944:2@lid", @@ -29,7 +43,7 @@ describe("resolveWhatsAppOutboundMentions", () => { ], }), ).toEqual({ - text: "ping @277038292303944", + text: expected, mentionedJids: ["277038292303944@lid"], }); }); @@ -115,6 +129,30 @@ describe("resolveWhatsAppOutboundMentions", () => { }); }); + it.each([ + "Run `notify @+5511976136970", + "Run `notify\n@+5511976136970", + "Run ``notify ` @+5511976136970", + "Run ``notify ` @+5511976136970``", + "literal \\\\` inside @+5511976136970", + ])( + "does not rewrite or mention phone numbers inside balanced or unterminated inline code: %j", + (text) => { + expect( + resolveWhatsAppOutboundMentions({ + chatJid: "120363000000000000@g.us", + text, + participants: [ + { + id: "277038292303944@lid", + phoneNumber: "5511976136970@s.whatsapp.net", + }, + ], + }), + ).toEqual({ text, mentionedJids: [] }); + }, + ); + it("does not mention numeric prefixes inside longer tokens", () => { expect( resolveWhatsAppOutboundMentions({ diff --git a/extensions/whatsapp/src/inbound/outbound-mentions.ts b/extensions/whatsapp/src/inbound/outbound-mentions.ts index 680de06087e4..1ce85cdc9648 100644 --- a/extensions/whatsapp/src/inbound/outbound-mentions.ts +++ b/extensions/whatsapp/src/inbound/outbound-mentions.ts @@ -16,7 +16,7 @@ export type WhatsAppOutboundMentionResolution = { }; const CODE_FENCE_RE = /```[\s\S]*?```/g; -const INLINE_CODE_RE = /`[^`\n]+`/g; +const INLINE_CODE_RE = /(?<=(?:^|[^\\])(?:\\\\)*)(`+)[\s\S]*?(?:(? { }); }); + it.each([ + { messageText: "Run `notify @15551234567" }, + { messageText: "Run `notify\n@15551234567" }, + { messageText: "Run ``notify ` @15551234567" }, + { messageText: "literal \\` ping @15551234567", nativeMention: true }, + { messageText: "literal \\\\` inside @15551234567" }, + ])( + "only sends native mentions for visible phone numbers outside inline code: $messageText", + async ({ messageText, nativeMention }) => { + api = createWebSendApi({ + sock: { sendMessage, sendPresenceUpdate }, + defaultAccountId: "main", + resolveOutboundMentions: ({ jid, text }) => + resolveWhatsAppOutboundMentions({ + chatJid: jid, + text, + participants: [{ id: "15551234567@s.whatsapp.net" }], + }), + }); + + await api.sendMessage("120363000000000000@g.us", markdownToWhatsApp(messageText)); + + expect(sendMessage).toHaveBeenCalledWith("120363000000000000@g.us", { + text: messageText, + ...(nativeMention ? { mentions: ["15551234567@s.whatsapp.net"] } : {}), + }); + }, + ); + it("supports image media with caption", async () => { const payload = Buffer.from("img"); await api.sendMessage("+1555", "cap", payload, "image/jpeg");