wa-multi-mongodb 3.9.2 → 3.9.4
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 +8 -0
- package/dist/Socket/index.d.ts.map +1 -1
- package/dist/Socket/index.js +112 -3
- package/dist/Utils/group-cache.d.ts +23 -0
- package/dist/Utils/group-cache.d.ts.map +1 -0
- package/dist/Utils/group-cache.js +176 -0
- package/dist/Utils/index.d.ts +1 -0
- package/dist/Utils/index.d.ts.map +1 -1
- package/dist/Utils/index.js +1 -0
- package/package.json +41 -37
- package/readme.md +106 -2
package/dist/Socket/index.d.ts
CHANGED
|
@@ -65,4 +65,12 @@ export declare const setCredentialsDir: (dirname?: string) => void;
|
|
|
65
65
|
* @returns Promise<boolean> indicating success
|
|
66
66
|
*/
|
|
67
67
|
export declare const reconnect: (sessionId: string) => Promise<boolean>;
|
|
68
|
+
export declare const setGroupCacheConfig: (options: {
|
|
69
|
+
stdTTL?: number;
|
|
70
|
+
checkperiod?: number;
|
|
71
|
+
}) => void;
|
|
72
|
+
export declare const getGroupMetadata: (sessionId: string, jid: string, forceFetch?: boolean) => Promise<any>;
|
|
73
|
+
export declare const clearGroupMetadataCache: (sessionId: string, jid: string) => Promise<void>;
|
|
74
|
+
export declare const clearSessionGroupMetadataCache: (sessionId: string) => Promise<void>;
|
|
75
|
+
export declare const clearAllGroupMetadataCache: () => void;
|
|
68
76
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -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;
|
|
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,EAClB,iCAAiC,EAClC,MAAM,UAAU,CAAC;AA8BlB;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAU,KAAK,MAAM,kBAkB5C,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,GAAG,QAEjD;AAkBD,eAAO,MAAM,YAAY,GACvB,kBAAuB,EACvB,UAAS,kBAAsC,KAC9C,OAAO,CAAC,QAAQ,CAkIlB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,2BAA2B,GACtC,WAAW,MAAM,EACjB,SAAS,iCAAiC,KACzC,OAAO,CAAC,QAAQ,CAuGlB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,iCAxPf,kBAAkB,KAC1B,OAAO,CAAC,QAAQ,CAuPsB,CAAC;AAE1C,eAAO,MAAM,aAAa,GAAU,WAAW,MAAM,kBAkCpD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,QAAa,OAAO,CAAC,MAAM,EAAE,CAsBtD,CAAC;AAGF,eAAO,MAAM,iBAAiB,QAAO,MAAM,EAAiC,CAAC;AAE7E,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,KAAG,QAAQ,GAAG,SACrB,CAAC;AAoChC;;GAEG;AACH,eAAO,MAAM,uBAAuB,YAMnC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,UAAU,CAAC,GAAG,EAAE,eAAe,KAAK,GAAG,SAExE,CAAC;AACF,eAAO,MAAM,WAAW,GACtB,UAAU,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,KAAK,GAAG,SAGxE,CAAC;AACF,eAAO,MAAM,WAAW,GAAI,UAAU,CAAC,SAAS,EAAE,MAAM,KAAK,GAAG,SAE/D,CAAC;AACF,eAAO,MAAM,cAAc,GAAI,UAAU,CAAC,SAAS,EAAE,MAAM,KAAK,GAAG,SAElE,CAAC;AACF,eAAO,MAAM,YAAY,GAAI,UAAU,CAAC,SAAS,EAAE,MAAM,KAAK,GAAG,SAEhE,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,UAAU,CAAC,IAAI,EAAE,cAAc,KAAK,GAAG,SAEtE,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,GAAG,SAGnD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,qBAcjC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,SAAQ,MAAqB,EAAE,iBAAgB,MAAe,SAI7F,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAS,MAAyB,SAGnE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GAAU,WAAW,MAAM,KAAG,OAAO,CAAC,OAAO,CAsDlE,CAAC;AAGF,eAAO,MAAM,mBAAmB,GAAI,SAAS;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,SAEA,CAAC;AAGF,eAAO,MAAM,gBAAgB,GAC3B,WAAW,MAAM,EACjB,KAAK,MAAM,EACX,aAAY,OAAe,KAC1B,OAAO,CAAC,GAAG,CA4Bb,CAAC;AAGF,eAAO,MAAM,uBAAuB,GAAU,WAAW,MAAM,EAAE,KAAK,MAAM,kBAE3E,CAAC;AAGF,eAAO,MAAM,8BAA8B,GAAU,WAAW,MAAM,kBAErE,CAAC;AAGF,eAAO,MAAM,0BAA0B,YAEtC,CAAC"}
|
package/dist/Socket/index.js
CHANGED
|
@@ -45,13 +45,15 @@ 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.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.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"));
|
|
52
52
|
const fs_1 = __importDefault(require("fs"));
|
|
53
|
+
const qrcode_1 = __importDefault(require("qrcode"));
|
|
53
54
|
const Defaults_1 = require("../Defaults");
|
|
54
55
|
const save_media_1 = require("../Utils/save-media");
|
|
56
|
+
const Utils_1 = require("../Utils");
|
|
55
57
|
const Error_1 = require("../Error");
|
|
56
58
|
const message_status_1 = require("../Utils/message-status");
|
|
57
59
|
const mongodb_1 = require("mongodb");
|
|
@@ -75,6 +77,8 @@ let mongoURI = process.env.MONGODB_URI || "mongodb://localhost:27017";
|
|
|
75
77
|
*/
|
|
76
78
|
const setMongoURI = (uri) => __awaiter(void 0, void 0, void 0, function* () {
|
|
77
79
|
mongoURI = uri;
|
|
80
|
+
// Configure group cache MongoDB connection as well
|
|
81
|
+
yield Utils_1.groupCache.setMongoURI(uri);
|
|
78
82
|
// Reset MongoDB client and collection to ensure they are recreated with new URI
|
|
79
83
|
if (mongoClient) {
|
|
80
84
|
try {
|
|
@@ -116,11 +120,14 @@ const startSession = (...args_1) => __awaiter(void 0, [...args_1], void 0, funct
|
|
|
116
120
|
const { state, saveCreds } = yield (0, mongo_auth_state_1.useMongoAuthState)(sessionId, authCollection);
|
|
117
121
|
const sock = (0, baileys_1.default)({
|
|
118
122
|
version,
|
|
119
|
-
printQRInTerminal: options.printQR,
|
|
120
123
|
auth: state,
|
|
121
124
|
logger: P,
|
|
122
125
|
markOnlineOnConnect: false,
|
|
123
126
|
browser: baileys_1.Browsers.ubuntu("Chrome"),
|
|
127
|
+
// Configure caching group metadata using our hybrid implementation with session ID
|
|
128
|
+
cachedGroupMetadata: (jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
129
|
+
return yield Utils_1.groupCache.get(sessionId, jid);
|
|
130
|
+
})
|
|
124
131
|
});
|
|
125
132
|
sessions.set(sessionId, Object.assign({}, sock));
|
|
126
133
|
try {
|
|
@@ -130,6 +137,17 @@ const startSession = (...args_1) => __awaiter(void 0, [...args_1], void 0, funct
|
|
|
130
137
|
const update = events["connection.update"];
|
|
131
138
|
const { connection, lastDisconnect } = update;
|
|
132
139
|
if (update.qr) {
|
|
140
|
+
if (options.printQR) {
|
|
141
|
+
qrcode_1.default.toString(update.qr, {
|
|
142
|
+
type: 'terminal',
|
|
143
|
+
small: true,
|
|
144
|
+
margin: 1
|
|
145
|
+
}, (err, qrString) => {
|
|
146
|
+
if (!err) {
|
|
147
|
+
console.log(qrString);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
133
151
|
(_a = callback.get(Defaults_1.CALLBACK_KEY.ON_QR)) === null || _a === void 0 ? void 0 : _a({
|
|
134
152
|
sessionId,
|
|
135
153
|
qr: update.qr,
|
|
@@ -168,6 +186,32 @@ const startSession = (...args_1) => __awaiter(void 0, [...args_1], void 0, funct
|
|
|
168
186
|
if (events["creds.update"]) {
|
|
169
187
|
yield saveCreds();
|
|
170
188
|
}
|
|
189
|
+
// Menangani event update data grup
|
|
190
|
+
if (events["groups.update"]) {
|
|
191
|
+
const updates = events["groups.update"];
|
|
192
|
+
for (const update of updates) {
|
|
193
|
+
try {
|
|
194
|
+
// Dapatkan metadata grup terbaru dan simpan ke cache dengan sessionId
|
|
195
|
+
const metadata = yield sock.groupMetadata(update.id);
|
|
196
|
+
yield Utils_1.groupCache.set(sessionId, update.id, metadata);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
console.error(`Error updating group metadata in cache: ${error}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Menangani event perubahan peserta grup
|
|
204
|
+
if (events["group-participants.update"]) {
|
|
205
|
+
const update = events["group-participants.update"];
|
|
206
|
+
try {
|
|
207
|
+
// Dapatkan metadata grup terbaru dan simpan ke cache dengan sessionId
|
|
208
|
+
const metadata = yield sock.groupMetadata(update.id);
|
|
209
|
+
yield Utils_1.groupCache.set(sessionId, update.id, metadata);
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
console.error(`Error updating group participants in cache: ${error}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
171
215
|
if (events["messages.update"]) {
|
|
172
216
|
const msg = events["messages.update"][0];
|
|
173
217
|
const data = Object.assign({ sessionId: sessionId, messageStatus: (0, message_status_1.parseMessageStatusCodeToReadable)(msg.update.status) }, msg);
|
|
@@ -210,7 +254,6 @@ const startSessionWithPairingCode = (sessionId, options) => __awaiter(void 0, vo
|
|
|
210
254
|
const { state, saveCreds } = yield (0, mongo_auth_state_1.useMongoAuthState)(sessionId, authCollection);
|
|
211
255
|
const sock = (0, baileys_1.default)({
|
|
212
256
|
version,
|
|
213
|
-
printQRInTerminal: false,
|
|
214
257
|
auth: state,
|
|
215
258
|
logger: P,
|
|
216
259
|
markOnlineOnConnect: false,
|
|
@@ -230,6 +273,15 @@ const startSessionWithPairingCode = (sessionId, options) => __awaiter(void 0, vo
|
|
|
230
273
|
const update = events["connection.update"];
|
|
231
274
|
const { connection, lastDisconnect } = update;
|
|
232
275
|
if (update.qr) {
|
|
276
|
+
qrcode_1.default.toString(update.qr, {
|
|
277
|
+
type: 'terminal',
|
|
278
|
+
small: true,
|
|
279
|
+
margin: 1
|
|
280
|
+
}, (err, qrString) => {
|
|
281
|
+
if (!err) {
|
|
282
|
+
console.log(qrString);
|
|
283
|
+
}
|
|
284
|
+
});
|
|
233
285
|
(_a = callback.get(Defaults_1.CALLBACK_KEY.ON_QR)) === null || _a === void 0 ? void 0 : _a({
|
|
234
286
|
sessionId,
|
|
235
287
|
qr: update.qr,
|
|
@@ -314,6 +366,14 @@ const deleteSession = (sessionId) => __awaiter(void 0, void 0, void 0, function*
|
|
|
314
366
|
console.error(`Error deleting session ${sessionId} from MongoDB:`, error);
|
|
315
367
|
}
|
|
316
368
|
}
|
|
369
|
+
// Hapus cache grup untuk session ini
|
|
370
|
+
try {
|
|
371
|
+
yield Utils_1.groupCache.clearSessionCache(sessionId);
|
|
372
|
+
console.log(`Group metadata cache for session ${sessionId} cleared`);
|
|
373
|
+
}
|
|
374
|
+
catch (error) {
|
|
375
|
+
console.error(`Error clearing group cache for session ${sessionId}:`, error);
|
|
376
|
+
}
|
|
317
377
|
// Legacy: hapus juga dari file system jika ada
|
|
318
378
|
const dir = path_1.default.resolve(Defaults_1.CREDENTIALS.DIR_NAME, sessionId + Defaults_1.CREDENTIALS.PREFIX);
|
|
319
379
|
if (fs_1.default.existsSync(dir)) {
|
|
@@ -525,3 +585,52 @@ const reconnect = (sessionId) => __awaiter(void 0, void 0, void 0, function* ()
|
|
|
525
585
|
}
|
|
526
586
|
});
|
|
527
587
|
exports.reconnect = reconnect;
|
|
588
|
+
// Fungsi baru untuk mendapatkan konfigurasi TTL cache grup
|
|
589
|
+
const setGroupCacheConfig = (options) => {
|
|
590
|
+
Utils_1.groupCache.setConfig(options);
|
|
591
|
+
};
|
|
592
|
+
exports.setGroupCacheConfig = setGroupCacheConfig;
|
|
593
|
+
// Fungsi baru untuk mendapatkan atau memuat data grup dengan multi-session support
|
|
594
|
+
const getGroupMetadata = (sessionId_1, jid_1, ...args_1) => __awaiter(void 0, [sessionId_1, jid_1, ...args_1], void 0, function* (sessionId, jid, forceFetch = false) {
|
|
595
|
+
// Get the session socket
|
|
596
|
+
const sock = (0, exports.getSession)(sessionId);
|
|
597
|
+
if (!sock) {
|
|
598
|
+
throw new Error_1.WhatsappError(Defaults_1.Messages.sessionNotFound(sessionId));
|
|
599
|
+
}
|
|
600
|
+
try {
|
|
601
|
+
// Jika forceFetch true, langsung ambil dari server dan update cache
|
|
602
|
+
if (forceFetch) {
|
|
603
|
+
const metadata = yield sock.groupMetadata(jid);
|
|
604
|
+
yield Utils_1.groupCache.set(sessionId, jid, metadata);
|
|
605
|
+
return metadata;
|
|
606
|
+
}
|
|
607
|
+
// Coba ambil dari cache dulu
|
|
608
|
+
const cachedData = yield Utils_1.groupCache.get(sessionId, jid);
|
|
609
|
+
if (cachedData) {
|
|
610
|
+
return cachedData;
|
|
611
|
+
}
|
|
612
|
+
// Jika tidak ada di cache, ambil dari server dan simpan ke cache
|
|
613
|
+
const metadata = yield sock.groupMetadata(jid);
|
|
614
|
+
yield Utils_1.groupCache.set(sessionId, jid, metadata);
|
|
615
|
+
return metadata;
|
|
616
|
+
}
|
|
617
|
+
catch (error) {
|
|
618
|
+
throw new Error_1.WhatsappError(`Failed to fetch group metadata: ${error.message || String(error)}`);
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
exports.getGroupMetadata = getGroupMetadata;
|
|
622
|
+
// Fungsi baru untuk menghapus cache grup tertentu
|
|
623
|
+
const clearGroupMetadataCache = (sessionId, jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
624
|
+
yield Utils_1.groupCache.delete(sessionId, jid);
|
|
625
|
+
});
|
|
626
|
+
exports.clearGroupMetadataCache = clearGroupMetadataCache;
|
|
627
|
+
// Fungsi untuk membersihkan seluruh cache grup untuk session tertentu
|
|
628
|
+
const clearSessionGroupMetadataCache = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
629
|
+
yield Utils_1.groupCache.clearSessionCache(sessionId);
|
|
630
|
+
});
|
|
631
|
+
exports.clearSessionGroupMetadataCache = clearSessionGroupMetadataCache;
|
|
632
|
+
// Fungsi untuk membersihkan seluruh cache grup untuk semua session
|
|
633
|
+
const clearAllGroupMetadataCache = () => {
|
|
634
|
+
Utils_1.groupCache.flush();
|
|
635
|
+
};
|
|
636
|
+
exports.clearAllGroupMetadataCache = clearAllGroupMetadataCache;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { GroupMetadata } from "baileys";
|
|
2
|
+
export declare class GroupMetadataCache {
|
|
3
|
+
private static instance;
|
|
4
|
+
private cache;
|
|
5
|
+
private mongoClient;
|
|
6
|
+
private mongoCollection;
|
|
7
|
+
private mongoURI;
|
|
8
|
+
private constructor();
|
|
9
|
+
static getInstance(): GroupMetadataCache;
|
|
10
|
+
setMongoURI(uri: string): Promise<void>;
|
|
11
|
+
private createCacheKey;
|
|
12
|
+
get(sessionId: string, groupId: string): Promise<GroupMetadata | null>;
|
|
13
|
+
set(sessionId: string, groupId: string, metadata: GroupMetadata): Promise<void>;
|
|
14
|
+
delete(sessionId: string, groupId: string): Promise<void>;
|
|
15
|
+
clearSessionCache(sessionId: string): Promise<void>;
|
|
16
|
+
setConfig(options: {
|
|
17
|
+
stdTTL?: number;
|
|
18
|
+
checkperiod?: number;
|
|
19
|
+
}): void;
|
|
20
|
+
flush(): void;
|
|
21
|
+
}
|
|
22
|
+
export declare const groupCache: GroupMetadataCache;
|
|
23
|
+
//# sourceMappingURL=group-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"group-cache.d.ts","sourceRoot":"","sources":["../../src/Utils/group-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAKxC,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAqB;IAC5C,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAuB;IAGvC,OAAO;WAUO,WAAW,IAAI,kBAAkB;IAQlC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBpD,OAAO,CAAC,cAAc;IAKT,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAoCtE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA4B/E,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBzD,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBzD,SAAS,CAAC,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE;IAU5D,KAAK,IAAI,IAAI;CAGrB;AAGD,eAAO,MAAM,UAAU,oBAAmC,CAAC"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.groupCache = exports.GroupMetadataCache = void 0;
|
|
16
|
+
const node_cache_1 = __importDefault(require("node-cache"));
|
|
17
|
+
const mongodb_1 = require("mongodb");
|
|
18
|
+
const Defaults_1 = require("../Defaults");
|
|
19
|
+
// Class untuk mengelola cache group metadata dengan pendekatan hybrid (NodeCache + MongoDB)
|
|
20
|
+
class GroupMetadataCache {
|
|
21
|
+
// Konstruktor private untuk singleton pattern
|
|
22
|
+
constructor() {
|
|
23
|
+
this.mongoClient = null;
|
|
24
|
+
this.mongoCollection = null;
|
|
25
|
+
this.mongoURI = null;
|
|
26
|
+
// Inisialisasi node-cache dengan standar TTL 5 menit
|
|
27
|
+
this.cache = new node_cache_1.default({
|
|
28
|
+
stdTTL: 5 * 60, // 5 menit dalam detik
|
|
29
|
+
checkperiod: 60, // Cek expired keys setiap 1 menit
|
|
30
|
+
useClones: false // Untuk performa lebih baik
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
// Mendapatkan instance singleton
|
|
34
|
+
static getInstance() {
|
|
35
|
+
if (!GroupMetadataCache.instance) {
|
|
36
|
+
GroupMetadataCache.instance = new GroupMetadataCache();
|
|
37
|
+
}
|
|
38
|
+
return GroupMetadataCache.instance;
|
|
39
|
+
}
|
|
40
|
+
// Mengatur MongoDB URI dan menginisialisasi koneksi
|
|
41
|
+
setMongoURI(uri) {
|
|
42
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
43
|
+
if (this.mongoURI !== uri) {
|
|
44
|
+
this.mongoURI = uri;
|
|
45
|
+
// Tutup koneksi yang ada jika ada
|
|
46
|
+
if (this.mongoClient) {
|
|
47
|
+
yield this.mongoClient.close();
|
|
48
|
+
}
|
|
49
|
+
this.mongoClient = new mongodb_1.MongoClient(uri);
|
|
50
|
+
yield this.mongoClient.connect();
|
|
51
|
+
// Inisialisasi collection
|
|
52
|
+
const dbName = Defaults_1.CREDENTIALS.MONGO_DB_NAME;
|
|
53
|
+
const collectionName = "group_metadata";
|
|
54
|
+
this.mongoCollection = this.mongoClient.db(dbName).collection(collectionName);
|
|
55
|
+
// Buat indeks pada id grup dan sessionId untuk performa query
|
|
56
|
+
yield this.mongoCollection.createIndex({ id: 1, sessionId: 1 });
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
// Membuat kunci cache yang mencakup sessionId
|
|
61
|
+
createCacheKey(sessionId, groupId) {
|
|
62
|
+
return `${sessionId}:${groupId}`;
|
|
63
|
+
}
|
|
64
|
+
// Mendapatkan metadata grup dari cache atau MongoDB
|
|
65
|
+
get(sessionId, groupId) {
|
|
66
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
// Buat kunci cache dengan kombinasi sessionId dan groupId
|
|
68
|
+
const cacheKey = this.createCacheKey(sessionId, groupId);
|
|
69
|
+
// Coba ambil dari cache memory dulu
|
|
70
|
+
const cachedData = this.cache.get(cacheKey);
|
|
71
|
+
if (cachedData) {
|
|
72
|
+
return cachedData;
|
|
73
|
+
}
|
|
74
|
+
// Jika tidak ada di cache dan MongoDB tersedia, coba ambil dari MongoDB
|
|
75
|
+
if (this.mongoCollection) {
|
|
76
|
+
try {
|
|
77
|
+
const data = yield this.mongoCollection.findOne({
|
|
78
|
+
id: groupId,
|
|
79
|
+
sessionId: sessionId
|
|
80
|
+
});
|
|
81
|
+
if (data) {
|
|
82
|
+
// Hapus _id dari MongoDB yang tidak diperlukan
|
|
83
|
+
delete data._id;
|
|
84
|
+
delete data.sessionId; // Hapus sessionId dari data yang dikembalikan
|
|
85
|
+
// Simpan ke cache memory untuk akses cepat
|
|
86
|
+
this.cache.set(cacheKey, data);
|
|
87
|
+
return data;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
console.error("Error fetching group metadata from MongoDB:", error);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// Menyimpan metadata grup ke cache dan MongoDB
|
|
98
|
+
set(sessionId, groupId, metadata) {
|
|
99
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
100
|
+
// Buat kunci cache dengan kombinasi sessionId dan groupId
|
|
101
|
+
const cacheKey = this.createCacheKey(sessionId, groupId);
|
|
102
|
+
// Simpan ke cache memory
|
|
103
|
+
this.cache.set(cacheKey, metadata);
|
|
104
|
+
// Jika MongoDB tersedia, simpan juga ke MongoDB
|
|
105
|
+
if (this.mongoCollection) {
|
|
106
|
+
try {
|
|
107
|
+
// Tambahkan sessionId ke data yang disimpan
|
|
108
|
+
const dataToStore = Object.assign(Object.assign({}, metadata), { sessionId });
|
|
109
|
+
yield this.mongoCollection.updateOne({
|
|
110
|
+
id: groupId,
|
|
111
|
+
sessionId: sessionId
|
|
112
|
+
}, { $set: dataToStore }, { upsert: true });
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
console.error("Error saving group metadata to MongoDB:", error);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
// Menghapus metadata grup dari cache dan MongoDB
|
|
121
|
+
delete(sessionId, groupId) {
|
|
122
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
123
|
+
// Buat kunci cache dengan kombinasi sessionId dan groupId
|
|
124
|
+
const cacheKey = this.createCacheKey(sessionId, groupId);
|
|
125
|
+
// Hapus dari cache memory
|
|
126
|
+
this.cache.del(cacheKey);
|
|
127
|
+
// Jika MongoDB tersedia, hapus juga dari MongoDB
|
|
128
|
+
if (this.mongoCollection) {
|
|
129
|
+
try {
|
|
130
|
+
yield this.mongoCollection.deleteOne({
|
|
131
|
+
id: groupId,
|
|
132
|
+
sessionId: sessionId
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
console.error("Error deleting group metadata from MongoDB:", error);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
// Menghapus semua cache untuk session tertentu
|
|
142
|
+
clearSessionCache(sessionId) {
|
|
143
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
+
// Hapus dari MongoDB
|
|
145
|
+
if (this.mongoCollection) {
|
|
146
|
+
try {
|
|
147
|
+
yield this.mongoCollection.deleteMany({ sessionId: sessionId });
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
console.error(`Error clearing session ${sessionId} cache from MongoDB:`, error);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Hapus dari memory cache
|
|
154
|
+
// Karena NodeCache tidak mendukung wildcard delete, kita harus mendapatkan semua kunci dulu
|
|
155
|
+
const allKeys = this.cache.keys();
|
|
156
|
+
const sessionKeys = allKeys.filter(key => key.startsWith(`${sessionId}:`));
|
|
157
|
+
sessionKeys.forEach(key => this.cache.del(key));
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
// Mengatur atau mengubah konfigurasi cache
|
|
161
|
+
setConfig(options) {
|
|
162
|
+
if (options.stdTTL) {
|
|
163
|
+
this.cache.options.stdTTL = options.stdTTL;
|
|
164
|
+
}
|
|
165
|
+
if (options.checkperiod) {
|
|
166
|
+
this.cache.options.checkperiod = options.checkperiod;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Membersihkan seluruh cache
|
|
170
|
+
flush() {
|
|
171
|
+
this.cache.flushAll();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
exports.GroupMetadataCache = GroupMetadataCache;
|
|
175
|
+
// Export singleton instance
|
|
176
|
+
exports.groupCache = GroupMetadataCache.getInstance();
|
package/dist/Utils/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC"}
|
package/dist/Utils/index.js
CHANGED
|
@@ -17,5 +17,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./phone-to-jid"), exports);
|
|
18
18
|
__exportStar(require("./is-exist"), exports);
|
|
19
19
|
__exportStar(require("./create-delay"), exports);
|
|
20
|
+
__exportStar(require("./group-cache"), exports);
|
|
20
21
|
// Note: setCredentialsDir & setMongoDBNames have been moved to src/Socket/index.ts
|
|
21
22
|
// Please import them directly from there instead
|
package/package.json
CHANGED
|
@@ -1,37 +1,41 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "wa-multi-mongodb",
|
|
3
|
-
"version": "3.9.
|
|
4
|
-
"description": "Multi Session Whatsapp Library with MongoDB Integration",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"files": [
|
|
8
|
-
"dist/**/*"
|
|
9
|
-
],
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "tsc",
|
|
12
|
-
"start": "tsc && node ./dist/index.js",
|
|
13
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
14
|
-
},
|
|
15
|
-
"author": "wahdalo",
|
|
16
|
-
"license": "ISC",
|
|
17
|
-
"dependencies": {
|
|
18
|
-
"@adiwajshing/keyed-db": "^0.2.4",
|
|
19
|
-
"@hapi/boom": "^10.0.1",
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
},
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "wa-multi-mongodb",
|
|
3
|
+
"version": "3.9.4",
|
|
4
|
+
"description": "Multi Session Whatsapp Library with MongoDB Integration",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist/**/*"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "tsc && node ./dist/index.js",
|
|
13
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
14
|
+
},
|
|
15
|
+
"author": "wahdalo",
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@adiwajshing/keyed-db": "^0.2.4",
|
|
19
|
+
"@hapi/boom": "^10.0.1",
|
|
20
|
+
"@types/node-cache": "^4.1.3",
|
|
21
|
+
"@types/qrcode": "^1.5.5",
|
|
22
|
+
"baileys": "^6.7.18",
|
|
23
|
+
"dotenv": "^16.5.0",
|
|
24
|
+
"link-preview-js": "^3.0.14",
|
|
25
|
+
"mime": "^3.0.0",
|
|
26
|
+
"mongodb": "^5.7.0",
|
|
27
|
+
"node-cache": "^5.1.2",
|
|
28
|
+
"pino": "^9.5.0",
|
|
29
|
+
"qrcode": "^1.5.4",
|
|
30
|
+
"qrcode-terminal": "^0.12.0"
|
|
31
|
+
},
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/wahdalo/wa-multi-mongodb.git"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/mime": "^3.0.1",
|
|
38
|
+
"@types/mongodb": "^4.0.6",
|
|
39
|
+
"typescript": "^5.7.2"
|
|
40
|
+
}
|
|
41
|
+
}
|
package/readme.md
CHANGED
|
@@ -17,6 +17,7 @@ Built on [Baileys](https://github.com/WhiskeySockets/Baileys) Library.
|
|
|
17
17
|
- Better group chat support
|
|
18
18
|
- Automatic retry for failed message deliveries
|
|
19
19
|
- Automatic group chat detection (v3.9.0+)
|
|
20
|
+
- Hybrid caching system for group metadata (v3.9.4+)
|
|
20
21
|
|
|
21
22
|
## Installation
|
|
22
23
|
|
|
@@ -225,6 +226,60 @@ whatsapp.onMessageReceived(async (msg) => {
|
|
|
225
226
|
});
|
|
226
227
|
```
|
|
227
228
|
|
|
229
|
+
### Group Metadata Caching (v3.9.4+)
|
|
230
|
+
|
|
231
|
+
The library now implements a hybrid caching system for group metadata using both in-memory (NodeCache) and persistent storage (MongoDB). This significantly improves performance for applications that frequently use group metadata information.
|
|
232
|
+
|
|
233
|
+
```javascript
|
|
234
|
+
// Configure cache settings (optional, has default values)
|
|
235
|
+
whatsapp.setGroupCacheConfig({
|
|
236
|
+
stdTTL: 10 * 60, // Time-to-live in seconds (10 minutes)
|
|
237
|
+
checkperiod: 120 // Check for expired keys every 2 minutes
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Get group metadata (automatically uses cache if available)
|
|
241
|
+
const metadata = await whatsapp.getGroupMetadata(sessionId, groupJid);
|
|
242
|
+
console.log(`Group name: ${metadata.subject}`);
|
|
243
|
+
console.log(`Participants: ${metadata.participants.length}`);
|
|
244
|
+
console.log(`Created on: ${new Date(metadata.creation * 1000).toLocaleString()}`);
|
|
245
|
+
|
|
246
|
+
// Force fetch fresh data from server and update cache
|
|
247
|
+
const freshData = await whatsapp.getGroupMetadata(sessionId, groupJid, true);
|
|
248
|
+
|
|
249
|
+
// Clear cache for specific group in a specific session
|
|
250
|
+
await whatsapp.clearGroupMetadataCache(sessionId, groupJid);
|
|
251
|
+
|
|
252
|
+
// Clear all group metadata cache for a specific session
|
|
253
|
+
await whatsapp.clearSessionGroupMetadataCache(sessionId);
|
|
254
|
+
|
|
255
|
+
// Clear all cached group metadata for all sessions
|
|
256
|
+
whatsapp.clearAllGroupMetadataCache();
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Benefits of the hybrid caching system:
|
|
260
|
+
1. Significantly reduces WhatsApp API calls for group metadata
|
|
261
|
+
2. Improves response time for group-related features
|
|
262
|
+
3. Persistent cache in MongoDB survives application restarts
|
|
263
|
+
4. In-memory cache provides ultra-fast access for frequently used groups
|
|
264
|
+
5. Automatic cache invalidation on group updates (members, settings, etc.)
|
|
265
|
+
6. **Full multi-session support** - each session has isolated cache for group metadata
|
|
266
|
+
7. Automatic cleanup when sessions are deleted or invalidated
|
|
267
|
+
|
|
268
|
+
#### Multi-Session Caching Architecture
|
|
269
|
+
|
|
270
|
+
The group metadata cache system is designed to support multiple WhatsApp sessions running simultaneously without any cache collision:
|
|
271
|
+
|
|
272
|
+
- Each session maintains its own isolated cache for group metadata
|
|
273
|
+
- Cache keys combine both session ID and group ID to ensure separation
|
|
274
|
+
- MongoDB storage includes session information for persistent separation
|
|
275
|
+
- Cache cleanup happens automatically when sessions are deleted or invalidated
|
|
276
|
+
- Memory and database efficiency through shared infrastructure
|
|
277
|
+
|
|
278
|
+
This approach ensures that in multi-session environments:
|
|
279
|
+
- Session A and Session B can both cache metadata for the same group ID without conflicts
|
|
280
|
+
- Each session gets its own view of its accessible groups
|
|
281
|
+
- Cache invalidation in one session doesn't affect other sessions
|
|
282
|
+
|
|
228
283
|
## Utility Functions
|
|
229
284
|
|
|
230
285
|
```javascript
|
|
@@ -313,6 +368,12 @@ async function startApp() {
|
|
|
313
368
|
// Detect if message is from a group
|
|
314
369
|
const isGroup = msg.key.remoteJid.endsWith('@g.us');
|
|
315
370
|
|
|
371
|
+
// Using group metadata cache (v3.9.4+)
|
|
372
|
+
if (isGroup) {
|
|
373
|
+
const metadata = await whatsapp.getGroupMetadata(msg.sessionId, msg.key.remoteJid);
|
|
374
|
+
console.log(`Message from group: ${metadata.subject} with ${metadata.participants.length} members`);
|
|
375
|
+
}
|
|
376
|
+
|
|
316
377
|
// Mark message as read
|
|
317
378
|
try {
|
|
318
379
|
await whatsapp.readMessage({
|
|
@@ -345,7 +406,6 @@ async function startApp() {
|
|
|
345
406
|
to: msg.key.remoteJid,
|
|
346
407
|
text: "Hello! How can I help you?",
|
|
347
408
|
answering: msg,
|
|
348
|
-
// isGroup parameter is optional (v3.9.0+)
|
|
349
409
|
}),
|
|
350
410
|
timeoutMs,
|
|
351
411
|
"Message sending timed out"
|
|
@@ -354,6 +414,34 @@ async function startApp() {
|
|
|
354
414
|
console.error("Error sending message:", error.message);
|
|
355
415
|
}
|
|
356
416
|
}
|
|
417
|
+
|
|
418
|
+
// Example command to get group info
|
|
419
|
+
if (messageContent === "!groupinfo" && isGroup) {
|
|
420
|
+
try {
|
|
421
|
+
// Force fetch fresh data
|
|
422
|
+
const metadata = await whatsapp.getGroupMetadata(msg.sessionId, msg.key.remoteJid, true);
|
|
423
|
+
|
|
424
|
+
const adminList = metadata.participants
|
|
425
|
+
.filter(p => p.admin)
|
|
426
|
+
.map(p => p.id.split('@')[0])
|
|
427
|
+
.join(", ");
|
|
428
|
+
|
|
429
|
+
const infoText = `*Group Info*\n` +
|
|
430
|
+
`Name: ${metadata.subject}\n` +
|
|
431
|
+
`Description: ${metadata.desc || 'None'}\n` +
|
|
432
|
+
`Members: ${metadata.participants.length}\n` +
|
|
433
|
+
`Admins: ${adminList}\n` +
|
|
434
|
+
`Created: ${new Date(metadata.creation * 1000).toLocaleString()}`;
|
|
435
|
+
|
|
436
|
+
await whatsapp.sendTextMessage({
|
|
437
|
+
sessionId: msg.sessionId,
|
|
438
|
+
to: msg.key.remoteJid,
|
|
439
|
+
text: infoText
|
|
440
|
+
});
|
|
441
|
+
} catch (error) {
|
|
442
|
+
console.error("Error getting group info:", error.message);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
357
445
|
} catch (error) {
|
|
358
446
|
// Prevent application crash
|
|
359
447
|
console.error("Error processing message:", error.message);
|
|
@@ -394,6 +482,7 @@ startApp().catch(err => {
|
|
|
394
482
|
4. **Handle Errors**: Implement retry mechanisms for failed group messages
|
|
395
483
|
5. **Announcement Channels**: Groups with announcement channels may trigger `MessageCounterError` (handled automatically in v3.9.1+)
|
|
396
484
|
6. **Retry Strategy**: For announcement channel groups, the library will automatically retry sending messages up to 3 times with increasing delays
|
|
485
|
+
7. **Group Metadata Caching**: Use the hybrid caching system (v3.9.4+) to improve performance when working with groups
|
|
397
486
|
|
|
398
487
|
## WhatsApp Limitations
|
|
399
488
|
|
|
@@ -403,7 +492,22 @@ startApp().catch(err => {
|
|
|
403
492
|
|
|
404
493
|
## Changelog
|
|
405
494
|
|
|
406
|
-
### v3.9.
|
|
495
|
+
### v3.9.4 (current)
|
|
496
|
+
- Updated baileys dependency to v6.7.18
|
|
497
|
+
- Added hybrid caching system for group metadata (NodeCache + MongoDB)
|
|
498
|
+
- Improved group operations performance with automatic caching
|
|
499
|
+
- New functions for group metadata management:
|
|
500
|
+
- `getGroupMetadata()` - Get metadata with automatic caching
|
|
501
|
+
- `setGroupCacheConfig()` - Configure cache TTL and check periods
|
|
502
|
+
- `clearGroupMetadataCache()` - Clear specific group metadata
|
|
503
|
+
- `clearAllGroupMetadataCache()` - Clear all cached group metadata
|
|
504
|
+
|
|
505
|
+
### v3.9.3
|
|
506
|
+
- Updated QR code implementation for better display in terminal
|
|
507
|
+
- Replaced deprecated `printQRInTerminal` option with `qrcode` library implementation
|
|
508
|
+
- Added support for latest Baileys version
|
|
509
|
+
|
|
510
|
+
### v3.9.2
|
|
407
511
|
- Updated Baileys dependency to v6.7.17 for improved stability and compatibility
|
|
408
512
|
|
|
409
513
|
### v3.9.1
|