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.
@@ -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"}
@@ -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;
@@ -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;AA6BlB;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAU,KAAK,MAAM,kBAe5C,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,GAAG,QAEjD;AAkBD,eAAO,MAAM,YAAY,GACvB,kBAAuB,EACvB,UAAS,kBAAsC,KAC9C,OAAO,CAAC,QAAQ,CAsGlB,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,iCA5Nf,kBAAkB,KAC1B,OAAO,CAAC,QAAQ,CA2NsB,CAAC;AAE1C,eAAO,MAAM,aAAa,GAAU,WAAW,MAAM,kBA0BpD,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"}
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"}
@@ -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();
@@ -1,4 +1,5 @@
1
1
  export * from "./phone-to-jid";
2
2
  export * from "./is-exist";
3
3
  export * from "./create-delay";
4
+ export * from "./group-cache";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -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"}
@@ -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.3",
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/qrcode": "^1.5.5",
21
- "baileys": "^6.7.17",
22
- "dotenv": "^16.5.0",
23
- "link-preview-js": "^3.0.14",
24
- "mime": "^3.0.0",
25
- "mongodb": "^5.7.0",
26
- "pino": "^9.5.0",
27
- "qrcode": "^1.5.4",
28
- "qrcode-terminal": "^0.12.0"
29
- },
30
- "repository": {
31
- "type": "git",
32
- "url": "git+https://github.com/wahdalo/wa-multi-mongodb.git"
33
- },
34
- "devDependencies": {
35
- "@types/mime": "^3.0.1",
36
- "@types/mongodb": "^4.0.6",
37
- "typescript": "^5.7.2"
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.3 (Current)
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