mirror of
https://github.com/moltbot/moltbot.git
synced 2026-05-13 23:56:07 +00:00
fix: hydrate WhatsApp participating groups on connect (#58007) (thanks @neeravmakwana)
* Web: hydrate participating groups on connect * Web: avoid blocking inbox listeners during group hydration
This commit is contained in:
@@ -100,6 +100,7 @@ vi.mock("./session.js", async () => {
|
||||
sendPresenceUpdate: vi.fn().mockResolvedValue(undefined),
|
||||
sendMessage: vi.fn().mockResolvedValue(undefined),
|
||||
readMessages: vi.fn().mockResolvedValue(undefined),
|
||||
groupFetchAllParticipating: vi.fn().mockResolvedValue({}),
|
||||
updateMediaMessage: vi.fn(),
|
||||
logger: {},
|
||||
user: { id: "me@s.whatsapp.net" },
|
||||
|
||||
@@ -531,6 +531,20 @@ export async function monitorWebInbox(options: {
|
||||
handleConnectionUpdate as unknown as (...args: unknown[]) => void,
|
||||
);
|
||||
|
||||
void (async () => {
|
||||
try {
|
||||
const groups = await sock.groupFetchAllParticipating();
|
||||
if (shouldLogVerbose()) {
|
||||
logVerbose(`Hydrated ${Object.keys(groups ?? {}).length} participating groups on connect`);
|
||||
}
|
||||
} catch (err) {
|
||||
const error = String(err);
|
||||
inboundLogger.warn({ error }, "failed hydrating participating groups on connect");
|
||||
inboundConsoleLog.warn(`Failed hydrating participating groups on connect: ${error}`);
|
||||
logVerbose(`Failed to hydrate participating groups on connect: ${error}`);
|
||||
}
|
||||
})();
|
||||
|
||||
const sendApi = createWebSendApi({
|
||||
sock: {
|
||||
sendMessage: (jid: string, content: AnyMessageContent) => sendTrackedMessage(jid, content),
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
InboxOnMessage,
|
||||
buildNotifyMessageUpsert,
|
||||
getAuthDir,
|
||||
getSock,
|
||||
installWebMonitorInboxUnitTestHooks,
|
||||
startInboxMonitor,
|
||||
waitForMessageCalls,
|
||||
@@ -126,6 +127,54 @@ describe("web monitor inbox", () => {
|
||||
await listener.close();
|
||||
});
|
||||
|
||||
it("hydrates participating groups once after connect", async () => {
|
||||
const { listener, sock } = await startInboxMonitor(vi.fn(async () => {}) as InboxOnMessage);
|
||||
|
||||
expect(sock.groupFetchAllParticipating).toHaveBeenCalledTimes(1);
|
||||
|
||||
await listener.close();
|
||||
});
|
||||
|
||||
it("continues when group hydration fails on connect", async () => {
|
||||
const sock = getSock();
|
||||
sock.groupFetchAllParticipating.mockRejectedValueOnce(new Error("no groups"));
|
||||
|
||||
const { listener } = await startInboxMonitor(vi.fn(async () => {}) as InboxOnMessage);
|
||||
|
||||
expect(sock.groupFetchAllParticipating).toHaveBeenCalledTimes(1);
|
||||
expect(sock.sendPresenceUpdate).toHaveBeenCalledWith("available");
|
||||
|
||||
await listener.close();
|
||||
});
|
||||
|
||||
it("does not block inbound listeners while group hydration is pending", async () => {
|
||||
let resolveHydration!: () => void;
|
||||
const sock = getSock();
|
||||
const pendingHydration = new Promise<Record<string, never>>((resolve) => {
|
||||
resolveHydration = () => resolve({});
|
||||
});
|
||||
sock.groupFetchAllParticipating.mockImplementationOnce(() => pendingHydration);
|
||||
const onMessage = vi.fn(async () => {
|
||||
return;
|
||||
});
|
||||
|
||||
const { listener } = await startInboxMonitor(onMessage as InboxOnMessage);
|
||||
sock.ev.emit(
|
||||
"messages.upsert",
|
||||
buildNotifyMessageUpsert({
|
||||
id: nextMessageId("pending-hydration"),
|
||||
remoteJid: "999@s.whatsapp.net",
|
||||
text: "ping",
|
||||
timestamp: 1_700_000_000,
|
||||
pushName: "Tester",
|
||||
}),
|
||||
);
|
||||
await waitForMessageCalls(onMessage, 1);
|
||||
|
||||
resolveHydration();
|
||||
await listener.close();
|
||||
});
|
||||
|
||||
it("deduplicates redelivered messages by id", async () => {
|
||||
const onMessage = vi.fn(async () => {
|
||||
return;
|
||||
|
||||
@@ -39,6 +39,7 @@ export type MockSock = {
|
||||
sendPresenceUpdate: AnyMockFn;
|
||||
sendMessage: AnyMockFn;
|
||||
readMessages: AnyMockFn;
|
||||
groupFetchAllParticipating: AnyMockFn;
|
||||
updateMediaMessage: AnyMockFn;
|
||||
logger: Record<string, unknown>;
|
||||
signalRepository: {
|
||||
@@ -65,6 +66,7 @@ function createMockSock(): MockSock {
|
||||
sendPresenceUpdate: createResolvedMock(),
|
||||
sendMessage: createResolvedMock(),
|
||||
readMessages: createResolvedMock(),
|
||||
groupFetchAllParticipating: vi.fn().mockResolvedValue({}),
|
||||
updateMediaMessage: vi.fn(),
|
||||
logger: {},
|
||||
signalRepository: {
|
||||
|
||||
@@ -21,6 +21,7 @@ export type MockBaileysSocket = {
|
||||
sendPresenceUpdate: ReturnType<typeof vi.fn>;
|
||||
sendMessage: ReturnType<typeof vi.fn>;
|
||||
readMessages: ReturnType<typeof vi.fn>;
|
||||
groupFetchAllParticipating: ReturnType<typeof vi.fn>;
|
||||
user?: { id?: string };
|
||||
};
|
||||
|
||||
@@ -138,6 +139,7 @@ export function createMockBaileys(): {
|
||||
sendPresenceUpdate: vi.fn().mockResolvedValue(undefined),
|
||||
sendMessage: vi.fn().mockResolvedValue({ key: { id: "msg123" } }),
|
||||
readMessages: vi.fn().mockResolvedValue(undefined),
|
||||
groupFetchAllParticipating: vi.fn().mockResolvedValue({}),
|
||||
user: { id: "123@s.whatsapp.net" },
|
||||
};
|
||||
setImmediate(() => ev.emit("connection.update", { connection: "open" }));
|
||||
|
||||
Reference in New Issue
Block a user