wa-multi-mongodb 3.8.1 → 3.9.1

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.
@@ -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,CAoF7D,CAAC;AAaF,eAAO,MAAM,SAAS,GAAU,wEAS7B,cAAc,KAAG,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,SAAS,CAyI3D,CAAC;AAEF,eAAO,MAAM,aAAa,GAAU,6CAMjC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,KAAG,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,SAAS,CAwBzE,CAAC;AAEF,eAAO,MAAM,WAAW,GAAU,6CAM/B,cAAc,KAAG,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,SAAS,CAuB3D,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,GAAU,uCAK9B,eAAe,KAAG,OAAO,CAAC,IAAI,CAuDhC,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"}
@@ -32,153 +32,123 @@ const is_exist_1 = require("../Utils/is-exist");
32
32
  const mime_1 = __importDefault(require("mime"));
33
33
  const Error_1 = require("../Error");
34
34
  const sendTextMessage = (_a) => __awaiter(void 0, void 0, void 0, function* () {
35
- var _b;
36
35
  var { sessionId, to, text = "", isGroup = false } = _a, props = __rest(_a, ["sessionId", "to", "text", "isGroup"]);
37
36
  const session = (0, Socket_1.getSession)(sessionId);
38
37
  if (!session)
39
38
  throw new Error_1.WhatsappError(Defaults_1.Messages.sessionNotFound(sessionId));
40
- to = (0, Utils_1.phoneToJid)({ to, isGroup });
41
- try {
42
- // Gunakan flag force untuk mencoba memaksa pengiriman pesan bahkan jika koneksi tidak stabil
43
- const messageOptions = {
44
- quoted: props.answering,
45
- };
46
- // Deteksi apakah ini grup berdasarkan format JID
47
- const isGroupChat = to.endsWith('@g.us');
48
- // Gunakan waktu jeda untuk memastikan koneksi siap
49
- yield (0, create_delay_1.createDelay)(500);
50
- // Beri timeout yang lebih pendek untuk grup untuk mencegah hanging
51
- const timeoutMs = isGroupChat ? 15000 : 30000;
52
- // Gunakan withTimeout untuk membatasi waktu operasi
53
- return yield (0, create_delay_1.withTimeout)(session.sendMessage(to, {
54
- text: text,
55
- }, messageOptions), timeoutMs, `Pengiriman pesan ke ${to} melebihi batas waktu ${timeoutMs / 1000} detik`);
39
+ // Deteksi otomatis apakah ini adalah grup berdasarkan format JID
40
+ const toStr = to.toString();
41
+ const isGroupChat = toStr.includes('@g.us');
42
+ // Jika sudah dalam format grup, gunakan to langsung
43
+ // Jika tidak, gunakan phoneToJid untuk mengkonversi ke format yang benar
44
+ let jid;
45
+ if (isGroupChat) {
46
+ if (!toStr.endsWith('@g.us')) {
47
+ jid = toStr + '@g.us';
48
+ }
49
+ else {
50
+ jid = toStr;
51
+ }
56
52
  }
57
- catch (error) {
58
- console.error(`Error saat mengirim pesan: ${(error === null || error === void 0 ? void 0 : error.message) || 'Unknown error'}`);
59
- // Jika koneksi tertutup, coba reconnect
60
- if ((_b = error === null || error === void 0 ? void 0 : error.message) === null || _b === void 0 ? void 0 : _b.includes('Connection Closed')) {
53
+ else {
54
+ jid = (0, Utils_1.phoneToJid)({ to, isGroup: isGroup || isGroupChat });
55
+ }
56
+ let retryCount = 0;
57
+ const maxRetries = 3;
58
+ const attemptSend = () => __awaiter(void 0, void 0, void 0, function* () {
59
+ var _a, _b, _c;
60
+ try {
61
+ // Gunakan flag force untuk mencoba memaksa pengiriman pesan bahkan jika koneksi tidak stabil
62
+ const messageOptions = {
63
+ quoted: props.answering,
64
+ };
65
+ // Konfirmasi sekali lagi apakah ini grup berdasarkan format JID setelah konversi
66
+ const isDestinationGroup = jid.endsWith('@g.us');
67
+ // Gunakan waktu jeda untuk memastikan koneksi siap
68
+ yield (0, create_delay_1.createDelay)(500);
69
+ // Beri timeout yang lebih pendek untuk grup untuk mencegah hanging
70
+ const timeoutMs = isDestinationGroup ? 15000 : 30000;
71
+ // Gunakan withTimeout untuk membatasi waktu operasi
72
+ return yield (0, create_delay_1.withTimeout)(session.sendMessage(jid, {
73
+ text: text,
74
+ }, messageOptions), timeoutMs, `Pengiriman pesan ke ${jid} melebihi batas waktu ${timeoutMs / 1000} detik`);
75
+ }
76
+ catch (error) {
77
+ console.error(`Error saat mengirim pesan (percobaan ${retryCount + 1}/${maxRetries}): ${(error === null || error === void 0 ? void 0 : error.message) || 'Unknown error'}`);
78
+ // Jika error terkait MessageCounterError (grup dengan channel pengumuman)
79
+ if (((_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.includes('MessageCounterError')) || ((_b = error === null || error === void 0 ? void 0 : error.stack) === null || _b === void 0 ? void 0 : _b.includes('MessageCounterError'))) {
80
+ console.warn('Terdeteksi MessageCounterError, kemungkinan grup dengan channel pengumuman');
81
+ if (retryCount < maxRetries) {
82
+ retryCount++;
83
+ // Tambahkan delay lebih lama antara percobaan
84
+ yield (0, create_delay_1.createDelay)(2000 * retryCount);
85
+ console.log(`Mencoba kembali pengiriman pesan (${retryCount}/${maxRetries})...`);
86
+ return attemptSend();
87
+ }
88
+ else {
89
+ console.error('Batas maksimum percobaan ulang tercapai');
90
+ throw new Error_1.WhatsappError(`Gagal mengirim pesan ke grup dengan channel pengumuman setelah ${maxRetries} kali percobaan`);
91
+ }
92
+ }
93
+ // Jika koneksi tertutup, coba reconnect
94
+ if ((_c = error === null || error === void 0 ? void 0 : error.message) === null || _c === void 0 ? void 0 : _c.includes('Connection Closed')) {
95
+ try {
96
+ yield (0, Socket_1.reconnect)(sessionId);
97
+ yield (0, create_delay_1.createDelay)(3000); // Beri waktu untuk reconnect sepenuhnya
98
+ // Coba kirim lagi setelah reconnect
99
+ return yield (0, create_delay_1.withTimeout)(session.sendMessage(jid, {
100
+ text: text,
101
+ }, {
102
+ quoted: props.answering,
103
+ }), 30000, `Pengiriman pesan setelah reconnect melebihi batas waktu`);
104
+ }
105
+ catch (reconnectError) {
106
+ console.error(`Gagal reconnect: ${(reconnectError === null || reconnectError === void 0 ? void 0 : reconnectError.message) || 'Unknown error'}`);
107
+ throw new Error_1.WhatsappError(`Koneksi terputus dan gagal reconnect: ${(reconnectError === null || reconnectError === void 0 ? void 0 : reconnectError.message) || 'Unknown error'}`);
108
+ }
109
+ }
110
+ // Jika ada error timeout atau error lain, coba lagi sekali dengan delay lebih lama
61
111
  try {
62
- yield (0, Socket_1.reconnect)(sessionId);
63
- yield (0, create_delay_1.createDelay)(3000); // Beri waktu untuk reconnect sepenuhnya
64
- // Coba kirim lagi setelah reconnect
65
- return yield (0, create_delay_1.withTimeout)(session.sendMessage(to, {
112
+ yield (0, create_delay_1.createDelay)(2000);
113
+ // Untuk percobaan kedua, gunakan timeout yang lebih lama
114
+ return yield (0, create_delay_1.withTimeout)(session.sendMessage(jid, {
66
115
  text: text,
67
116
  }, {
68
117
  quoted: props.answering,
69
- }), 30000, `Pengiriman pesan setelah reconnect melebihi batas waktu`);
118
+ }), 20000, `Percobaan kedua pengiriman pesan melebihi batas waktu`);
70
119
  }
71
- catch (reconnectError) {
72
- console.error(`Gagal reconnect: ${(reconnectError === null || reconnectError === void 0 ? void 0 : reconnectError.message) || 'Unknown error'}`);
73
- throw new Error_1.WhatsappError(`Koneksi terputus dan gagal reconnect: ${(reconnectError === null || reconnectError === void 0 ? void 0 : reconnectError.message) || 'Unknown error'}`);
120
+ catch (retryError) {
121
+ console.error(`Gagal pada percobaan kedua: ${(retryError === null || retryError === void 0 ? void 0 : retryError.message) || 'Unknown error'}`);
122
+ throw new Error_1.WhatsappError(`Gagal mengirim pesan: ${(retryError === null || retryError === void 0 ? void 0 : retryError.message) || 'Unknown error'}`);
74
123
  }
75
124
  }
76
- // Jika ada error timeout atau error lain, coba lagi sekali dengan delay lebih lama
77
- try {
78
- yield (0, create_delay_1.createDelay)(2000);
79
- // Untuk percobaan kedua, gunakan timeout yang lebih lama
80
- return yield (0, create_delay_1.withTimeout)(session.sendMessage(to, {
81
- text: text,
82
- }, {
83
- quoted: props.answering,
84
- }), 20000, `Percobaan kedua pengiriman pesan melebihi batas waktu`);
85
- }
86
- catch (retryError) {
87
- console.error(`Gagal pada percobaan kedua: ${(retryError === null || retryError === void 0 ? void 0 : retryError.message) || 'Unknown error'}`);
88
- throw new Error_1.WhatsappError(`Gagal mengirim pesan: ${(retryError === null || retryError === void 0 ? void 0 : retryError.message) || 'Unknown error'}`);
89
- }
90
- }
125
+ });
126
+ return attemptSend();
91
127
  });
92
128
  exports.sendTextMessage = sendTextMessage;
93
129
  const sendMedia = (_a) => __awaiter(void 0, [_a], void 0, function* ({ sessionId, to, media, type, caption = "", fileName, isGroup = false, answering, }) {
94
- var _b;
95
130
  const session = (0, Socket_1.getSession)(sessionId);
96
131
  if (!session)
97
132
  throw new Error_1.WhatsappError(Defaults_1.Messages.sessionNotFound(sessionId));
98
- to = (0, Utils_1.phoneToJid)({ to, isGroup });
99
- try {
100
- const mimeType = mime_1.default.getType(typeof media === 'string' ? media : (fileName || '')) || 'application/octet-stream';
101
- if (!mimeType && type !== 'image' && type !== 'video')
102
- throw new Error("Cannot get file mimetype!");
103
- const messageContent = {};
104
- const options = answering ? { quoted: answering } : {};
105
- // Deteksi apakah ini grup berdasarkan format JID
106
- const isGroupChat = to.endsWith('@g.us');
107
- // Tunda sejenak untuk memastikan koneksi stabil
108
- yield (0, create_delay_1.createDelay)(500);
109
- // Persiapkan media dengan isExist
110
- const processedMedia = (0, is_exist_1.isExist)(media);
111
- switch (type) {
112
- case "image":
113
- messageContent.image = processedMedia;
114
- messageContent.caption = caption;
115
- if (fileName)
116
- messageContent.fileName = fileName;
117
- break;
118
- case "video":
119
- messageContent.video = processedMedia;
120
- messageContent.caption = caption;
121
- if (fileName)
122
- messageContent.fileName = fileName;
123
- break;
124
- case "audio":
125
- messageContent.audio = processedMedia;
126
- messageContent.mimetype = mimeType;
127
- if (fileName)
128
- messageContent.fileName = fileName;
129
- break;
130
- case "pdf":
131
- case "xls":
132
- case "xlsx":
133
- case "doc":
134
- case "docx":
135
- case "zip":
136
- case "mp3":
137
- messageContent.document = processedMedia;
138
- messageContent.mimetype = mimeType;
139
- messageContent.caption = caption;
140
- if (fileName)
141
- messageContent.fileName = fileName;
142
- break;
143
- default:
144
- throw new Error("Media type not found! (image, video, audio, pdf)");
133
+ // Deteksi otomatis apakah ini adalah grup berdasarkan format JID
134
+ const toStr = to.toString();
135
+ const isGroupChat = toStr.includes('@g.us');
136
+ // Jika sudah dalam format grup, gunakan to langsung
137
+ // Jika tidak, gunakan phoneToJid untuk mengkonversi ke format yang benar
138
+ let jid;
139
+ if (isGroupChat) {
140
+ if (!toStr.endsWith('@g.us')) {
141
+ jid = toStr + '@g.us';
145
142
  }
146
- // Timeout lebih lama untuk media karena ukuran file
147
- const timeoutMs = isGroupChat ? 60000 : 120000;
148
- return yield (0, create_delay_1.withTimeout)(session.sendMessage(to, messageContent, options), timeoutMs, `Pengiriman media melebihi batas waktu ${timeoutMs / 1000} detik`);
149
- }
150
- catch (error) {
151
- console.error(`Error saat mengirim media: ${(error === null || error === void 0 ? void 0 : error.message) || 'Unknown error'}`);
152
- // Jika koneksi tertutup, coba reconnect
153
- if ((_b = error === null || error === void 0 ? void 0 : error.message) === null || _b === void 0 ? void 0 : _b.includes('Connection Closed')) {
154
- try {
155
- yield (0, Socket_1.reconnect)(sessionId);
156
- yield (0, create_delay_1.createDelay)(3000); // Beri waktu untuk reconnect sepenuhnya
157
- // Siapkan content media untuk percobaan ulang
158
- const retryContent = getMessageContent();
159
- // Coba kirim lagi setelah reconnect
160
- return yield (0, create_delay_1.withTimeout)(session.sendMessage(to, retryContent, answering ? { quoted: answering } : {}), 180000, // 3 menit untuk percobaan setelah reconnect
161
- `Pengiriman media setelah reconnect melebihi batas waktu`);
162
- }
163
- catch (reconnectError) {
164
- console.error(`Gagal reconnect: ${(reconnectError === null || reconnectError === void 0 ? void 0 : reconnectError.message) || 'Unknown error'}`);
165
- throw new Error_1.WhatsappError(`Koneksi terputus dan gagal reconnect: ${(reconnectError === null || reconnectError === void 0 ? void 0 : reconnectError.message) || 'Unknown error'}`);
166
- }
167
- }
168
- // Untuk error timeout atau error lain, coba lagi dengan timeout lebih lama
169
- try {
170
- yield (0, create_delay_1.createDelay)(3000);
171
- // Siapkan content media untuk percobaan ulang
172
- const retryContent = getMessageContent();
173
- // Untuk percobaan kedua, gunakan timeout yang lebih lama
174
- return yield (0, create_delay_1.withTimeout)(session.sendMessage(to, retryContent, answering ? { quoted: answering } : {}), 180000, // 3 menit untuk percobaan kedua
175
- `Percobaan kedua pengiriman media melebihi batas waktu`);
176
- }
177
- catch (retryError) {
178
- console.error(`Gagal pada percobaan kedua: ${(retryError === null || retryError === void 0 ? void 0 : retryError.message) || 'Unknown error'}`);
179
- throw new Error_1.WhatsappError(`Gagal mengirim media: ${(retryError === null || retryError === void 0 ? void 0 : retryError.message) || 'Unknown error'}`);
143
+ else {
144
+ jid = toStr;
180
145
  }
181
146
  }
147
+ else {
148
+ jid = (0, Utils_1.phoneToJid)({ to, isGroup: isGroup || isGroupChat });
149
+ }
150
+ let retryCount = 0;
151
+ const maxRetries = 3;
182
152
  // Helper function untuk mendapatkan message content berdasarkan tipe
183
153
  function getMessageContent() {
184
154
  const processedMedia = (0, is_exist_1.isExist)(media);
@@ -212,6 +182,108 @@ const sendMedia = (_a) => __awaiter(void 0, [_a], void 0, function* ({ sessionId
212
182
  }
213
183
  return content;
214
184
  }
185
+ const attemptSend = () => __awaiter(void 0, void 0, void 0, function* () {
186
+ var _a, _b, _c;
187
+ try {
188
+ const mimeType = mime_1.default.getType(typeof media === 'string' ? media : (fileName || '')) || 'application/octet-stream';
189
+ if (!mimeType && type !== 'image' && type !== 'video')
190
+ throw new Error("Cannot get file mimetype!");
191
+ const messageContent = {};
192
+ const options = answering ? { quoted: answering } : {};
193
+ // Konfirmasi sekali lagi apakah ini grup berdasarkan format JID setelah konversi
194
+ const isDestinationGroup = jid.endsWith('@g.us');
195
+ // Tunda sejenak untuk memastikan koneksi stabil
196
+ yield (0, create_delay_1.createDelay)(500);
197
+ // Persiapkan media dengan isExist
198
+ const processedMedia = (0, is_exist_1.isExist)(media);
199
+ switch (type) {
200
+ case "image":
201
+ messageContent.image = processedMedia;
202
+ messageContent.caption = caption;
203
+ if (fileName)
204
+ messageContent.fileName = fileName;
205
+ break;
206
+ case "video":
207
+ messageContent.video = processedMedia;
208
+ messageContent.caption = caption;
209
+ if (fileName)
210
+ messageContent.fileName = fileName;
211
+ break;
212
+ case "audio":
213
+ messageContent.audio = processedMedia;
214
+ messageContent.mimetype = mimeType;
215
+ if (fileName)
216
+ messageContent.fileName = fileName;
217
+ break;
218
+ case "pdf":
219
+ case "xls":
220
+ case "xlsx":
221
+ case "doc":
222
+ case "docx":
223
+ case "zip":
224
+ case "mp3":
225
+ messageContent.document = processedMedia;
226
+ messageContent.mimetype = mimeType;
227
+ messageContent.caption = caption;
228
+ if (fileName)
229
+ messageContent.fileName = fileName;
230
+ break;
231
+ default:
232
+ throw new Error("Media type not found! (image, video, audio, pdf)");
233
+ }
234
+ // Timeout lebih lama untuk media karena ukuran file
235
+ const timeoutMs = isDestinationGroup ? 60000 : 120000;
236
+ return yield (0, create_delay_1.withTimeout)(session.sendMessage(jid, messageContent, options), timeoutMs, `Pengiriman media melebihi batas waktu ${timeoutMs / 1000} detik`);
237
+ }
238
+ catch (error) {
239
+ console.error(`Error saat mengirim media (percobaan ${retryCount + 1}/${maxRetries}): ${(error === null || error === void 0 ? void 0 : error.message) || 'Unknown error'}`);
240
+ // Jika error terkait MessageCounterError (grup dengan channel pengumuman)
241
+ if (((_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.includes('MessageCounterError')) || ((_b = error === null || error === void 0 ? void 0 : error.stack) === null || _b === void 0 ? void 0 : _b.includes('MessageCounterError'))) {
242
+ console.warn('Terdeteksi MessageCounterError, kemungkinan grup dengan channel pengumuman');
243
+ if (retryCount < maxRetries) {
244
+ retryCount++;
245
+ // Tambahkan delay lebih lama antara percobaan
246
+ yield (0, create_delay_1.createDelay)(2000 * retryCount);
247
+ console.log(`Mencoba kembali pengiriman media (${retryCount}/${maxRetries})...`);
248
+ return attemptSend();
249
+ }
250
+ else {
251
+ console.error('Batas maksimum percobaan ulang tercapai');
252
+ throw new Error_1.WhatsappError(`Gagal mengirim media ke grup dengan channel pengumuman setelah ${maxRetries} kali percobaan`);
253
+ }
254
+ }
255
+ // Jika koneksi tertutup, coba reconnect
256
+ if ((_c = error === null || error === void 0 ? void 0 : error.message) === null || _c === void 0 ? void 0 : _c.includes('Connection Closed')) {
257
+ try {
258
+ yield (0, Socket_1.reconnect)(sessionId);
259
+ yield (0, create_delay_1.createDelay)(3000); // Beri waktu untuk reconnect sepenuhnya
260
+ // Siapkan content media untuk percobaan ulang
261
+ const retryContent = getMessageContent();
262
+ // Coba kirim lagi setelah reconnect
263
+ return yield (0, create_delay_1.withTimeout)(session.sendMessage(jid, retryContent, answering ? { quoted: answering } : {}), 180000, // 3 menit untuk percobaan setelah reconnect
264
+ `Pengiriman media setelah reconnect melebihi batas waktu`);
265
+ }
266
+ catch (reconnectError) {
267
+ console.error(`Gagal reconnect: ${(reconnectError === null || reconnectError === void 0 ? void 0 : reconnectError.message) || 'Unknown error'}`);
268
+ throw new Error_1.WhatsappError(`Koneksi terputus dan gagal reconnect: ${(reconnectError === null || reconnectError === void 0 ? void 0 : reconnectError.message) || 'Unknown error'}`);
269
+ }
270
+ }
271
+ // Untuk error timeout atau error lain, coba lagi dengan timeout lebih lama
272
+ try {
273
+ yield (0, create_delay_1.createDelay)(3000);
274
+ // Siapkan content media untuk percobaan ulang
275
+ const retryContent = getMessageContent();
276
+ // Untuk percobaan kedua, gunakan timeout yang lebih lama
277
+ return yield (0, create_delay_1.withTimeout)(session.sendMessage(jid, retryContent, answering ? { quoted: answering } : {}), 180000, // 3 menit untuk percobaan kedua
278
+ `Percobaan kedua pengiriman media melebihi batas waktu`);
279
+ }
280
+ catch (retryError) {
281
+ console.error(`Gagal pada percobaan kedua: ${(retryError === null || retryError === void 0 ? void 0 : retryError.message) || 'Unknown error'}`);
282
+ throw new Error_1.WhatsappError(`Gagal mengirim media: ${(retryError === null || retryError === void 0 ? void 0 : retryError.message) || 'Unknown error'}`);
283
+ }
284
+ }
285
+ });
286
+ return attemptSend();
215
287
  });
216
288
  exports.sendMedia = sendMedia;
217
289
  const sendVoiceNote = (_a) => __awaiter(void 0, void 0, void 0, function* () {
@@ -219,20 +291,87 @@ const sendVoiceNote = (_a) => __awaiter(void 0, void 0, void 0, function* () {
219
291
  const session = (0, Socket_1.getSession)(sessionId);
220
292
  if (!session)
221
293
  throw new Error_1.WhatsappError(Defaults_1.Messages.sessionNotFound(sessionId));
222
- to = (0, Utils_1.phoneToJid)({ to, isGroup });
294
+ // Deteksi otomatis apakah ini adalah grup berdasarkan format JID
295
+ const toStr = to.toString();
296
+ const isGroupChat = toStr.includes('@g.us');
297
+ // Jika sudah dalam format grup, gunakan to langsung
298
+ // Jika tidak, gunakan phoneToJid untuk mengkonversi ke format yang benar
299
+ let jid;
300
+ if (isGroupChat) {
301
+ if (!toStr.endsWith('@g.us')) {
302
+ jid = toStr + '@g.us';
303
+ }
304
+ else {
305
+ jid = toStr;
306
+ }
307
+ }
308
+ else {
309
+ jid = (0, Utils_1.phoneToJid)({ to, isGroup: isGroup || isGroupChat });
310
+ }
223
311
  if (!media) {
224
312
  throw new Error_1.WhatsappError(`Invalid Media`);
225
313
  }
226
- return yield session.sendMessage(to, {
227
- audio: typeof media == "string"
228
- ? {
229
- url: media,
314
+ let retryCount = 0;
315
+ const maxRetries = 3;
316
+ const attemptSend = () => __awaiter(void 0, void 0, void 0, function* () {
317
+ var _a, _b, _c;
318
+ try {
319
+ // Gunakan timeout untuk mencegah hanging
320
+ return yield (0, create_delay_1.withTimeout)(session.sendMessage(jid, {
321
+ audio: typeof media == "string"
322
+ ? {
323
+ url: media,
324
+ }
325
+ : media,
326
+ ptt: true,
327
+ }, {
328
+ quoted: props.answering,
329
+ }), 60000, `Pengiriman voice note melebihi batas waktu`);
330
+ }
331
+ catch (error) {
332
+ console.error(`Error saat mengirim voice note (percobaan ${retryCount + 1}/${maxRetries}): ${(error === null || error === void 0 ? void 0 : error.message) || 'Unknown error'}`);
333
+ // Jika error terkait MessageCounterError (grup dengan channel pengumuman)
334
+ if (((_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.includes('MessageCounterError')) || ((_b = error === null || error === void 0 ? void 0 : error.stack) === null || _b === void 0 ? void 0 : _b.includes('MessageCounterError'))) {
335
+ console.warn('Terdeteksi MessageCounterError, kemungkinan grup dengan channel pengumuman');
336
+ if (retryCount < maxRetries) {
337
+ retryCount++;
338
+ // Tambahkan delay lebih lama antara percobaan
339
+ yield (0, create_delay_1.createDelay)(2000 * retryCount);
340
+ console.log(`Mencoba kembali pengiriman voice note (${retryCount}/${maxRetries})...`);
341
+ return attemptSend();
342
+ }
343
+ else {
344
+ console.error('Batas maksimum percobaan ulang tercapai');
345
+ throw new Error_1.WhatsappError(`Gagal mengirim voice note ke grup dengan channel pengumuman setelah ${maxRetries} kali percobaan`);
346
+ }
230
347
  }
231
- : media,
232
- ptt: true,
233
- }, {
234
- quoted: props.answering,
348
+ // Jika koneksi tertutup, coba reconnect
349
+ if ((_c = error === null || error === void 0 ? void 0 : error.message) === null || _c === void 0 ? void 0 : _c.includes('Connection Closed')) {
350
+ try {
351
+ yield (0, Socket_1.reconnect)(sessionId);
352
+ yield (0, create_delay_1.createDelay)(3000); // Beri waktu untuk reconnect sepenuhnya
353
+ // Coba kirim lagi setelah reconnect
354
+ return yield (0, create_delay_1.withTimeout)(session.sendMessage(jid, {
355
+ audio: typeof media == "string"
356
+ ? {
357
+ url: media,
358
+ }
359
+ : media,
360
+ ptt: true,
361
+ }, {
362
+ quoted: props.answering,
363
+ }), 60000, `Pengiriman voice note setelah reconnect melebihi batas waktu`);
364
+ }
365
+ catch (reconnectError) {
366
+ console.error(`Gagal reconnect: ${(reconnectError === null || reconnectError === void 0 ? void 0 : reconnectError.message) || 'Unknown error'}`);
367
+ throw new Error_1.WhatsappError(`Koneksi terputus dan gagal reconnect: ${(reconnectError === null || reconnectError === void 0 ? void 0 : reconnectError.message) || 'Unknown error'}`);
368
+ }
369
+ }
370
+ // Re-throw error jika bukan masalah koneksi atau reconnect gagal
371
+ throw new Error_1.WhatsappError(`Gagal mengirim voice note: ${(error === null || error === void 0 ? void 0 : error.message) || 'Unknown error'}`);
372
+ }
235
373
  });
374
+ return attemptSend();
236
375
  });
237
376
  exports.sendVoiceNote = sendVoiceNote;
238
377
  const sendSticker = (_a) => __awaiter(void 0, void 0, void 0, function* () {
@@ -240,19 +379,85 @@ const sendSticker = (_a) => __awaiter(void 0, void 0, void 0, function* () {
240
379
  const session = (0, Socket_1.getSession)(sessionId);
241
380
  if (!session)
242
381
  throw new Error_1.WhatsappError(Defaults_1.Messages.sessionNotFound(sessionId));
243
- to = (0, Utils_1.phoneToJid)({ to, isGroup });
382
+ // Deteksi otomatis apakah ini adalah grup berdasarkan format JID
383
+ const toStr = to.toString();
384
+ const isGroupChat = toStr.includes('@g.us');
385
+ // Jika sudah dalam format grup, gunakan to langsung
386
+ // Jika tidak, gunakan phoneToJid untuk mengkonversi ke format yang benar
387
+ let jid;
388
+ if (isGroupChat) {
389
+ if (!toStr.endsWith('@g.us')) {
390
+ jid = toStr + '@g.us';
391
+ }
392
+ else {
393
+ jid = toStr;
394
+ }
395
+ }
396
+ else {
397
+ jid = (0, Utils_1.phoneToJid)({ to, isGroup: isGroup || isGroupChat });
398
+ }
244
399
  if (!media) {
245
400
  throw new Error_1.WhatsappError(`Invalid Media`);
246
401
  }
247
- return yield session.sendMessage(to, {
248
- sticker: typeof media == "string"
249
- ? {
250
- url: media,
402
+ let retryCount = 0;
403
+ const maxRetries = 3;
404
+ const attemptSend = () => __awaiter(void 0, void 0, void 0, function* () {
405
+ var _a, _b, _c;
406
+ try {
407
+ // Gunakan timeout untuk mencegah hanging
408
+ return yield (0, create_delay_1.withTimeout)(session.sendMessage(jid, {
409
+ sticker: typeof media == "string"
410
+ ? {
411
+ url: media,
412
+ }
413
+ : media,
414
+ }, {
415
+ quoted: props.answering,
416
+ }), 60000, `Pengiriman sticker melebihi batas waktu`);
417
+ }
418
+ catch (error) {
419
+ console.error(`Error saat mengirim sticker (percobaan ${retryCount + 1}/${maxRetries}): ${(error === null || error === void 0 ? void 0 : error.message) || 'Unknown error'}`);
420
+ // Jika error terkait MessageCounterError (grup dengan channel pengumuman)
421
+ if (((_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.includes('MessageCounterError')) || ((_b = error === null || error === void 0 ? void 0 : error.stack) === null || _b === void 0 ? void 0 : _b.includes('MessageCounterError'))) {
422
+ console.warn('Terdeteksi MessageCounterError, kemungkinan grup dengan channel pengumuman');
423
+ if (retryCount < maxRetries) {
424
+ retryCount++;
425
+ // Tambahkan delay lebih lama antara percobaan
426
+ yield (0, create_delay_1.createDelay)(2000 * retryCount);
427
+ console.log(`Mencoba kembali pengiriman sticker (${retryCount}/${maxRetries})...`);
428
+ return attemptSend();
429
+ }
430
+ else {
431
+ console.error('Batas maksimum percobaan ulang tercapai');
432
+ throw new Error_1.WhatsappError(`Gagal mengirim sticker ke grup dengan channel pengumuman setelah ${maxRetries} kali percobaan`);
433
+ }
434
+ }
435
+ // Jika koneksi tertutup, coba reconnect
436
+ if ((_c = error === null || error === void 0 ? void 0 : error.message) === null || _c === void 0 ? void 0 : _c.includes('Connection Closed')) {
437
+ try {
438
+ yield (0, Socket_1.reconnect)(sessionId);
439
+ yield (0, create_delay_1.createDelay)(3000); // Beri waktu untuk reconnect sepenuhnya
440
+ // Coba kirim lagi setelah reconnect
441
+ return yield (0, create_delay_1.withTimeout)(session.sendMessage(jid, {
442
+ sticker: typeof media == "string"
443
+ ? {
444
+ url: media,
445
+ }
446
+ : media,
447
+ }, {
448
+ quoted: props.answering,
449
+ }), 60000, `Pengiriman sticker setelah reconnect melebihi batas waktu`);
450
+ }
451
+ catch (reconnectError) {
452
+ console.error(`Gagal reconnect: ${(reconnectError === null || reconnectError === void 0 ? void 0 : reconnectError.message) || 'Unknown error'}`);
453
+ throw new Error_1.WhatsappError(`Koneksi terputus dan gagal reconnect: ${(reconnectError === null || reconnectError === void 0 ? void 0 : reconnectError.message) || 'Unknown error'}`);
454
+ }
251
455
  }
252
- : media,
253
- }, {
254
- quoted: props.answering,
456
+ // Re-throw error jika bukan masalah koneksi atau reconnect gagal
457
+ throw new Error_1.WhatsappError(`Gagal mengirim sticker: ${(error === null || error === void 0 ? void 0 : error.message) || 'Unknown error'}`);
458
+ }
255
459
  });
460
+ return attemptSend();
256
461
  });
257
462
  exports.sendSticker = sendSticker;
258
463
  /**
@@ -270,17 +475,33 @@ const sendTyping = (_a) => __awaiter(void 0, [_a], void 0, function* ({ sessionI
270
475
  const session = (0, Socket_1.getSession)(sessionId);
271
476
  if (!session)
272
477
  throw new Error_1.WhatsappError(Defaults_1.Messages.sessionNotFound(sessionId));
273
- to = (0, Utils_1.phoneToJid)({ to, isGroup });
478
+ // Deteksi otomatis apakah ini adalah grup berdasarkan format JID
479
+ const toStr = to.toString();
480
+ const isGroupChat = toStr.includes('@g.us');
481
+ // Jika sudah dalam format grup, gunakan to langsung
482
+ // Jika tidak, gunakan phoneToJid untuk mengkonversi ke format yang benar
483
+ let jid;
484
+ if (isGroupChat) {
485
+ if (!toStr.endsWith('@g.us')) {
486
+ jid = toStr + '@g.us';
487
+ }
488
+ else {
489
+ jid = toStr;
490
+ }
491
+ }
492
+ else {
493
+ jid = (0, Utils_1.phoneToJid)({ to, isGroup: isGroup || isGroupChat });
494
+ }
274
495
  try {
275
496
  // Deteksi apakah ini grup
276
- const isGroupChat = to.endsWith('@g.us');
277
- const timeoutMs = isGroupChat ? 5000 : 10000;
497
+ const isDestinationGroup = jid.endsWith('@g.us');
498
+ const timeoutMs = isDestinationGroup ? 5000 : 10000;
278
499
  // Kirim status mengetik dengan timeout
279
- yield (0, create_delay_1.withTimeout)(session.sendPresenceUpdate("composing", to), timeoutMs, `Timeout saat mengirim status mengetik`);
500
+ yield (0, create_delay_1.withTimeout)(session.sendPresenceUpdate("composing", jid), timeoutMs, `Timeout saat mengirim status mengetik`);
280
501
  // Tunggu durasi yang ditentukan
281
502
  yield (0, create_delay_1.createDelay)(duration);
282
503
  // Setelah durasi, atur kembali status
283
- yield (0, create_delay_1.withTimeout)(session.sendPresenceUpdate("paused", to), timeoutMs, `Timeout saat menghentikan status mengetik`);
504
+ yield (0, create_delay_1.withTimeout)(session.sendPresenceUpdate("paused", jid), timeoutMs, `Timeout saat menghentikan status mengetik`);
284
505
  }
285
506
  catch (error) {
286
507
  // Jika koneksi tertutup, coba reconnect
@@ -289,11 +510,11 @@ const sendTyping = (_a) => __awaiter(void 0, [_a], void 0, function* ({ sessionI
289
510
  yield (0, Socket_1.reconnect)(sessionId);
290
511
  yield (0, create_delay_1.createDelay)(2000); // Beri waktu untuk reconnect sepenuhnya
291
512
  // Setelah reconnect, coba kirim status mengetik lagi
292
- const isGroupChat = to.endsWith('@g.us');
293
- const timeoutMs = isGroupChat ? 5000 : 10000;
294
- yield (0, create_delay_1.withTimeout)(session.sendPresenceUpdate("composing", to), timeoutMs, `Timeout saat mengirim status mengetik setelah reconnect`);
513
+ const isDestinationGroup = jid.endsWith('@g.us');
514
+ const timeoutMs = isDestinationGroup ? 5000 : 10000;
515
+ yield (0, create_delay_1.withTimeout)(session.sendPresenceUpdate("composing", jid), timeoutMs, `Timeout saat mengirim status mengetik setelah reconnect`);
295
516
  yield (0, create_delay_1.createDelay)(duration);
296
- yield (0, create_delay_1.withTimeout)(session.sendPresenceUpdate("paused", to), timeoutMs, `Timeout saat menghentikan status mengetik setelah reconnect`);
517
+ yield (0, create_delay_1.withTimeout)(session.sendPresenceUpdate("paused", jid), timeoutMs, `Timeout saat menghentikan status mengetik setelah reconnect`);
297
518
  }
298
519
  catch (reconnectError) {
299
520
  // Tidak melempar error agar aplikasi tetap berjalan
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wa-multi-mongodb",
3
- "version": "3.8.1",
3
+ "version": "3.9.1",
4
4
  "description": "Multi Session Whatsapp Library with MongoDB Integration",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "repository": {
29
29
  "type": "git",
30
- "url": "https://github.com/wahdalo/wa-multi-mongodb"
30
+ "url": "git+https://github.com/wahdalo/wa-multi-mongodb.git"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/mime": "^3.0.1",
package/readme.md CHANGED
@@ -16,6 +16,7 @@ Built on [Baileys](https://github.com/WhiskeySockets/Baileys) Library.
16
16
  - Auto-reconnect when connection is lost
17
17
  - Better group chat support
18
18
  - Automatic retry for failed message deliveries
19
+ - Automatic group chat detection (v3.9.0+)
19
20
 
20
21
  ## Installation
21
22
 
@@ -123,8 +124,25 @@ await whatsapp.loadSessionsFromMongo();
123
124
  await whatsapp.sendTextMessage({
124
125
  sessionId: "mysession",
125
126
  to: "6281234567890", // always include country code
126
- text: "Hello from wa-multi-mongodb!",
127
- isGroup: false, // set true if sending to a group
127
+ text: "Hello from wa-multi-mongodb!"
128
+ // isGroup parameter is optional (v3.9.0+)
129
+ // The library will automatically detect if the destination is a group
130
+ });
131
+
132
+ // Send to a group (automatic detection in v3.9.0+)
133
+ await whatsapp.sendTextMessage({
134
+ sessionId: "mysession",
135
+ to: "120363152682073800", // group ID
136
+ text: "Hello group!"
137
+ // No need for isGroup: true parameter in v3.9.0+
138
+ });
139
+
140
+ // Send to a group (compatible with older versions)
141
+ await whatsapp.sendTextMessage({
142
+ sessionId: "mysession",
143
+ to: "120363152682073800", // group ID
144
+ text: "Hello group!",
145
+ isGroup: true // still works but optional in v3.9.0+
128
146
  });
129
147
 
130
148
  // Send media (unified function)
@@ -135,7 +153,7 @@ await whatsapp.sendMedia({
135
153
  media: fs.readFileSync("./image.jpg"), // or URL string
136
154
  caption: "Image caption",
137
155
  fileName: "image.jpg", // required for documents
138
- isGroup: false,
156
+ // isGroup parameter is optional (v3.9.0+)
139
157
  });
140
158
 
141
159
  // Send voice note
@@ -143,6 +161,7 @@ await whatsapp.sendVoiceNote({
143
161
  sessionId: "mysession",
144
162
  to: "6281234567890",
145
163
  media: fs.readFileSync("./audio.mp3"),
164
+ // isGroup parameter is optional (v3.9.0+)
146
165
  });
147
166
 
148
167
  // Mark message as read
@@ -151,23 +170,15 @@ await whatsapp.readMessage({
151
170
  key: msg.key,
152
171
  });
153
172
 
154
- // Send typing indicator (private chats only)
173
+ // Send typing indicator
155
174
  await whatsapp.sendTyping({
156
175
  sessionId: "mysession",
157
- to: "6281234567890",
176
+ to: "6281234567890", // or group ID
158
177
  duration: 3000, // milliseconds
178
+ // isGroup parameter is optional (v3.9.0+)
159
179
  });
160
180
  ```
161
181
 
162
- > **⚠️ Important:** The "typing" indicator **only works in private chats**. Always check if you're messaging a group:
163
- >
164
- > ```js
165
- > const isGroup = remoteJid.endsWith('@g.us');
166
- > if (!isGroup) {
167
- > await whatsapp.sendTyping({...});
168
- > }
169
- > ```
170
-
171
182
  ### Event Listeners
172
183
 
173
184
  ```javascript
@@ -296,8 +307,8 @@ async function startApp() {
296
307
  if (msg.key.fromMe || msg.key.remoteJid.includes("status")) return;
297
308
 
298
309
  const messageContent = msg.message?.conversation ||
299
- msg.message?.extendedTextMessage?.text ||
300
- "";
310
+ msg.message?.extendedTextMessage?.text ||
311
+ "";
301
312
 
302
313
  // Detect if message is from a group
303
314
  const isGroup = msg.key.remoteJid.endsWith('@g.us');
@@ -317,14 +328,12 @@ async function startApp() {
317
328
 
318
329
  // Reply to messages containing "hello"
319
330
  if (messageContent.toLowerCase().includes("hello")) {
320
- // Show typing indicator (only for private chats)
321
- if (!isGroup) {
322
- await whatsapp.sendTyping({
323
- sessionId: msg.sessionId,
324
- to: msg.key.remoteJid,
325
- duration: 2000,
326
- });
327
- }
331
+ // Show typing indicator (works in both private and group chats since v3.9.1+)
332
+ await whatsapp.sendTyping({
333
+ sessionId: msg.sessionId,
334
+ to: msg.key.remoteJid,
335
+ duration: 2000,
336
+ });
328
337
 
329
338
  // Use different timeouts for groups vs private chats
330
339
  const timeoutMs = isGroup ? 60000 : 30000;
@@ -336,7 +345,7 @@ async function startApp() {
336
345
  to: msg.key.remoteJid,
337
346
  text: "Hello! How can I help you?",
338
347
  answering: msg,
339
- isGroup: isGroup
348
+ // isGroup parameter is optional (v3.9.0+)
340
349
  }),
341
350
  timeoutMs,
342
351
  "Message sending timed out"
@@ -379,20 +388,32 @@ startApp().catch(err => {
379
388
 
380
389
  ## Best Practices for Group Chats
381
390
 
382
- 1. **Always Identify Groups**: Use `remoteJid.endsWith('@g.us')` before sending messages
383
- 2. **No Typing Indicators**: WhatsApp doesn't support typing indicators in groups
391
+ 1. **Auto Group Detection**: Since v3.9.0, the library automatically detects if a chat is a group based on its JID format
392
+ 2. **Typing Indicators**: Typing indicators now work in both private and group chats (v3.9.1+)
384
393
  3. **Longer Timeouts**: Use longer timeouts when sending media to groups (60+ seconds)
385
394
  4. **Handle Errors**: Implement retry mechanisms for failed group messages
395
+ 5. **Announcement Channels**: Groups with announcement channels may trigger `MessageCounterError` (handled automatically in v3.9.1+)
396
+ 6. **Retry Strategy**: For announcement channel groups, the library will automatically retry sending messages up to 3 times with increasing delays
386
397
 
387
398
  ## WhatsApp Limitations
388
399
 
389
- 1. **Typing Indicators**: Only work in private chats, not in groups
390
- 2. **Media Transfer**: Large media files to groups may take longer or timeout
391
- 3. **Connection Stability**: Auto-reconnect may be needed in production apps
400
+ 1. **Media Transfer**: Large media files to groups may take longer or timeout
401
+ 2. **Connection Stability**: Auto-reconnect may be needed in production apps
402
+ 3. **Announcement Channels**: Some groups with announcement channels may still fail after multiple retries
392
403
 
393
404
  ## Changelog
394
405
 
395
- ### v3.8.1 (Current)
406
+ ### v3.9.1 (Current)
407
+ - Added special handling for `MessageCounterError` in group chats with announcement channels
408
+ - Implemented automatic retry mechanism for messages to announcement channels
409
+ - Enhanced error reporting for group chat issues
410
+ - Fixed typing indicators to work properly in group chats
411
+ - Added automatic group chat detection - no need to specify `isGroup: true` parameter
412
+ - Improved message sending reliability for group chats
413
+ - Enhanced error handling with better timeout management
414
+ - Implemented automatic format detection for group IDs
415
+
416
+ ### v3.8.1
396
417
  - Updated baileys to v6.7.16
397
418
  - Improved MongoDB integration
398
419
  - Enhanced error handling and connection stability