wa-multi-mongodb 3.10.2 → 3.10.3
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/Defaults/index.js +4 -9
- package/dist/Error/index.js +1 -5
- package/dist/Messaging/index.d.ts +1 -1
- package/dist/Messaging/index.js +123 -137
- package/dist/Profile/index.d.ts +1 -1
- package/dist/Profile/index.js +6 -10
- package/dist/Socket/index.d.ts +1 -1
- package/dist/Socket/index.d.ts.map +1 -1
- package/dist/Socket/index.js +134 -200
- package/dist/Types/index.js +1 -2
- package/dist/Types/profile.js +1 -2
- package/dist/Utils/create-delay.js +2 -7
- package/dist/Utils/error.js +1 -4
- package/dist/Utils/group-cache.js +8 -15
- package/dist/Utils/index.d.ts +5 -5
- package/dist/Utils/index.js +5 -21
- package/dist/Utils/is-exist.d.ts +1 -1
- package/dist/Utils/is-exist.js +7 -10
- package/dist/Utils/lid-utils.js +13 -20
- package/dist/Utils/message-status.d.ts +1 -1
- package/dist/Utils/message-status.js +7 -11
- package/dist/Utils/mongo-auth-state.js +10 -13
- package/dist/Utils/phone-to-jid.js +6 -14
- package/dist/Utils/save-media.d.ts +1 -1
- package/dist/Utils/save-media.js +16 -26
- package/dist/cjs/Defaults/index.d.ts +21 -0
- package/dist/cjs/Defaults/index.d.ts.map +1 -0
- package/dist/cjs/Defaults/index.js +31 -0
- package/dist/cjs/Error/index.d.ts +5 -0
- package/dist/cjs/Error/index.d.ts.map +1 -0
- package/dist/cjs/Error/index.js +14 -0
- package/dist/cjs/Messaging/index.d.ts +45 -0
- package/dist/cjs/Messaging/index.d.ts.map +1 -0
- package/dist/cjs/Messaging/index.js +784 -0
- package/dist/cjs/Profile/index.d.ts +9 -0
- package/dist/cjs/Profile/index.d.ts.map +1 -0
- package/dist/cjs/Profile/index.js +34 -0
- package/dist/cjs/Socket/index.d.ts +105 -0
- package/dist/cjs/Socket/index.d.ts.map +1 -0
- package/dist/cjs/Socket/index.js +875 -0
- package/dist/cjs/Types/index.d.ts +74 -0
- package/dist/cjs/Types/index.d.ts.map +1 -0
- package/dist/cjs/Types/index.js +2 -0
- package/dist/cjs/Types/profile.d.ts +5 -0
- package/dist/cjs/Types/profile.d.ts.map +1 -0
- package/dist/cjs/Types/profile.js +2 -0
- package/dist/cjs/Utils/create-delay.d.ts +17 -0
- package/dist/cjs/Utils/create-delay.d.ts.map +1 -0
- package/dist/cjs/Utils/create-delay.js +38 -0
- package/dist/cjs/Utils/error.d.ts +4 -0
- package/dist/cjs/Utils/error.d.ts.map +1 -0
- package/dist/cjs/Utils/error.js +8 -0
- package/dist/cjs/Utils/group-cache.d.ts +23 -0
- package/dist/cjs/Utils/group-cache.d.ts.map +1 -0
- package/dist/cjs/Utils/group-cache.js +176 -0
- package/dist/cjs/Utils/index.d.ts +6 -0
- package/dist/cjs/Utils/index.d.ts.map +1 -0
- package/dist/cjs/Utils/index.js +23 -0
- package/dist/cjs/Utils/is-exist.d.ts +6 -0
- package/dist/cjs/Utils/is-exist.d.ts.map +1 -0
- package/dist/cjs/Utils/is-exist.js +53 -0
- package/dist/cjs/Utils/lid-utils.d.ts +26 -0
- package/dist/cjs/Utils/lid-utils.d.ts.map +1 -0
- package/dist/cjs/Utils/lid-utils.js +81 -0
- package/dist/cjs/Utils/message-status.d.ts +4 -0
- package/dist/cjs/Utils/message-status.d.ts.map +1 -0
- package/dist/cjs/Utils/message-status.js +18 -0
- package/dist/cjs/Utils/mongo-auth-state.d.ts +15 -0
- package/dist/cjs/Utils/mongo-auth-state.d.ts.map +1 -0
- package/dist/cjs/Utils/mongo-auth-state.js +109 -0
- package/dist/cjs/Utils/phone-to-jid.d.ts +17 -0
- package/dist/cjs/Utils/phone-to-jid.d.ts.map +1 -0
- package/dist/cjs/Utils/phone-to-jid.js +51 -0
- package/dist/cjs/Utils/save-media.d.ts +6 -0
- package/dist/cjs/Utils/save-media.d.ts.map +1 -0
- package/dist/cjs/Utils/save-media.js +55 -0
- package/dist/cjs/index.d.ts +8 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +46 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.js +7 -46
- package/package.json +57 -42
|
@@ -0,0 +1,875 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
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
|
+
exports.setMongoCollection = setMongoCollection;
|
|
50
|
+
const baileys_1 = __importStar(require("baileys"));
|
|
51
|
+
const path_1 = __importDefault(require("path"));
|
|
52
|
+
const fs_1 = __importDefault(require("fs"));
|
|
53
|
+
const qrcode_1 = __importDefault(require("qrcode"));
|
|
54
|
+
const pino_1 = __importDefault(require("pino"));
|
|
55
|
+
const Defaults_1 = require("../Defaults");
|
|
56
|
+
const save_media_1 = require("../Utils/save-media");
|
|
57
|
+
const Utils_1 = require("../Utils");
|
|
58
|
+
const Error_1 = require("../Error");
|
|
59
|
+
const message_status_1 = require("../Utils/message-status");
|
|
60
|
+
const mongodb_1 = require("mongodb");
|
|
61
|
+
const mongo_auth_state_1 = require("../Utils/mongo-auth-state");
|
|
62
|
+
const create_delay_1 = require("../Utils/create-delay");
|
|
63
|
+
const sessions = new Map();
|
|
64
|
+
const callback = new Map();
|
|
65
|
+
const retryCount = new Map();
|
|
66
|
+
// Tambahkan Map untuk melacak session yang menggunakan pairing code
|
|
67
|
+
const pairingCodeSessions = new Map();
|
|
68
|
+
const P = (0, pino_1.default)({
|
|
69
|
+
level: "silent",
|
|
70
|
+
});
|
|
71
|
+
// Tambahkan variabel global untuk koneksi MongoDB dan collection
|
|
72
|
+
let mongoClient;
|
|
73
|
+
let authCollection = null;
|
|
74
|
+
let mongoURI = process.env.MONGODB_URI || "mongodb://localhost:27017";
|
|
75
|
+
/**
|
|
76
|
+
* Set MongoDB URI for connection
|
|
77
|
+
* This function will be used to configure MongoDB connection with just the URI
|
|
78
|
+
*
|
|
79
|
+
* @param uri MongoDB connection URI
|
|
80
|
+
*/
|
|
81
|
+
const setMongoURI = (uri) => __awaiter(void 0, void 0, void 0, function* () {
|
|
82
|
+
mongoURI = uri;
|
|
83
|
+
// Configure group cache MongoDB connection as well
|
|
84
|
+
yield Utils_1.groupCache.setMongoURI(uri);
|
|
85
|
+
// Reset MongoDB client and collection to ensure they are recreated with new URI
|
|
86
|
+
if (mongoClient) {
|
|
87
|
+
try {
|
|
88
|
+
yield mongoClient.close();
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
console.error("Error closing existing MongoDB connection:", error);
|
|
92
|
+
}
|
|
93
|
+
mongoClient = undefined;
|
|
94
|
+
authCollection = null;
|
|
95
|
+
}
|
|
96
|
+
// MongoDB URI configured successfully - removed console.log for npm package
|
|
97
|
+
});
|
|
98
|
+
exports.setMongoURI = setMongoURI;
|
|
99
|
+
function setMongoCollection(collection) {
|
|
100
|
+
authCollection = collection;
|
|
101
|
+
}
|
|
102
|
+
function initMongo() {
|
|
103
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
104
|
+
if (!authCollection) {
|
|
105
|
+
if (!mongoClient) {
|
|
106
|
+
mongoClient = new mongodb_1.MongoClient(mongoURI);
|
|
107
|
+
yield mongoClient.connect();
|
|
108
|
+
}
|
|
109
|
+
// Gunakan variabel dari CREDENTIALS
|
|
110
|
+
const dbName = Defaults_1.CREDENTIALS.MONGO_DB_NAME;
|
|
111
|
+
const collectionName = Defaults_1.CREDENTIALS.MONGO_COLLECTION_NAME;
|
|
112
|
+
authCollection = mongoClient.db(dbName).collection(collectionName);
|
|
113
|
+
// console.log(`MongoDB initialized with database "${dbName}" and collection "${collectionName}"`);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const startSession = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (sessionId = "mysession", options = { printQR: true }) {
|
|
118
|
+
if (isSessionExistAndRunning(sessionId))
|
|
119
|
+
throw new Error_1.WhatsappError(Defaults_1.Messages.sessionAlreadyExist(sessionId));
|
|
120
|
+
yield initMongo();
|
|
121
|
+
const { version } = yield (0, baileys_1.fetchLatestBaileysVersion)();
|
|
122
|
+
const startSocket = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
123
|
+
const { state, saveCreds } = yield (0, mongo_auth_state_1.useMongoAuthState)(sessionId, authCollection);
|
|
124
|
+
const sock = (0, baileys_1.default)({
|
|
125
|
+
version,
|
|
126
|
+
auth: state,
|
|
127
|
+
logger: P,
|
|
128
|
+
markOnlineOnConnect: false,
|
|
129
|
+
browser: baileys_1.Browsers.ubuntu("Chrome"),
|
|
130
|
+
// Configure caching group metadata using our hybrid implementation with session ID
|
|
131
|
+
cachedGroupMetadata: (jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
132
|
+
return yield Utils_1.groupCache.get(sessionId, jid);
|
|
133
|
+
})
|
|
134
|
+
});
|
|
135
|
+
sessions.set(sessionId, Object.assign({}, sock));
|
|
136
|
+
try {
|
|
137
|
+
sock.ev.process((events) => __awaiter(void 0, void 0, void 0, function* () {
|
|
138
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
139
|
+
if (events["connection.update"]) {
|
|
140
|
+
const update = events["connection.update"];
|
|
141
|
+
const { connection, lastDisconnect } = update;
|
|
142
|
+
if (update.qr) {
|
|
143
|
+
// Print QR to console if requested
|
|
144
|
+
if (options.printQR) {
|
|
145
|
+
qrcode_1.default.toString(update.qr, {
|
|
146
|
+
type: 'terminal',
|
|
147
|
+
small: true,
|
|
148
|
+
margin: 1
|
|
149
|
+
}, (err, qrString) => {
|
|
150
|
+
if (!err) {
|
|
151
|
+
console.log(qrString);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// Send QR data raw to callback for frontend processing
|
|
156
|
+
(_a = callback.get(Defaults_1.CALLBACK_KEY.ON_QR)) === null || _a === void 0 ? void 0 : _a({
|
|
157
|
+
sessionId,
|
|
158
|
+
qr: update.qr
|
|
159
|
+
});
|
|
160
|
+
(_b = options.onQRUpdated) === null || _b === void 0 ? void 0 : _b.call(options, update.qr);
|
|
161
|
+
}
|
|
162
|
+
if (connection == "connecting") {
|
|
163
|
+
(_c = callback.get(Defaults_1.CALLBACK_KEY.ON_CONNECTING)) === null || _c === void 0 ? void 0 : _c(sessionId);
|
|
164
|
+
(_d = options.onConnecting) === null || _d === void 0 ? void 0 : _d.call(options);
|
|
165
|
+
}
|
|
166
|
+
if (connection === "close") {
|
|
167
|
+
const code = (_f = (_e = lastDisconnect === null || lastDisconnect === void 0 ? void 0 : lastDisconnect.error) === null || _e === void 0 ? void 0 : _e.output) === null || _f === void 0 ? void 0 : _f.statusCode;
|
|
168
|
+
let retryAttempt = (_g = retryCount.get(sessionId)) !== null && _g !== void 0 ? _g : 0;
|
|
169
|
+
let shouldRetry;
|
|
170
|
+
if (code != baileys_1.DisconnectReason.loggedOut && retryAttempt < 10) {
|
|
171
|
+
shouldRetry = true;
|
|
172
|
+
}
|
|
173
|
+
if (shouldRetry) {
|
|
174
|
+
retryAttempt++;
|
|
175
|
+
retryCount.set(sessionId, retryAttempt);
|
|
176
|
+
startSocket();
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
retryCount.delete(sessionId);
|
|
180
|
+
// For pairing code sessions, preserve data for future reconnection
|
|
181
|
+
if (pairingCodeSessions.has(sessionId)) {
|
|
182
|
+
yield softDeleteSession(sessionId, true);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
// For regular sessions, completely delete
|
|
186
|
+
yield softDeleteSession(sessionId, false);
|
|
187
|
+
}
|
|
188
|
+
(_h = callback.get(Defaults_1.CALLBACK_KEY.ON_DISCONNECTED)) === null || _h === void 0 ? void 0 : _h(sessionId);
|
|
189
|
+
(_j = options.onDisconnected) === null || _j === void 0 ? void 0 : _j.call(options);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (connection == "open") {
|
|
193
|
+
retryCount.delete(sessionId);
|
|
194
|
+
(_k = callback.get(Defaults_1.CALLBACK_KEY.ON_CONNECTED)) === null || _k === void 0 ? void 0 : _k(sessionId);
|
|
195
|
+
(_l = options.onConnected) === null || _l === void 0 ? void 0 : _l.call(options);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (events["creds.update"]) {
|
|
199
|
+
yield saveCreds();
|
|
200
|
+
}
|
|
201
|
+
// Menangani event update data grup
|
|
202
|
+
if (events["groups.update"]) {
|
|
203
|
+
const updates = events["groups.update"];
|
|
204
|
+
for (const update of updates) {
|
|
205
|
+
try {
|
|
206
|
+
// Dapatkan metadata grup terbaru dan simpan ke cache dengan sessionId
|
|
207
|
+
const metadata = yield sock.groupMetadata(update.id);
|
|
208
|
+
yield Utils_1.groupCache.set(sessionId, update.id, metadata);
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
console.error(`Error updating group metadata in cache: ${error}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// Menangani event perubahan peserta grup
|
|
216
|
+
if (events["group-participants.update"]) {
|
|
217
|
+
const update = events["group-participants.update"];
|
|
218
|
+
try {
|
|
219
|
+
// Dapatkan metadata grup terbaru dan simpan ke cache dengan sessionId
|
|
220
|
+
const metadata = yield sock.groupMetadata(update.id);
|
|
221
|
+
yield Utils_1.groupCache.set(sessionId, update.id, metadata);
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
console.error(`Error updating group participants in cache: ${error}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (events["messages.update"]) {
|
|
228
|
+
const msg = events["messages.update"][0];
|
|
229
|
+
const data = Object.assign({ sessionId: sessionId, messageStatus: (0, message_status_1.parseMessageStatusCodeToReadable)(msg.update.status) }, msg);
|
|
230
|
+
(_m = callback.get(Defaults_1.CALLBACK_KEY.ON_MESSAGE_UPDATED)) === null || _m === void 0 ? void 0 : _m(sessionId, data);
|
|
231
|
+
(_o = options.onMessageUpdated) === null || _o === void 0 ? void 0 : _o.call(options, data);
|
|
232
|
+
}
|
|
233
|
+
if (events["messages.upsert"]) {
|
|
234
|
+
const messages = events["messages.upsert"].messages || [];
|
|
235
|
+
for (const rawMsg of messages) {
|
|
236
|
+
// Skip protocol messages and system messages
|
|
237
|
+
if ((_p = rawMsg.message) === null || _p === void 0 ? void 0 : _p.protocolMessage) {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
// Skip messages without content
|
|
241
|
+
if (!rawMsg.message || Object.keys(rawMsg.message).length === 0) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
const msg = rawMsg;
|
|
245
|
+
msg.sessionId = sessionId;
|
|
246
|
+
msg.saveImage = (path) => (0, save_media_1.saveImageHandler)(msg, path);
|
|
247
|
+
msg.saveVideo = (path) => (0, save_media_1.saveVideoHandler)(msg, path);
|
|
248
|
+
msg.saveDocument = (path) => (0, save_media_1.saveDocumentHandler)(msg, path);
|
|
249
|
+
msg.saveAudio = (path) => (0, save_media_1.saveAudioHandler)(msg, path);
|
|
250
|
+
(_q = callback.get(Defaults_1.CALLBACK_KEY.ON_MESSAGE_RECEIVED)) === null || _q === void 0 ? void 0 : _q(Object.assign({}, msg));
|
|
251
|
+
(_r = options.onMessageReceived) === null || _r === void 0 ? void 0 : _r.call(options, msg);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}));
|
|
255
|
+
return sock;
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
// console.log("SOCKET ERROR", error);
|
|
259
|
+
return sock;
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
return startSocket();
|
|
263
|
+
});
|
|
264
|
+
exports.startSession = startSession;
|
|
265
|
+
/**
|
|
266
|
+
* Start WhatsApp session using pairing code method
|
|
267
|
+
* This is the recommended way to create sessions with pairing code
|
|
268
|
+
*
|
|
269
|
+
* @param sessionId Unique session identifier
|
|
270
|
+
* @param phoneNumber Phone number with country code (without + prefix)
|
|
271
|
+
* @param options Optional configuration for the session
|
|
272
|
+
* @returns Promise<WASocket> The WhatsApp socket instance
|
|
273
|
+
*/
|
|
274
|
+
const startSessionWithPairingCode = (sessionId_1, phoneNumber_1, ...args_1) => __awaiter(void 0, [sessionId_1, phoneNumber_1, ...args_1], void 0, function* (sessionId, phoneNumber, options = {}) {
|
|
275
|
+
if (isSessionExistAndRunning(sessionId))
|
|
276
|
+
throw new Error_1.WhatsappError(Defaults_1.Messages.sessionAlreadyExist(sessionId));
|
|
277
|
+
// Simpan informasi session pairing code untuk auto-reconnect
|
|
278
|
+
pairingCodeSessions.set(sessionId, { phoneNumber, options });
|
|
279
|
+
yield initMongo();
|
|
280
|
+
const { version } = yield (0, baileys_1.fetchLatestBaileysVersion)();
|
|
281
|
+
const startSocket = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
282
|
+
var _a, _b;
|
|
283
|
+
const { state, saveCreds } = yield (0, mongo_auth_state_1.useMongoAuthState)(sessionId, authCollection);
|
|
284
|
+
const sock = (0, baileys_1.default)({
|
|
285
|
+
version,
|
|
286
|
+
auth: state,
|
|
287
|
+
logger: P,
|
|
288
|
+
markOnlineOnConnect: false,
|
|
289
|
+
browser: baileys_1.Browsers.ubuntu("Chrome"),
|
|
290
|
+
// Opsi tambahan untuk meningkatkan kompatibilitas
|
|
291
|
+
linkPreviewImageThumbnailWidth: 300,
|
|
292
|
+
generateHighQualityLinkPreview: true,
|
|
293
|
+
syncFullHistory: false, // Sinkronisasi hanya riwayat baru
|
|
294
|
+
connectTimeoutMs: 60000, // Timeout koneksi ditingkatkan
|
|
295
|
+
printQRInTerminal: false, // QR tidak dicetak untuk pairing code
|
|
296
|
+
// Configure caching group metadata using our hybrid implementation with session ID
|
|
297
|
+
cachedGroupMetadata: (jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
298
|
+
return yield Utils_1.groupCache.get(sessionId, jid);
|
|
299
|
+
})
|
|
300
|
+
});
|
|
301
|
+
sessions.set(sessionId, Object.assign({}, sock));
|
|
302
|
+
try {
|
|
303
|
+
if (!sock.authState.creds.registered) {
|
|
304
|
+
// Pastikan kita mendapatkan kode pairing dan menampilkannya dengan jelas
|
|
305
|
+
try {
|
|
306
|
+
// Tambahkan delay untuk memastikan state sudah siap
|
|
307
|
+
yield new Promise(resolve => setTimeout(resolve, 2000));
|
|
308
|
+
// Hapus awalan + dari nomor telepon jika ada
|
|
309
|
+
const phoneNumberFormatted = phoneNumber.replace(/^\+/, '');
|
|
310
|
+
// Memanggil fungsi requestPairingCode dengan nomor telepon yang sudah dibersihkan
|
|
311
|
+
const code = yield sock.requestPairingCode(phoneNumberFormatted);
|
|
312
|
+
// Pastikan kode ada dan merupakan string
|
|
313
|
+
if (code && typeof code === 'string') {
|
|
314
|
+
console.log(`Pairing code untuk session ${sessionId}: ${code}`);
|
|
315
|
+
// Panggil callback yang terdaftar
|
|
316
|
+
(_a = callback.get(Defaults_1.CALLBACK_KEY.ON_PAIRING_CODE)) === null || _a === void 0 ? void 0 : _a(sessionId, code);
|
|
317
|
+
(_b = options.onPairingCode) === null || _b === void 0 ? void 0 : _b.call(options, code);
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
console.error("Error: Kode pairing tidak valid atau kosong");
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
console.error("Error saat meminta kode pairing:", error);
|
|
325
|
+
throw new Error_1.WhatsappError(`Gagal mendapatkan kode pairing: ${error.message || String(error)}`);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
sock.ev.process((events) => __awaiter(void 0, void 0, void 0, function* () {
|
|
329
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
330
|
+
if (events["connection.update"]) {
|
|
331
|
+
const update = events["connection.update"];
|
|
332
|
+
const { connection, lastDisconnect } = update;
|
|
333
|
+
if (update.qr) {
|
|
334
|
+
// Send QR data raw to callback for frontend processing
|
|
335
|
+
(_a = callback.get(Defaults_1.CALLBACK_KEY.ON_QR)) === null || _a === void 0 ? void 0 : _a({
|
|
336
|
+
sessionId,
|
|
337
|
+
qr: update.qr
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
if (connection == "connecting") {
|
|
341
|
+
(_b = callback.get(Defaults_1.CALLBACK_KEY.ON_CONNECTING)) === null || _b === void 0 ? void 0 : _b(sessionId);
|
|
342
|
+
(_c = options.onConnecting) === null || _c === void 0 ? void 0 : _c.call(options);
|
|
343
|
+
}
|
|
344
|
+
if (connection === "close") {
|
|
345
|
+
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;
|
|
346
|
+
let retryAttempt = (_f = retryCount.get(sessionId)) !== null && _f !== void 0 ? _f : 0;
|
|
347
|
+
let shouldRetry;
|
|
348
|
+
if (code != baileys_1.DisconnectReason.loggedOut && retryAttempt < 10) {
|
|
349
|
+
shouldRetry = true;
|
|
350
|
+
}
|
|
351
|
+
if (shouldRetry) {
|
|
352
|
+
retryAttempt++;
|
|
353
|
+
retryCount.set(sessionId, retryAttempt);
|
|
354
|
+
// Untuk session pairing code, coba reconnect dengan metode yang tepat
|
|
355
|
+
try {
|
|
356
|
+
// Tunggu sebentar sebelum reconnect
|
|
357
|
+
yield (0, create_delay_1.createDelay)(2000);
|
|
358
|
+
startSocket();
|
|
359
|
+
}
|
|
360
|
+
catch (reconnectError) {
|
|
361
|
+
console.error(`Auto-reconnect failed for session ${sessionId}:`, reconnectError.message);
|
|
362
|
+
// Jika reconnect gagal beberapa kali, coba dengan pairing code lagi (jika masih dalam 3 attempt pertama)
|
|
363
|
+
if (retryAttempt <= 3 && pairingCodeSessions.has(sessionId)) {
|
|
364
|
+
const sessionInfo = pairingCodeSessions.get(sessionId);
|
|
365
|
+
// Bersihkan session lama
|
|
366
|
+
sessions.delete(sessionId);
|
|
367
|
+
// Coba mulai ulang dengan pairing code baru
|
|
368
|
+
setTimeout(() => {
|
|
369
|
+
startSocket().catch(err => {
|
|
370
|
+
console.error(`Failed to restart with pairing code for session ${sessionId}:`, err);
|
|
371
|
+
});
|
|
372
|
+
}, 3000);
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
// Jika sudah terlalu banyak gagal, panggil startSocket biasa
|
|
376
|
+
startSocket();
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
retryCount.delete(sessionId);
|
|
382
|
+
// For pairing code sessions, preserve data for future reconnection
|
|
383
|
+
if (pairingCodeSessions.has(sessionId)) {
|
|
384
|
+
yield softDeleteSession(sessionId, true);
|
|
385
|
+
// Don't remove from pairing code tracking completely to allow manual reconnection
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
pairingCodeSessions.delete(sessionId); // Only delete from tracking if it's not a pairing code session
|
|
389
|
+
yield softDeleteSession(sessionId, false);
|
|
390
|
+
}
|
|
391
|
+
(_g = callback.get(Defaults_1.CALLBACK_KEY.ON_DISCONNECTED)) === null || _g === void 0 ? void 0 : _g(sessionId);
|
|
392
|
+
(_h = options.onDisconnected) === null || _h === void 0 ? void 0 : _h.call(options);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (connection == "open") {
|
|
396
|
+
retryCount.delete(sessionId);
|
|
397
|
+
(_j = callback.get(Defaults_1.CALLBACK_KEY.ON_CONNECTED)) === null || _j === void 0 ? void 0 : _j(sessionId);
|
|
398
|
+
(_k = options.onConnected) === null || _k === void 0 ? void 0 : _k.call(options);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
if (events["creds.update"]) {
|
|
402
|
+
yield saveCreds();
|
|
403
|
+
}
|
|
404
|
+
// Menangani event update data grup
|
|
405
|
+
if (events["groups.update"]) {
|
|
406
|
+
const updates = events["groups.update"];
|
|
407
|
+
for (const update of updates) {
|
|
408
|
+
try {
|
|
409
|
+
// Dapatkan metadata grup terbaru dan simpan ke cache dengan sessionId
|
|
410
|
+
const metadata = yield sock.groupMetadata(update.id);
|
|
411
|
+
yield Utils_1.groupCache.set(sessionId, update.id, metadata);
|
|
412
|
+
}
|
|
413
|
+
catch (error) {
|
|
414
|
+
console.error(`Error updating group metadata in cache: ${error}`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
// Menangani event perubahan peserta grup
|
|
419
|
+
if (events["group-participants.update"]) {
|
|
420
|
+
const update = events["group-participants.update"];
|
|
421
|
+
try {
|
|
422
|
+
// Dapatkan metadata grup terbaru dan simpan ke cache dengan sessionId
|
|
423
|
+
const metadata = yield sock.groupMetadata(update.id);
|
|
424
|
+
yield Utils_1.groupCache.set(sessionId, update.id, metadata);
|
|
425
|
+
}
|
|
426
|
+
catch (error) {
|
|
427
|
+
console.error(`Error updating group participants in cache: ${error}`);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
if (events["messages.update"]) {
|
|
431
|
+
const msg = events["messages.update"][0];
|
|
432
|
+
const data = Object.assign({ sessionId: sessionId, messageStatus: (0, message_status_1.parseMessageStatusCodeToReadable)(msg.update.status) }, msg);
|
|
433
|
+
(_l = callback.get(Defaults_1.CALLBACK_KEY.ON_MESSAGE_UPDATED)) === null || _l === void 0 ? void 0 : _l(sessionId, data);
|
|
434
|
+
(_m = options.onMessageUpdated) === null || _m === void 0 ? void 0 : _m.call(options, data);
|
|
435
|
+
}
|
|
436
|
+
if (events["messages.upsert"]) {
|
|
437
|
+
const messages = events["messages.upsert"].messages || [];
|
|
438
|
+
for (const rawMsg of messages) {
|
|
439
|
+
// Skip protocol messages and system messages
|
|
440
|
+
if ((_o = rawMsg.message) === null || _o === void 0 ? void 0 : _o.protocolMessage) {
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
// Skip messages without content
|
|
444
|
+
if (!rawMsg.message || Object.keys(rawMsg.message).length === 0) {
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
const msg = rawMsg;
|
|
448
|
+
msg.sessionId = sessionId;
|
|
449
|
+
msg.saveImage = (path) => (0, save_media_1.saveImageHandler)(msg, path);
|
|
450
|
+
msg.saveVideo = (path) => (0, save_media_1.saveVideoHandler)(msg, path);
|
|
451
|
+
msg.saveDocument = (path) => (0, save_media_1.saveDocumentHandler)(msg, path);
|
|
452
|
+
msg.saveAudio = (path) => (0, save_media_1.saveAudioHandler)(msg, path);
|
|
453
|
+
(_p = callback.get(Defaults_1.CALLBACK_KEY.ON_MESSAGE_RECEIVED)) === null || _p === void 0 ? void 0 : _p(Object.assign({}, msg));
|
|
454
|
+
(_q = options.onMessageReceived) === null || _q === void 0 ? void 0 : _q.call(options, msg);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}));
|
|
458
|
+
return sock;
|
|
459
|
+
}
|
|
460
|
+
catch (error) {
|
|
461
|
+
// console.log("SOCKET ERROR", error);
|
|
462
|
+
return sock;
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
return startSocket();
|
|
466
|
+
});
|
|
467
|
+
exports.startSessionWithPairingCode = startSessionWithPairingCode;
|
|
468
|
+
/**
|
|
469
|
+
* @deprecated Use startSession method instead
|
|
470
|
+
*/
|
|
471
|
+
exports.startWhatsapp = exports.startSession;
|
|
472
|
+
/**
|
|
473
|
+
* Soft delete session - removes from memory but preserves MongoDB data for pairing code sessions
|
|
474
|
+
* @param sessionId Session ID to soft delete
|
|
475
|
+
*/
|
|
476
|
+
const softDeleteSession = (sessionId_1, ...args_1) => __awaiter(void 0, [sessionId_1, ...args_1], void 0, function* (sessionId, preserveData = false) {
|
|
477
|
+
const session = (0, exports.getSession)(sessionId);
|
|
478
|
+
try {
|
|
479
|
+
yield (session === null || session === void 0 ? void 0 : session.logout());
|
|
480
|
+
}
|
|
481
|
+
catch (error) { }
|
|
482
|
+
session === null || session === void 0 ? void 0 : session.end(undefined);
|
|
483
|
+
sessions.delete(sessionId);
|
|
484
|
+
// Only completely remove from MongoDB if not preserving data or not a pairing code session
|
|
485
|
+
if (!preserveData && !pairingCodeSessions.has(sessionId)) {
|
|
486
|
+
if (authCollection) {
|
|
487
|
+
try {
|
|
488
|
+
yield authCollection.deleteOne({ sessionId });
|
|
489
|
+
}
|
|
490
|
+
catch (error) {
|
|
491
|
+
console.error(`Error deleting session ${sessionId} from MongoDB:`, error);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
else if (pairingCodeSessions.has(sessionId)) {
|
|
496
|
+
// Preserving MongoDB data for pairing code session
|
|
497
|
+
}
|
|
498
|
+
// Hapus cache grup untuk session ini
|
|
499
|
+
try {
|
|
500
|
+
yield Utils_1.groupCache.clearSessionCache(sessionId);
|
|
501
|
+
}
|
|
502
|
+
catch (error) {
|
|
503
|
+
console.error(`Error clearing group cache for session ${sessionId}:`, error);
|
|
504
|
+
}
|
|
505
|
+
// Legacy: hapus juga dari file system jika ada
|
|
506
|
+
const dir = path_1.default.resolve(Defaults_1.CREDENTIALS.DIR_NAME, sessionId + Defaults_1.CREDENTIALS.PREFIX);
|
|
507
|
+
if (fs_1.default.existsSync(dir)) {
|
|
508
|
+
fs_1.default.rmSync(dir, { force: true, recursive: true });
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
const deleteSession = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
512
|
+
const session = (0, exports.getSession)(sessionId);
|
|
513
|
+
try {
|
|
514
|
+
yield (session === null || session === void 0 ? void 0 : session.logout());
|
|
515
|
+
}
|
|
516
|
+
catch (error) { }
|
|
517
|
+
session === null || session === void 0 ? void 0 : session.end(undefined);
|
|
518
|
+
sessions.delete(sessionId);
|
|
519
|
+
// Hapus tracking pairing code session jika ada
|
|
520
|
+
pairingCodeSessions.delete(sessionId);
|
|
521
|
+
// Hapus juga dari MongoDB jika authCollection ada
|
|
522
|
+
if (authCollection) {
|
|
523
|
+
try {
|
|
524
|
+
yield authCollection.deleteOne({ sessionId });
|
|
525
|
+
}
|
|
526
|
+
catch (error) {
|
|
527
|
+
console.error(`Error deleting session ${sessionId} from MongoDB:`, error);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
// Hapus cache grup untuk session ini
|
|
531
|
+
try {
|
|
532
|
+
yield Utils_1.groupCache.clearSessionCache(sessionId);
|
|
533
|
+
}
|
|
534
|
+
catch (error) {
|
|
535
|
+
console.error(`Error clearing group cache for session ${sessionId}:`, error);
|
|
536
|
+
}
|
|
537
|
+
// Legacy: hapus juga dari file system jika ada
|
|
538
|
+
const dir = path_1.default.resolve(Defaults_1.CREDENTIALS.DIR_NAME, sessionId + Defaults_1.CREDENTIALS.PREFIX);
|
|
539
|
+
if (fs_1.default.existsSync(dir)) {
|
|
540
|
+
fs_1.default.rmSync(dir, { force: true, recursive: true });
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
exports.deleteSession = deleteSession;
|
|
544
|
+
/**
|
|
545
|
+
* Get all active session IDs
|
|
546
|
+
* @returns Array of session IDs
|
|
547
|
+
*/
|
|
548
|
+
const getAllSession = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
549
|
+
// Return active sessions from Map (sessions yang sudah running di memori)
|
|
550
|
+
const runningSessionIds = Array.from(sessions.keys());
|
|
551
|
+
// Jika authCollection belum diinisialisasi, kembalikan hanya sessions dari memori
|
|
552
|
+
if (!authCollection) {
|
|
553
|
+
return runningSessionIds;
|
|
554
|
+
}
|
|
555
|
+
try {
|
|
556
|
+
// Ambil semua sessionId dari MongoDB
|
|
557
|
+
const sessionDocs = yield authCollection.find({}).toArray();
|
|
558
|
+
const mongoSessionIds = sessionDocs.map((doc) => doc.sessionId);
|
|
559
|
+
// Gabungkan dan deduplikasi session IDs
|
|
560
|
+
const allSessionIds = [...new Set([...runningSessionIds, ...mongoSessionIds])];
|
|
561
|
+
return allSessionIds;
|
|
562
|
+
}
|
|
563
|
+
catch (error) {
|
|
564
|
+
console.error("Error fetching sessions from MongoDB:", error);
|
|
565
|
+
// Fallback ke sessions yang ada di memori jika MongoDB error
|
|
566
|
+
return runningSessionIds;
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
exports.getAllSession = getAllSession;
|
|
570
|
+
// Untuk backward compatibility
|
|
571
|
+
const getAllSessionSync = () => Array.from(sessions.keys());
|
|
572
|
+
exports.getAllSessionSync = getAllSessionSync;
|
|
573
|
+
const getSession = (key) => sessions.get(key);
|
|
574
|
+
exports.getSession = getSession;
|
|
575
|
+
const isSessionExistAndRunning = (sessionId) => {
|
|
576
|
+
// Cek jika session sudah berjalan di memory
|
|
577
|
+
if ((0, exports.getSession)(sessionId)) {
|
|
578
|
+
return true;
|
|
579
|
+
}
|
|
580
|
+
return false;
|
|
581
|
+
};
|
|
582
|
+
/**
|
|
583
|
+
* Check if session should be loaded
|
|
584
|
+
* @param sessionId Session ID to check
|
|
585
|
+
* @returns Boolean indicating if session should be loaded
|
|
586
|
+
*/
|
|
587
|
+
const shouldLoadSession = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
588
|
+
// Jika session sudah berjalan di memory, tidak perlu load lagi
|
|
589
|
+
if ((0, exports.getSession)(sessionId)) {
|
|
590
|
+
return false;
|
|
591
|
+
}
|
|
592
|
+
// Jika authCollection belum diinisialisasi, tidak bisa load
|
|
593
|
+
if (!authCollection) {
|
|
594
|
+
return false;
|
|
595
|
+
}
|
|
596
|
+
try {
|
|
597
|
+
// Periksa apakah session ada di MongoDB
|
|
598
|
+
const sessionDoc = yield authCollection.findOne({ sessionId });
|
|
599
|
+
return !!sessionDoc; // Return true jika session ditemukan di MongoDB
|
|
600
|
+
}
|
|
601
|
+
catch (error) {
|
|
602
|
+
console.error(`Error checking session ${sessionId} in MongoDB:`, error);
|
|
603
|
+
return false;
|
|
604
|
+
}
|
|
605
|
+
});
|
|
606
|
+
/**
|
|
607
|
+
* @deprecated Use loadSessionsFromMongo instead
|
|
608
|
+
*/
|
|
609
|
+
const loadSessionsFromStorage = () => {
|
|
610
|
+
console.warn("loadSessionsFromStorage is deprecated, use loadSessionsFromMongo instead");
|
|
611
|
+
// Redirect ke fungsi loadSessionsFromMongo untuk backward compatibility
|
|
612
|
+
(0, exports.loadSessionsFromMongo)().catch(err => {
|
|
613
|
+
console.error("Error loading sessions from MongoDB:", err);
|
|
614
|
+
});
|
|
615
|
+
};
|
|
616
|
+
exports.loadSessionsFromStorage = loadSessionsFromStorage;
|
|
617
|
+
const onMessageReceived = (listener) => {
|
|
618
|
+
callback.set(Defaults_1.CALLBACK_KEY.ON_MESSAGE_RECEIVED, listener);
|
|
619
|
+
};
|
|
620
|
+
exports.onMessageReceived = onMessageReceived;
|
|
621
|
+
const onQRUpdated = (listener) => {
|
|
622
|
+
callback.set(Defaults_1.CALLBACK_KEY.ON_QR, listener);
|
|
623
|
+
};
|
|
624
|
+
exports.onQRUpdated = onQRUpdated;
|
|
625
|
+
const onConnected = (listener) => {
|
|
626
|
+
callback.set(Defaults_1.CALLBACK_KEY.ON_CONNECTED, listener);
|
|
627
|
+
};
|
|
628
|
+
exports.onConnected = onConnected;
|
|
629
|
+
const onDisconnected = (listener) => {
|
|
630
|
+
callback.set(Defaults_1.CALLBACK_KEY.ON_DISCONNECTED, listener);
|
|
631
|
+
};
|
|
632
|
+
exports.onDisconnected = onDisconnected;
|
|
633
|
+
const onConnecting = (listener) => {
|
|
634
|
+
callback.set(Defaults_1.CALLBACK_KEY.ON_CONNECTING, listener);
|
|
635
|
+
};
|
|
636
|
+
exports.onConnecting = onConnecting;
|
|
637
|
+
const onMessageUpdate = (listener) => {
|
|
638
|
+
callback.set(Defaults_1.CALLBACK_KEY.ON_MESSAGE_UPDATED, listener);
|
|
639
|
+
};
|
|
640
|
+
exports.onMessageUpdate = onMessageUpdate;
|
|
641
|
+
const onPairingCode = (listener) => {
|
|
642
|
+
// Set callback ke registry dengan key yang benar
|
|
643
|
+
callback.set(Defaults_1.CALLBACK_KEY.ON_PAIRING_CODE, listener);
|
|
644
|
+
};
|
|
645
|
+
exports.onPairingCode = onPairingCode;
|
|
646
|
+
/**
|
|
647
|
+
* Load all sessions from MongoDB and start them automatically
|
|
648
|
+
*/
|
|
649
|
+
const loadSessionsFromMongo = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
650
|
+
yield initMongo();
|
|
651
|
+
const sessionDocs = yield authCollection.find({}).toArray();
|
|
652
|
+
for (const doc of sessionDocs) {
|
|
653
|
+
const sessionId = doc.sessionId;
|
|
654
|
+
if (sessionId && !(0, exports.getSession)(sessionId)) {
|
|
655
|
+
try {
|
|
656
|
+
yield (0, exports.startSession)(sessionId, { printQR: false });
|
|
657
|
+
}
|
|
658
|
+
catch (e) {
|
|
659
|
+
// Optional: log error jika gagal load session tertentu
|
|
660
|
+
console.error(`Failed to load session ${sessionId}:`, e);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
exports.loadSessionsFromMongo = loadSessionsFromMongo;
|
|
666
|
+
/**
|
|
667
|
+
* Configure MongoDB database and collection names
|
|
668
|
+
*
|
|
669
|
+
* @param dbName MongoDB database name (default: "wa_session")
|
|
670
|
+
* @param collectionName MongoDB collection name for auth storage (default: "auth")
|
|
671
|
+
*/
|
|
672
|
+
const setMongoDBNames = (dbName = "wa_session", collectionName = "auth") => {
|
|
673
|
+
Defaults_1.CREDENTIALS.MONGO_DB_NAME = dbName;
|
|
674
|
+
Defaults_1.CREDENTIALS.MONGO_COLLECTION_NAME = collectionName;
|
|
675
|
+
};
|
|
676
|
+
exports.setMongoDBNames = setMongoDBNames;
|
|
677
|
+
/**
|
|
678
|
+
* Sets the directory name for storing credentials (File-based storage)
|
|
679
|
+
*
|
|
680
|
+
* @deprecated When using MongoDB, this setting has no effect. Only used for legacy file-based storage.
|
|
681
|
+
* @param dirname Directory name for storing credentials (default: "wa_credentials")
|
|
682
|
+
*/
|
|
683
|
+
const setCredentialsDir = (dirname = "wa_credentials") => {
|
|
684
|
+
console.warn("setCredentialsDir() is deprecated when using MongoDB storage. This setting only affects legacy file-based storage.");
|
|
685
|
+
Defaults_1.CREDENTIALS.DIR_NAME = dirname;
|
|
686
|
+
};
|
|
687
|
+
exports.setCredentialsDir = setCredentialsDir;
|
|
688
|
+
/**
|
|
689
|
+
* Attempt to reconnect a disconnected session
|
|
690
|
+
*
|
|
691
|
+
* @param sessionId Session ID to reconnect
|
|
692
|
+
* @returns Promise<boolean> indicating success
|
|
693
|
+
*/
|
|
694
|
+
const reconnect = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
695
|
+
try {
|
|
696
|
+
// Cek jika session masih ada di memory
|
|
697
|
+
const existingSession = sessions.get(sessionId);
|
|
698
|
+
// Hapus session terlebih dahulu untuk menghindari konflik
|
|
699
|
+
if (existingSession) {
|
|
700
|
+
try {
|
|
701
|
+
// Coba lakukan logout jika memungkinkan (tapi jangan crash jika gagal)
|
|
702
|
+
yield existingSession.logout().catch((e) => { });
|
|
703
|
+
}
|
|
704
|
+
catch (logoutError) {
|
|
705
|
+
// Abaikan error saat logout
|
|
706
|
+
}
|
|
707
|
+
// Akhiri session dan hapus dari map secara paksa
|
|
708
|
+
try {
|
|
709
|
+
existingSession.end(undefined);
|
|
710
|
+
}
|
|
711
|
+
catch (endError) {
|
|
712
|
+
// Abaikan error saat mengakhiri
|
|
713
|
+
}
|
|
714
|
+
sessions.delete(sessionId);
|
|
715
|
+
}
|
|
716
|
+
// Tunggu sedikit waktu untuk memastikan cleanup selesai
|
|
717
|
+
yield (0, create_delay_1.createDelay)(1000);
|
|
718
|
+
// Cek jika ini session pairing code dari tracking terlebih dahulu
|
|
719
|
+
const pairingInfo = pairingCodeSessions.get(sessionId);
|
|
720
|
+
if (pairingInfo) {
|
|
721
|
+
// Ini adalah session pairing code, gunakan metode pairing code untuk reconnect
|
|
722
|
+
try {
|
|
723
|
+
// Reset retry count untuk session ini
|
|
724
|
+
retryCount.delete(sessionId);
|
|
725
|
+
yield (0, exports.startSessionWithPairingCode)(sessionId, pairingInfo.phoneNumber, Object.assign(Object.assign({}, pairingInfo.options), { printQR: false,
|
|
726
|
+
// Tambahkan callback khusus untuk reconnect
|
|
727
|
+
onConnected: () => {
|
|
728
|
+
// Pairing code session reconnected successfully
|
|
729
|
+
}, onDisconnected: () => {
|
|
730
|
+
// Pairing code session disconnected after reconnect
|
|
731
|
+
} }));
|
|
732
|
+
// Periksa jika session berhasil dimulai
|
|
733
|
+
return !!(0, exports.getSession)(sessionId);
|
|
734
|
+
}
|
|
735
|
+
catch (startError) {
|
|
736
|
+
console.error(`Failed to reconnect pairing code session ${sessionId}:`, startError.message);
|
|
737
|
+
return false;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
else {
|
|
741
|
+
// Cek jika data session tersedia di MongoDB untuk session biasa
|
|
742
|
+
yield initMongo();
|
|
743
|
+
const sessionExists = yield shouldLoadSession(sessionId);
|
|
744
|
+
if (sessionExists) {
|
|
745
|
+
// Session biasa, gunakan metode startSession normal
|
|
746
|
+
try {
|
|
747
|
+
yield (0, exports.startSession)(sessionId, {
|
|
748
|
+
printQR: false,
|
|
749
|
+
// Tambahkan callback khusus untuk reconnect
|
|
750
|
+
onConnected: () => {
|
|
751
|
+
// Session reconnected successfully
|
|
752
|
+
},
|
|
753
|
+
onDisconnected: () => {
|
|
754
|
+
// Session disconnected after reconnect
|
|
755
|
+
},
|
|
756
|
+
onQRUpdated: (qr) => {
|
|
757
|
+
// QR code updated for reconnecting session
|
|
758
|
+
}
|
|
759
|
+
});
|
|
760
|
+
// Periksa jika session berhasil dimulai
|
|
761
|
+
return !!(0, exports.getSession)(sessionId);
|
|
762
|
+
}
|
|
763
|
+
catch (startError) {
|
|
764
|
+
console.error(`Failed to reconnect session ${sessionId}:`, startError.message);
|
|
765
|
+
return false;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
else {
|
|
769
|
+
// No session data found in MongoDB
|
|
770
|
+
return false;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
catch (error) {
|
|
775
|
+
console.error(`Error during reconnect for session ${sessionId}:`, error.message);
|
|
776
|
+
return false;
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
exports.reconnect = reconnect;
|
|
780
|
+
/**
|
|
781
|
+
* Reconnect all pairing code sessions that are tracked
|
|
782
|
+
* Useful for bulk reconnection after system restart
|
|
783
|
+
*/
|
|
784
|
+
const reconnectAllPairingCodeSessions = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
785
|
+
const results = {};
|
|
786
|
+
for (const [sessionId, sessionInfo] of pairingCodeSessions.entries()) {
|
|
787
|
+
try {
|
|
788
|
+
const success = yield (0, exports.reconnect)(sessionId);
|
|
789
|
+
results[sessionId] = success;
|
|
790
|
+
// Add delay between reconnection attempts
|
|
791
|
+
yield (0, create_delay_1.createDelay)(2000);
|
|
792
|
+
}
|
|
793
|
+
catch (error) {
|
|
794
|
+
console.error(`Error reconnecting pairing code session ${sessionId}:`, error.message);
|
|
795
|
+
results[sessionId] = false;
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
return results;
|
|
799
|
+
});
|
|
800
|
+
exports.reconnectAllPairingCodeSessions = reconnectAllPairingCodeSessions;
|
|
801
|
+
/**
|
|
802
|
+
* Get all tracked pairing code sessions
|
|
803
|
+
* @returns Array of session IDs that were created with pairing code
|
|
804
|
+
*/
|
|
805
|
+
const getPairingCodeSessions = () => {
|
|
806
|
+
return Array.from(pairingCodeSessions.keys());
|
|
807
|
+
};
|
|
808
|
+
exports.getPairingCodeSessions = getPairingCodeSessions;
|
|
809
|
+
/**
|
|
810
|
+
* Get session status information
|
|
811
|
+
* @param sessionId Session ID to check
|
|
812
|
+
* @returns Object with session status information
|
|
813
|
+
*/
|
|
814
|
+
const getSessionStatus = (sessionId) => {
|
|
815
|
+
const isRunning = !!(0, exports.getSession)(sessionId);
|
|
816
|
+
const isPairingCodeSession = pairingCodeSessions.has(sessionId);
|
|
817
|
+
const retryAttempts = retryCount.get(sessionId) || 0;
|
|
818
|
+
return {
|
|
819
|
+
sessionId,
|
|
820
|
+
isRunning,
|
|
821
|
+
isPairingCodeSession,
|
|
822
|
+
retryAttempts,
|
|
823
|
+
hasCredentials: isRunning ? true : null // null means unknown when not running
|
|
824
|
+
};
|
|
825
|
+
};
|
|
826
|
+
exports.getSessionStatus = getSessionStatus;
|
|
827
|
+
// Fungsi baru untuk mendapatkan konfigurasi TTL cache grup
|
|
828
|
+
const setGroupCacheConfig = (options) => {
|
|
829
|
+
Utils_1.groupCache.setConfig(options);
|
|
830
|
+
};
|
|
831
|
+
exports.setGroupCacheConfig = setGroupCacheConfig;
|
|
832
|
+
// Fungsi baru untuk mendapatkan atau memuat data grup dengan multi-session support
|
|
833
|
+
const getGroupMetadata = (sessionId_1, jid_1, ...args_1) => __awaiter(void 0, [sessionId_1, jid_1, ...args_1], void 0, function* (sessionId, jid, forceFetch = false) {
|
|
834
|
+
// Get the session socket
|
|
835
|
+
const sock = (0, exports.getSession)(sessionId);
|
|
836
|
+
if (!sock) {
|
|
837
|
+
throw new Error_1.WhatsappError(Defaults_1.Messages.sessionNotFound(sessionId));
|
|
838
|
+
}
|
|
839
|
+
try {
|
|
840
|
+
// Jika forceFetch true, langsung ambil dari server dan update cache
|
|
841
|
+
if (forceFetch) {
|
|
842
|
+
const metadata = yield sock.groupMetadata(jid);
|
|
843
|
+
yield Utils_1.groupCache.set(sessionId, jid, metadata);
|
|
844
|
+
return metadata;
|
|
845
|
+
}
|
|
846
|
+
// Coba ambil dari cache dulu
|
|
847
|
+
const cachedData = yield Utils_1.groupCache.get(sessionId, jid);
|
|
848
|
+
if (cachedData) {
|
|
849
|
+
return cachedData;
|
|
850
|
+
}
|
|
851
|
+
// Jika tidak ada di cache, ambil dari server dan simpan ke cache
|
|
852
|
+
const metadata = yield sock.groupMetadata(jid);
|
|
853
|
+
yield Utils_1.groupCache.set(sessionId, jid, metadata);
|
|
854
|
+
return metadata;
|
|
855
|
+
}
|
|
856
|
+
catch (error) {
|
|
857
|
+
throw new Error_1.WhatsappError(`Failed to fetch group metadata: ${error.message || String(error)}`);
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
exports.getGroupMetadata = getGroupMetadata;
|
|
861
|
+
// Fungsi baru untuk menghapus cache grup tertentu
|
|
862
|
+
const clearGroupMetadataCache = (sessionId, jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
863
|
+
yield Utils_1.groupCache.delete(sessionId, jid);
|
|
864
|
+
});
|
|
865
|
+
exports.clearGroupMetadataCache = clearGroupMetadataCache;
|
|
866
|
+
// Fungsi untuk membersihkan seluruh cache grup untuk session tertentu
|
|
867
|
+
const clearSessionGroupMetadataCache = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
868
|
+
yield Utils_1.groupCache.clearSessionCache(sessionId);
|
|
869
|
+
});
|
|
870
|
+
exports.clearSessionGroupMetadataCache = clearSessionGroupMetadataCache;
|
|
871
|
+
// Fungsi untuk membersihkan seluruh cache grup untuk semua session
|
|
872
|
+
const clearAllGroupMetadataCache = () => {
|
|
873
|
+
Utils_1.groupCache.flush();
|
|
874
|
+
};
|
|
875
|
+
exports.clearAllGroupMetadataCache = clearAllGroupMetadataCache;
|