mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-20 21:23:23 +00:00
fix(whatsapp): restore implicit reply mentions for LID identities (#48494)
Threads selfLid from the Baileys socket through the inbound WhatsApp pipeline and adds LID-format matching to the implicit mention check in group gating, so reply-to-bot detection works when WhatsApp sends the quoted sender in @lid format. Also fixes the device-suffix stripping regex (was a silent no-op). Closes #23029 Co-authored-by: sparkyrider <sparkyrider@users.noreply.github.com> Reviewed-by: @ademczuk
This commit is contained in:
@@ -183,6 +183,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Auth/login lockout recovery: clear stale `auth_permanent` and `billing` disabled state for all profiles matching the target provider when `openclaw models auth login` is invoked, so users locked out by expired or revoked OAuth tokens can recover by re-authenticating instead of waiting for the cooldown timer to expire. (#43057)
|
||||
- Auto-reply/context-engine compaction: persist the exact embedded-run metadata compaction count for main and followup runner session accounting, so metadata-only auto-compactions no longer undercount multi-compaction runs. (#42629) thanks @uf-hy.
|
||||
- Auth/Codex CLI reuse: sync reused Codex CLI credentials into the supported `openai-codex:default` OAuth profile instead of reviving the deprecated `openai-codex:codex-cli` slot, so doctor cleanup no longer loops. (#45353) thanks @Gugu-sugar.
|
||||
- WhatsApp/group replies: recognize implicit reply-to-bot mentions when WhatsApp sends the quoted sender in `@lid` format, including device-suffixed self identities. (#23029) Thanks @sparkyrider.
|
||||
|
||||
## 2026.3.12
|
||||
|
||||
|
||||
@@ -127,14 +127,17 @@ export function applyGroupGating(params: ApplyGroupGatingParams) {
|
||||
conversationId: params.conversationId,
|
||||
});
|
||||
const requireMention = activation !== "always";
|
||||
const selfJid = params.msg.selfJid?.replace(/:\\d+/, "");
|
||||
const replySenderJid = params.msg.replyToSenderJid?.replace(/:\\d+/, "");
|
||||
const selfJid = params.msg.selfJid?.replace(/:\d+/, "");
|
||||
const selfLid = params.msg.selfLid?.replace(/:\d+/, "");
|
||||
// replyToSenderJid may carry either a standard JID or an @lid identifier.
|
||||
const replySenderJid = params.msg.replyToSenderJid?.replace(/:\d+/, "");
|
||||
const selfE164 = params.msg.selfE164 ? normalizeE164(params.msg.selfE164) : null;
|
||||
const replySenderE164 = params.msg.replyToSenderE164
|
||||
? normalizeE164(params.msg.replyToSenderE164)
|
||||
: null;
|
||||
const implicitMention = Boolean(
|
||||
(selfJid && replySenderJid && selfJid === replySenderJid) ||
|
||||
(selfLid && replySenderJid && selfLid === replySenderJid) ||
|
||||
(selfE164 && replySenderE164 && selfE164 === replySenderE164),
|
||||
);
|
||||
const mentionGate = resolveMentionGating({
|
||||
|
||||
@@ -112,7 +112,7 @@ describe("applyGroupGating", () => {
|
||||
accountId: "default",
|
||||
body: "following up",
|
||||
timestamp: Date.now(),
|
||||
selfJid: "15551234567@s.whatsapp.net",
|
||||
selfJid: "15551234567:1@s.whatsapp.net",
|
||||
selfE164: "+15551234567",
|
||||
replyToId: "m0",
|
||||
replyToBody: "bot said hi",
|
||||
@@ -125,6 +125,29 @@ describe("applyGroupGating", () => {
|
||||
expect(result.shouldProcess).toBe(true);
|
||||
});
|
||||
|
||||
it("treats LID-format reply-to-bot as implicit mention", () => {
|
||||
const cfg = makeConfig({});
|
||||
const { result } = runGroupGating({
|
||||
cfg,
|
||||
msg: createGroupMessage({
|
||||
id: "m1-lid",
|
||||
to: "+15550000",
|
||||
accountId: "default",
|
||||
body: "following up",
|
||||
timestamp: Date.now(),
|
||||
selfJid: "15551234567@s.whatsapp.net",
|
||||
selfLid: "1234567890123:1@lid",
|
||||
selfE164: "+15551234567",
|
||||
replyToId: "m0",
|
||||
replyToBody: "bot said hi",
|
||||
replyToSender: "1234567890123@lid",
|
||||
replyToSenderJid: "1234567890123@lid",
|
||||
}),
|
||||
});
|
||||
|
||||
expect(result.shouldProcess).toBe(true);
|
||||
});
|
||||
|
||||
it.each([
|
||||
{ id: "g-new", command: "/new" },
|
||||
{ id: "g-status", command: "/status" },
|
||||
|
||||
@@ -66,6 +66,7 @@ export async function monitorWebInbox(options: {
|
||||
}
|
||||
|
||||
const selfJid = sock.user?.id;
|
||||
const selfLid = sock.user?.lid;
|
||||
const selfE164 = selfJid ? jidToE164(selfJid) : null;
|
||||
const debouncer = createInboundDebouncer<WebInboundMessage>({
|
||||
debounceMs: options.debounceMs ?? 0,
|
||||
@@ -372,6 +373,7 @@ export async function monitorWebInbox(options: {
|
||||
groupParticipants: inbound.groupParticipants,
|
||||
mentionedJids: mentionedJids ?? undefined,
|
||||
selfJid,
|
||||
selfLid,
|
||||
selfE164,
|
||||
fromMe: Boolean(msg.key?.fromMe),
|
||||
location: enriched.location ?? undefined,
|
||||
|
||||
@@ -30,6 +30,7 @@ export type WebInboundMessage = {
|
||||
groupParticipants?: string[];
|
||||
mentionedJids?: string[];
|
||||
selfJid?: string | null;
|
||||
selfLid?: string | null;
|
||||
selfE164?: string | null;
|
||||
fromMe?: boolean;
|
||||
location?: NormalizedLocation;
|
||||
|
||||
@@ -118,7 +118,12 @@ describe("web monitor inbox", () => {
|
||||
await tick();
|
||||
|
||||
expect(onMessage).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ body: "ping", from: "+999", to: "+123" }),
|
||||
expect.objectContaining({
|
||||
body: "ping",
|
||||
from: "+999",
|
||||
to: "+123",
|
||||
selfLid: "123:1@lid",
|
||||
}),
|
||||
);
|
||||
expect(sock.readMessages).toHaveBeenCalledWith([
|
||||
{
|
||||
@@ -181,7 +186,12 @@ describe("web monitor inbox", () => {
|
||||
|
||||
expect(getPNForLID).toHaveBeenCalledWith("999@lid");
|
||||
expect(onMessage).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ body: "ping", from: "+999", to: "+123" }),
|
||||
expect.objectContaining({
|
||||
body: "ping",
|
||||
from: "+999",
|
||||
to: "+123",
|
||||
selfLid: "123:1@lid",
|
||||
}),
|
||||
);
|
||||
|
||||
await listener.close();
|
||||
|
||||
@@ -44,7 +44,7 @@ export type MockSock = {
|
||||
getPNForLID: AnyMockFn;
|
||||
};
|
||||
};
|
||||
user: { id: string };
|
||||
user: { id: string; lid?: string };
|
||||
};
|
||||
|
||||
function createResolvedMock() {
|
||||
@@ -66,7 +66,7 @@ function createMockSock(): MockSock {
|
||||
getPNForLID: vi.fn().mockResolvedValue(null),
|
||||
},
|
||||
},
|
||||
user: { id: "123@s.whatsapp.net" },
|
||||
user: { id: "123@s.whatsapp.net", lid: "123:1@lid" },
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user