web: send read receipts for inbound messages

This commit is contained in:
Peter Steinberger
2025-11-25 06:36:22 +01:00
parent 716f31f17a
commit a331bd5ea1
3 changed files with 60 additions and 0 deletions

View File

@@ -171,6 +171,9 @@ describe("provider-web", () => {
expect(onMessage).toHaveBeenCalledWith(
expect.objectContaining({ body: "ping", from: "+999", to: "+123" }),
);
expect(sock.readMessages).toHaveBeenCalledWith([
{ remoteJid: "999@s.whatsapp.net", id: "abc", participant: undefined, fromMe: false },
]);
expect(sock.sendPresenceUpdate).toHaveBeenCalledWith(
"composing",
"999@s.whatsapp.net",
@@ -207,6 +210,47 @@ describe("provider-web", () => {
mediaType: "image/jpeg",
}),
);
expect(sock.readMessages).toHaveBeenCalledWith([
{
remoteJid: "888@s.whatsapp.net",
id: "med1",
participant: undefined,
fromMe: false,
},
]);
await listener.close();
});
it("monitorWebInbox includes participant when marking group messages read", async () => {
const onMessage = vi.fn();
const listener = await monitorWebInbox({ verbose: false, onMessage });
const sock = getLastSocket();
const upsert = {
type: "notify",
messages: [
{
key: {
id: "grp1",
fromMe: false,
remoteJid: "12345-67890@g.us",
participant: "111@s.whatsapp.net",
},
message: { conversation: "group ping" },
},
],
};
sock.ev.emit("messages.upsert", upsert);
await new Promise((resolve) => setImmediate(resolve));
expect(sock.readMessages).toHaveBeenCalledWith([
{
remoteJid: "12345-67890@g.us",
id: "grp1",
participant: "111@s.whatsapp.net",
fromMe: false,
},
]);
await listener.close();
});

View File

@@ -260,6 +260,20 @@ export async function monitorWebInbox(options: {
// Ignore status/broadcast traffic; we only care about direct chats.
if (remoteJid.endsWith("@status") || remoteJid.endsWith("@broadcast"))
continue;
if (id) {
const participant = msg.key?.participant;
try {
await sock.readMessages([
{ remoteJid, id, participant, fromMe: false },
]);
if (isVerbose()) {
const suffix = participant ? ` (participant ${participant})` : "";
logVerbose(`Marked message ${id} as read for ${remoteJid}${suffix}`);
}
} catch (err) {
logVerbose(`Failed to mark message ${id} read: ${String(err)}`);
}
}
const from = jidToE164(remoteJid);
if (!from) continue;
let body = extractText(msg.message ?? undefined);

View File

@@ -5,6 +5,7 @@ export type MockBaileysSocket = {
ws: { close: ReturnType<typeof vi.fn> };
sendPresenceUpdate: ReturnType<typeof vi.fn>;
sendMessage: ReturnType<typeof vi.fn>;
readMessages: ReturnType<typeof vi.fn>;
user?: { id?: string };
};
@@ -28,6 +29,7 @@ export function createMockBaileys(): { mod: MockBaileysModule; lastSocket: () =>
ws: { close: vi.fn() },
sendPresenceUpdate: vi.fn().mockResolvedValue(undefined),
sendMessage: vi.fn().mockResolvedValue({ key: { id: "msg123" } }),
readMessages: vi.fn().mockResolvedValue(undefined),
user: { id: "123@s.whatsapp.net" },
};
setImmediate(() => ev.emit("connection.update", { connection: "open" }));