wa-multi-mongodb 3.9.5 → 3.9.7
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 +303 -65
- package/dist/Types/index.d.ts +1 -0
- package/dist/Types/index.d.ts.map +1 -1
- package/package.json +3 -2
- package/readme.md +278 -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
|
}
|
|
@@ -219,15 +230,25 @@ const startSession = (...args_1) => __awaiter(void 0, [...args_1], void 0, funct
|
|
|
219
230
|
(_o = options.onMessageUpdated) === null || _o === void 0 ? void 0 : _o.call(options, data);
|
|
220
231
|
}
|
|
221
232
|
if (events["messages.upsert"]) {
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
233
|
+
const messages = events["messages.upsert"].messages || [];
|
|
234
|
+
for (const rawMsg of messages) {
|
|
235
|
+
// Skip protocol messages and system messages
|
|
236
|
+
if ((_p = rawMsg.message) === null || _p === void 0 ? void 0 : _p.protocolMessage) {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
// Skip messages without content
|
|
240
|
+
if (!rawMsg.message || Object.keys(rawMsg.message).length === 0) {
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
const msg = rawMsg;
|
|
244
|
+
msg.sessionId = sessionId;
|
|
245
|
+
msg.saveImage = (path) => (0, save_media_1.saveImageHandler)(msg, path);
|
|
246
|
+
msg.saveVideo = (path) => (0, save_media_1.saveVideoHandler)(msg, path);
|
|
247
|
+
msg.saveDocument = (path) => (0, save_media_1.saveDocumentHandler)(msg, path);
|
|
248
|
+
msg.saveAudio = (path) => (0, save_media_1.saveAudioHandler)(msg, path);
|
|
249
|
+
(_q = callback.get(Defaults_1.CALLBACK_KEY.ON_MESSAGE_RECEIVED)) === null || _q === void 0 ? void 0 : _q(Object.assign({}, msg));
|
|
250
|
+
(_r = options.onMessageReceived) === null || _r === void 0 ? void 0 : _r.call(options, msg);
|
|
251
|
+
}
|
|
231
252
|
}
|
|
232
253
|
}));
|
|
233
254
|
return sock;
|
|
@@ -241,16 +262,23 @@ const startSession = (...args_1) => __awaiter(void 0, [...args_1], void 0, funct
|
|
|
241
262
|
});
|
|
242
263
|
exports.startSession = startSession;
|
|
243
264
|
/**
|
|
265
|
+
* Start WhatsApp session using pairing code method
|
|
266
|
+
* This is the recommended way to create sessions with pairing code
|
|
244
267
|
*
|
|
245
|
-
* @
|
|
268
|
+
* @param sessionId Unique session identifier
|
|
269
|
+
* @param phoneNumber Phone number with country code (without + prefix)
|
|
270
|
+
* @param options Optional configuration for the session
|
|
271
|
+
* @returns Promise<WASocket> The WhatsApp socket instance
|
|
246
272
|
*/
|
|
247
|
-
const startSessionWithPairingCode = (
|
|
273
|
+
const startSessionWithPairingCode = (sessionId_1, phoneNumber_1, ...args_1) => __awaiter(void 0, [sessionId_1, phoneNumber_1, ...args_1], void 0, function* (sessionId, phoneNumber, options = {}) {
|
|
248
274
|
if (isSessionExistAndRunning(sessionId))
|
|
249
275
|
throw new Error_1.WhatsappError(Defaults_1.Messages.sessionAlreadyExist(sessionId));
|
|
276
|
+
// Simpan informasi session pairing code untuk auto-reconnect
|
|
277
|
+
pairingCodeSessions.set(sessionId, { phoneNumber, options });
|
|
250
278
|
yield initMongo();
|
|
251
279
|
const { version } = yield (0, baileys_1.fetchLatestBaileysVersion)();
|
|
252
280
|
const startSocket = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
253
|
-
var _a;
|
|
281
|
+
var _a, _b;
|
|
254
282
|
const { state, saveCreds } = yield (0, mongo_auth_state_1.useMongoAuthState)(sessionId, authCollection);
|
|
255
283
|
const sock = (0, baileys_1.default)({
|
|
256
284
|
version,
|
|
@@ -258,80 +286,172 @@ const startSessionWithPairingCode = (sessionId, options) => __awaiter(void 0, vo
|
|
|
258
286
|
logger: P,
|
|
259
287
|
markOnlineOnConnect: false,
|
|
260
288
|
browser: baileys_1.Browsers.ubuntu("Chrome"),
|
|
289
|
+
// Opsi tambahan untuk meningkatkan kompatibilitas
|
|
290
|
+
linkPreviewImageThumbnailWidth: 300,
|
|
291
|
+
generateHighQualityLinkPreview: true,
|
|
292
|
+
syncFullHistory: false, // Sinkronisasi hanya riwayat baru
|
|
293
|
+
connectTimeoutMs: 60000, // Timeout koneksi ditingkatkan
|
|
294
|
+
printQRInTerminal: false, // QR tidak dicetak untuk pairing code
|
|
295
|
+
// Configure caching group metadata using our hybrid implementation with session ID
|
|
296
|
+
cachedGroupMetadata: (jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
297
|
+
return yield Utils_1.groupCache.get(sessionId, jid);
|
|
298
|
+
})
|
|
261
299
|
});
|
|
262
300
|
sessions.set(sessionId, Object.assign({}, sock));
|
|
263
301
|
try {
|
|
264
302
|
if (!sock.authState.creds.registered) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
303
|
+
// Pastikan kita mendapatkan kode pairing dan menampilkannya dengan jelas
|
|
304
|
+
try {
|
|
305
|
+
// Tambahkan delay untuk memastikan state sudah siap
|
|
306
|
+
yield new Promise(resolve => setTimeout(resolve, 2000));
|
|
307
|
+
// Hapus awalan + dari nomor telepon jika ada
|
|
308
|
+
const phoneNumberFormatted = phoneNumber.replace(/^\+/, '');
|
|
309
|
+
// Memanggil fungsi requestPairingCode dengan nomor telepon yang sudah dibersihkan
|
|
310
|
+
const code = yield sock.requestPairingCode(phoneNumberFormatted);
|
|
311
|
+
// Pastikan kode ada dan merupakan string
|
|
312
|
+
if (code && typeof code === 'string') {
|
|
313
|
+
console.log(`Pairing code untuk session ${sessionId}: ${code}`);
|
|
314
|
+
// Panggil callback yang terdaftar
|
|
315
|
+
(_a = callback.get(Defaults_1.CALLBACK_KEY.ON_PAIRING_CODE)) === null || _a === void 0 ? void 0 : _a(sessionId, code);
|
|
316
|
+
(_b = options.onPairingCode) === null || _b === void 0 ? void 0 : _b.call(options, code);
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
console.error("Error: Kode pairing tidak valid atau kosong");
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
console.error("Error saat meminta kode pairing:", error);
|
|
324
|
+
throw new Error_1.WhatsappError(`Gagal mendapatkan kode pairing: ${error.message || String(error)}`);
|
|
325
|
+
}
|
|
269
326
|
}
|
|
270
327
|
sock.ev.process((events) => __awaiter(void 0, void 0, void 0, function* () {
|
|
271
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
328
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
272
329
|
if (events["connection.update"]) {
|
|
273
330
|
const update = events["connection.update"];
|
|
274
331
|
const { connection, lastDisconnect } = update;
|
|
275
332
|
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
|
-
});
|
|
333
|
+
// Send QR data raw to callback for frontend processing
|
|
285
334
|
(_a = callback.get(Defaults_1.CALLBACK_KEY.ON_QR)) === null || _a === void 0 ? void 0 : _a({
|
|
286
335
|
sessionId,
|
|
287
|
-
qr: update.qr
|
|
336
|
+
qr: update.qr
|
|
288
337
|
});
|
|
289
338
|
}
|
|
290
339
|
if (connection == "connecting") {
|
|
291
340
|
(_b = callback.get(Defaults_1.CALLBACK_KEY.ON_CONNECTING)) === null || _b === void 0 ? void 0 : _b(sessionId);
|
|
341
|
+
(_c = options.onConnecting) === null || _c === void 0 ? void 0 : _c.call(options);
|
|
292
342
|
}
|
|
293
343
|
if (connection === "close") {
|
|
294
|
-
const code = (
|
|
295
|
-
let retryAttempt = (
|
|
344
|
+
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;
|
|
345
|
+
let retryAttempt = (_f = retryCount.get(sessionId)) !== null && _f !== void 0 ? _f : 0;
|
|
296
346
|
let shouldRetry;
|
|
297
347
|
if (code != baileys_1.DisconnectReason.loggedOut && retryAttempt < 10) {
|
|
298
348
|
shouldRetry = true;
|
|
299
349
|
}
|
|
300
350
|
if (shouldRetry) {
|
|
301
351
|
retryAttempt++;
|
|
302
|
-
}
|
|
303
|
-
if (shouldRetry) {
|
|
304
352
|
retryCount.set(sessionId, retryAttempt);
|
|
305
|
-
|
|
353
|
+
// Untuk session pairing code, coba reconnect dengan metode yang tepat
|
|
354
|
+
try {
|
|
355
|
+
// Tunggu sebentar sebelum reconnect
|
|
356
|
+
yield (0, create_delay_1.createDelay)(2000);
|
|
357
|
+
startSocket();
|
|
358
|
+
}
|
|
359
|
+
catch (reconnectError) {
|
|
360
|
+
console.error(`Auto-reconnect failed for session ${sessionId}:`, reconnectError.message);
|
|
361
|
+
// Jika reconnect gagal beberapa kali, coba dengan pairing code lagi (jika masih dalam 3 attempt pertama)
|
|
362
|
+
if (retryAttempt <= 3 && pairingCodeSessions.has(sessionId)) {
|
|
363
|
+
const sessionInfo = pairingCodeSessions.get(sessionId);
|
|
364
|
+
// Bersihkan session lama
|
|
365
|
+
sessions.delete(sessionId);
|
|
366
|
+
// Coba mulai ulang dengan pairing code baru
|
|
367
|
+
setTimeout(() => {
|
|
368
|
+
startSocket().catch(err => {
|
|
369
|
+
console.error(`Failed to restart with pairing code for session ${sessionId}:`, err);
|
|
370
|
+
});
|
|
371
|
+
}, 3000);
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
// Jika sudah terlalu banyak gagal, panggil startSocket biasa
|
|
375
|
+
startSocket();
|
|
376
|
+
}
|
|
377
|
+
}
|
|
306
378
|
}
|
|
307
379
|
else {
|
|
308
380
|
retryCount.delete(sessionId);
|
|
309
|
-
|
|
310
|
-
(
|
|
381
|
+
// For pairing code sessions, preserve data for future reconnection
|
|
382
|
+
if (pairingCodeSessions.has(sessionId)) {
|
|
383
|
+
yield softDeleteSession(sessionId, true);
|
|
384
|
+
// Don't remove from pairing code tracking completely to allow manual reconnection
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
pairingCodeSessions.delete(sessionId); // Only delete from tracking if it's not a pairing code session
|
|
388
|
+
yield softDeleteSession(sessionId, false);
|
|
389
|
+
}
|
|
390
|
+
(_g = callback.get(Defaults_1.CALLBACK_KEY.ON_DISCONNECTED)) === null || _g === void 0 ? void 0 : _g(sessionId);
|
|
391
|
+
(_h = options.onDisconnected) === null || _h === void 0 ? void 0 : _h.call(options);
|
|
311
392
|
}
|
|
312
393
|
}
|
|
313
394
|
if (connection == "open") {
|
|
314
395
|
retryCount.delete(sessionId);
|
|
315
|
-
(
|
|
396
|
+
(_j = callback.get(Defaults_1.CALLBACK_KEY.ON_CONNECTED)) === null || _j === void 0 ? void 0 : _j(sessionId);
|
|
397
|
+
(_k = options.onConnected) === null || _k === void 0 ? void 0 : _k.call(options);
|
|
316
398
|
}
|
|
317
399
|
}
|
|
318
400
|
if (events["creds.update"]) {
|
|
319
401
|
yield saveCreds();
|
|
320
402
|
}
|
|
403
|
+
// Menangani event update data grup
|
|
404
|
+
if (events["groups.update"]) {
|
|
405
|
+
const updates = events["groups.update"];
|
|
406
|
+
for (const update of updates) {
|
|
407
|
+
try {
|
|
408
|
+
// Dapatkan metadata grup terbaru dan simpan ke cache dengan sessionId
|
|
409
|
+
const metadata = yield sock.groupMetadata(update.id);
|
|
410
|
+
yield Utils_1.groupCache.set(sessionId, update.id, metadata);
|
|
411
|
+
}
|
|
412
|
+
catch (error) {
|
|
413
|
+
console.error(`Error updating group metadata in cache: ${error}`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
// Menangani event perubahan peserta grup
|
|
418
|
+
if (events["group-participants.update"]) {
|
|
419
|
+
const update = events["group-participants.update"];
|
|
420
|
+
try {
|
|
421
|
+
// Dapatkan metadata grup terbaru dan simpan ke cache dengan sessionId
|
|
422
|
+
const metadata = yield sock.groupMetadata(update.id);
|
|
423
|
+
yield Utils_1.groupCache.set(sessionId, update.id, metadata);
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
console.error(`Error updating group participants in cache: ${error}`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
321
429
|
if (events["messages.update"]) {
|
|
322
430
|
const msg = events["messages.update"][0];
|
|
323
431
|
const data = Object.assign({ sessionId: sessionId, messageStatus: (0, message_status_1.parseMessageStatusCodeToReadable)(msg.update.status) }, msg);
|
|
324
|
-
(
|
|
432
|
+
(_l = callback.get(Defaults_1.CALLBACK_KEY.ON_MESSAGE_UPDATED)) === null || _l === void 0 ? void 0 : _l(sessionId, data);
|
|
433
|
+
(_m = options.onMessageUpdated) === null || _m === void 0 ? void 0 : _m.call(options, data);
|
|
325
434
|
}
|
|
326
435
|
if (events["messages.upsert"]) {
|
|
327
|
-
const
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
436
|
+
const messages = events["messages.upsert"].messages || [];
|
|
437
|
+
for (const rawMsg of messages) {
|
|
438
|
+
// Skip protocol messages and system messages
|
|
439
|
+
if ((_o = rawMsg.message) === null || _o === void 0 ? void 0 : _o.protocolMessage) {
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
// Skip messages without content
|
|
443
|
+
if (!rawMsg.message || Object.keys(rawMsg.message).length === 0) {
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
const msg = rawMsg;
|
|
447
|
+
msg.sessionId = sessionId;
|
|
448
|
+
msg.saveImage = (path) => (0, save_media_1.saveImageHandler)(msg, path);
|
|
449
|
+
msg.saveVideo = (path) => (0, save_media_1.saveVideoHandler)(msg, path);
|
|
450
|
+
msg.saveDocument = (path) => (0, save_media_1.saveDocumentHandler)(msg, path);
|
|
451
|
+
msg.saveAudio = (path) => (0, save_media_1.saveAudioHandler)(msg, path);
|
|
452
|
+
(_p = callback.get(Defaults_1.CALLBACK_KEY.ON_MESSAGE_RECEIVED)) === null || _p === void 0 ? void 0 : _p(Object.assign({}, msg));
|
|
453
|
+
(_q = options.onMessageReceived) === null || _q === void 0 ? void 0 : _q.call(options, msg);
|
|
454
|
+
}
|
|
335
455
|
}
|
|
336
456
|
}));
|
|
337
457
|
return sock;
|
|
@@ -348,6 +468,45 @@ exports.startSessionWithPairingCode = startSessionWithPairingCode;
|
|
|
348
468
|
* @deprecated Use startSession method instead
|
|
349
469
|
*/
|
|
350
470
|
exports.startWhatsapp = exports.startSession;
|
|
471
|
+
/**
|
|
472
|
+
* Soft delete session - removes from memory but preserves MongoDB data for pairing code sessions
|
|
473
|
+
* @param sessionId Session ID to soft delete
|
|
474
|
+
*/
|
|
475
|
+
const softDeleteSession = (sessionId_1, ...args_1) => __awaiter(void 0, [sessionId_1, ...args_1], void 0, function* (sessionId, preserveData = false) {
|
|
476
|
+
const session = (0, exports.getSession)(sessionId);
|
|
477
|
+
try {
|
|
478
|
+
yield (session === null || session === void 0 ? void 0 : session.logout());
|
|
479
|
+
}
|
|
480
|
+
catch (error) { }
|
|
481
|
+
session === null || session === void 0 ? void 0 : session.end(undefined);
|
|
482
|
+
sessions.delete(sessionId);
|
|
483
|
+
// Only completely remove from MongoDB if not preserving data or not a pairing code session
|
|
484
|
+
if (!preserveData && !pairingCodeSessions.has(sessionId)) {
|
|
485
|
+
if (authCollection) {
|
|
486
|
+
try {
|
|
487
|
+
yield authCollection.deleteOne({ sessionId });
|
|
488
|
+
}
|
|
489
|
+
catch (error) {
|
|
490
|
+
console.error(`Error deleting session ${sessionId} from MongoDB:`, error);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
else if (pairingCodeSessions.has(sessionId)) {
|
|
495
|
+
// Preserving MongoDB data for pairing code session
|
|
496
|
+
}
|
|
497
|
+
// Hapus cache grup untuk session ini
|
|
498
|
+
try {
|
|
499
|
+
yield Utils_1.groupCache.clearSessionCache(sessionId);
|
|
500
|
+
}
|
|
501
|
+
catch (error) {
|
|
502
|
+
console.error(`Error clearing group cache for session ${sessionId}:`, error);
|
|
503
|
+
}
|
|
504
|
+
// Legacy: hapus juga dari file system jika ada
|
|
505
|
+
const dir = path_1.default.resolve(Defaults_1.CREDENTIALS.DIR_NAME, sessionId + Defaults_1.CREDENTIALS.PREFIX);
|
|
506
|
+
if (fs_1.default.existsSync(dir)) {
|
|
507
|
+
fs_1.default.rmSync(dir, { force: true, recursive: true });
|
|
508
|
+
}
|
|
509
|
+
});
|
|
351
510
|
const deleteSession = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
352
511
|
const session = (0, exports.getSession)(sessionId);
|
|
353
512
|
try {
|
|
@@ -356,11 +515,12 @@ const deleteSession = (sessionId) => __awaiter(void 0, void 0, void 0, function*
|
|
|
356
515
|
catch (error) { }
|
|
357
516
|
session === null || session === void 0 ? void 0 : session.end(undefined);
|
|
358
517
|
sessions.delete(sessionId);
|
|
518
|
+
// Hapus tracking pairing code session jika ada
|
|
519
|
+
pairingCodeSessions.delete(sessionId);
|
|
359
520
|
// Hapus juga dari MongoDB jika authCollection ada
|
|
360
521
|
if (authCollection) {
|
|
361
522
|
try {
|
|
362
523
|
yield authCollection.deleteOne({ sessionId });
|
|
363
|
-
console.log(`Session ${sessionId} deleted from MongoDB`);
|
|
364
524
|
}
|
|
365
525
|
catch (error) {
|
|
366
526
|
console.error(`Error deleting session ${sessionId} from MongoDB:`, error);
|
|
@@ -369,7 +529,6 @@ const deleteSession = (sessionId) => __awaiter(void 0, void 0, void 0, function*
|
|
|
369
529
|
// Hapus cache grup untuk session ini
|
|
370
530
|
try {
|
|
371
531
|
yield Utils_1.groupCache.clearSessionCache(sessionId);
|
|
372
|
-
console.log(`Group metadata cache for session ${sessionId} cleared`);
|
|
373
532
|
}
|
|
374
533
|
catch (error) {
|
|
375
534
|
console.error(`Error clearing group cache for session ${sessionId}:`, error);
|
|
@@ -479,7 +638,8 @@ const onMessageUpdate = (listener) => {
|
|
|
479
638
|
};
|
|
480
639
|
exports.onMessageUpdate = onMessageUpdate;
|
|
481
640
|
const onPairingCode = (listener) => {
|
|
482
|
-
callback
|
|
641
|
+
// Set callback ke registry dengan key yang benar
|
|
642
|
+
callback.set(Defaults_1.CALLBACK_KEY.ON_PAIRING_CODE, listener);
|
|
483
643
|
};
|
|
484
644
|
exports.onPairingCode = onPairingCode;
|
|
485
645
|
/**
|
|
@@ -511,7 +671,6 @@ exports.loadSessionsFromMongo = loadSessionsFromMongo;
|
|
|
511
671
|
const setMongoDBNames = (dbName = "wa_session", collectionName = "auth") => {
|
|
512
672
|
Defaults_1.CREDENTIALS.MONGO_DB_NAME = dbName;
|
|
513
673
|
Defaults_1.CREDENTIALS.MONGO_COLLECTION_NAME = collectionName;
|
|
514
|
-
console.log(`MongoDB names configured: database="${dbName}", collection="${collectionName}"`);
|
|
515
674
|
};
|
|
516
675
|
exports.setMongoDBNames = setMongoDBNames;
|
|
517
676
|
/**
|
|
@@ -555,36 +714,115 @@ const reconnect = (sessionId) => __awaiter(void 0, void 0, void 0, function* ()
|
|
|
555
714
|
}
|
|
556
715
|
// Tunggu sedikit waktu untuk memastikan cleanup selesai
|
|
557
716
|
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
|
|
717
|
+
// Cek jika ini session pairing code dari tracking terlebih dahulu
|
|
718
|
+
const pairingInfo = pairingCodeSessions.get(sessionId);
|
|
719
|
+
if (pairingInfo) {
|
|
720
|
+
// Ini adalah session pairing code, gunakan metode pairing code untuk reconnect
|
|
564
721
|
try {
|
|
565
|
-
|
|
566
|
-
|
|
722
|
+
// Reset retry count untuk session ini
|
|
723
|
+
retryCount.delete(sessionId);
|
|
724
|
+
yield (0, exports.startSessionWithPairingCode)(sessionId, pairingInfo.phoneNumber, Object.assign(Object.assign({}, pairingInfo.options), { printQR: false,
|
|
567
725
|
// Tambahkan callback khusus untuk reconnect
|
|
568
|
-
onConnected: () => {
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
726
|
+
onConnected: () => {
|
|
727
|
+
// Pairing code session reconnected successfully
|
|
728
|
+
}, onDisconnected: () => {
|
|
729
|
+
// Pairing code session disconnected after reconnect
|
|
730
|
+
} }));
|
|
572
731
|
// Periksa jika session berhasil dimulai
|
|
573
732
|
return !!(0, exports.getSession)(sessionId);
|
|
574
733
|
}
|
|
575
734
|
catch (startError) {
|
|
735
|
+
console.error(`Failed to reconnect pairing code session ${sessionId}:`, startError.message);
|
|
576
736
|
return false;
|
|
577
737
|
}
|
|
578
738
|
}
|
|
579
739
|
else {
|
|
580
|
-
|
|
740
|
+
// Cek jika data session tersedia di MongoDB untuk session biasa
|
|
741
|
+
yield initMongo();
|
|
742
|
+
const sessionExists = yield shouldLoadSession(sessionId);
|
|
743
|
+
if (sessionExists) {
|
|
744
|
+
// Session biasa, gunakan metode startSession normal
|
|
745
|
+
try {
|
|
746
|
+
yield (0, exports.startSession)(sessionId, {
|
|
747
|
+
printQR: false,
|
|
748
|
+
// Tambahkan callback khusus untuk reconnect
|
|
749
|
+
onConnected: () => {
|
|
750
|
+
// Session reconnected successfully
|
|
751
|
+
},
|
|
752
|
+
onDisconnected: () => {
|
|
753
|
+
// Session disconnected after reconnect
|
|
754
|
+
},
|
|
755
|
+
onQRUpdated: (qr) => {
|
|
756
|
+
// QR code updated for reconnecting session
|
|
757
|
+
}
|
|
758
|
+
});
|
|
759
|
+
// Periksa jika session berhasil dimulai
|
|
760
|
+
return !!(0, exports.getSession)(sessionId);
|
|
761
|
+
}
|
|
762
|
+
catch (startError) {
|
|
763
|
+
console.error(`Failed to reconnect session ${sessionId}:`, startError.message);
|
|
764
|
+
return false;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
else {
|
|
768
|
+
// No session data found in MongoDB
|
|
769
|
+
return false;
|
|
770
|
+
}
|
|
581
771
|
}
|
|
582
772
|
}
|
|
583
773
|
catch (error) {
|
|
774
|
+
console.error(`Error during reconnect for session ${sessionId}:`, error.message);
|
|
584
775
|
return false;
|
|
585
776
|
}
|
|
586
777
|
});
|
|
587
778
|
exports.reconnect = reconnect;
|
|
779
|
+
/**
|
|
780
|
+
* Reconnect all pairing code sessions that are tracked
|
|
781
|
+
* Useful for bulk reconnection after system restart
|
|
782
|
+
*/
|
|
783
|
+
const reconnectAllPairingCodeSessions = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
784
|
+
const results = {};
|
|
785
|
+
for (const [sessionId, sessionInfo] of pairingCodeSessions.entries()) {
|
|
786
|
+
try {
|
|
787
|
+
const success = yield (0, exports.reconnect)(sessionId);
|
|
788
|
+
results[sessionId] = success;
|
|
789
|
+
// Add delay between reconnection attempts
|
|
790
|
+
yield (0, create_delay_1.createDelay)(2000);
|
|
791
|
+
}
|
|
792
|
+
catch (error) {
|
|
793
|
+
console.error(`Error reconnecting pairing code session ${sessionId}:`, error.message);
|
|
794
|
+
results[sessionId] = false;
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
return results;
|
|
798
|
+
});
|
|
799
|
+
exports.reconnectAllPairingCodeSessions = reconnectAllPairingCodeSessions;
|
|
800
|
+
/**
|
|
801
|
+
* Get all tracked pairing code sessions
|
|
802
|
+
* @returns Array of session IDs that were created with pairing code
|
|
803
|
+
*/
|
|
804
|
+
const getPairingCodeSessions = () => {
|
|
805
|
+
return Array.from(pairingCodeSessions.keys());
|
|
806
|
+
};
|
|
807
|
+
exports.getPairingCodeSessions = getPairingCodeSessions;
|
|
808
|
+
/**
|
|
809
|
+
* Get session status information
|
|
810
|
+
* @param sessionId Session ID to check
|
|
811
|
+
* @returns Object with session status information
|
|
812
|
+
*/
|
|
813
|
+
const getSessionStatus = (sessionId) => {
|
|
814
|
+
const isRunning = !!(0, exports.getSession)(sessionId);
|
|
815
|
+
const isPairingCodeSession = pairingCodeSessions.has(sessionId);
|
|
816
|
+
const retryAttempts = retryCount.get(sessionId) || 0;
|
|
817
|
+
return {
|
|
818
|
+
sessionId,
|
|
819
|
+
isRunning,
|
|
820
|
+
isPairingCodeSession,
|
|
821
|
+
retryAttempts,
|
|
822
|
+
hasCredentials: isRunning ? true : null // null means unknown when not running
|
|
823
|
+
};
|
|
824
|
+
};
|
|
825
|
+
exports.getSessionStatus = getSessionStatus;
|
|
588
826
|
// Fungsi baru untuk mendapatkan konfigurasi TTL cache grup
|
|
589
827
|
const setGroupCacheConfig = (options) => {
|
|
590
828
|
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.7",
|
|
4
4
|
"description": "Multi Session Whatsapp Library with MongoDB Integration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"@hapi/boom": "^10.0.1",
|
|
20
20
|
"@types/node-cache": "^4.1.3",
|
|
21
21
|
"@types/qrcode": "^1.5.5",
|
|
22
|
-
"
|
|
22
|
+
"aws4": "^1.13.2",
|
|
23
|
+
"baileys": "github:WhiskeySockets/Baileys#next",
|
|
23
24
|
"dotenv": "^16.5.0",
|
|
24
25
|
"link-preview-js": "^3.0.14",
|
|
25
26
|
"mime": "^3.0.0",
|
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,37 @@ startApp().catch(err => {
|
|
|
529
773
|
|
|
530
774
|
## Changelog
|
|
531
775
|
|
|
532
|
-
### v3.9.
|
|
776
|
+
### v3.9.7 (latest)
|
|
777
|
+
- **Enhanced Message Processing for Group Chats**: Fixed issues with group message handling and improved message processing architecture
|
|
778
|
+
- **Multiple Message Processing**: Event handler `messages.upsert` now processes all messages in array instead of only the first message
|
|
779
|
+
- **Improved Message Filtering**: Added intelligent filtering to skip protocol messages and empty messages while preserving valid group messages
|
|
780
|
+
- **Enhanced Group Message Support**: Better detection and processing of group messages with participant information
|
|
781
|
+
- **Group vs Private Chat Detection**: Better differentiation between group and private messages
|
|
782
|
+
- **Improved Error Recovery**: Better error handling without changing existing error patterns
|
|
783
|
+
|
|
784
|
+
### v3.9.6
|
|
785
|
+
- **Enhanced Pairing Code Support**: Added comprehensive pairing code session management with auto-reconnect capabilities
|
|
786
|
+
- New `startSessionWithPairingCode()` function for creating sessions using pairing codes
|
|
787
|
+
- Intelligent session tracking system that preserves pairing code session data across disconnections
|
|
788
|
+
- Enhanced auto-reconnect mechanism that differentiates between QR code and pairing code sessions
|
|
789
|
+
- Session persistence in MongoDB for pairing code sessions to enable seamless reconnection
|
|
790
|
+
- **New Utility Functions for Session Management**:
|
|
791
|
+
- `reconnect(sessionId)` - Manual reconnection for any session type
|
|
792
|
+
- `reconnectAllPairingCodeSessions()` - Bulk reconnection for all tracked pairing code sessions
|
|
793
|
+
- `getPairingCodeSessions()` - Get list of all pairing code session IDs
|
|
794
|
+
- `getSessionStatus(sessionId)` - Get detailed session status information including session type
|
|
795
|
+
- **QR Data Raw for Frontend Integration**: Simplified QR handling optimized for frontend development
|
|
796
|
+
- Cleaned up QR callback to provide only essential QR data raw for frontend processing
|
|
797
|
+
- Removed unnecessary QR string complexity from callbacks for better performance
|
|
798
|
+
- QR data can be directly used with any frontend QR code library (React, Vue, Angular, etc.)
|
|
799
|
+
- Terminal QR display handled automatically via `printQR` option
|
|
800
|
+
- **Breaking Changes**:
|
|
801
|
+
- Simplified `onQRUpdated` callback signature: removed `qrString` parameter, now only provides raw QR data
|
|
802
|
+
- Session-level `onQRUpdated` option simplified from `(qr, qrString)` to `(qr)` only
|
|
803
|
+
- **Enhanced Session Persistence**: Pairing code sessions maintain authentication state in MongoDB during disconnections
|
|
804
|
+
- **Improved Error Handling**: Better error recovery and automatic session restoration for pairing code sessions
|
|
805
|
+
|
|
806
|
+
### v3.9.5
|
|
533
807
|
- New `deleteMessage()` function for deleting messages
|
|
534
808
|
- Support for deleting both own messages and others' messages (requires admin permissions in groups)
|
|
535
809
|
- Auto-delete message utility function example
|
|
@@ -592,4 +866,4 @@ startApp().catch(err => {
|
|
|
592
866
|
|
|
593
867
|
## License
|
|
594
868
|
|
|
595
|
-
ISC
|
|
869
|
+
ISC
|