fix(bot): explicit assertSessions before group send

groupMetadata alone wasn't enough — Baileys won't establish individual
libsignal sessions lazily during sendMessage, so the first send to a
freshly-paired group fails per-participant. Cast to the internal
assertSessions(jids, force=true) and call it on every participant before
attempting to send.
This commit is contained in:
yiekheng 2026-05-09 16:50:51 +08:00
parent 99cece16c0
commit 2fdcdb6202

View File

@ -1,19 +1,33 @@
import type { WASocket } from "@whiskeysockets/baileys";
// Internal Baileys method used to fetch pre-key bundles and establish individual
// libsignal sessions for a list of JIDs. Not part of the public type, but it's
// the only way to avoid "No sessions" on the first group send after pairing.
type SocketWithAssertSessions = WASocket & {
assertSessions?: (jids: string[], force: boolean) => Promise<boolean>;
};
async function ensureSessionsForGroup(socket: WASocket, groupJid: string): Promise<void> {
const metadata = await socket.groupMetadata(groupJid);
const participantJids = metadata.participants.map((p) => p.id);
const internal = socket as SocketWithAssertSessions;
if (typeof internal.assertSessions === "function") {
await internal.assertSessions(participantJids, true);
}
}
export async function sendTextToGroup(
socket: WASocket,
groupJid: string,
text: string,
): Promise<{ messageId: string | undefined }> {
// Force-fetch group metadata so Baileys populates its internal participant
// map and triggers libsignal session establishment for any unknown member.
// Without this, the first send to a freshly-paired group fails with
// "No sessions" from libsignal-node.
// Establish individual signal sessions with every participant before sending
// — group sends fan out per participant and need a per-participant session,
// but Baileys won't establish them lazily inside sendMessage.
try {
await socket.groupMetadata(groupJid);
await ensureSessionsForGroup(socket, groupJid);
} catch {
// If metadata fetch itself fails we still try the send — sendMessage will
// surface a clearer error than the metadata layer.
// Non-fatal: fall through and let sendMessage surface its error
}
try {
@ -24,7 +38,12 @@ export async function sendTextToGroup(
// once after a brief delay before giving up.
const message = (err as Error)?.message ?? "";
if (message.includes("No sessions")) {
await new Promise((resolve) => setTimeout(resolve, 1500));
await new Promise((resolve) => setTimeout(resolve, 2000));
try {
await ensureSessionsForGroup(socket, groupJid);
} catch {
// ignore
}
const result = await socket.sendMessage(groupJid, { text });
return { messageId: result?.key?.id ?? undefined };
}