wa-multi-mongodb 3.9.3 → 3.9.5
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/Messaging/index.d.ts +9 -0
- package/dist/Messaging/index.d.ts.map +1 -1
- package/dist/Messaging/index.js +43 -1
- package/dist/Socket/index.d.ts +8 -0
- package/dist/Socket/index.d.ts.map +1 -1
- package/dist/Socket/index.js +91 -1
- 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 -39
- package/readme.md +143 -2
|
@@ -22,4 +22,13 @@ export declare const sendTyping: ({ sessionId, to, duration, isGroup, }: SendTyp
|
|
|
22
22
|
* @param key - Message key to mark as read
|
|
23
23
|
*/
|
|
24
24
|
export declare const readMessage: ({ sessionId, key, }: SendReadTypes) => Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Menghapus pesan yang telah dikirim
|
|
27
|
+
*
|
|
28
|
+
* Dapat digunakan untuk menghapus pesan bot sendiri atau menghapus pesan orang lain (jika bot adalah admin di grup)
|
|
29
|
+
*
|
|
30
|
+
* @param sessionId - Session ID
|
|
31
|
+
* @param key - Message key dari pesan yang akan dihapus
|
|
32
|
+
*/
|
|
33
|
+
export declare const deleteMessage: ({ sessionId, key, }: SendReadTypes) => Promise<void>;
|
|
25
34
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Messaging/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,SAAS,CAAC;AAGnD,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,eAAe,EAChB,MAAM,UAAU,CAAC;AAOlB,eAAO,MAAM,eAAe,GAAU,4CAMnC,gBAAgB,KAAG,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,SAAS,CA2H7D,CAAC;AAaF,eAAO,MAAM,SAAS,GAAU,wEAS7B,cAAc,KAAG,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,SAAS,CAgL3D,CAAC;AAEF,eAAO,MAAM,aAAa,GAAU,6CAMjC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,KAAG,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,SAAS,CA2GzE,CAAC;AAEF,eAAO,MAAM,WAAW,GAAU,6CAM/B,cAAc,KAAG,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,SAAS,CAyG3D,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,GAAU,uCAK9B,eAAe,KAAG,OAAO,CAAC,IAAI,CAuEhC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAU,qBAG/B,aAAa,KAAG,OAAO,CAAC,IAAI,CA6B9B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Messaging/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,SAAS,CAAC;AAGnD,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,eAAe,EAChB,MAAM,UAAU,CAAC;AAOlB,eAAO,MAAM,eAAe,GAAU,4CAMnC,gBAAgB,KAAG,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,SAAS,CA2H7D,CAAC;AAaF,eAAO,MAAM,SAAS,GAAU,wEAS7B,cAAc,KAAG,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,SAAS,CAgL3D,CAAC;AAEF,eAAO,MAAM,aAAa,GAAU,6CAMjC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,KAAG,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,SAAS,CA2GzE,CAAC;AAEF,eAAO,MAAM,WAAW,GAAU,6CAM/B,cAAc,KAAG,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,SAAS,CAyG3D,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,GAAU,uCAK9B,eAAe,KAAG,OAAO,CAAC,IAAI,CAuEhC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAU,qBAG/B,aAAa,KAAG,OAAO,CAAC,IAAI,CA6B9B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GAAU,qBAGjC,aAAa,KAAG,OAAO,CAAC,IAAI,CAsC9B,CAAC"}
|
package/dist/Messaging/index.js
CHANGED
|
@@ -23,7 +23,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
23
23
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.readMessage = exports.sendTyping = exports.sendSticker = exports.sendVoiceNote = exports.sendMedia = exports.sendTextMessage = void 0;
|
|
26
|
+
exports.deleteMessage = exports.readMessage = exports.sendTyping = exports.sendSticker = exports.sendVoiceNote = exports.sendMedia = exports.sendTextMessage = void 0;
|
|
27
27
|
const Defaults_1 = require("../Defaults");
|
|
28
28
|
const Socket_1 = require("../Socket");
|
|
29
29
|
const Utils_1 = require("../Utils");
|
|
@@ -554,3 +554,45 @@ const readMessage = (_a) => __awaiter(void 0, [_a], void 0, function* ({ session
|
|
|
554
554
|
}
|
|
555
555
|
});
|
|
556
556
|
exports.readMessage = readMessage;
|
|
557
|
+
/**
|
|
558
|
+
* Menghapus pesan yang telah dikirim
|
|
559
|
+
*
|
|
560
|
+
* Dapat digunakan untuk menghapus pesan bot sendiri atau menghapus pesan orang lain (jika bot adalah admin di grup)
|
|
561
|
+
*
|
|
562
|
+
* @param sessionId - Session ID
|
|
563
|
+
* @param key - Message key dari pesan yang akan dihapus
|
|
564
|
+
*/
|
|
565
|
+
const deleteMessage = (_a) => __awaiter(void 0, [_a], void 0, function* ({ sessionId, key, }) {
|
|
566
|
+
var _b;
|
|
567
|
+
const session = (0, Socket_1.getSession)(sessionId);
|
|
568
|
+
if (!session)
|
|
569
|
+
throw new Error_1.WhatsappError(Defaults_1.Messages.sessionNotFound(sessionId));
|
|
570
|
+
try {
|
|
571
|
+
// Hapus pesan dengan timeout untuk mencegah hanging
|
|
572
|
+
yield (0, create_delay_1.withTimeout)(session.sendMessage(key.remoteJid, {
|
|
573
|
+
delete: key
|
|
574
|
+
}), 10000, "Timeout saat menghapus pesan");
|
|
575
|
+
}
|
|
576
|
+
catch (error) {
|
|
577
|
+
console.error(`Error saat menghapus pesan: ${(error === null || error === void 0 ? void 0 : error.message) || 'Unknown error'}`);
|
|
578
|
+
// Jika koneksi tertutup, coba reconnect
|
|
579
|
+
if ((_b = error === null || error === void 0 ? void 0 : error.message) === null || _b === void 0 ? void 0 : _b.includes('Connection Closed')) {
|
|
580
|
+
try {
|
|
581
|
+
yield (0, Socket_1.reconnect)(sessionId);
|
|
582
|
+
yield (0, create_delay_1.createDelay)(2000); // Beri waktu untuk reconnect sepenuhnya
|
|
583
|
+
// Coba hapus lagi setelah reconnect
|
|
584
|
+
yield (0, create_delay_1.withTimeout)(session.sendMessage(key.remoteJid, {
|
|
585
|
+
delete: key
|
|
586
|
+
}), 10000, "Timeout saat menghapus pesan setelah reconnect");
|
|
587
|
+
}
|
|
588
|
+
catch (reconnectError) {
|
|
589
|
+
console.error(`Gagal reconnect atau menghapus pesan: ${(reconnectError === null || reconnectError === void 0 ? void 0 : reconnectError.message) || 'Unknown error'}`);
|
|
590
|
+
throw new Error_1.WhatsappError(`Gagal menghapus pesan: ${(reconnectError === null || reconnectError === void 0 ? void 0 : reconnectError.message) || 'Unknown error'}`);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
else {
|
|
594
|
+
throw new Error_1.WhatsappError(`Gagal menghapus pesan: ${(error === null || error === void 0 ? void 0 : error.message) || 'Unknown error'}`);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
exports.deleteMessage = deleteMessage;
|
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;AAKjB,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,iCAAiC,EAClC,MAAM,UAAU,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,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.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"));
|
|
@@ -53,6 +53,7 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
53
53
|
const qrcode_1 = __importDefault(require("qrcode"));
|
|
54
54
|
const Defaults_1 = require("../Defaults");
|
|
55
55
|
const save_media_1 = require("../Utils/save-media");
|
|
56
|
+
const Utils_1 = require("../Utils");
|
|
56
57
|
const Error_1 = require("../Error");
|
|
57
58
|
const message_status_1 = require("../Utils/message-status");
|
|
58
59
|
const mongodb_1 = require("mongodb");
|
|
@@ -76,6 +77,8 @@ let mongoURI = process.env.MONGODB_URI || "mongodb://localhost:27017";
|
|
|
76
77
|
*/
|
|
77
78
|
const setMongoURI = (uri) => __awaiter(void 0, void 0, void 0, function* () {
|
|
78
79
|
mongoURI = uri;
|
|
80
|
+
// Configure group cache MongoDB connection as well
|
|
81
|
+
yield Utils_1.groupCache.setMongoURI(uri);
|
|
79
82
|
// Reset MongoDB client and collection to ensure they are recreated with new URI
|
|
80
83
|
if (mongoClient) {
|
|
81
84
|
try {
|
|
@@ -121,6 +124,10 @@ const startSession = (...args_1) => __awaiter(void 0, [...args_1], void 0, funct
|
|
|
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 {
|
|
@@ -179,6 +186,32 @@ const startSession = (...args_1) => __awaiter(void 0, [...args_1], void 0, funct
|
|
|
179
186
|
if (events["creds.update"]) {
|
|
180
187
|
yield saveCreds();
|
|
181
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
|
+
}
|
|
182
215
|
if (events["messages.update"]) {
|
|
183
216
|
const msg = events["messages.update"][0];
|
|
184
217
|
const data = Object.assign({ sessionId: sessionId, messageStatus: (0, message_status_1.parseMessageStatusCodeToReadable)(msg.update.status) }, msg);
|
|
@@ -333,6 +366,14 @@ const deleteSession = (sessionId) => __awaiter(void 0, void 0, void 0, function*
|
|
|
333
366
|
console.error(`Error deleting session ${sessionId} from MongoDB:`, error);
|
|
334
367
|
}
|
|
335
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
|
+
}
|
|
336
377
|
// Legacy: hapus juga dari file system jika ada
|
|
337
378
|
const dir = path_1.default.resolve(Defaults_1.CREDENTIALS.DIR_NAME, sessionId + Defaults_1.CREDENTIALS.PREFIX);
|
|
338
379
|
if (fs_1.default.existsSync(dir)) {
|
|
@@ -544,3 +585,52 @@ const reconnect = (sessionId) => __awaiter(void 0, void 0, void 0, function* ()
|
|
|
544
585
|
}
|
|
545
586
|
});
|
|
546
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,39 +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
|
-
"@types/
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "wa-multi-mongodb",
|
|
3
|
+
"version": "3.9.5",
|
|
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,8 @@ 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+)
|
|
21
|
+
- Message deletion for self and others (v3.9.5+)
|
|
20
22
|
|
|
21
23
|
## Installation
|
|
22
24
|
|
|
@@ -177,6 +179,42 @@ await whatsapp.sendTyping({
|
|
|
177
179
|
duration: 3000, // milliseconds
|
|
178
180
|
// isGroup parameter is optional (v3.9.0+)
|
|
179
181
|
});
|
|
182
|
+
|
|
183
|
+
// Delete message (v3.9.5+)
|
|
184
|
+
// Delete own message for everyone
|
|
185
|
+
await whatsapp.deleteMessage({
|
|
186
|
+
sessionId: "mysession",
|
|
187
|
+
key: messageObject.key, // message key from received or sent message
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Delete someone else's message (requires admin permissions in groups)
|
|
191
|
+
await whatsapp.deleteMessage({
|
|
192
|
+
sessionId: "mysession",
|
|
193
|
+
key: {
|
|
194
|
+
remoteJid: "120363152682073800@g.us", // group ID with @g.us
|
|
195
|
+
fromMe: false,
|
|
196
|
+
id: "MESSAGE_ID",
|
|
197
|
+
participant: "SENDER_JID" // required for group messages
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Auto-delete message after delay (helper function example)
|
|
202
|
+
function autoDeleteMessage(sessionId, message, delayMs = 3000) {
|
|
203
|
+
setTimeout(async () => {
|
|
204
|
+
try {
|
|
205
|
+
await whatsapp.deleteMessage({
|
|
206
|
+
sessionId: sessionId,
|
|
207
|
+
key: message.key
|
|
208
|
+
});
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.error("Error auto-deleting message:", error);
|
|
211
|
+
}
|
|
212
|
+
}, delayMs);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Usage: Auto-delete a sent message after 5 seconds
|
|
216
|
+
const sentMsg = await whatsapp.sendTextMessage({/*...*/});
|
|
217
|
+
autoDeleteMessage("mysession", sentMsg, 5000);
|
|
180
218
|
```
|
|
181
219
|
|
|
182
220
|
### Event Listeners
|
|
@@ -225,6 +263,60 @@ whatsapp.onMessageReceived(async (msg) => {
|
|
|
225
263
|
});
|
|
226
264
|
```
|
|
227
265
|
|
|
266
|
+
### Group Metadata Caching (v3.9.4+)
|
|
267
|
+
|
|
268
|
+
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.
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
// Configure cache settings (optional, has default values)
|
|
272
|
+
whatsapp.setGroupCacheConfig({
|
|
273
|
+
stdTTL: 10 * 60, // Time-to-live in seconds (10 minutes)
|
|
274
|
+
checkperiod: 120 // Check for expired keys every 2 minutes
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// Get group metadata (automatically uses cache if available)
|
|
278
|
+
const metadata = await whatsapp.getGroupMetadata(sessionId, groupJid);
|
|
279
|
+
console.log(`Group name: ${metadata.subject}`);
|
|
280
|
+
console.log(`Participants: ${metadata.participants.length}`);
|
|
281
|
+
console.log(`Created on: ${new Date(metadata.creation * 1000).toLocaleString()}`);
|
|
282
|
+
|
|
283
|
+
// Force fetch fresh data from server and update cache
|
|
284
|
+
const freshData = await whatsapp.getGroupMetadata(sessionId, groupJid, true);
|
|
285
|
+
|
|
286
|
+
// Clear cache for specific group in a specific session
|
|
287
|
+
await whatsapp.clearGroupMetadataCache(sessionId, groupJid);
|
|
288
|
+
|
|
289
|
+
// Clear all group metadata cache for a specific session
|
|
290
|
+
await whatsapp.clearSessionGroupMetadataCache(sessionId);
|
|
291
|
+
|
|
292
|
+
// Clear all cached group metadata for all sessions
|
|
293
|
+
whatsapp.clearAllGroupMetadataCache();
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Benefits of the hybrid caching system:
|
|
297
|
+
1. Significantly reduces WhatsApp API calls for group metadata
|
|
298
|
+
2. Improves response time for group-related features
|
|
299
|
+
3. Persistent cache in MongoDB survives application restarts
|
|
300
|
+
4. In-memory cache provides ultra-fast access for frequently used groups
|
|
301
|
+
5. Automatic cache invalidation on group updates (members, settings, etc.)
|
|
302
|
+
6. **Full multi-session support** - each session has isolated cache for group metadata
|
|
303
|
+
7. Automatic cleanup when sessions are deleted or invalidated
|
|
304
|
+
|
|
305
|
+
#### Multi-Session Caching Architecture
|
|
306
|
+
|
|
307
|
+
The group metadata cache system is designed to support multiple WhatsApp sessions running simultaneously without any cache collision:
|
|
308
|
+
|
|
309
|
+
- Each session maintains its own isolated cache for group metadata
|
|
310
|
+
- Cache keys combine both session ID and group ID to ensure separation
|
|
311
|
+
- MongoDB storage includes session information for persistent separation
|
|
312
|
+
- Cache cleanup happens automatically when sessions are deleted or invalidated
|
|
313
|
+
- Memory and database efficiency through shared infrastructure
|
|
314
|
+
|
|
315
|
+
This approach ensures that in multi-session environments:
|
|
316
|
+
- Session A and Session B can both cache metadata for the same group ID without conflicts
|
|
317
|
+
- Each session gets its own view of its accessible groups
|
|
318
|
+
- Cache invalidation in one session doesn't affect other sessions
|
|
319
|
+
|
|
228
320
|
## Utility Functions
|
|
229
321
|
|
|
230
322
|
```javascript
|
|
@@ -313,6 +405,12 @@ async function startApp() {
|
|
|
313
405
|
// Detect if message is from a group
|
|
314
406
|
const isGroup = msg.key.remoteJid.endsWith('@g.us');
|
|
315
407
|
|
|
408
|
+
// Using group metadata cache (v3.9.4+)
|
|
409
|
+
if (isGroup) {
|
|
410
|
+
const metadata = await whatsapp.getGroupMetadata(msg.sessionId, msg.key.remoteJid);
|
|
411
|
+
console.log(`Message from group: ${metadata.subject} with ${metadata.participants.length} members`);
|
|
412
|
+
}
|
|
413
|
+
|
|
316
414
|
// Mark message as read
|
|
317
415
|
try {
|
|
318
416
|
await whatsapp.readMessage({
|
|
@@ -345,7 +443,6 @@ async function startApp() {
|
|
|
345
443
|
to: msg.key.remoteJid,
|
|
346
444
|
text: "Hello! How can I help you?",
|
|
347
445
|
answering: msg,
|
|
348
|
-
// isGroup parameter is optional (v3.9.0+)
|
|
349
446
|
}),
|
|
350
447
|
timeoutMs,
|
|
351
448
|
"Message sending timed out"
|
|
@@ -354,6 +451,34 @@ async function startApp() {
|
|
|
354
451
|
console.error("Error sending message:", error.message);
|
|
355
452
|
}
|
|
356
453
|
}
|
|
454
|
+
|
|
455
|
+
// Example command to get group info
|
|
456
|
+
if (messageContent === "!groupinfo" && isGroup) {
|
|
457
|
+
try {
|
|
458
|
+
// Force fetch fresh data
|
|
459
|
+
const metadata = await whatsapp.getGroupMetadata(msg.sessionId, msg.key.remoteJid, true);
|
|
460
|
+
|
|
461
|
+
const adminList = metadata.participants
|
|
462
|
+
.filter(p => p.admin)
|
|
463
|
+
.map(p => p.id.split('@')[0])
|
|
464
|
+
.join(", ");
|
|
465
|
+
|
|
466
|
+
const infoText = `*Group Info*\n` +
|
|
467
|
+
`Name: ${metadata.subject}\n` +
|
|
468
|
+
`Description: ${metadata.desc || 'None'}\n` +
|
|
469
|
+
`Members: ${metadata.participants.length}\n` +
|
|
470
|
+
`Admins: ${adminList}\n` +
|
|
471
|
+
`Created: ${new Date(metadata.creation * 1000).toLocaleString()}`;
|
|
472
|
+
|
|
473
|
+
await whatsapp.sendTextMessage({
|
|
474
|
+
sessionId: msg.sessionId,
|
|
475
|
+
to: msg.key.remoteJid,
|
|
476
|
+
text: infoText
|
|
477
|
+
});
|
|
478
|
+
} catch (error) {
|
|
479
|
+
console.error("Error getting group info:", error.message);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
357
482
|
} catch (error) {
|
|
358
483
|
// Prevent application crash
|
|
359
484
|
console.error("Error processing message:", error.message);
|
|
@@ -394,6 +519,7 @@ startApp().catch(err => {
|
|
|
394
519
|
4. **Handle Errors**: Implement retry mechanisms for failed group messages
|
|
395
520
|
5. **Announcement Channels**: Groups with announcement channels may trigger `MessageCounterError` (handled automatically in v3.9.1+)
|
|
396
521
|
6. **Retry Strategy**: For announcement channel groups, the library will automatically retry sending messages up to 3 times with increasing delays
|
|
522
|
+
7. **Group Metadata Caching**: Use the hybrid caching system (v3.9.4+) to improve performance when working with groups
|
|
397
523
|
|
|
398
524
|
## WhatsApp Limitations
|
|
399
525
|
|
|
@@ -403,7 +529,22 @@ startApp().catch(err => {
|
|
|
403
529
|
|
|
404
530
|
## Changelog
|
|
405
531
|
|
|
406
|
-
### v3.9.
|
|
532
|
+
### v3.9.5 (current)
|
|
533
|
+
- New `deleteMessage()` function for deleting messages
|
|
534
|
+
- Support for deleting both own messages and others' messages (requires admin permissions in groups)
|
|
535
|
+
- Auto-delete message utility function example
|
|
536
|
+
|
|
537
|
+
### v3.9.4
|
|
538
|
+
- Updated baileys dependency to v6.7.18
|
|
539
|
+
- Added hybrid caching system for group metadata (NodeCache + MongoDB)
|
|
540
|
+
- Improved group operations performance with automatic caching
|
|
541
|
+
- New functions for group metadata management:
|
|
542
|
+
- `getGroupMetadata()` - Get metadata with automatic caching
|
|
543
|
+
- `setGroupCacheConfig()` - Configure cache TTL and check periods
|
|
544
|
+
- `clearGroupMetadataCache()` - Clear specific group metadata
|
|
545
|
+
- `clearAllGroupMetadataCache()` - Clear all cached group metadata
|
|
546
|
+
|
|
547
|
+
### v3.9.3
|
|
407
548
|
- Updated QR code implementation for better display in terminal
|
|
408
549
|
- Replaced deprecated `printQRInTerminal` option with `qrcode` library implementation
|
|
409
550
|
- Added support for latest Baileys version
|