feat(bot): add Baileys session wrapper
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
dd1eb711df
commit
fc05a8b459
74
apps/bot/src/whatsapp/session.ts
Normal file
74
apps/bot/src/whatsapp/session.ts
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import { mkdir } from "node:fs/promises";
|
||||||
|
import { join } from "node:path";
|
||||||
|
import {
|
||||||
|
makeWASocket,
|
||||||
|
useMultiFileAuthState,
|
||||||
|
type WASocket,
|
||||||
|
type ConnectionState,
|
||||||
|
DisconnectReason,
|
||||||
|
Browsers,
|
||||||
|
} from "@whiskeysockets/baileys";
|
||||||
|
import { logger } from "../logger.js";
|
||||||
|
import { env } from "../env.js";
|
||||||
|
|
||||||
|
export type SessionEvent =
|
||||||
|
| { type: "qr"; payload: string }
|
||||||
|
| { type: "open"; phoneNumber: string | undefined }
|
||||||
|
| { type: "close"; reason: number; loggedOut: boolean };
|
||||||
|
|
||||||
|
export type SessionEventHandler = (event: SessionEvent) => void | Promise<void>;
|
||||||
|
|
||||||
|
export type Session = {
|
||||||
|
accountId: string;
|
||||||
|
socket: WASocket;
|
||||||
|
close: () => Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function startSession(params: {
|
||||||
|
accountId: string;
|
||||||
|
onEvent: SessionEventHandler;
|
||||||
|
}): Promise<Session> {
|
||||||
|
const { accountId, onEvent } = params;
|
||||||
|
const sessionDir = join(env.SESSIONS_DIR, accountId);
|
||||||
|
await mkdir(sessionDir, { recursive: true });
|
||||||
|
|
||||||
|
const { state, saveCreds } = await useMultiFileAuthState(sessionDir);
|
||||||
|
|
||||||
|
const socket = makeWASocket({
|
||||||
|
auth: state,
|
||||||
|
printQRInTerminal: false,
|
||||||
|
browser: Browsers.macOS("Safari"),
|
||||||
|
syncFullHistory: false,
|
||||||
|
logger: logger.child({ accountId, component: "baileys" }) as never,
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.ev.on("creds.update", () => void saveCreds());
|
||||||
|
|
||||||
|
socket.ev.on("connection.update", (update: Partial<ConnectionState>) => {
|
||||||
|
if (update.qr) {
|
||||||
|
void onEvent({ type: "qr", payload: update.qr });
|
||||||
|
}
|
||||||
|
if (update.connection === "open") {
|
||||||
|
const phoneNumber = socket.user?.id?.split(":")[0];
|
||||||
|
void onEvent({ type: "open", phoneNumber });
|
||||||
|
}
|
||||||
|
if (update.connection === "close") {
|
||||||
|
const reason =
|
||||||
|
(update.lastDisconnect?.error as { output?: { statusCode?: number } } | undefined)?.output?.statusCode ?? 0;
|
||||||
|
const loggedOut = reason === DisconnectReason.loggedOut;
|
||||||
|
void onEvent({ type: "close", reason, loggedOut });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
accountId,
|
||||||
|
socket,
|
||||||
|
close: async () => {
|
||||||
|
try {
|
||||||
|
socket.end(undefined);
|
||||||
|
} catch (err) {
|
||||||
|
logger.warn({ err, accountId }, "session.close: error closing socket");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user