wa-multi-mongodb 3.9.3 → 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.
@@ -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.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,17 @@ startApp().catch(err => {
403
492
 
404
493
  ## Changelog
405
494
 
406
- ### v3.9.3 (Current)
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
407
506
  - Updated QR code implementation for better display in terminal
408
507
  - Replaced deprecated `printQRInTerminal` option with `qrcode` library implementation
409
508
  - Added support for latest Baileys version