wa-multi-mongodb 3.9.5 → 3.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Socket/index.d.ts +32 -3
- package/dist/Socket/index.d.ts.map +1 -1
- package/dist/Socket/index.js +269 -51
- package/dist/Types/index.d.ts +1 -0
- package/dist/Types/index.d.ts.map +1 -1
- package/package.json +2 -1
- package/readme.md +270 -4
package/dist/Socket/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WASocket } from "baileys";
|
|
2
|
-
import type { MessageReceived, MessageUpdated, StartSessionParams
|
|
2
|
+
import type { MessageReceived, MessageUpdated, StartSessionParams } from "../Types";
|
|
3
3
|
/**
|
|
4
4
|
* Set MongoDB URI for connection
|
|
5
5
|
* This function will be used to configure MongoDB connection with just the URI
|
|
@@ -10,10 +10,15 @@ export declare const setMongoURI: (uri: string) => Promise<void>;
|
|
|
10
10
|
export declare function setMongoCollection(collection: any): void;
|
|
11
11
|
export declare const startSession: (sessionId?: string, options?: StartSessionParams) => Promise<WASocket>;
|
|
12
12
|
/**
|
|
13
|
+
* Start WhatsApp session using pairing code method
|
|
14
|
+
* This is the recommended way to create sessions with pairing code
|
|
13
15
|
*
|
|
14
|
-
* @
|
|
16
|
+
* @param sessionId Unique session identifier
|
|
17
|
+
* @param phoneNumber Phone number with country code (without + prefix)
|
|
18
|
+
* @param options Optional configuration for the session
|
|
19
|
+
* @returns Promise<WASocket> The WhatsApp socket instance
|
|
15
20
|
*/
|
|
16
|
-
export declare const startSessionWithPairingCode: (sessionId: string,
|
|
21
|
+
export declare const startSessionWithPairingCode: (sessionId: string, phoneNumber: string, options?: StartSessionParams) => Promise<WASocket>;
|
|
17
22
|
/**
|
|
18
23
|
* @deprecated Use startSession method instead
|
|
19
24
|
*/
|
|
@@ -65,6 +70,30 @@ export declare const setCredentialsDir: (dirname?: string) => void;
|
|
|
65
70
|
* @returns Promise<boolean> indicating success
|
|
66
71
|
*/
|
|
67
72
|
export declare const reconnect: (sessionId: string) => Promise<boolean>;
|
|
73
|
+
/**
|
|
74
|
+
* Reconnect all pairing code sessions that are tracked
|
|
75
|
+
* Useful for bulk reconnection after system restart
|
|
76
|
+
*/
|
|
77
|
+
export declare const reconnectAllPairingCodeSessions: () => Promise<{
|
|
78
|
+
[sessionId: string]: boolean;
|
|
79
|
+
}>;
|
|
80
|
+
/**
|
|
81
|
+
* Get all tracked pairing code sessions
|
|
82
|
+
* @returns Array of session IDs that were created with pairing code
|
|
83
|
+
*/
|
|
84
|
+
export declare const getPairingCodeSessions: () => string[];
|
|
85
|
+
/**
|
|
86
|
+
* Get session status information
|
|
87
|
+
* @param sessionId Session ID to check
|
|
88
|
+
* @returns Object with session status information
|
|
89
|
+
*/
|
|
90
|
+
export declare const getSessionStatus: (sessionId: string) => {
|
|
91
|
+
sessionId: string;
|
|
92
|
+
isRunning: boolean;
|
|
93
|
+
isPairingCodeSession: boolean;
|
|
94
|
+
retryAttempts: number;
|
|
95
|
+
hasCredentials: boolean;
|
|
96
|
+
};
|
|
68
97
|
export declare const setGroupCacheConfig: (options: {
|
|
69
98
|
stdTTL?: number;
|
|
70
99
|
checkperiod?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Socket/index.ts"],"names":[],"mappings":"AAAA,OAAqB,EAInB,QAAQ,EACT,MAAM,SAAS,CAAC;AAKjB,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Socket/index.ts"],"names":[],"mappings":"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"}
|
package/dist/Socket/index.js
CHANGED
|
@@ -45,7 +45,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
45
45
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
46
|
};
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
-
exports.clearAllGroupMetadataCache = exports.clearSessionGroupMetadataCache = exports.clearGroupMetadataCache = exports.getGroupMetadata = exports.setGroupCacheConfig = exports.reconnect = exports.setCredentialsDir = exports.setMongoDBNames = exports.loadSessionsFromMongo = exports.onPairingCode = exports.onMessageUpdate = exports.onConnecting = exports.onDisconnected = exports.onConnected = exports.onQRUpdated = exports.onMessageReceived = exports.loadSessionsFromStorage = exports.getSession = exports.getAllSessionSync = exports.getAllSession = exports.deleteSession = exports.startWhatsapp = exports.startSessionWithPairingCode = exports.startSession = exports.setMongoURI = void 0;
|
|
48
|
+
exports.clearAllGroupMetadataCache = exports.clearSessionGroupMetadataCache = exports.clearGroupMetadataCache = exports.getGroupMetadata = exports.setGroupCacheConfig = exports.getSessionStatus = exports.getPairingCodeSessions = exports.reconnectAllPairingCodeSessions = exports.reconnect = exports.setCredentialsDir = exports.setMongoDBNames = exports.loadSessionsFromMongo = exports.onPairingCode = exports.onMessageUpdate = exports.onConnecting = exports.onDisconnected = exports.onConnected = exports.onQRUpdated = exports.onMessageReceived = exports.loadSessionsFromStorage = exports.getSession = exports.getAllSessionSync = exports.getAllSession = exports.deleteSession = exports.startWhatsapp = exports.startSessionWithPairingCode = exports.startSession = exports.setMongoURI = void 0;
|
|
49
49
|
exports.setMongoCollection = setMongoCollection;
|
|
50
50
|
const baileys_1 = __importStar(require("baileys"));
|
|
51
51
|
const path_1 = __importDefault(require("path"));
|
|
@@ -62,6 +62,8 @@ const create_delay_1 = require("../Utils/create-delay");
|
|
|
62
62
|
const sessions = new Map();
|
|
63
63
|
const callback = new Map();
|
|
64
64
|
const retryCount = new Map();
|
|
65
|
+
// Tambahkan Map untuk melacak session yang menggunakan pairing code
|
|
66
|
+
const pairingCodeSessions = new Map();
|
|
65
67
|
const P = require("pino")({
|
|
66
68
|
level: "silent",
|
|
67
69
|
});
|
|
@@ -90,7 +92,7 @@ const setMongoURI = (uri) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
90
92
|
mongoClient = undefined;
|
|
91
93
|
authCollection = null;
|
|
92
94
|
}
|
|
93
|
-
|
|
95
|
+
// MongoDB URI configured successfully - removed console.log for npm package
|
|
94
96
|
});
|
|
95
97
|
exports.setMongoURI = setMongoURI;
|
|
96
98
|
function setMongoCollection(collection) {
|
|
@@ -137,6 +139,7 @@ const startSession = (...args_1) => __awaiter(void 0, [...args_1], void 0, funct
|
|
|
137
139
|
const update = events["connection.update"];
|
|
138
140
|
const { connection, lastDisconnect } = update;
|
|
139
141
|
if (update.qr) {
|
|
142
|
+
// Print QR to console if requested
|
|
140
143
|
if (options.printQR) {
|
|
141
144
|
qrcode_1.default.toString(update.qr, {
|
|
142
145
|
type: 'terminal',
|
|
@@ -148,9 +151,10 @@ const startSession = (...args_1) => __awaiter(void 0, [...args_1], void 0, funct
|
|
|
148
151
|
}
|
|
149
152
|
});
|
|
150
153
|
}
|
|
154
|
+
// Send QR data raw to callback for frontend processing
|
|
151
155
|
(_a = callback.get(Defaults_1.CALLBACK_KEY.ON_QR)) === null || _a === void 0 ? void 0 : _a({
|
|
152
156
|
sessionId,
|
|
153
|
-
qr: update.qr
|
|
157
|
+
qr: update.qr
|
|
154
158
|
});
|
|
155
159
|
(_b = options.onQRUpdated) === null || _b === void 0 ? void 0 : _b.call(options, update.qr);
|
|
156
160
|
}
|
|
@@ -172,7 +176,14 @@ const startSession = (...args_1) => __awaiter(void 0, [...args_1], void 0, funct
|
|
|
172
176
|
}
|
|
173
177
|
else {
|
|
174
178
|
retryCount.delete(sessionId);
|
|
175
|
-
|
|
179
|
+
// For pairing code sessions, preserve data for future reconnection
|
|
180
|
+
if (pairingCodeSessions.has(sessionId)) {
|
|
181
|
+
yield softDeleteSession(sessionId, true);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
// For regular sessions, completely delete
|
|
185
|
+
yield softDeleteSession(sessionId, false);
|
|
186
|
+
}
|
|
176
187
|
(_h = callback.get(Defaults_1.CALLBACK_KEY.ON_DISCONNECTED)) === null || _h === void 0 ? void 0 : _h(sessionId);
|
|
177
188
|
(_j = options.onDisconnected) === null || _j === void 0 ? void 0 : _j.call(options);
|
|
178
189
|
}
|
|
@@ -241,16 +252,23 @@ const startSession = (...args_1) => __awaiter(void 0, [...args_1], void 0, funct
|
|
|
241
252
|
});
|
|
242
253
|
exports.startSession = startSession;
|
|
243
254
|
/**
|
|
255
|
+
* Start WhatsApp session using pairing code method
|
|
256
|
+
* This is the recommended way to create sessions with pairing code
|
|
244
257
|
*
|
|
245
|
-
* @
|
|
258
|
+
* @param sessionId Unique session identifier
|
|
259
|
+
* @param phoneNumber Phone number with country code (without + prefix)
|
|
260
|
+
* @param options Optional configuration for the session
|
|
261
|
+
* @returns Promise<WASocket> The WhatsApp socket instance
|
|
246
262
|
*/
|
|
247
|
-
const startSessionWithPairingCode = (
|
|
263
|
+
const startSessionWithPairingCode = (sessionId_1, phoneNumber_1, ...args_1) => __awaiter(void 0, [sessionId_1, phoneNumber_1, ...args_1], void 0, function* (sessionId, phoneNumber, options = {}) {
|
|
248
264
|
if (isSessionExistAndRunning(sessionId))
|
|
249
265
|
throw new Error_1.WhatsappError(Defaults_1.Messages.sessionAlreadyExist(sessionId));
|
|
266
|
+
// Simpan informasi session pairing code untuk auto-reconnect
|
|
267
|
+
pairingCodeSessions.set(sessionId, { phoneNumber, options });
|
|
250
268
|
yield initMongo();
|
|
251
269
|
const { version } = yield (0, baileys_1.fetchLatestBaileysVersion)();
|
|
252
270
|
const startSocket = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
253
|
-
var _a;
|
|
271
|
+
var _a, _b;
|
|
254
272
|
const { state, saveCreds } = yield (0, mongo_auth_state_1.useMongoAuthState)(sessionId, authCollection);
|
|
255
273
|
const sock = (0, baileys_1.default)({
|
|
256
274
|
version,
|
|
@@ -258,80 +276,162 @@ const startSessionWithPairingCode = (sessionId, options) => __awaiter(void 0, vo
|
|
|
258
276
|
logger: P,
|
|
259
277
|
markOnlineOnConnect: false,
|
|
260
278
|
browser: baileys_1.Browsers.ubuntu("Chrome"),
|
|
279
|
+
// Opsi tambahan untuk meningkatkan kompatibilitas
|
|
280
|
+
linkPreviewImageThumbnailWidth: 300,
|
|
281
|
+
generateHighQualityLinkPreview: true,
|
|
282
|
+
syncFullHistory: false, // Sinkronisasi hanya riwayat baru
|
|
283
|
+
connectTimeoutMs: 60000, // Timeout koneksi ditingkatkan
|
|
284
|
+
printQRInTerminal: false, // QR tidak dicetak untuk pairing code
|
|
285
|
+
// Configure caching group metadata using our hybrid implementation with session ID
|
|
286
|
+
cachedGroupMetadata: (jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
287
|
+
return yield Utils_1.groupCache.get(sessionId, jid);
|
|
288
|
+
})
|
|
261
289
|
});
|
|
262
290
|
sessions.set(sessionId, Object.assign({}, sock));
|
|
263
291
|
try {
|
|
264
292
|
if (!sock.authState.creds.registered) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
293
|
+
// Pastikan kita mendapatkan kode pairing dan menampilkannya dengan jelas
|
|
294
|
+
try {
|
|
295
|
+
// Tambahkan delay untuk memastikan state sudah siap
|
|
296
|
+
yield new Promise(resolve => setTimeout(resolve, 2000));
|
|
297
|
+
// Hapus awalan + dari nomor telepon jika ada
|
|
298
|
+
const phoneNumberFormatted = phoneNumber.replace(/^\+/, '');
|
|
299
|
+
// Memanggil fungsi requestPairingCode dengan nomor telepon yang sudah dibersihkan
|
|
300
|
+
const code = yield sock.requestPairingCode(phoneNumberFormatted);
|
|
301
|
+
// Pastikan kode ada dan merupakan string
|
|
302
|
+
if (code && typeof code === 'string') {
|
|
303
|
+
console.log(`Pairing code untuk session ${sessionId}: ${code}`);
|
|
304
|
+
// Panggil callback yang terdaftar
|
|
305
|
+
(_a = callback.get(Defaults_1.CALLBACK_KEY.ON_PAIRING_CODE)) === null || _a === void 0 ? void 0 : _a(sessionId, code);
|
|
306
|
+
(_b = options.onPairingCode) === null || _b === void 0 ? void 0 : _b.call(options, code);
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
console.error("Error: Kode pairing tidak valid atau kosong");
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
catch (error) {
|
|
313
|
+
console.error("Error saat meminta kode pairing:", error);
|
|
314
|
+
throw new Error_1.WhatsappError(`Gagal mendapatkan kode pairing: ${error.message || String(error)}`);
|
|
315
|
+
}
|
|
269
316
|
}
|
|
270
317
|
sock.ev.process((events) => __awaiter(void 0, void 0, void 0, function* () {
|
|
271
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
318
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
272
319
|
if (events["connection.update"]) {
|
|
273
320
|
const update = events["connection.update"];
|
|
274
321
|
const { connection, lastDisconnect } = update;
|
|
275
322
|
if (update.qr) {
|
|
276
|
-
|
|
277
|
-
type: 'terminal',
|
|
278
|
-
small: true,
|
|
279
|
-
margin: 1
|
|
280
|
-
}, (err, qrString) => {
|
|
281
|
-
if (!err) {
|
|
282
|
-
console.log(qrString);
|
|
283
|
-
}
|
|
284
|
-
});
|
|
323
|
+
// Send QR data raw to callback for frontend processing
|
|
285
324
|
(_a = callback.get(Defaults_1.CALLBACK_KEY.ON_QR)) === null || _a === void 0 ? void 0 : _a({
|
|
286
325
|
sessionId,
|
|
287
|
-
qr: update.qr
|
|
326
|
+
qr: update.qr
|
|
288
327
|
});
|
|
289
328
|
}
|
|
290
329
|
if (connection == "connecting") {
|
|
291
330
|
(_b = callback.get(Defaults_1.CALLBACK_KEY.ON_CONNECTING)) === null || _b === void 0 ? void 0 : _b(sessionId);
|
|
331
|
+
(_c = options.onConnecting) === null || _c === void 0 ? void 0 : _c.call(options);
|
|
292
332
|
}
|
|
293
333
|
if (connection === "close") {
|
|
294
|
-
const code = (
|
|
295
|
-
let retryAttempt = (
|
|
334
|
+
const code = (_e = (_d = lastDisconnect === null || lastDisconnect === void 0 ? void 0 : lastDisconnect.error) === null || _d === void 0 ? void 0 : _d.output) === null || _e === void 0 ? void 0 : _e.statusCode;
|
|
335
|
+
let retryAttempt = (_f = retryCount.get(sessionId)) !== null && _f !== void 0 ? _f : 0;
|
|
296
336
|
let shouldRetry;
|
|
297
337
|
if (code != baileys_1.DisconnectReason.loggedOut && retryAttempt < 10) {
|
|
298
338
|
shouldRetry = true;
|
|
299
339
|
}
|
|
300
340
|
if (shouldRetry) {
|
|
301
341
|
retryAttempt++;
|
|
302
|
-
}
|
|
303
|
-
if (shouldRetry) {
|
|
304
342
|
retryCount.set(sessionId, retryAttempt);
|
|
305
|
-
|
|
343
|
+
// Untuk session pairing code, coba reconnect dengan metode yang tepat
|
|
344
|
+
try {
|
|
345
|
+
// Tunggu sebentar sebelum reconnect
|
|
346
|
+
yield (0, create_delay_1.createDelay)(2000);
|
|
347
|
+
startSocket();
|
|
348
|
+
}
|
|
349
|
+
catch (reconnectError) {
|
|
350
|
+
console.error(`Auto-reconnect failed for session ${sessionId}:`, reconnectError.message);
|
|
351
|
+
// Jika reconnect gagal beberapa kali, coba dengan pairing code lagi (jika masih dalam 3 attempt pertama)
|
|
352
|
+
if (retryAttempt <= 3 && pairingCodeSessions.has(sessionId)) {
|
|
353
|
+
const sessionInfo = pairingCodeSessions.get(sessionId);
|
|
354
|
+
// Bersihkan session lama
|
|
355
|
+
sessions.delete(sessionId);
|
|
356
|
+
// Coba mulai ulang dengan pairing code baru
|
|
357
|
+
setTimeout(() => {
|
|
358
|
+
startSocket().catch(err => {
|
|
359
|
+
console.error(`Failed to restart with pairing code for session ${sessionId}:`, err);
|
|
360
|
+
});
|
|
361
|
+
}, 3000);
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
// Jika sudah terlalu banyak gagal, panggil startSocket biasa
|
|
365
|
+
startSocket();
|
|
366
|
+
}
|
|
367
|
+
}
|
|
306
368
|
}
|
|
307
369
|
else {
|
|
308
370
|
retryCount.delete(sessionId);
|
|
309
|
-
|
|
310
|
-
(
|
|
371
|
+
// For pairing code sessions, preserve data for future reconnection
|
|
372
|
+
if (pairingCodeSessions.has(sessionId)) {
|
|
373
|
+
yield softDeleteSession(sessionId, true);
|
|
374
|
+
// Don't remove from pairing code tracking completely to allow manual reconnection
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
pairingCodeSessions.delete(sessionId); // Only delete from tracking if it's not a pairing code session
|
|
378
|
+
yield softDeleteSession(sessionId, false);
|
|
379
|
+
}
|
|
380
|
+
(_g = callback.get(Defaults_1.CALLBACK_KEY.ON_DISCONNECTED)) === null || _g === void 0 ? void 0 : _g(sessionId);
|
|
381
|
+
(_h = options.onDisconnected) === null || _h === void 0 ? void 0 : _h.call(options);
|
|
311
382
|
}
|
|
312
383
|
}
|
|
313
384
|
if (connection == "open") {
|
|
314
385
|
retryCount.delete(sessionId);
|
|
315
|
-
(
|
|
386
|
+
(_j = callback.get(Defaults_1.CALLBACK_KEY.ON_CONNECTED)) === null || _j === void 0 ? void 0 : _j(sessionId);
|
|
387
|
+
(_k = options.onConnected) === null || _k === void 0 ? void 0 : _k.call(options);
|
|
316
388
|
}
|
|
317
389
|
}
|
|
318
390
|
if (events["creds.update"]) {
|
|
319
391
|
yield saveCreds();
|
|
320
392
|
}
|
|
393
|
+
// Menangani event update data grup
|
|
394
|
+
if (events["groups.update"]) {
|
|
395
|
+
const updates = events["groups.update"];
|
|
396
|
+
for (const update of updates) {
|
|
397
|
+
try {
|
|
398
|
+
// Dapatkan metadata grup terbaru dan simpan ke cache dengan sessionId
|
|
399
|
+
const metadata = yield sock.groupMetadata(update.id);
|
|
400
|
+
yield Utils_1.groupCache.set(sessionId, update.id, metadata);
|
|
401
|
+
}
|
|
402
|
+
catch (error) {
|
|
403
|
+
console.error(`Error updating group metadata in cache: ${error}`);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
// Menangani event perubahan peserta grup
|
|
408
|
+
if (events["group-participants.update"]) {
|
|
409
|
+
const update = events["group-participants.update"];
|
|
410
|
+
try {
|
|
411
|
+
// Dapatkan metadata grup terbaru dan simpan ke cache dengan sessionId
|
|
412
|
+
const metadata = yield sock.groupMetadata(update.id);
|
|
413
|
+
yield Utils_1.groupCache.set(sessionId, update.id, metadata);
|
|
414
|
+
}
|
|
415
|
+
catch (error) {
|
|
416
|
+
console.error(`Error updating group participants in cache: ${error}`);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
321
419
|
if (events["messages.update"]) {
|
|
322
420
|
const msg = events["messages.update"][0];
|
|
323
421
|
const data = Object.assign({ sessionId: sessionId, messageStatus: (0, message_status_1.parseMessageStatusCodeToReadable)(msg.update.status) }, msg);
|
|
324
|
-
(
|
|
422
|
+
(_l = callback.get(Defaults_1.CALLBACK_KEY.ON_MESSAGE_UPDATED)) === null || _l === void 0 ? void 0 : _l(sessionId, data);
|
|
423
|
+
(_m = options.onMessageUpdated) === null || _m === void 0 ? void 0 : _m.call(options, data);
|
|
325
424
|
}
|
|
326
425
|
if (events["messages.upsert"]) {
|
|
327
|
-
const msg = (
|
|
328
|
-
.messages) === null ||
|
|
426
|
+
const msg = (_o = events["messages.upsert"]
|
|
427
|
+
.messages) === null || _o === void 0 ? void 0 : _o[0];
|
|
329
428
|
msg.sessionId = sessionId;
|
|
330
429
|
msg.saveImage = (path) => (0, save_media_1.saveImageHandler)(msg, path);
|
|
331
430
|
msg.saveVideo = (path) => (0, save_media_1.saveVideoHandler)(msg, path);
|
|
332
431
|
msg.saveDocument = (path) => (0, save_media_1.saveDocumentHandler)(msg, path);
|
|
333
432
|
msg.saveAudio = (path) => (0, save_media_1.saveAudioHandler)(msg, path);
|
|
334
|
-
(
|
|
433
|
+
(_p = callback.get(Defaults_1.CALLBACK_KEY.ON_MESSAGE_RECEIVED)) === null || _p === void 0 ? void 0 : _p(Object.assign({}, msg));
|
|
434
|
+
(_q = options.onMessageReceived) === null || _q === void 0 ? void 0 : _q.call(options, msg);
|
|
335
435
|
}
|
|
336
436
|
}));
|
|
337
437
|
return sock;
|
|
@@ -348,6 +448,45 @@ exports.startSessionWithPairingCode = startSessionWithPairingCode;
|
|
|
348
448
|
* @deprecated Use startSession method instead
|
|
349
449
|
*/
|
|
350
450
|
exports.startWhatsapp = exports.startSession;
|
|
451
|
+
/**
|
|
452
|
+
* Soft delete session - removes from memory but preserves MongoDB data for pairing code sessions
|
|
453
|
+
* @param sessionId Session ID to soft delete
|
|
454
|
+
*/
|
|
455
|
+
const softDeleteSession = (sessionId_1, ...args_1) => __awaiter(void 0, [sessionId_1, ...args_1], void 0, function* (sessionId, preserveData = false) {
|
|
456
|
+
const session = (0, exports.getSession)(sessionId);
|
|
457
|
+
try {
|
|
458
|
+
yield (session === null || session === void 0 ? void 0 : session.logout());
|
|
459
|
+
}
|
|
460
|
+
catch (error) { }
|
|
461
|
+
session === null || session === void 0 ? void 0 : session.end(undefined);
|
|
462
|
+
sessions.delete(sessionId);
|
|
463
|
+
// Only completely remove from MongoDB if not preserving data or not a pairing code session
|
|
464
|
+
if (!preserveData && !pairingCodeSessions.has(sessionId)) {
|
|
465
|
+
if (authCollection) {
|
|
466
|
+
try {
|
|
467
|
+
yield authCollection.deleteOne({ sessionId });
|
|
468
|
+
}
|
|
469
|
+
catch (error) {
|
|
470
|
+
console.error(`Error deleting session ${sessionId} from MongoDB:`, error);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
else if (pairingCodeSessions.has(sessionId)) {
|
|
475
|
+
// Preserving MongoDB data for pairing code session
|
|
476
|
+
}
|
|
477
|
+
// Hapus cache grup untuk session ini
|
|
478
|
+
try {
|
|
479
|
+
yield Utils_1.groupCache.clearSessionCache(sessionId);
|
|
480
|
+
}
|
|
481
|
+
catch (error) {
|
|
482
|
+
console.error(`Error clearing group cache for session ${sessionId}:`, error);
|
|
483
|
+
}
|
|
484
|
+
// Legacy: hapus juga dari file system jika ada
|
|
485
|
+
const dir = path_1.default.resolve(Defaults_1.CREDENTIALS.DIR_NAME, sessionId + Defaults_1.CREDENTIALS.PREFIX);
|
|
486
|
+
if (fs_1.default.existsSync(dir)) {
|
|
487
|
+
fs_1.default.rmSync(dir, { force: true, recursive: true });
|
|
488
|
+
}
|
|
489
|
+
});
|
|
351
490
|
const deleteSession = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
352
491
|
const session = (0, exports.getSession)(sessionId);
|
|
353
492
|
try {
|
|
@@ -356,11 +495,12 @@ const deleteSession = (sessionId) => __awaiter(void 0, void 0, void 0, function*
|
|
|
356
495
|
catch (error) { }
|
|
357
496
|
session === null || session === void 0 ? void 0 : session.end(undefined);
|
|
358
497
|
sessions.delete(sessionId);
|
|
498
|
+
// Hapus tracking pairing code session jika ada
|
|
499
|
+
pairingCodeSessions.delete(sessionId);
|
|
359
500
|
// Hapus juga dari MongoDB jika authCollection ada
|
|
360
501
|
if (authCollection) {
|
|
361
502
|
try {
|
|
362
503
|
yield authCollection.deleteOne({ sessionId });
|
|
363
|
-
console.log(`Session ${sessionId} deleted from MongoDB`);
|
|
364
504
|
}
|
|
365
505
|
catch (error) {
|
|
366
506
|
console.error(`Error deleting session ${sessionId} from MongoDB:`, error);
|
|
@@ -369,7 +509,6 @@ const deleteSession = (sessionId) => __awaiter(void 0, void 0, void 0, function*
|
|
|
369
509
|
// Hapus cache grup untuk session ini
|
|
370
510
|
try {
|
|
371
511
|
yield Utils_1.groupCache.clearSessionCache(sessionId);
|
|
372
|
-
console.log(`Group metadata cache for session ${sessionId} cleared`);
|
|
373
512
|
}
|
|
374
513
|
catch (error) {
|
|
375
514
|
console.error(`Error clearing group cache for session ${sessionId}:`, error);
|
|
@@ -479,7 +618,8 @@ const onMessageUpdate = (listener) => {
|
|
|
479
618
|
};
|
|
480
619
|
exports.onMessageUpdate = onMessageUpdate;
|
|
481
620
|
const onPairingCode = (listener) => {
|
|
482
|
-
callback
|
|
621
|
+
// Set callback ke registry dengan key yang benar
|
|
622
|
+
callback.set(Defaults_1.CALLBACK_KEY.ON_PAIRING_CODE, listener);
|
|
483
623
|
};
|
|
484
624
|
exports.onPairingCode = onPairingCode;
|
|
485
625
|
/**
|
|
@@ -511,7 +651,6 @@ exports.loadSessionsFromMongo = loadSessionsFromMongo;
|
|
|
511
651
|
const setMongoDBNames = (dbName = "wa_session", collectionName = "auth") => {
|
|
512
652
|
Defaults_1.CREDENTIALS.MONGO_DB_NAME = dbName;
|
|
513
653
|
Defaults_1.CREDENTIALS.MONGO_COLLECTION_NAME = collectionName;
|
|
514
|
-
console.log(`MongoDB names configured: database="${dbName}", collection="${collectionName}"`);
|
|
515
654
|
};
|
|
516
655
|
exports.setMongoDBNames = setMongoDBNames;
|
|
517
656
|
/**
|
|
@@ -555,36 +694,115 @@ const reconnect = (sessionId) => __awaiter(void 0, void 0, void 0, function* ()
|
|
|
555
694
|
}
|
|
556
695
|
// Tunggu sedikit waktu untuk memastikan cleanup selesai
|
|
557
696
|
yield (0, create_delay_1.createDelay)(1000);
|
|
558
|
-
// Cek jika
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
// Mulai session baru dari data yang tersimpan di MongoDB
|
|
563
|
-
// Gunakan opsi khusus untuk reconnect
|
|
697
|
+
// Cek jika ini session pairing code dari tracking terlebih dahulu
|
|
698
|
+
const pairingInfo = pairingCodeSessions.get(sessionId);
|
|
699
|
+
if (pairingInfo) {
|
|
700
|
+
// Ini adalah session pairing code, gunakan metode pairing code untuk reconnect
|
|
564
701
|
try {
|
|
565
|
-
|
|
566
|
-
|
|
702
|
+
// Reset retry count untuk session ini
|
|
703
|
+
retryCount.delete(sessionId);
|
|
704
|
+
yield (0, exports.startSessionWithPairingCode)(sessionId, pairingInfo.phoneNumber, Object.assign(Object.assign({}, pairingInfo.options), { printQR: false,
|
|
567
705
|
// Tambahkan callback khusus untuk reconnect
|
|
568
|
-
onConnected: () => {
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
706
|
+
onConnected: () => {
|
|
707
|
+
// Pairing code session reconnected successfully
|
|
708
|
+
}, onDisconnected: () => {
|
|
709
|
+
// Pairing code session disconnected after reconnect
|
|
710
|
+
} }));
|
|
572
711
|
// Periksa jika session berhasil dimulai
|
|
573
712
|
return !!(0, exports.getSession)(sessionId);
|
|
574
713
|
}
|
|
575
714
|
catch (startError) {
|
|
715
|
+
console.error(`Failed to reconnect pairing code session ${sessionId}:`, startError.message);
|
|
576
716
|
return false;
|
|
577
717
|
}
|
|
578
718
|
}
|
|
579
719
|
else {
|
|
580
|
-
|
|
720
|
+
// Cek jika data session tersedia di MongoDB untuk session biasa
|
|
721
|
+
yield initMongo();
|
|
722
|
+
const sessionExists = yield shouldLoadSession(sessionId);
|
|
723
|
+
if (sessionExists) {
|
|
724
|
+
// Session biasa, gunakan metode startSession normal
|
|
725
|
+
try {
|
|
726
|
+
yield (0, exports.startSession)(sessionId, {
|
|
727
|
+
printQR: false,
|
|
728
|
+
// Tambahkan callback khusus untuk reconnect
|
|
729
|
+
onConnected: () => {
|
|
730
|
+
// Session reconnected successfully
|
|
731
|
+
},
|
|
732
|
+
onDisconnected: () => {
|
|
733
|
+
// Session disconnected after reconnect
|
|
734
|
+
},
|
|
735
|
+
onQRUpdated: (qr) => {
|
|
736
|
+
// QR code updated for reconnecting session
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
// Periksa jika session berhasil dimulai
|
|
740
|
+
return !!(0, exports.getSession)(sessionId);
|
|
741
|
+
}
|
|
742
|
+
catch (startError) {
|
|
743
|
+
console.error(`Failed to reconnect session ${sessionId}:`, startError.message);
|
|
744
|
+
return false;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
else {
|
|
748
|
+
// No session data found in MongoDB
|
|
749
|
+
return false;
|
|
750
|
+
}
|
|
581
751
|
}
|
|
582
752
|
}
|
|
583
753
|
catch (error) {
|
|
754
|
+
console.error(`Error during reconnect for session ${sessionId}:`, error.message);
|
|
584
755
|
return false;
|
|
585
756
|
}
|
|
586
757
|
});
|
|
587
758
|
exports.reconnect = reconnect;
|
|
759
|
+
/**
|
|
760
|
+
* Reconnect all pairing code sessions that are tracked
|
|
761
|
+
* Useful for bulk reconnection after system restart
|
|
762
|
+
*/
|
|
763
|
+
const reconnectAllPairingCodeSessions = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
764
|
+
const results = {};
|
|
765
|
+
for (const [sessionId, sessionInfo] of pairingCodeSessions.entries()) {
|
|
766
|
+
try {
|
|
767
|
+
const success = yield (0, exports.reconnect)(sessionId);
|
|
768
|
+
results[sessionId] = success;
|
|
769
|
+
// Add delay between reconnection attempts
|
|
770
|
+
yield (0, create_delay_1.createDelay)(2000);
|
|
771
|
+
}
|
|
772
|
+
catch (error) {
|
|
773
|
+
console.error(`Error reconnecting pairing code session ${sessionId}:`, error.message);
|
|
774
|
+
results[sessionId] = false;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
return results;
|
|
778
|
+
});
|
|
779
|
+
exports.reconnectAllPairingCodeSessions = reconnectAllPairingCodeSessions;
|
|
780
|
+
/**
|
|
781
|
+
* Get all tracked pairing code sessions
|
|
782
|
+
* @returns Array of session IDs that were created with pairing code
|
|
783
|
+
*/
|
|
784
|
+
const getPairingCodeSessions = () => {
|
|
785
|
+
return Array.from(pairingCodeSessions.keys());
|
|
786
|
+
};
|
|
787
|
+
exports.getPairingCodeSessions = getPairingCodeSessions;
|
|
788
|
+
/**
|
|
789
|
+
* Get session status information
|
|
790
|
+
* @param sessionId Session ID to check
|
|
791
|
+
* @returns Object with session status information
|
|
792
|
+
*/
|
|
793
|
+
const getSessionStatus = (sessionId) => {
|
|
794
|
+
const isRunning = !!(0, exports.getSession)(sessionId);
|
|
795
|
+
const isPairingCodeSession = pairingCodeSessions.has(sessionId);
|
|
796
|
+
const retryAttempts = retryCount.get(sessionId) || 0;
|
|
797
|
+
return {
|
|
798
|
+
sessionId,
|
|
799
|
+
isRunning,
|
|
800
|
+
isPairingCodeSession,
|
|
801
|
+
retryAttempts,
|
|
802
|
+
hasCredentials: isRunning ? true : null // null means unknown when not running
|
|
803
|
+
};
|
|
804
|
+
};
|
|
805
|
+
exports.getSessionStatus = getSessionStatus;
|
|
588
806
|
// Fungsi baru untuk mendapatkan konfigurasi TTL cache grup
|
|
589
807
|
const setGroupCacheConfig = (options) => {
|
|
590
808
|
Utils_1.groupCache.setConfig(options);
|
package/dist/Types/index.d.ts
CHANGED
|
@@ -54,6 +54,7 @@ export interface StartSessionParams {
|
|
|
54
54
|
onConnected?: () => void;
|
|
55
55
|
onConnecting?: () => void;
|
|
56
56
|
onDisconnected?: () => void;
|
|
57
|
+
onPairingCode?: (code: string) => void;
|
|
57
58
|
onMessageReceived?: (message: MessageReceived) => void;
|
|
58
59
|
onMessageUpdated?: (message: MessageUpdated) => void;
|
|
59
60
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,KAAK,CAAC,eAAe,CAAC;CACnC;AAED,MAAM,WAAW,cAAe,SAAQ,gBAAgB;IACtD,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;IAC5F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,KAAK,CAAC,WAAW,CAAC;CACxB;AAED,MAAM,WAAW,eAAgB,SAAQ,KAAK,CAAC,eAAe;IAC5D;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C;;;OAGG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C;;;OAGG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C;;;OAGG;IACH,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAGlB,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,KAAK,CAAC,eAAe,CAAC;CACnC;AAED,MAAM,WAAW,cAAe,SAAQ,gBAAgB;IACtD,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;IAC5F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,KAAK,CAAC,WAAW,CAAC;CACxB;AAED,MAAM,WAAW,eAAgB,SAAQ,KAAK,CAAC,eAAe;IAC5D;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C;;;OAGG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C;;;OAGG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C;;;OAGG;IACH,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAGlB,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAGvC,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACvD,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;CACtD;AAED,MAAM,WAAW,iCAAiC;IAChD;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EACT,OAAO,GACP,SAAS,GACT,QAAQ,GACR,WAAW,GACX,MAAM,GACN,QAAQ,CAAC;CACd,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wa-multi-mongodb",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.6",
|
|
4
4
|
"description": "Multi Session Whatsapp Library with MongoDB Integration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"@hapi/boom": "^10.0.1",
|
|
20
20
|
"@types/node-cache": "^4.1.3",
|
|
21
21
|
"@types/qrcode": "^1.5.5",
|
|
22
|
+
"aws4": "^1.13.2",
|
|
22
23
|
"baileys": "^6.7.18",
|
|
23
24
|
"dotenv": "^16.5.0",
|
|
24
25
|
"link-preview-js": "^3.0.14",
|
package/readme.md
CHANGED
|
@@ -98,7 +98,7 @@ For secure MongoDB URI management, we recommend using environment variables:
|
|
|
98
98
|
### Session Management
|
|
99
99
|
|
|
100
100
|
```javascript
|
|
101
|
-
// Start a new session
|
|
101
|
+
// Start a new session with QR Code
|
|
102
102
|
const session = await whatsapp.startSession("mysession");
|
|
103
103
|
|
|
104
104
|
// Start with options
|
|
@@ -106,7 +106,22 @@ await whatsapp.startSession("mysession2", {
|
|
|
106
106
|
printQR: true,
|
|
107
107
|
onConnected: () => console.log("Connected!"),
|
|
108
108
|
onDisconnected: () => console.log("Disconnected!"),
|
|
109
|
-
onQRUpdated: (qr) =>
|
|
109
|
+
onQRUpdated: (qr) => {
|
|
110
|
+
console.log("New QR:", qr);
|
|
111
|
+
// QR data is raw and ready for frontend use
|
|
112
|
+
// You can display this in React, Vue, Angular, etc.
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Start session with Pairing Code (v3.9.6+)
|
|
117
|
+
await whatsapp.startSessionWithPairingCode("mysession3", {
|
|
118
|
+
mobile: "6281234567890", // your phone number with country code
|
|
119
|
+
onConnected: () => console.log("Pairing session connected!"),
|
|
120
|
+
onDisconnected: () => console.log("Pairing session disconnected!"),
|
|
121
|
+
onPairingCode: (code) => {
|
|
122
|
+
console.log("Pairing code:", code);
|
|
123
|
+
// Enter this code in your WhatsApp app: Settings > Linked Devices > Link a Device > Link with phone number
|
|
124
|
+
}
|
|
110
125
|
});
|
|
111
126
|
|
|
112
127
|
// Get all active sessions
|
|
@@ -117,6 +132,27 @@ const sessionData = whatsapp.getSession("mysession");
|
|
|
117
132
|
|
|
118
133
|
// Load all saved sessions from MongoDB
|
|
119
134
|
await whatsapp.loadSessionsFromMongo();
|
|
135
|
+
|
|
136
|
+
// Session Management Utilities (v3.9.6+)
|
|
137
|
+
// Get session status with detailed information
|
|
138
|
+
const status = await whatsapp.getSessionStatus("mysession");
|
|
139
|
+
console.log("Session status:", status);
|
|
140
|
+
// Returns: { exists: true, connected: true, sessionType: 'qr' | 'pairing' }
|
|
141
|
+
|
|
142
|
+
// Manual reconnection for any session
|
|
143
|
+
try {
|
|
144
|
+
const reconnected = await whatsapp.reconnect("mysession");
|
|
145
|
+
console.log("Reconnection successful:", reconnected);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
console.error("Reconnection failed:", error);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Get all pairing code sessions
|
|
151
|
+
const pairingSessions = whatsapp.getPairingCodeSessions();
|
|
152
|
+
console.log("Pairing code sessions:", pairingSessions);
|
|
153
|
+
|
|
154
|
+
// Bulk reconnect all pairing code sessions
|
|
155
|
+
await whatsapp.reconnectAllPairingCodeSessions();
|
|
120
156
|
```
|
|
121
157
|
|
|
122
158
|
### Sending Messages
|
|
@@ -511,6 +547,214 @@ startApp().catch(err => {
|
|
|
511
547
|
});
|
|
512
548
|
```
|
|
513
549
|
|
|
550
|
+
## Complete Example: Pairing Code with Auto-Reconnect (v3.9.6+)
|
|
551
|
+
|
|
552
|
+
```javascript
|
|
553
|
+
import * as whatsapp from "wa-multi-mongodb";
|
|
554
|
+
require('dotenv').config();
|
|
555
|
+
|
|
556
|
+
// Store connection status
|
|
557
|
+
const sessionStatus = {};
|
|
558
|
+
|
|
559
|
+
async function startPairingApp() {
|
|
560
|
+
// MongoDB Configuration
|
|
561
|
+
await whatsapp.setMongoURI(process.env.MONGODB_URI);
|
|
562
|
+
|
|
563
|
+
// Event listeners for pairing code sessions
|
|
564
|
+
whatsapp.onConnected((sessionId) => {
|
|
565
|
+
console.log(`Pairing session ${sessionId} connected!`);
|
|
566
|
+
sessionStatus[sessionId] = 'connected';
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
whatsapp.onDisconnected(async (sessionId) => {
|
|
570
|
+
console.log(`Pairing session ${sessionId} disconnected!`);
|
|
571
|
+
sessionStatus[sessionId] = 'disconnected';
|
|
572
|
+
|
|
573
|
+
// Check if it's a pairing code session
|
|
574
|
+
const status = await whatsapp.getSessionStatus(sessionId);
|
|
575
|
+
if (status.sessionType === 'pairing') {
|
|
576
|
+
console.log(`Attempting to reconnect pairing session ${sessionId}...`);
|
|
577
|
+
|
|
578
|
+
// Auto-reconnect after 5 seconds
|
|
579
|
+
setTimeout(async () => {
|
|
580
|
+
try {
|
|
581
|
+
const reconnected = await whatsapp.reconnect(sessionId);
|
|
582
|
+
if (reconnected) {
|
|
583
|
+
console.log(`Pairing session ${sessionId} reconnected successfully!`);
|
|
584
|
+
sessionStatus[sessionId] = 'connected';
|
|
585
|
+
}
|
|
586
|
+
} catch (error) {
|
|
587
|
+
console.error(`Failed to reconnect pairing session ${sessionId}:`, error);
|
|
588
|
+
}
|
|
589
|
+
}, 5000);
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
// Message handler
|
|
594
|
+
whatsapp.onMessageReceived(async (msg) => {
|
|
595
|
+
if (msg.key.fromMe || msg.key.remoteJid.includes("status")) return;
|
|
596
|
+
|
|
597
|
+
const messageContent = msg.message?.conversation ||
|
|
598
|
+
msg.message?.extendedTextMessage?.text ||
|
|
599
|
+
"";
|
|
600
|
+
|
|
601
|
+
console.log(`Message from ${msg.key.remoteJid}: ${messageContent}`);
|
|
602
|
+
|
|
603
|
+
// Auto-reply example
|
|
604
|
+
if (messageContent.toLowerCase().includes("ping")) {
|
|
605
|
+
await whatsapp.sendTextMessage({
|
|
606
|
+
sessionId: msg.sessionId,
|
|
607
|
+
to: msg.key.remoteJid,
|
|
608
|
+
text: "Pong! Message received from pairing session.",
|
|
609
|
+
answering: msg
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
// Load existing sessions from MongoDB
|
|
615
|
+
await whatsapp.loadSessionsFromMongo();
|
|
616
|
+
|
|
617
|
+
// Start a new pairing code session
|
|
618
|
+
const pairingSessionId = "pairing_session_1";
|
|
619
|
+
const yourPhoneNumber = "6281234567890"; // Replace with your phone number
|
|
620
|
+
|
|
621
|
+
try {
|
|
622
|
+
await whatsapp.startSessionWithPairingCode(pairingSessionId, {
|
|
623
|
+
mobile: yourPhoneNumber,
|
|
624
|
+
onConnected: () => {
|
|
625
|
+
console.log("Pairing session connected successfully!");
|
|
626
|
+
sessionStatus[pairingSessionId] = 'connected';
|
|
627
|
+
},
|
|
628
|
+
onDisconnected: () => {
|
|
629
|
+
console.log("Pairing session disconnected!");
|
|
630
|
+
sessionStatus[pairingSessionId] = 'disconnected';
|
|
631
|
+
},
|
|
632
|
+
onPairingCode: (code) => {
|
|
633
|
+
console.log("\n" + "=".repeat(50));
|
|
634
|
+
console.log("📱 PAIRING CODE:", code);
|
|
635
|
+
console.log("=".repeat(50));
|
|
636
|
+
console.log("1. Open WhatsApp on your phone");
|
|
637
|
+
console.log("2. Go to Settings > Linked Devices");
|
|
638
|
+
console.log("3. Tap 'Link a Device'");
|
|
639
|
+
console.log("4. Tap 'Link with phone number instead'");
|
|
640
|
+
console.log("5. Enter the pairing code above");
|
|
641
|
+
console.log("=".repeat(50) + "\n");
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
sessionStatus[pairingSessionId] = 'connecting';
|
|
646
|
+
} catch (error) {
|
|
647
|
+
console.error("Error starting pairing session:", error);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// Periodic health check for pairing sessions
|
|
651
|
+
setInterval(async () => {
|
|
652
|
+
const pairingSessions = whatsapp.getPairingCodeSessions();
|
|
653
|
+
console.log(`Active pairing sessions: ${pairingSessions.length}`);
|
|
654
|
+
|
|
655
|
+
// Check each pairing session status
|
|
656
|
+
for (const sessionId of pairingSessions) {
|
|
657
|
+
const status = await whatsapp.getSessionStatus(sessionId);
|
|
658
|
+
console.log(`Session ${sessionId}: ${status.connected ? 'Connected' : 'Disconnected'}`);
|
|
659
|
+
|
|
660
|
+
if (!status.connected && sessionStatus[sessionId] === 'connected') {
|
|
661
|
+
console.log(`Detected disconnection for ${sessionId}, attempting reconnect...`);
|
|
662
|
+
try {
|
|
663
|
+
await whatsapp.reconnect(sessionId);
|
|
664
|
+
} catch (error) {
|
|
665
|
+
console.error(`Reconnect failed for ${sessionId}:`, error);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}, 30000); // Check every 30 seconds
|
|
670
|
+
|
|
671
|
+
// Bulk reconnect utility
|
|
672
|
+
setInterval(async () => {
|
|
673
|
+
try {
|
|
674
|
+
await whatsapp.reconnectAllPairingCodeSessions();
|
|
675
|
+
console.log("Bulk reconnect completed for all pairing sessions");
|
|
676
|
+
} catch (error) {
|
|
677
|
+
console.error("Bulk reconnect failed:", error);
|
|
678
|
+
}
|
|
679
|
+
}, 10 * 60 * 1000); // Every 10 minutes
|
|
680
|
+
|
|
681
|
+
console.log("Pairing code application started!");
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
startPairingApp().catch(err => {
|
|
685
|
+
console.error("Failed to start pairing application:", err);
|
|
686
|
+
process.exit(1);
|
|
687
|
+
});
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
## Frontend Integration Example: QR Code Display (v3.9.6+)
|
|
691
|
+
|
|
692
|
+
```javascript
|
|
693
|
+
// React.js example for QR code display
|
|
694
|
+
import React, { useState, useEffect } from 'react';
|
|
695
|
+
import QRCode from 'qrcode';
|
|
696
|
+
import * as whatsapp from "wa-multi-mongodb";
|
|
697
|
+
|
|
698
|
+
function WhatsAppQRComponent() {
|
|
699
|
+
const [qrDataURL, setQrDataURL] = useState('');
|
|
700
|
+
const [sessionStatus, setSessionStatus] = useState('disconnected');
|
|
701
|
+
|
|
702
|
+
useEffect(() => {
|
|
703
|
+
// Initialize WhatsApp connection
|
|
704
|
+
const initWhatsApp = async () => {
|
|
705
|
+
await whatsapp.setMongoURI(process.env.REACT_APP_MONGODB_URI);
|
|
706
|
+
|
|
707
|
+
// Start session with simplified QR callback
|
|
708
|
+
await whatsapp.startSession("frontend_session", {
|
|
709
|
+
printQR: false, // Don't print in terminal
|
|
710
|
+
onQRUpdated: async (qr) => {
|
|
711
|
+
// QR data is raw and ready for frontend use
|
|
712
|
+
try {
|
|
713
|
+
const qrDataURL = await QRCode.toDataURL(qr);
|
|
714
|
+
setQrDataURL(qrDataURL);
|
|
715
|
+
} catch (error) {
|
|
716
|
+
console.error('Error generating QR code:', error);
|
|
717
|
+
}
|
|
718
|
+
},
|
|
719
|
+
onConnected: () => {
|
|
720
|
+
setSessionStatus('connected');
|
|
721
|
+
setQrDataURL(''); // Clear QR when connected
|
|
722
|
+
},
|
|
723
|
+
onDisconnected: () => {
|
|
724
|
+
setSessionStatus('disconnected');
|
|
725
|
+
}
|
|
726
|
+
});
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
initWhatsApp().catch(console.error);
|
|
730
|
+
}, []);
|
|
731
|
+
|
|
732
|
+
return (
|
|
733
|
+
<div className="whatsapp-qr">
|
|
734
|
+
<h2>WhatsApp Connection</h2>
|
|
735
|
+
<div className="status">
|
|
736
|
+
Status: <span className={sessionStatus}>{sessionStatus}</span>
|
|
737
|
+
</div>
|
|
738
|
+
|
|
739
|
+
{qrDataURL && (
|
|
740
|
+
<div className="qr-container">
|
|
741
|
+
<p>Scan this QR code with WhatsApp:</p>
|
|
742
|
+
<img src={qrDataURL} alt="WhatsApp QR Code" />
|
|
743
|
+
</div>
|
|
744
|
+
)}
|
|
745
|
+
|
|
746
|
+
{sessionStatus === 'connected' && (
|
|
747
|
+
<div className="connected">
|
|
748
|
+
<p>✅ WhatsApp connected successfully!</p>
|
|
749
|
+
</div>
|
|
750
|
+
)}
|
|
751
|
+
</div>
|
|
752
|
+
);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
export default WhatsAppQRComponent;
|
|
756
|
+
```
|
|
757
|
+
|
|
514
758
|
## Best Practices for Group Chats
|
|
515
759
|
|
|
516
760
|
1. **Auto Group Detection**: Since v3.9.0, the library automatically detects if a chat is a group based on its JID format
|
|
@@ -529,7 +773,29 @@ startApp().catch(err => {
|
|
|
529
773
|
|
|
530
774
|
## Changelog
|
|
531
775
|
|
|
532
|
-
### v3.9.
|
|
776
|
+
### v3.9.6 (latest)
|
|
777
|
+
- **Enhanced Pairing Code Support**: Added comprehensive pairing code session management with auto-reconnect capabilities
|
|
778
|
+
- New `startSessionWithPairingCode()` function for creating sessions using pairing codes
|
|
779
|
+
- Intelligent session tracking system that preserves pairing code session data across disconnections
|
|
780
|
+
- Enhanced auto-reconnect mechanism that differentiates between QR code and pairing code sessions
|
|
781
|
+
- Session persistence in MongoDB for pairing code sessions to enable seamless reconnection
|
|
782
|
+
- **New Utility Functions for Session Management**:
|
|
783
|
+
- `reconnect(sessionId)` - Manual reconnection for any session type
|
|
784
|
+
- `reconnectAllPairingCodeSessions()` - Bulk reconnection for all tracked pairing code sessions
|
|
785
|
+
- `getPairingCodeSessions()` - Get list of all pairing code session IDs
|
|
786
|
+
- `getSessionStatus(sessionId)` - Get detailed session status information including session type
|
|
787
|
+
- **QR Data Raw for Frontend Integration**: Simplified QR handling optimized for frontend development
|
|
788
|
+
- Cleaned up QR callback to provide only essential QR data raw for frontend processing
|
|
789
|
+
- Removed unnecessary QR string complexity from callbacks for better performance
|
|
790
|
+
- QR data can be directly used with any frontend QR code library (React, Vue, Angular, etc.)
|
|
791
|
+
- Terminal QR display handled automatically via `printQR` option
|
|
792
|
+
- **Breaking Changes**:
|
|
793
|
+
- Simplified `onQRUpdated` callback signature: removed `qrString` parameter, now only provides raw QR data
|
|
794
|
+
- Session-level `onQRUpdated` option simplified from `(qr, qrString)` to `(qr)` only
|
|
795
|
+
- **Enhanced Session Persistence**: Pairing code sessions maintain authentication state in MongoDB during disconnections
|
|
796
|
+
- **Improved Error Handling**: Better error recovery and automatic session restoration for pairing code sessions
|
|
797
|
+
|
|
798
|
+
### v3.9.5
|
|
533
799
|
- New `deleteMessage()` function for deleting messages
|
|
534
800
|
- Support for deleting both own messages and others' messages (requires admin permissions in groups)
|
|
535
801
|
- Auto-delete message utility function example
|
|
@@ -592,4 +858,4 @@ startApp().catch(err => {
|
|
|
592
858
|
|
|
593
859
|
## License
|
|
594
860
|
|
|
595
|
-
ISC
|
|
861
|
+
ISC
|