miaw-core 0.9.0 → 1.1.0

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,63 +1,77 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.MiawClient = void 0;
40
- const baileys_1 = __importStar(require("@whiskeysockets/baileys"));
41
- const events_1 = require("events");
42
- const pino_1 = __importDefault(require("pino"));
43
- const path = __importStar(require("path"));
44
- const AuthHandler_1 = require("../handlers/AuthHandler");
45
- const MessageHandler_1 = require("../handlers/MessageHandler");
1
+ import makeWASocket, { DisconnectReason, fetchLatestBaileysVersion, makeCacheableSignalKeyStore, downloadMediaMessage, } from "@whiskeysockets/baileys";
2
+ import { EventEmitter } from "node:events";
3
+ import pino from "pino";
4
+ import * as path from "node:path";
5
+ import { AuthHandler } from "../handlers/AuthHandler.js";
6
+ import { MessageHandler } from "../handlers/MessageHandler.js";
7
+ /**
8
+ * LRU Cache for LID to JID mappings
9
+ * Prevents unbounded memory growth while maintaining frequently used mappings
10
+ */
11
+ class LruCache {
12
+ cache;
13
+ maxSize;
14
+ constructor(maxSize = 1000) {
15
+ this.cache = new Map();
16
+ this.maxSize = maxSize;
17
+ }
18
+ get(key) {
19
+ const value = this.cache.get(key);
20
+ if (value !== undefined) {
21
+ // Move to end (most recently used)
22
+ this.cache.delete(key);
23
+ this.cache.set(key, value);
24
+ }
25
+ return value;
26
+ }
27
+ set(key, value) {
28
+ // Remove existing if present (will be re-added at end)
29
+ if (this.cache.has(key)) {
30
+ this.cache.delete(key);
31
+ }
32
+ // Add to end (most recently used)
33
+ this.cache.set(key, value);
34
+ // Evict oldest if at capacity
35
+ if (this.cache.size > this.maxSize) {
36
+ const firstKey = this.cache.keys().next().value;
37
+ if (firstKey !== undefined) {
38
+ this.cache.delete(firstKey);
39
+ }
40
+ }
41
+ }
42
+ has(key) {
43
+ return this.cache.has(key);
44
+ }
45
+ clear() {
46
+ this.cache.clear();
47
+ }
48
+ get size() {
49
+ return this.cache.size;
50
+ }
51
+ }
46
52
  /**
47
53
  * Main client class for interacting with WhatsApp
48
54
  */
49
- class MiawClient extends events_1.EventEmitter {
55
+ export class MiawClient extends EventEmitter {
56
+ options;
57
+ socket = null;
58
+ authHandler;
59
+ connectionState = "disconnected";
60
+ reconnectAttempts = 0;
61
+ reconnectTimer = null;
62
+ logger;
63
+ lidToJidMap = new LruCache(1000);
64
+ // In-memory stores for v0.9.0
65
+ contactsStore = new Map();
66
+ labelsStore = new Map();
67
+ messagesStore = new Map(); // JID -> messages
68
+ chatsStore = new Map(); // JID -> chat info
50
69
  constructor(options) {
51
70
  super();
52
- this.socket = null;
53
- this.connectionState = 'disconnected';
54
- this.reconnectAttempts = 0;
55
- this.reconnectTimer = null;
56
- this.lidToJidMap = new Map();
57
71
  // Set default options
58
72
  this.options = {
59
73
  instanceId: options.instanceId,
60
- sessionPath: options.sessionPath || './sessions',
74
+ sessionPath: options.sessionPath || "./sessions",
61
75
  debug: options.debug || false,
62
76
  logger: options.logger,
63
77
  autoReconnect: options.autoReconnect !== false,
@@ -65,41 +79,46 @@ class MiawClient extends events_1.EventEmitter {
65
79
  reconnectDelay: options.reconnectDelay || 3000,
66
80
  };
67
81
  // Initialize logger
68
- this.logger = this.options.logger || (0, pino_1.default)({
69
- level: this.options.debug ? 'debug' : 'silent'
70
- });
82
+ this.logger =
83
+ this.options.logger ||
84
+ pino({
85
+ level: this.options.debug ? "debug" : "silent",
86
+ });
71
87
  // Initialize handlers
72
- this.authHandler = new AuthHandler_1.AuthHandler(this.options.sessionPath, this.options.instanceId);
88
+ this.authHandler = new AuthHandler(this.options.sessionPath, this.options.instanceId);
73
89
  }
74
90
  /**
75
91
  * Connect to WhatsApp
76
92
  */
77
93
  async connect() {
78
94
  try {
79
- this.updateConnectionState('connecting');
95
+ this.updateConnectionState("connecting");
80
96
  // Load auth state
81
97
  const { state, saveCreds } = await this.authHandler.initialize();
82
98
  // Get latest Baileys version
83
- const { version } = await (0, baileys_1.fetchLatestBaileysVersion)();
99
+ const { version } = await fetchLatestBaileysVersion();
84
100
  // Create socket
85
- this.socket = (0, baileys_1.default)({
101
+ this.socket = makeWASocket({
86
102
  version,
87
103
  logger: this.logger,
88
104
  printQRInTerminal: false,
89
105
  auth: {
90
106
  creds: state.creds,
91
- keys: (0, baileys_1.makeCacheableSignalKeyStore)(state.keys, this.logger),
107
+ keys: makeCacheableSignalKeyStore(state.keys, this.logger),
92
108
  },
93
- browser: ['Miaw', 'Chrome', '1.0.0'],
109
+ browser: ["Miaw", "Chrome", "1.0.0"],
94
110
  generateHighQualityLinkPreview: true,
111
+ // Enable app state sync for labels and other features
112
+ syncFullHistory: false,
113
+ fireInitQueries: true,
95
114
  });
96
115
  // Register event handlers
97
116
  this.registerSocketEvents(saveCreds);
98
- this.logger.info('Connection initiated');
117
+ this.logger.info("Connection initiated");
99
118
  }
100
119
  catch (error) {
101
- this.logger.error('Failed to connect:', error);
102
- this.emit('error', error);
120
+ this.logger.error("Failed to connect:", error);
121
+ this.emit("error", error);
103
122
  if (this.options.autoReconnect) {
104
123
  this.scheduleReconnect();
105
124
  }
@@ -112,56 +131,65 @@ class MiawClient extends events_1.EventEmitter {
112
131
  if (!this.socket)
113
132
  return;
114
133
  // Connection updates
115
- this.socket.ev.on('connection.update', async (update) => {
134
+ this.socket.ev.on("connection.update", async (update) => {
116
135
  const { connection, lastDisconnect, qr } = update;
117
136
  // Handle QR code
118
137
  if (qr) {
119
- this.updateConnectionState('qr_required');
120
- this.emit('qr', qr);
138
+ this.updateConnectionState("qr_required");
139
+ this.emit("qr", qr);
121
140
  }
122
141
  // Handle connection state
123
- if (connection === 'close') {
142
+ if (connection === "close") {
124
143
  const shouldReconnect = this.handleDisconnect(lastDisconnect);
125
144
  if (shouldReconnect && this.options.autoReconnect) {
126
145
  this.scheduleReconnect();
127
146
  }
128
147
  }
129
- else if (connection === 'open') {
148
+ else if (connection === "open") {
130
149
  this.reconnectAttempts = 0;
131
- this.updateConnectionState('connected');
132
- this.emit('ready');
133
- this.logger.info('Connected to WhatsApp');
150
+ this.updateConnectionState("connected");
151
+ this.emit("ready");
152
+ this.logger.info("Connected to WhatsApp");
153
+ // Sync app state to populate labels (WhatsApp Business)
154
+ // Labels are stored in the 'regular' app state collection
155
+ this.syncLabelsFromAppState().catch((error) => {
156
+ this.logger.warn("Failed to sync labels from app state:", error);
157
+ });
134
158
  }
135
159
  });
136
160
  // Credentials update
137
- this.socket.ev.on('creds.update', async () => {
161
+ this.socket.ev.on("creds.update", async () => {
138
162
  await saveCreds();
139
- this.emit('session_saved');
163
+ this.emit("session_saved");
140
164
  });
141
- // Contact updates - build LID to JID mapping
142
- this.socket.ev.on('contacts.upsert', (contacts) => {
165
+ // Contact updates - build LID to JID mapping and populate contacts store
166
+ this.socket.ev.on("contacts.upsert", (contacts) => {
143
167
  this.updateLidToJidMapping(contacts);
168
+ this.updateContactsStore(contacts);
144
169
  });
145
- this.socket.ev.on('contacts.update', (contacts) => {
170
+ this.socket.ev.on("contacts.update", (contacts) => {
146
171
  this.updateLidToJidMapping(contacts);
172
+ this.updateContactsStore(contacts);
147
173
  });
148
- // Chat updates - extract LID mappings from chat data
149
- this.socket.ev.on('chats.upsert', (chats) => {
174
+ // Chat updates - extract LID mappings from chat data and populate chats store
175
+ this.socket.ev.on("chats.upsert", (chats) => {
150
176
  this.updateLidFromChats(chats);
177
+ this.updateChatsStore(chats);
151
178
  });
152
- this.socket.ev.on('chats.update', (chats) => {
179
+ this.socket.ev.on("chats.update", (chats) => {
153
180
  this.updateLidFromChats(chats);
181
+ this.updateChatsStore(chats);
154
182
  });
155
183
  // Messages
156
- this.socket.ev.on('messages.upsert', async (m) => {
157
- if (m.type !== 'notify')
184
+ this.socket.ev.on("messages.upsert", async (m) => {
185
+ if (m.type !== "notify")
158
186
  return;
159
187
  for (const msg of m.messages) {
160
188
  // Debug: Log raw Baileys message structure
161
189
  if (this.options.debug) {
162
- console.log('\n========== RAW BAILEYS MESSAGE ==========');
190
+ console.log("\n========== RAW BAILEYS MESSAGE ==========");
163
191
  console.log(JSON.stringify(msg, null, 2));
164
- console.log('=========================================\n');
192
+ console.log("=========================================\n");
165
193
  }
166
194
  // Check for protocol messages (edits and deletes)
167
195
  const protocolMessage = msg.message?.protocolMessage;
@@ -171,42 +199,50 @@ class MiawClient extends events_1.EventEmitter {
171
199
  }
172
200
  // Build LID to JID mapping from incoming messages
173
201
  // Incoming messages have remoteJid (phone) and senderLid (LID)
174
- if (!msg.key.fromMe && msg.key.senderLid && msg.key.remoteJid) {
175
- const lid = msg.key.senderLid.endsWith('@lid')
176
- ? msg.key.senderLid
177
- : `${msg.key.senderLid}@lid`;
178
- this.lidToJidMap.set(lid, msg.key.remoteJid);
202
+ // Note: senderLid may exist at runtime but isn't in Baileys v7 types
203
+ const msgKey = msg.key;
204
+ if (!msgKey.fromMe && msgKey.senderLid && msgKey.remoteJid) {
205
+ const lid = msgKey.senderLid.endsWith("@lid")
206
+ ? msgKey.senderLid
207
+ : `${msgKey.senderLid}@lid`;
208
+ this.lidToJidMap.set(lid, msgKey.remoteJid);
179
209
  if (this.options.debug) {
180
210
  console.log(`[LID Mapping] ${lid} -> ${msg.key.remoteJid}`);
181
211
  }
182
212
  }
183
- const normalized = MessageHandler_1.MessageHandler.normalize({ messages: [msg] });
213
+ const normalized = MessageHandler.normalize({ messages: [msg] });
184
214
  if (normalized) {
185
- this.emit('message', normalized);
215
+ // Store message in messagesStore (v0.9.0)
216
+ const chatJid = normalized.from;
217
+ if (!this.messagesStore.has(chatJid)) {
218
+ this.messagesStore.set(chatJid, []);
219
+ }
220
+ this.messagesStore.get(chatJid).push(normalized);
221
+ this.emit("message", normalized);
186
222
  }
187
223
  }
188
224
  });
189
225
  // Reactions
190
- this.socket.ev.on('messages.reaction', (reactions) => {
226
+ this.socket.ev.on("messages.reaction", (reactions) => {
191
227
  for (const { key, reaction } of reactions) {
192
228
  const reactionData = {
193
- messageId: key.id || '',
194
- chatId: key.remoteJid || '',
195
- reactorId: reaction.key?.participant || reaction.key?.remoteJid || '',
196
- emoji: reaction.text || '',
229
+ messageId: key.id || "",
230
+ chatId: key.remoteJid || "",
231
+ reactorId: reaction.key?.participant || reaction.key?.remoteJid || "",
232
+ emoji: reaction.text || "",
197
233
  isRemoval: !reaction.text,
198
234
  raw: { key, reaction },
199
235
  };
200
236
  if (this.options.debug) {
201
- console.log('\n========== REACTION ==========');
237
+ console.log("\n========== REACTION ==========");
202
238
  console.log(JSON.stringify(reactionData, null, 2));
203
- console.log('==============================\n');
239
+ console.log("==============================\n");
204
240
  }
205
- this.emit('message_reaction', reactionData);
241
+ this.emit("message_reaction", reactionData);
206
242
  }
207
243
  });
208
244
  // Presence updates
209
- this.socket.ev.on('presence.update', (presence) => {
245
+ this.socket.ev.on("presence.update", (presence) => {
210
246
  const jid = presence.id;
211
247
  const presences = presence.presences;
212
248
  for (const [participantJid, presenceData] of Object.entries(presences)) {
@@ -216,11 +252,35 @@ class MiawClient extends events_1.EventEmitter {
216
252
  lastSeen: presenceData.lastSeen,
217
253
  };
218
254
  if (this.options.debug) {
219
- console.log('\n========== PRESENCE UPDATE ==========');
255
+ console.log("\n========== PRESENCE UPDATE ==========");
220
256
  console.log(JSON.stringify(update, null, 2));
221
- console.log('=====================================\n');
257
+ console.log("=====================================\n");
258
+ }
259
+ this.emit("presence", update);
260
+ }
261
+ });
262
+ // Label updates (WhatsApp Business)
263
+ this.socket.ev.on("labels.edit", (label) => {
264
+ if (this.options.debug) {
265
+ console.log("\n========== LABEL UPDATE ==========");
266
+ console.log(JSON.stringify(label, null, 2));
267
+ console.log("==================================\n");
268
+ }
269
+ // Update label in store
270
+ if (label.id) {
271
+ if (label.deleted) {
272
+ this.labelsStore.delete(label.id);
273
+ }
274
+ else {
275
+ const labelData = {
276
+ id: label.id,
277
+ name: label.name || "",
278
+ color: label.color ?? 0,
279
+ predefinedId: label.predefinedId,
280
+ deleted: label.deleted,
281
+ };
282
+ this.labelsStore.set(label.id, labelData);
222
283
  }
223
- this.emit('presence', update);
224
284
  }
225
285
  });
226
286
  }
@@ -233,18 +293,18 @@ class MiawClient extends events_1.EventEmitter {
233
293
  // Type 0 = REVOKE (delete)
234
294
  if (type === 0 && key) {
235
295
  const deletion = {
236
- messageId: key.id || '',
237
- chatId: key.remoteJid || msg.key.remoteJid || '',
296
+ messageId: key.id || "",
297
+ chatId: key.remoteJid || msg.key.remoteJid || "",
238
298
  fromMe: key.fromMe || false,
239
299
  participant: key.participant,
240
300
  raw: msg,
241
301
  };
242
302
  if (this.options.debug) {
243
- console.log('\n========== MESSAGE DELETED ==========');
303
+ console.log("\n========== MESSAGE DELETED ==========");
244
304
  console.log(JSON.stringify(deletion, null, 2));
245
- console.log('=====================================\n');
305
+ console.log("=====================================\n");
246
306
  }
247
- this.emit('message_delete', deletion);
307
+ this.emit("message_delete", deletion);
248
308
  }
249
309
  // Type 14 = MESSAGE_EDIT
250
310
  if (type === 14 && protocolMessage.editedMessage) {
@@ -254,8 +314,8 @@ class MiawClient extends events_1.EventEmitter {
254
314
  editedMessage.imageMessage?.caption ||
255
315
  editedMessage.videoMessage?.caption;
256
316
  const edit = {
257
- messageId: key?.id || '',
258
- chatId: key?.remoteJid || msg.key.remoteJid || '',
317
+ messageId: key?.id || "",
318
+ chatId: key?.remoteJid || msg.key.remoteJid || "",
259
319
  newText,
260
320
  editTimestamp: protocolMessage.timestampMs
261
321
  ? Number(protocolMessage.timestampMs)
@@ -263,11 +323,11 @@ class MiawClient extends events_1.EventEmitter {
263
323
  raw: msg,
264
324
  };
265
325
  if (this.options.debug) {
266
- console.log('\n========== MESSAGE EDITED ==========');
326
+ console.log("\n========== MESSAGE EDITED ==========");
267
327
  console.log(JSON.stringify(edit, null, 2));
268
- console.log('====================================\n');
328
+ console.log("====================================\n");
269
329
  }
270
- this.emit('message_edit', edit);
330
+ this.emit("message_edit", edit);
271
331
  }
272
332
  }
273
333
  /**
@@ -276,14 +336,14 @@ class MiawClient extends events_1.EventEmitter {
276
336
  updateLidToJidMapping(contacts) {
277
337
  for (const contact of contacts) {
278
338
  // Contact has both lid and jid - create mapping
279
- if (contact.lid && contact.id && !contact.id.endsWith('@lid')) {
339
+ if (contact.lid && contact.id && !contact.id.endsWith("@lid")) {
280
340
  this.lidToJidMap.set(contact.lid, contact.id);
281
341
  if (this.options.debug) {
282
342
  console.log(`[Contact LID Mapping] ${contact.lid} -> ${contact.id}`);
283
343
  }
284
344
  }
285
345
  // Also check if id is the LID and jid field exists
286
- if (contact.id?.endsWith('@lid') && contact.jid) {
346
+ if (contact.id?.endsWith("@lid") && contact.jid) {
287
347
  this.lidToJidMap.set(contact.id, contact.jid);
288
348
  if (this.options.debug) {
289
349
  console.log(`[Contact LID Mapping] ${contact.id} -> ${contact.jid}`);
@@ -291,14 +351,68 @@ class MiawClient extends events_1.EventEmitter {
291
351
  }
292
352
  }
293
353
  }
354
+ /**
355
+ * Update in-memory contacts store (v0.9.0)
356
+ * @param contacts - Array of contact objects from Baileys
357
+ */
358
+ updateContactsStore(contacts) {
359
+ for (const contact of contacts) {
360
+ // Extract the JID (prefer non-lid IDs)
361
+ const jid = contact.id?.endsWith("@lid")
362
+ ? contact.jid || contact.id
363
+ : contact.id;
364
+ if (!jid)
365
+ continue;
366
+ // Extract phone number from JID
367
+ const phone = jid.endsWith("@s.whatsapp.net")
368
+ ? jid.replace("@s.whatsapp.net", "")
369
+ : undefined;
370
+ // Build contact info
371
+ const contactInfo = {
372
+ jid,
373
+ phone,
374
+ name: contact.name || contact.notify || undefined,
375
+ };
376
+ // Update store
377
+ this.contactsStore.set(jid, contactInfo);
378
+ }
379
+ }
380
+ /**
381
+ * Update in-memory chats store (v0.9.0)
382
+ * @param chats - Array of chat objects from Baileys
383
+ */
384
+ updateChatsStore(chats) {
385
+ for (const chat of chats) {
386
+ const jid = chat.id;
387
+ if (!jid)
388
+ continue;
389
+ // Extract phone number from JID
390
+ const phone = jid.endsWith("@s.whatsapp.net")
391
+ ? jid.replace("@s.whatsapp.net", "")
392
+ : undefined;
393
+ // Build chat info
394
+ const chatInfo = {
395
+ jid,
396
+ phone,
397
+ name: chat.name || undefined,
398
+ isGroup: jid.endsWith("@g.us"),
399
+ lastMessageTimestamp: chat.timestamp || undefined,
400
+ unreadCount: chat.unreadCount || undefined,
401
+ isArchived: chat.archived || false,
402
+ isPinned: chat.pinned || false,
403
+ };
404
+ // Update store
405
+ this.chatsStore.set(jid, chatInfo);
406
+ }
407
+ }
294
408
  /**
295
409
  * Update LID to JID mapping from chat data
296
410
  */
297
411
  updateLidFromChats(chats) {
298
412
  for (const chat of chats) {
299
413
  // Chat may have both id (could be phone or LID) and lidJid
300
- if (chat.lidJid && chat.id && !chat.id.endsWith('@lid')) {
301
- const lid = chat.lidJid.endsWith('@lid')
414
+ if (chat.lidJid && chat.id && !chat.id.endsWith("@lid")) {
415
+ const lid = chat.lidJid.endsWith("@lid")
302
416
  ? chat.lidJid
303
417
  : `${chat.lidJid}@lid`;
304
418
  this.lidToJidMap.set(lid, chat.id);
@@ -307,7 +421,7 @@ class MiawClient extends events_1.EventEmitter {
307
421
  }
308
422
  }
309
423
  // Reverse: if id is LID and we have a phone JID
310
- if (chat.id?.endsWith('@lid') && chat.jid) {
424
+ if (chat.id?.endsWith("@lid") && chat.jid) {
311
425
  this.lidToJidMap.set(chat.id, chat.jid);
312
426
  if (this.options.debug) {
313
427
  console.log(`[Chat LID Mapping] ${chat.id} -> ${chat.jid}`);
@@ -321,7 +435,7 @@ class MiawClient extends events_1.EventEmitter {
321
435
  * @returns The phone number JID if found, or the original LID
322
436
  */
323
437
  resolveLidToJid(lid) {
324
- if (!lid?.endsWith('@lid')) {
438
+ if (!lid?.endsWith("@lid")) {
325
439
  return lid;
326
440
  }
327
441
  return this.lidToJidMap.get(lid) || lid;
@@ -333,8 +447,8 @@ class MiawClient extends events_1.EventEmitter {
333
447
  */
334
448
  getPhoneFromJid(jid) {
335
449
  const resolved = this.resolveLidToJid(jid);
336
- if (resolved.endsWith('@s.whatsapp.net')) {
337
- return resolved.replace('@s.whatsapp.net', '');
450
+ if (resolved.endsWith("@s.whatsapp.net")) {
451
+ return resolved.replace("@s.whatsapp.net", "");
338
452
  }
339
453
  return undefined;
340
454
  }
@@ -345,8 +459,8 @@ class MiawClient extends events_1.EventEmitter {
345
459
  * @param phoneJid - The phone JID (e.g., '6281234567890@s.whatsapp.net' or just '6281234567890')
346
460
  */
347
461
  registerLidMapping(lid, phoneJid) {
348
- const normalizedLid = lid.includes('@') ? lid : `${lid}@lid`;
349
- const normalizedJid = phoneJid.includes('@')
462
+ const normalizedLid = lid.includes("@") ? lid : `${lid}@lid`;
463
+ const normalizedJid = phoneJid.includes("@")
350
464
  ? phoneJid
351
465
  : `${phoneJid}@s.whatsapp.net`;
352
466
  this.lidToJidMap.set(normalizedLid, normalizedJid);
@@ -356,7 +470,53 @@ class MiawClient extends events_1.EventEmitter {
356
470
  * Useful for persisting mappings to storage
357
471
  */
358
472
  getLidMappings() {
359
- return new Map(this.lidToJidMap);
473
+ const result = {};
474
+ // Iterate through the cache
475
+ for (const [key, value] of this.lidToJidMap.cache) {
476
+ result[key] = value;
477
+ }
478
+ return result;
479
+ }
480
+ /**
481
+ * Get LID cache size
482
+ */
483
+ getLidCacheSize() {
484
+ return this.lidToJidMap.size;
485
+ }
486
+ /**
487
+ * Clear LID cache
488
+ */
489
+ clearLidCache() {
490
+ this.lidToJidMap.clear();
491
+ }
492
+ /**
493
+ * Clear session data for this instance.
494
+ * This will delete all stored authentication credentials.
495
+ * After calling this, the next connect() will require scanning a new QR code.
496
+ * @returns true if session was cleared, false if no session existed
497
+ */
498
+ clearSession() {
499
+ return this.authHandler.clearSession();
500
+ }
501
+ /**
502
+ * Dispose client and clean up resources
503
+ */
504
+ async dispose() {
505
+ // Clear reconnect timer
506
+ if (this.reconnectTimer) {
507
+ clearTimeout(this.reconnectTimer);
508
+ this.reconnectTimer = null;
509
+ }
510
+ // Clear LID cache
511
+ this.lidToJidMap.clear();
512
+ // Remove all event listeners
513
+ this.removeAllListeners();
514
+ // Close socket if connected
515
+ if (this.socket) {
516
+ this.socket.end(undefined);
517
+ this.socket = null;
518
+ }
519
+ this.updateConnectionState("disconnected");
360
520
  }
361
521
  /**
362
522
  * Handle disconnection
@@ -364,13 +524,14 @@ class MiawClient extends events_1.EventEmitter {
364
524
  */
365
525
  handleDisconnect(lastDisconnect) {
366
526
  const statusCode = lastDisconnect?.error?.output?.statusCode;
367
- const reason = baileys_1.DisconnectReason[statusCode] || 'unknown';
368
- this.logger.info('Disconnected:', reason, 'Code:', statusCode);
369
- this.updateConnectionState('disconnected');
370
- this.emit('disconnected', reason);
371
- // Don't reconnect if logged out
372
- if (statusCode === baileys_1.DisconnectReason.loggedOut) {
373
- this.logger.info('Logged out, not reconnecting');
527
+ const reason = DisconnectReason[statusCode] || "unknown";
528
+ this.logger.info("Disconnected:", reason, "Code:", statusCode);
529
+ this.updateConnectionState("disconnected");
530
+ this.emit("disconnected", reason);
531
+ // Don't reconnect if logged out - clear session for fresh QR code on next connect
532
+ if (statusCode === DisconnectReason.loggedOut) {
533
+ this.logger.info("Logged out, clearing session for fresh authentication");
534
+ this.authHandler.clearSession();
374
535
  return false;
375
536
  }
376
537
  return true;
@@ -380,16 +541,16 @@ class MiawClient extends events_1.EventEmitter {
380
541
  */
381
542
  scheduleReconnect() {
382
543
  if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
383
- this.logger.error('Max reconnection attempts reached');
384
- this.emit('error', new Error('Max reconnection attempts reached'));
544
+ this.logger.error("Max reconnection attempts reached");
545
+ this.emit("error", new Error("Max reconnection attempts reached"));
385
546
  return;
386
547
  }
387
548
  if (this.reconnectTimer) {
388
549
  clearTimeout(this.reconnectTimer);
389
550
  }
390
551
  this.reconnectAttempts++;
391
- this.updateConnectionState('reconnecting');
392
- this.emit('reconnecting', this.reconnectAttempts);
552
+ this.updateConnectionState("reconnecting");
553
+ this.emit("reconnecting", this.reconnectAttempts);
393
554
  this.reconnectTimer = setTimeout(() => {
394
555
  this.logger.info(`Reconnecting... Attempt ${this.reconnectAttempts}`);
395
556
  this.connect();
@@ -400,7 +561,7 @@ class MiawClient extends events_1.EventEmitter {
400
561
  */
401
562
  updateConnectionState(state) {
402
563
  this.connectionState = state;
403
- this.emit('connection', state);
564
+ this.emit("connection", state);
404
565
  }
405
566
  /**
406
567
  * Send a text message
@@ -411,14 +572,16 @@ class MiawClient extends events_1.EventEmitter {
411
572
  async sendText(to, text, options) {
412
573
  try {
413
574
  if (!this.socket) {
414
- throw new Error('Not connected. Call connect() first.');
575
+ throw new Error("Not connected. Call connect() first.");
415
576
  }
416
- if (this.connectionState !== 'connected') {
577
+ if (this.connectionState !== "connected") {
417
578
  throw new Error(`Cannot send message. Connection state: ${this.connectionState}`);
418
579
  }
419
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(to);
580
+ const jid = MessageHandler.formatPhoneToJid(to);
420
581
  // Build send options (for quoting/replying)
421
- const sendOptions = options?.quoted?.raw ? { quoted: options.quoted.raw } : undefined;
582
+ const sendOptions = options?.quoted?.raw
583
+ ? { quoted: options.quoted.raw }
584
+ : undefined;
422
585
  const result = await this.socket.sendMessage(jid, { text }, sendOptions);
423
586
  return {
424
587
  success: true,
@@ -426,7 +589,7 @@ class MiawClient extends events_1.EventEmitter {
426
589
  };
427
590
  }
428
591
  catch (error) {
429
- this.logger.error('Failed to send message:', error);
592
+ this.logger.error("Failed to send message:", error);
430
593
  return {
431
594
  success: false,
432
595
  error: error.message,
@@ -442,12 +605,12 @@ class MiawClient extends events_1.EventEmitter {
442
605
  async sendImage(to, image, options) {
443
606
  try {
444
607
  if (!this.socket) {
445
- throw new Error('Not connected. Call connect() first.');
608
+ throw new Error("Not connected. Call connect() first.");
446
609
  }
447
- if (this.connectionState !== 'connected') {
610
+ if (this.connectionState !== "connected") {
448
611
  throw new Error(`Cannot send message. Connection state: ${this.connectionState}`);
449
612
  }
450
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(to);
613
+ const jid = MessageHandler.formatPhoneToJid(to);
451
614
  // Build image message payload
452
615
  const imageContent = {
453
616
  image: Buffer.isBuffer(image) ? image : { url: image },
@@ -455,7 +618,9 @@ class MiawClient extends events_1.EventEmitter {
455
618
  viewOnce: options?.viewOnce,
456
619
  };
457
620
  // Build send options (for quoting/replying)
458
- const sendOptions = options?.quoted?.raw ? { quoted: options.quoted.raw } : undefined;
621
+ const sendOptions = options?.quoted?.raw
622
+ ? { quoted: options.quoted.raw }
623
+ : undefined;
459
624
  const result = await this.socket.sendMessage(jid, imageContent, sendOptions);
460
625
  return {
461
626
  success: true,
@@ -463,7 +628,7 @@ class MiawClient extends events_1.EventEmitter {
463
628
  };
464
629
  }
465
630
  catch (error) {
466
- this.logger.error('Failed to send image:', error);
631
+ this.logger.error("Failed to send image:", error);
467
632
  return {
468
633
  success: false,
469
634
  error: error.message,
@@ -479,12 +644,12 @@ class MiawClient extends events_1.EventEmitter {
479
644
  async sendDocument(to, document, options) {
480
645
  try {
481
646
  if (!this.socket) {
482
- throw new Error('Not connected. Call connect() first.');
647
+ throw new Error("Not connected. Call connect() first.");
483
648
  }
484
- if (this.connectionState !== 'connected') {
649
+ if (this.connectionState !== "connected") {
485
650
  throw new Error(`Cannot send message. Connection state: ${this.connectionState}`);
486
651
  }
487
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(to);
652
+ const jid = MessageHandler.formatPhoneToJid(to);
488
653
  // Determine filename and mimetype
489
654
  let fileName = options?.fileName;
490
655
  let mimetype = options?.mimetype;
@@ -499,12 +664,14 @@ class MiawClient extends events_1.EventEmitter {
499
664
  // Build document message payload
500
665
  const documentContent = {
501
666
  document: Buffer.isBuffer(document) ? document : { url: document },
502
- fileName: fileName || 'document',
503
- mimetype: mimetype || 'application/octet-stream',
667
+ fileName: fileName || "document",
668
+ mimetype: mimetype || "application/octet-stream",
504
669
  caption: options?.caption,
505
670
  };
506
671
  // Build send options (for quoting/replying)
507
- const sendOptions = options?.quoted?.raw ? { quoted: options.quoted.raw } : undefined;
672
+ const sendOptions = options?.quoted?.raw
673
+ ? { quoted: options.quoted.raw }
674
+ : undefined;
508
675
  const result = await this.socket.sendMessage(jid, documentContent, sendOptions);
509
676
  return {
510
677
  success: true,
@@ -512,7 +679,7 @@ class MiawClient extends events_1.EventEmitter {
512
679
  };
513
680
  }
514
681
  catch (error) {
515
- this.logger.error('Failed to send document:', error);
682
+ this.logger.error("Failed to send document:", error);
516
683
  return {
517
684
  success: false,
518
685
  error: error.message,
@@ -528,12 +695,12 @@ class MiawClient extends events_1.EventEmitter {
528
695
  async sendVideo(to, video, options) {
529
696
  try {
530
697
  if (!this.socket) {
531
- throw new Error('Not connected. Call connect() first.');
698
+ throw new Error("Not connected. Call connect() first.");
532
699
  }
533
- if (this.connectionState !== 'connected') {
700
+ if (this.connectionState !== "connected") {
534
701
  throw new Error(`Cannot send message. Connection state: ${this.connectionState}`);
535
702
  }
536
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(to);
703
+ const jid = MessageHandler.formatPhoneToJid(to);
537
704
  // Build video message payload
538
705
  const videoContent = {
539
706
  video: Buffer.isBuffer(video) ? video : { url: video },
@@ -543,7 +710,9 @@ class MiawClient extends events_1.EventEmitter {
543
710
  ptv: options?.ptv,
544
711
  };
545
712
  // Build send options (for quoting/replying)
546
- const sendOptions = options?.quoted?.raw ? { quoted: options.quoted.raw } : undefined;
713
+ const sendOptions = options?.quoted?.raw
714
+ ? { quoted: options.quoted.raw }
715
+ : undefined;
547
716
  const result = await this.socket.sendMessage(jid, videoContent, sendOptions);
548
717
  return {
549
718
  success: true,
@@ -551,7 +720,7 @@ class MiawClient extends events_1.EventEmitter {
551
720
  };
552
721
  }
553
722
  catch (error) {
554
- this.logger.error('Failed to send video:', error);
723
+ this.logger.error("Failed to send video:", error);
555
724
  return {
556
725
  success: false,
557
726
  error: error.message,
@@ -567,12 +736,12 @@ class MiawClient extends events_1.EventEmitter {
567
736
  async sendAudio(to, audio, options) {
568
737
  try {
569
738
  if (!this.socket) {
570
- throw new Error('Not connected. Call connect() first.');
739
+ throw new Error("Not connected. Call connect() first.");
571
740
  }
572
- if (this.connectionState !== 'connected') {
741
+ if (this.connectionState !== "connected") {
573
742
  throw new Error(`Cannot send message. Connection state: ${this.connectionState}`);
574
743
  }
575
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(to);
744
+ const jid = MessageHandler.formatPhoneToJid(to);
576
745
  // Determine mimetype
577
746
  let mimetype = options?.mimetype;
578
747
  if (!mimetype && !Buffer.isBuffer(audio)) {
@@ -581,11 +750,13 @@ class MiawClient extends events_1.EventEmitter {
581
750
  // Build audio message payload
582
751
  const audioContent = {
583
752
  audio: Buffer.isBuffer(audio) ? audio : { url: audio },
584
- mimetype: mimetype || 'audio/mp4',
753
+ mimetype: mimetype || "audio/mp4",
585
754
  ptt: options?.ptt,
586
755
  };
587
756
  // Build send options (for quoting/replying)
588
- const sendOptions = options?.quoted?.raw ? { quoted: options.quoted.raw } : undefined;
757
+ const sendOptions = options?.quoted?.raw
758
+ ? { quoted: options.quoted.raw }
759
+ : undefined;
589
760
  const result = await this.socket.sendMessage(jid, audioContent, sendOptions);
590
761
  return {
591
762
  success: true,
@@ -593,7 +764,7 @@ class MiawClient extends events_1.EventEmitter {
593
764
  };
594
765
  }
595
766
  catch (error) {
596
- this.logger.error('Failed to send audio:', error);
767
+ this.logger.error("Failed to send audio:", error);
597
768
  return {
598
769
  success: false,
599
770
  error: error.message,
@@ -608,14 +779,14 @@ class MiawClient extends events_1.EventEmitter {
608
779
  async downloadMedia(message) {
609
780
  try {
610
781
  if (!message.raw) {
611
- throw new Error('Message does not contain raw Baileys data. Cannot download media.');
782
+ throw new Error("Message does not contain raw Baileys data. Cannot download media.");
612
783
  }
613
784
  // Check if this is a media message
614
- const mediaTypes = ['image', 'video', 'audio', 'document', 'sticker'];
785
+ const mediaTypes = ["image", "video", "audio", "document", "sticker"];
615
786
  if (!mediaTypes.includes(message.type)) {
616
787
  throw new Error(`Message type '${message.type}' is not a downloadable media type.`);
617
788
  }
618
- const buffer = await (0, baileys_1.downloadMediaMessage)(message.raw, 'buffer', {}, {
789
+ const buffer = await downloadMediaMessage(message.raw, "buffer", {}, {
619
790
  logger: this.logger,
620
791
  // reuploadRequest allows re-uploading expired media
621
792
  reuploadRequest: this.socket
@@ -625,7 +796,7 @@ class MiawClient extends events_1.EventEmitter {
625
796
  return buffer;
626
797
  }
627
798
  catch (error) {
628
- this.logger.error('Failed to download media:', error);
799
+ this.logger.error("Failed to download media:", error);
629
800
  return null;
630
801
  }
631
802
  }
@@ -640,13 +811,13 @@ class MiawClient extends events_1.EventEmitter {
640
811
  async checkNumber(phone) {
641
812
  try {
642
813
  if (!this.socket) {
643
- throw new Error('Not connected. Call connect() first.');
814
+ throw new Error("Not connected. Call connect() first.");
644
815
  }
645
- if (this.connectionState !== 'connected') {
816
+ if (this.connectionState !== "connected") {
646
817
  throw new Error(`Cannot check number. Connection state: ${this.connectionState}`);
647
818
  }
648
819
  // Clean phone number - remove non-digits
649
- const cleanPhone = phone.replace(/\D/g, '');
820
+ const cleanPhone = phone.replace(/\D/g, "");
650
821
  const results = await this.socket.onWhatsApp(cleanPhone);
651
822
  const result = results?.[0];
652
823
  return {
@@ -655,7 +826,7 @@ class MiawClient extends events_1.EventEmitter {
655
826
  };
656
827
  }
657
828
  catch (error) {
658
- this.logger.error('Failed to check number:', error);
829
+ this.logger.error("Failed to check number:", error);
659
830
  return {
660
831
  exists: false,
661
832
  error: error.message,
@@ -670,13 +841,13 @@ class MiawClient extends events_1.EventEmitter {
670
841
  async checkNumbers(phones) {
671
842
  try {
672
843
  if (!this.socket) {
673
- throw new Error('Not connected. Call connect() first.');
844
+ throw new Error("Not connected. Call connect() first.");
674
845
  }
675
- if (this.connectionState !== 'connected') {
846
+ if (this.connectionState !== "connected") {
676
847
  throw new Error(`Cannot check numbers. Connection state: ${this.connectionState}`);
677
848
  }
678
849
  // Clean all phone numbers
679
- const cleanPhones = phones.map((p) => p.replace(/\D/g, ''));
850
+ const cleanPhones = phones.map((p) => p.replace(/\D/g, ""));
680
851
  const results = await this.socket.onWhatsApp(...cleanPhones);
681
852
  return (results || []).map((result) => ({
682
853
  exists: !!result?.exists,
@@ -684,7 +855,7 @@ class MiawClient extends events_1.EventEmitter {
684
855
  }));
685
856
  }
686
857
  catch (error) {
687
- this.logger.error('Failed to check numbers:', error);
858
+ this.logger.error("Failed to check numbers:", error);
688
859
  return phones.map(() => ({
689
860
  exists: false,
690
861
  error: error.message,
@@ -699,18 +870,20 @@ class MiawClient extends events_1.EventEmitter {
699
870
  async getContactInfo(jidOrPhone) {
700
871
  try {
701
872
  if (!this.socket) {
702
- throw new Error('Not connected. Call connect() first.');
873
+ throw new Error("Not connected. Call connect() first.");
703
874
  }
704
- if (this.connectionState !== 'connected') {
875
+ if (this.connectionState !== "connected") {
705
876
  throw new Error(`Cannot get contact info. Connection state: ${this.connectionState}`);
706
877
  }
707
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(jidOrPhone);
878
+ const jid = MessageHandler.formatPhoneToJid(jidOrPhone);
708
879
  // Fetch status
709
880
  let status;
710
881
  try {
711
882
  const statusResult = await this.socket.fetchStatus(jid);
712
883
  // fetchStatus returns an array, get first result
713
- const firstResult = Array.isArray(statusResult) ? statusResult[0] : statusResult;
884
+ const firstResult = Array.isArray(statusResult)
885
+ ? statusResult[0]
886
+ : statusResult;
714
887
  status = firstResult?.status?.status || undefined;
715
888
  }
716
889
  catch {
@@ -726,8 +899,8 @@ class MiawClient extends events_1.EventEmitter {
726
899
  // Not a business account or not available
727
900
  }
728
901
  // Extract phone from JID
729
- const phone = jid.endsWith('@s.whatsapp.net')
730
- ? jid.replace('@s.whatsapp.net', '')
902
+ const phone = jid.endsWith("@s.whatsapp.net")
903
+ ? jid.replace("@s.whatsapp.net", "")
731
904
  : undefined;
732
905
  return {
733
906
  jid,
@@ -737,7 +910,7 @@ class MiawClient extends events_1.EventEmitter {
737
910
  };
738
911
  }
739
912
  catch (error) {
740
- this.logger.error('Failed to get contact info:', error);
913
+ this.logger.error("Failed to get contact info:", error);
741
914
  return null;
742
915
  }
743
916
  }
@@ -749,12 +922,12 @@ class MiawClient extends events_1.EventEmitter {
749
922
  async getBusinessProfile(jidOrPhone) {
750
923
  try {
751
924
  if (!this.socket) {
752
- throw new Error('Not connected. Call connect() first.');
925
+ throw new Error("Not connected. Call connect() first.");
753
926
  }
754
- if (this.connectionState !== 'connected') {
927
+ if (this.connectionState !== "connected") {
755
928
  throw new Error(`Cannot get business profile. Connection state: ${this.connectionState}`);
756
929
  }
757
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(jidOrPhone);
930
+ const jid = MessageHandler.formatPhoneToJid(jidOrPhone);
758
931
  const profile = await this.socket.getBusinessProfile(jid);
759
932
  if (!profile) {
760
933
  return null;
@@ -762,13 +935,15 @@ class MiawClient extends events_1.EventEmitter {
762
935
  return {
763
936
  description: profile.description || undefined,
764
937
  category: profile.category || undefined,
765
- website: Array.isArray(profile.website) ? profile.website[0] : profile.website,
938
+ website: Array.isArray(profile.website)
939
+ ? profile.website[0]
940
+ : profile.website,
766
941
  email: profile.email || undefined,
767
942
  address: profile.address || undefined,
768
943
  };
769
944
  }
770
945
  catch (error) {
771
- this.logger.error('Failed to get business profile:', error);
946
+ this.logger.error("Failed to get business profile:", error);
772
947
  return null;
773
948
  }
774
949
  }
@@ -781,22 +956,245 @@ class MiawClient extends events_1.EventEmitter {
781
956
  async getProfilePicture(jidOrPhone, highRes = false) {
782
957
  try {
783
958
  if (!this.socket) {
784
- throw new Error('Not connected. Call connect() first.');
959
+ throw new Error("Not connected. Call connect() first.");
785
960
  }
786
- if (this.connectionState !== 'connected') {
961
+ if (this.connectionState !== "connected") {
787
962
  throw new Error(`Cannot get profile picture. Connection state: ${this.connectionState}`);
788
963
  }
789
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(jidOrPhone);
790
- const url = await this.socket.profilePictureUrl(jid, highRes ? 'image' : 'preview');
964
+ const jid = MessageHandler.formatPhoneToJid(jidOrPhone);
965
+ const url = await this.socket.profilePictureUrl(jid, highRes ? "image" : "preview");
791
966
  return url || null;
792
967
  }
793
968
  catch (error) {
794
969
  // Profile picture might not be available (privacy settings)
795
- this.logger.debug('Profile picture not available:', error);
970
+ this.logger.debug("Profile picture not available:", error);
796
971
  return null;
797
972
  }
798
973
  }
799
974
  // ============================================
975
+ // Basic GET Operations (v0.9.0)
976
+ // ============================================
977
+ /**
978
+ * Fetch all contacts from the in-memory store
979
+ * Note: Contacts are populated via history sync and contact events
980
+ * @returns FetchAllContactsResult with list of contacts
981
+ */
982
+ async fetchAllContacts() {
983
+ try {
984
+ const contacts = Array.from(this.contactsStore.values());
985
+ return {
986
+ success: true,
987
+ contacts,
988
+ };
989
+ }
990
+ catch (error) {
991
+ this.logger.error("Failed to fetch contacts:", error);
992
+ return {
993
+ success: false,
994
+ error: error.message,
995
+ };
996
+ }
997
+ }
998
+ /**
999
+ * Fetch all groups the user is participating in
1000
+ * @returns FetchAllGroupsResult with list of groups
1001
+ */
1002
+ async fetchAllGroups() {
1003
+ try {
1004
+ if (!this.socket) {
1005
+ throw new Error("Not connected. Call connect() first.");
1006
+ }
1007
+ if (this.connectionState !== "connected") {
1008
+ throw new Error(`Cannot fetch groups. Connection state: ${this.connectionState}`);
1009
+ }
1010
+ const groups = await this.socket.groupFetchAllParticipating();
1011
+ const groupList = Object.values(groups).map((g) => ({
1012
+ jid: g.id,
1013
+ name: g.subject,
1014
+ description: g.desc || undefined,
1015
+ owner: g.owner || undefined,
1016
+ createdAt: g.creation,
1017
+ participantCount: g.participants?.length || 0,
1018
+ participants: g.participants?.map((p) => ({
1019
+ jid: p.id,
1020
+ role: p.admin === "superadmin"
1021
+ ? "superadmin"
1022
+ : p.admin === "admin"
1023
+ ? "admin"
1024
+ : "member",
1025
+ })) || [],
1026
+ announce: g.announce,
1027
+ restrict: g.restrict,
1028
+ }));
1029
+ return {
1030
+ success: true,
1031
+ groups: groupList,
1032
+ };
1033
+ }
1034
+ catch (error) {
1035
+ this.logger.error("Failed to fetch groups:", error);
1036
+ return {
1037
+ success: false,
1038
+ error: error.message,
1039
+ };
1040
+ }
1041
+ }
1042
+ /**
1043
+ * Get own profile information
1044
+ * @returns OwnProfile or null if not available
1045
+ */
1046
+ async getOwnProfile() {
1047
+ try {
1048
+ if (!this.socket) {
1049
+ throw new Error("Not connected. Call connect() first.");
1050
+ }
1051
+ if (this.connectionState !== "connected") {
1052
+ throw new Error(`Cannot get own profile. Connection state: ${this.connectionState}`);
1053
+ }
1054
+ const jid = this.socket.user?.id;
1055
+ if (!jid) {
1056
+ throw new Error("User ID not available");
1057
+ }
1058
+ // Extract phone number from JID
1059
+ const phone = jid.endsWith("@s.whatsapp.net")
1060
+ ? jid.replace("@s.whatsapp.net", "")
1061
+ : undefined;
1062
+ // Fetch status
1063
+ let status;
1064
+ try {
1065
+ const statusResult = await this.socket.fetchStatus(jid);
1066
+ const firstResult = Array.isArray(statusResult)
1067
+ ? statusResult[0]
1068
+ : statusResult;
1069
+ status = firstResult?.status?.status || undefined;
1070
+ }
1071
+ catch {
1072
+ // Status might not be available
1073
+ }
1074
+ // Fetch profile picture URL
1075
+ let pictureUrl;
1076
+ try {
1077
+ pictureUrl = (await this.socket.profilePictureUrl(jid)) || undefined;
1078
+ }
1079
+ catch {
1080
+ // Profile picture might not be available
1081
+ }
1082
+ // Check if business account
1083
+ let isBusiness = false;
1084
+ try {
1085
+ const businessProfile = await this.socket.getBusinessProfile(jid);
1086
+ isBusiness = !!businessProfile;
1087
+ }
1088
+ catch {
1089
+ // Not a business account
1090
+ }
1091
+ return {
1092
+ jid,
1093
+ phone,
1094
+ status,
1095
+ pictureUrl,
1096
+ isBusiness,
1097
+ };
1098
+ }
1099
+ catch (error) {
1100
+ this.logger.error("Failed to get own profile:", error);
1101
+ return null;
1102
+ }
1103
+ }
1104
+ /**
1105
+ * Sync labels from WhatsApp app state
1106
+ * This triggers a resync of the 'regular' collection which contains labels
1107
+ * Labels will be emitted via labels.edit events and stored in labelsStore
1108
+ */
1109
+ async syncLabelsFromAppState() {
1110
+ if (!this.socket) {
1111
+ return;
1112
+ }
1113
+ try {
1114
+ // resyncAppState is provided by Baileys to sync app state collections
1115
+ // The 'regular' collection contains labels
1116
+ // The second parameter (false) means this is not an initial sync
1117
+ await this.socket.resyncAppState(["regular"], false);
1118
+ this.logger.info("App state sync completed, labels should be populated via labels.edit events");
1119
+ }
1120
+ catch (error) {
1121
+ // This is non-fatal - labels may already be synced or unavailable
1122
+ this.logger.debug("App state sync error (non-fatal):", error);
1123
+ }
1124
+ }
1125
+ /**
1126
+ * Fetch all labels from the in-memory store
1127
+ * Note: Labels are populated via history sync and label events
1128
+ * @param forceSync - If true, force a resync from WhatsApp before returning labels
1129
+ * @returns FetchAllLabelsResult with list of labels
1130
+ */
1131
+ async fetchAllLabels(forceSync = false) {
1132
+ try {
1133
+ // Force resync if requested or if store is empty (first call)
1134
+ if (forceSync || this.labelsStore.size === 0) {
1135
+ await this.syncLabelsFromAppState();
1136
+ // Give a brief moment for labels.edit events to be processed
1137
+ await new Promise((resolve) => setTimeout(resolve, 500));
1138
+ }
1139
+ const labels = Array.from(this.labelsStore.values());
1140
+ return {
1141
+ success: true,
1142
+ labels,
1143
+ };
1144
+ }
1145
+ catch (error) {
1146
+ this.logger.error("Failed to fetch labels:", error);
1147
+ return {
1148
+ success: false,
1149
+ error: error.message,
1150
+ };
1151
+ }
1152
+ }
1153
+ /**
1154
+ * Get chat messages from the in-memory store
1155
+ * Note: Messages are populated via messages.upsert events
1156
+ * @param jidOrPhone - Chat JID or phone number
1157
+ * @returns FetchChatMessagesResult with list of messages
1158
+ */
1159
+ async getChatMessages(jidOrPhone) {
1160
+ try {
1161
+ const jid = MessageHandler.formatPhoneToJid(jidOrPhone);
1162
+ const messages = this.messagesStore.get(jid) || [];
1163
+ return {
1164
+ success: true,
1165
+ messages,
1166
+ };
1167
+ }
1168
+ catch (error) {
1169
+ this.logger.error("Failed to get chat messages:", error);
1170
+ return {
1171
+ success: false,
1172
+ error: error.message,
1173
+ };
1174
+ }
1175
+ }
1176
+ /**
1177
+ * Fetch all chats from the in-memory store
1178
+ * Note: Chats are populated via history sync and chat events
1179
+ * @returns FetchAllChatsResult with list of chats
1180
+ */
1181
+ async fetchAllChats() {
1182
+ try {
1183
+ const chats = Array.from(this.chatsStore.values());
1184
+ return {
1185
+ success: true,
1186
+ chats,
1187
+ };
1188
+ }
1189
+ catch (error) {
1190
+ this.logger.error("Failed to fetch chats:", error);
1191
+ return {
1192
+ success: false,
1193
+ error: error.message,
1194
+ };
1195
+ }
1196
+ }
1197
+ // ============================================
800
1198
  // Group Methods (v0.4.0)
801
1199
  // ============================================
802
1200
  /**
@@ -807,19 +1205,23 @@ class MiawClient extends events_1.EventEmitter {
807
1205
  async getGroupInfo(groupJid) {
808
1206
  try {
809
1207
  if (!this.socket) {
810
- throw new Error('Not connected. Call connect() first.');
1208
+ throw new Error("Not connected. Call connect() first.");
811
1209
  }
812
- if (this.connectionState !== 'connected') {
1210
+ if (this.connectionState !== "connected") {
813
1211
  throw new Error(`Cannot get group info. Connection state: ${this.connectionState}`);
814
1212
  }
815
1213
  // Ensure it's a group JID
816
- if (!groupJid.endsWith('@g.us')) {
817
- throw new Error('Invalid group JID. Must end with @g.us');
1214
+ if (!groupJid.endsWith("@g.us")) {
1215
+ throw new Error("Invalid group JID. Must end with @g.us");
818
1216
  }
819
1217
  const metadata = await this.socket.groupMetadata(groupJid);
820
1218
  const participants = metadata.participants.map((p) => ({
821
1219
  jid: p.id,
822
- role: p.admin === 'superadmin' ? 'superadmin' : p.admin === 'admin' ? 'admin' : 'member',
1220
+ role: p.admin === "superadmin"
1221
+ ? "superadmin"
1222
+ : p.admin === "admin"
1223
+ ? "admin"
1224
+ : "member",
823
1225
  }));
824
1226
  return {
825
1227
  jid: metadata.id,
@@ -834,7 +1236,7 @@ class MiawClient extends events_1.EventEmitter {
834
1236
  };
835
1237
  }
836
1238
  catch (error) {
837
- this.logger.error('Failed to get group info:', error);
1239
+ this.logger.error("Failed to get group info:", error);
838
1240
  return null;
839
1241
  }
840
1242
  }
@@ -859,17 +1261,17 @@ class MiawClient extends events_1.EventEmitter {
859
1261
  async sendReaction(message, emoji) {
860
1262
  try {
861
1263
  if (!this.socket) {
862
- throw new Error('Not connected. Call connect() first.');
1264
+ throw new Error("Not connected. Call connect() first.");
863
1265
  }
864
- if (this.connectionState !== 'connected') {
1266
+ if (this.connectionState !== "connected") {
865
1267
  throw new Error(`Cannot send reaction. Connection state: ${this.connectionState}`);
866
1268
  }
867
1269
  if (!message.raw?.key) {
868
- throw new Error('Message does not contain raw Baileys key data. Cannot send reaction.');
1270
+ throw new Error("Message does not contain raw Baileys key data. Cannot send reaction.");
869
1271
  }
870
1272
  const jid = message.raw.key.remoteJid;
871
1273
  if (!jid) {
872
- throw new Error('Message does not have a valid chat JID.');
1274
+ throw new Error("Message does not have a valid chat JID.");
873
1275
  }
874
1276
  const result = await this.socket.sendMessage(jid, {
875
1277
  react: {
@@ -883,7 +1285,7 @@ class MiawClient extends events_1.EventEmitter {
883
1285
  };
884
1286
  }
885
1287
  catch (error) {
886
- this.logger.error('Failed to send reaction:', error);
1288
+ this.logger.error("Failed to send reaction:", error);
887
1289
  return {
888
1290
  success: false,
889
1291
  error: error.message,
@@ -896,7 +1298,7 @@ class MiawClient extends events_1.EventEmitter {
896
1298
  * @returns SendMessageResult
897
1299
  */
898
1300
  async removeReaction(message) {
899
- return this.sendReaction(message, '');
1301
+ return this.sendReaction(message, "");
900
1302
  }
901
1303
  /**
902
1304
  * Forward a message to another chat
@@ -907,15 +1309,15 @@ class MiawClient extends events_1.EventEmitter {
907
1309
  async forwardMessage(message, to) {
908
1310
  try {
909
1311
  if (!this.socket) {
910
- throw new Error('Not connected. Call connect() first.');
1312
+ throw new Error("Not connected. Call connect() first.");
911
1313
  }
912
- if (this.connectionState !== 'connected') {
1314
+ if (this.connectionState !== "connected") {
913
1315
  throw new Error(`Cannot forward message. Connection state: ${this.connectionState}`);
914
1316
  }
915
1317
  if (!message.raw) {
916
- throw new Error('Message does not contain raw Baileys data. Cannot forward.');
1318
+ throw new Error("Message does not contain raw Baileys data. Cannot forward.");
917
1319
  }
918
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(to);
1320
+ const jid = MessageHandler.formatPhoneToJid(to);
919
1321
  const result = await this.socket.sendMessage(jid, {
920
1322
  forward: message.raw,
921
1323
  });
@@ -925,7 +1327,7 @@ class MiawClient extends events_1.EventEmitter {
925
1327
  };
926
1328
  }
927
1329
  catch (error) {
928
- this.logger.error('Failed to forward message:', error);
1330
+ this.logger.error("Failed to forward message:", error);
929
1331
  return {
930
1332
  success: false,
931
1333
  error: error.message,
@@ -941,20 +1343,20 @@ class MiawClient extends events_1.EventEmitter {
941
1343
  async editMessage(message, newText) {
942
1344
  try {
943
1345
  if (!this.socket) {
944
- throw new Error('Not connected. Call connect() first.');
1346
+ throw new Error("Not connected. Call connect() first.");
945
1347
  }
946
- if (this.connectionState !== 'connected') {
1348
+ if (this.connectionState !== "connected") {
947
1349
  throw new Error(`Cannot edit message. Connection state: ${this.connectionState}`);
948
1350
  }
949
1351
  if (!message.raw?.key) {
950
- throw new Error('Message does not contain raw Baileys key data. Cannot edit.');
1352
+ throw new Error("Message does not contain raw Baileys key data. Cannot edit.");
951
1353
  }
952
1354
  if (!message.fromMe) {
953
- throw new Error('Can only edit your own messages.');
1355
+ throw new Error("Can only edit your own messages.");
954
1356
  }
955
1357
  const jid = message.raw.key.remoteJid;
956
1358
  if (!jid) {
957
- throw new Error('Message does not have a valid chat JID.');
1359
+ throw new Error("Message does not have a valid chat JID.");
958
1360
  }
959
1361
  const result = await this.socket.sendMessage(jid, {
960
1362
  text: newText,
@@ -966,7 +1368,7 @@ class MiawClient extends events_1.EventEmitter {
966
1368
  };
967
1369
  }
968
1370
  catch (error) {
969
- this.logger.error('Failed to edit message:', error);
1371
+ this.logger.error("Failed to edit message:", error);
970
1372
  return {
971
1373
  success: false,
972
1374
  error: error.message,
@@ -981,17 +1383,17 @@ class MiawClient extends events_1.EventEmitter {
981
1383
  async deleteMessage(message) {
982
1384
  try {
983
1385
  if (!this.socket) {
984
- throw new Error('Not connected. Call connect() first.');
1386
+ throw new Error("Not connected. Call connect() first.");
985
1387
  }
986
- if (this.connectionState !== 'connected') {
1388
+ if (this.connectionState !== "connected") {
987
1389
  throw new Error(`Cannot delete message. Connection state: ${this.connectionState}`);
988
1390
  }
989
1391
  if (!message.raw?.key) {
990
- throw new Error('Message does not contain raw Baileys key data. Cannot delete.');
1392
+ throw new Error("Message does not contain raw Baileys key data. Cannot delete.");
991
1393
  }
992
1394
  const jid = message.raw.key.remoteJid;
993
1395
  if (!jid) {
994
- throw new Error('Message does not have a valid chat JID.');
1396
+ throw new Error("Message does not have a valid chat JID.");
995
1397
  }
996
1398
  const result = await this.socket.sendMessage(jid, {
997
1399
  delete: message.raw.key,
@@ -1002,7 +1404,7 @@ class MiawClient extends events_1.EventEmitter {
1002
1404
  };
1003
1405
  }
1004
1406
  catch (error) {
1005
- this.logger.error('Failed to delete message:', error);
1407
+ this.logger.error("Failed to delete message:", error);
1006
1408
  return {
1007
1409
  success: false,
1008
1410
  error: error.message,
@@ -1018,17 +1420,17 @@ class MiawClient extends events_1.EventEmitter {
1018
1420
  async deleteMessageForMe(message, deleteMedia = true) {
1019
1421
  try {
1020
1422
  if (!this.socket) {
1021
- throw new Error('Not connected. Call connect() first.');
1423
+ throw new Error("Not connected. Call connect() first.");
1022
1424
  }
1023
- if (this.connectionState !== 'connected') {
1425
+ if (this.connectionState !== "connected") {
1024
1426
  throw new Error(`Cannot delete message. Connection state: ${this.connectionState}`);
1025
1427
  }
1026
1428
  if (!message.raw?.key) {
1027
- throw new Error('Message does not contain raw Baileys key data. Cannot delete.');
1429
+ throw new Error("Message does not contain raw Baileys key data. Cannot delete.");
1028
1430
  }
1029
1431
  const jid = message.raw.key.remoteJid;
1030
1432
  if (!jid) {
1031
- throw new Error('Message does not have a valid chat JID.');
1433
+ throw new Error("Message does not have a valid chat JID.");
1032
1434
  }
1033
1435
  await this.socket.chatModify({
1034
1436
  deleteForMe: {
@@ -1040,7 +1442,7 @@ class MiawClient extends events_1.EventEmitter {
1040
1442
  return true;
1041
1443
  }
1042
1444
  catch (error) {
1043
- this.logger.error('Failed to delete message for me:', error);
1445
+ this.logger.error("Failed to delete message for me:", error);
1044
1446
  return false;
1045
1447
  }
1046
1448
  }
@@ -1055,19 +1457,19 @@ class MiawClient extends events_1.EventEmitter {
1055
1457
  async markAsRead(message) {
1056
1458
  try {
1057
1459
  if (!this.socket) {
1058
- throw new Error('Not connected. Call connect() first.');
1460
+ throw new Error("Not connected. Call connect() first.");
1059
1461
  }
1060
- if (this.connectionState !== 'connected') {
1462
+ if (this.connectionState !== "connected") {
1061
1463
  throw new Error(`Cannot mark as read. Connection state: ${this.connectionState}`);
1062
1464
  }
1063
1465
  if (!message.raw?.key) {
1064
- throw new Error('Message does not contain raw Baileys key data.');
1466
+ throw new Error("Message does not contain raw Baileys key data.");
1065
1467
  }
1066
1468
  await this.socket.readMessages([message.raw.key]);
1067
1469
  return true;
1068
1470
  }
1069
1471
  catch (error) {
1070
- this.logger.error('Failed to mark as read:', error);
1472
+ this.logger.error("Failed to mark as read:", error);
1071
1473
  return false;
1072
1474
  }
1073
1475
  }
@@ -1078,16 +1480,16 @@ class MiawClient extends events_1.EventEmitter {
1078
1480
  async sendTyping(to) {
1079
1481
  try {
1080
1482
  if (!this.socket) {
1081
- throw new Error('Not connected. Call connect() first.');
1483
+ throw new Error("Not connected. Call connect() first.");
1082
1484
  }
1083
- if (this.connectionState !== 'connected') {
1485
+ if (this.connectionState !== "connected") {
1084
1486
  throw new Error(`Cannot send typing. Connection state: ${this.connectionState}`);
1085
1487
  }
1086
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(to);
1087
- await this.socket.sendPresenceUpdate('composing', jid);
1488
+ const jid = MessageHandler.formatPhoneToJid(to);
1489
+ await this.socket.sendPresenceUpdate("composing", jid);
1088
1490
  }
1089
1491
  catch (error) {
1090
- this.logger.error('Failed to send typing indicator:', error);
1492
+ this.logger.error("Failed to send typing indicator:", error);
1091
1493
  }
1092
1494
  }
1093
1495
  /**
@@ -1097,16 +1499,16 @@ class MiawClient extends events_1.EventEmitter {
1097
1499
  async sendRecording(to) {
1098
1500
  try {
1099
1501
  if (!this.socket) {
1100
- throw new Error('Not connected. Call connect() first.');
1502
+ throw new Error("Not connected. Call connect() first.");
1101
1503
  }
1102
- if (this.connectionState !== 'connected') {
1504
+ if (this.connectionState !== "connected") {
1103
1505
  throw new Error(`Cannot send recording. Connection state: ${this.connectionState}`);
1104
1506
  }
1105
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(to);
1106
- await this.socket.sendPresenceUpdate('recording', jid);
1507
+ const jid = MessageHandler.formatPhoneToJid(to);
1508
+ await this.socket.sendPresenceUpdate("recording", jid);
1107
1509
  }
1108
1510
  catch (error) {
1109
- this.logger.error('Failed to send recording indicator:', error);
1511
+ this.logger.error("Failed to send recording indicator:", error);
1110
1512
  }
1111
1513
  }
1112
1514
  /**
@@ -1116,16 +1518,16 @@ class MiawClient extends events_1.EventEmitter {
1116
1518
  async stopTyping(to) {
1117
1519
  try {
1118
1520
  if (!this.socket) {
1119
- throw new Error('Not connected. Call connect() first.');
1521
+ throw new Error("Not connected. Call connect() first.");
1120
1522
  }
1121
- if (this.connectionState !== 'connected') {
1523
+ if (this.connectionState !== "connected") {
1122
1524
  throw new Error(`Cannot stop typing. Connection state: ${this.connectionState}`);
1123
1525
  }
1124
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(to);
1125
- await this.socket.sendPresenceUpdate('paused', jid);
1526
+ const jid = MessageHandler.formatPhoneToJid(to);
1527
+ await this.socket.sendPresenceUpdate("paused", jid);
1126
1528
  }
1127
1529
  catch (error) {
1128
- this.logger.error('Failed to stop typing indicator:', error);
1530
+ this.logger.error("Failed to stop typing indicator:", error);
1129
1531
  }
1130
1532
  }
1131
1533
  /**
@@ -1135,15 +1537,15 @@ class MiawClient extends events_1.EventEmitter {
1135
1537
  async setPresence(status) {
1136
1538
  try {
1137
1539
  if (!this.socket) {
1138
- throw new Error('Not connected. Call connect() first.');
1540
+ throw new Error("Not connected. Call connect() first.");
1139
1541
  }
1140
- if (this.connectionState !== 'connected') {
1542
+ if (this.connectionState !== "connected") {
1141
1543
  throw new Error(`Cannot set presence. Connection state: ${this.connectionState}`);
1142
1544
  }
1143
1545
  await this.socket.sendPresenceUpdate(status);
1144
1546
  }
1145
1547
  catch (error) {
1146
- this.logger.error('Failed to set presence:', error);
1548
+ this.logger.error("Failed to set presence:", error);
1147
1549
  }
1148
1550
  }
1149
1551
  /**
@@ -1154,16 +1556,16 @@ class MiawClient extends events_1.EventEmitter {
1154
1556
  async subscribePresence(jidOrPhone) {
1155
1557
  try {
1156
1558
  if (!this.socket) {
1157
- throw new Error('Not connected. Call connect() first.');
1559
+ throw new Error("Not connected. Call connect() first.");
1158
1560
  }
1159
- if (this.connectionState !== 'connected') {
1561
+ if (this.connectionState !== "connected") {
1160
1562
  throw new Error(`Cannot subscribe to presence. Connection state: ${this.connectionState}`);
1161
1563
  }
1162
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(jidOrPhone);
1564
+ const jid = MessageHandler.formatPhoneToJid(jidOrPhone);
1163
1565
  await this.socket.presenceSubscribe(jid);
1164
1566
  }
1165
1567
  catch (error) {
1166
- this.logger.error('Failed to subscribe to presence:', error);
1568
+ this.logger.error("Failed to subscribe to presence:", error);
1167
1569
  }
1168
1570
  }
1169
1571
  // ============================================
@@ -1174,21 +1576,21 @@ class MiawClient extends events_1.EventEmitter {
1174
1576
  */
1175
1577
  async groupParticipantsOperation(groupJid, participants, action) {
1176
1578
  if (!this.socket) {
1177
- throw new Error('Not connected. Call connect() first.');
1579
+ throw new Error("Not connected. Call connect() first.");
1178
1580
  }
1179
- if (this.connectionState !== 'connected') {
1581
+ if (this.connectionState !== "connected") {
1180
1582
  throw new Error(`Cannot perform group operation. Connection state: ${this.connectionState}`);
1181
1583
  }
1182
- if (!groupJid.endsWith('@g.us')) {
1183
- throw new Error('Invalid group JID. Must end with @g.us');
1584
+ if (!groupJid.endsWith("@g.us")) {
1585
+ throw new Error("Invalid group JID. Must end with @g.us");
1184
1586
  }
1185
1587
  // Format participant JIDs
1186
- const formattedParticipants = participants.map((p) => MessageHandler_1.MessageHandler.formatPhoneToJid(p));
1588
+ const formattedParticipants = participants.map((p) => MessageHandler.formatPhoneToJid(p));
1187
1589
  const results = await this.socket.groupParticipantsUpdate(groupJid, formattedParticipants, action);
1188
1590
  return results.map((result) => ({
1189
- jid: result.jid || '',
1591
+ jid: result.jid || "",
1190
1592
  status: result.status,
1191
- success: result.status === '200',
1593
+ success: result.status === "200",
1192
1594
  }));
1193
1595
  }
1194
1596
  /**
@@ -1200,17 +1602,21 @@ class MiawClient extends events_1.EventEmitter {
1200
1602
  async createGroup(name, participants) {
1201
1603
  try {
1202
1604
  if (!this.socket) {
1203
- throw new Error('Not connected. Call connect() first.');
1605
+ throw new Error("Not connected. Call connect() first.");
1204
1606
  }
1205
- if (this.connectionState !== 'connected') {
1607
+ if (this.connectionState !== "connected") {
1206
1608
  throw new Error(`Cannot create group. Connection state: ${this.connectionState}`);
1207
1609
  }
1208
1610
  // Format participant JIDs
1209
- const formattedParticipants = participants.map((p) => MessageHandler_1.MessageHandler.formatPhoneToJid(p));
1611
+ const formattedParticipants = participants.map((p) => MessageHandler.formatPhoneToJid(p));
1210
1612
  const metadata = await this.socket.groupCreate(name, formattedParticipants);
1211
1613
  const groupParticipants = metadata.participants.map((p) => ({
1212
1614
  jid: p.id,
1213
- role: p.admin === 'superadmin' ? 'superadmin' : p.admin === 'admin' ? 'admin' : 'member',
1615
+ role: p.admin === "superadmin"
1616
+ ? "superadmin"
1617
+ : p.admin === "admin"
1618
+ ? "admin"
1619
+ : "member",
1214
1620
  }));
1215
1621
  return {
1216
1622
  success: true,
@@ -1229,7 +1635,7 @@ class MiawClient extends events_1.EventEmitter {
1229
1635
  };
1230
1636
  }
1231
1637
  catch (error) {
1232
- this.logger.error('Failed to create group:', error);
1638
+ this.logger.error("Failed to create group:", error);
1233
1639
  return {
1234
1640
  success: false,
1235
1641
  error: error.message,
@@ -1244,13 +1650,13 @@ class MiawClient extends events_1.EventEmitter {
1244
1650
  */
1245
1651
  async addParticipants(groupJid, participants) {
1246
1652
  try {
1247
- return await this.groupParticipantsOperation(groupJid, participants, 'add');
1653
+ return await this.groupParticipantsOperation(groupJid, participants, "add");
1248
1654
  }
1249
1655
  catch (error) {
1250
- this.logger.error('Failed to add participants:', error);
1656
+ this.logger.error("Failed to add participants:", error);
1251
1657
  return participants.map((p) => ({
1252
- jid: MessageHandler_1.MessageHandler.formatPhoneToJid(p),
1253
- status: 'error',
1658
+ jid: MessageHandler.formatPhoneToJid(p),
1659
+ status: "error",
1254
1660
  success: false,
1255
1661
  }));
1256
1662
  }
@@ -1263,13 +1669,13 @@ class MiawClient extends events_1.EventEmitter {
1263
1669
  */
1264
1670
  async removeParticipants(groupJid, participants) {
1265
1671
  try {
1266
- return await this.groupParticipantsOperation(groupJid, participants, 'remove');
1672
+ return await this.groupParticipantsOperation(groupJid, participants, "remove");
1267
1673
  }
1268
1674
  catch (error) {
1269
- this.logger.error('Failed to remove participants:', error);
1675
+ this.logger.error("Failed to remove participants:", error);
1270
1676
  return participants.map((p) => ({
1271
- jid: MessageHandler_1.MessageHandler.formatPhoneToJid(p),
1272
- status: 'error',
1677
+ jid: MessageHandler.formatPhoneToJid(p),
1678
+ status: "error",
1273
1679
  success: false,
1274
1680
  }));
1275
1681
  }
@@ -1282,19 +1688,19 @@ class MiawClient extends events_1.EventEmitter {
1282
1688
  async leaveGroup(groupJid) {
1283
1689
  try {
1284
1690
  if (!this.socket) {
1285
- throw new Error('Not connected. Call connect() first.');
1691
+ throw new Error("Not connected. Call connect() first.");
1286
1692
  }
1287
- if (this.connectionState !== 'connected') {
1693
+ if (this.connectionState !== "connected") {
1288
1694
  throw new Error(`Cannot leave group. Connection state: ${this.connectionState}`);
1289
1695
  }
1290
- if (!groupJid.endsWith('@g.us')) {
1291
- throw new Error('Invalid group JID. Must end with @g.us');
1696
+ if (!groupJid.endsWith("@g.us")) {
1697
+ throw new Error("Invalid group JID. Must end with @g.us");
1292
1698
  }
1293
1699
  await this.socket.groupLeave(groupJid);
1294
1700
  return { success: true };
1295
1701
  }
1296
1702
  catch (error) {
1297
- this.logger.error('Failed to leave group:', error);
1703
+ this.logger.error("Failed to leave group:", error);
1298
1704
  return {
1299
1705
  success: false,
1300
1706
  error: error.message,
@@ -1309,13 +1715,13 @@ class MiawClient extends events_1.EventEmitter {
1309
1715
  */
1310
1716
  async promoteToAdmin(groupJid, participants) {
1311
1717
  try {
1312
- return await this.groupParticipantsOperation(groupJid, participants, 'promote');
1718
+ return await this.groupParticipantsOperation(groupJid, participants, "promote");
1313
1719
  }
1314
1720
  catch (error) {
1315
- this.logger.error('Failed to promote participants:', error);
1721
+ this.logger.error("Failed to promote participants:", error);
1316
1722
  return participants.map((p) => ({
1317
- jid: MessageHandler_1.MessageHandler.formatPhoneToJid(p),
1318
- status: 'error',
1723
+ jid: MessageHandler.formatPhoneToJid(p),
1724
+ status: "error",
1319
1725
  success: false,
1320
1726
  }));
1321
1727
  }
@@ -1328,13 +1734,13 @@ class MiawClient extends events_1.EventEmitter {
1328
1734
  */
1329
1735
  async demoteFromAdmin(groupJid, participants) {
1330
1736
  try {
1331
- return await this.groupParticipantsOperation(groupJid, participants, 'demote');
1737
+ return await this.groupParticipantsOperation(groupJid, participants, "demote");
1332
1738
  }
1333
1739
  catch (error) {
1334
- this.logger.error('Failed to demote participants:', error);
1740
+ this.logger.error("Failed to demote participants:", error);
1335
1741
  return participants.map((p) => ({
1336
- jid: MessageHandler_1.MessageHandler.formatPhoneToJid(p),
1337
- status: 'error',
1742
+ jid: MessageHandler.formatPhoneToJid(p),
1743
+ status: "error",
1338
1744
  success: false,
1339
1745
  }));
1340
1746
  }
@@ -1348,19 +1754,19 @@ class MiawClient extends events_1.EventEmitter {
1348
1754
  async updateGroupName(groupJid, name) {
1349
1755
  try {
1350
1756
  if (!this.socket) {
1351
- throw new Error('Not connected. Call connect() first.');
1757
+ throw new Error("Not connected. Call connect() first.");
1352
1758
  }
1353
- if (this.connectionState !== 'connected') {
1759
+ if (this.connectionState !== "connected") {
1354
1760
  throw new Error(`Cannot update group name. Connection state: ${this.connectionState}`);
1355
1761
  }
1356
- if (!groupJid.endsWith('@g.us')) {
1357
- throw new Error('Invalid group JID. Must end with @g.us');
1762
+ if (!groupJid.endsWith("@g.us")) {
1763
+ throw new Error("Invalid group JID. Must end with @g.us");
1358
1764
  }
1359
1765
  await this.socket.groupUpdateSubject(groupJid, name);
1360
1766
  return { success: true };
1361
1767
  }
1362
1768
  catch (error) {
1363
- this.logger.error('Failed to update group name:', error);
1769
+ this.logger.error("Failed to update group name:", error);
1364
1770
  return {
1365
1771
  success: false,
1366
1772
  error: error.message,
@@ -1376,19 +1782,19 @@ class MiawClient extends events_1.EventEmitter {
1376
1782
  async updateGroupDescription(groupJid, description) {
1377
1783
  try {
1378
1784
  if (!this.socket) {
1379
- throw new Error('Not connected. Call connect() first.');
1785
+ throw new Error("Not connected. Call connect() first.");
1380
1786
  }
1381
- if (this.connectionState !== 'connected') {
1787
+ if (this.connectionState !== "connected") {
1382
1788
  throw new Error(`Cannot update group description. Connection state: ${this.connectionState}`);
1383
1789
  }
1384
- if (!groupJid.endsWith('@g.us')) {
1385
- throw new Error('Invalid group JID. Must end with @g.us');
1790
+ if (!groupJid.endsWith("@g.us")) {
1791
+ throw new Error("Invalid group JID. Must end with @g.us");
1386
1792
  }
1387
1793
  await this.socket.groupUpdateDescription(groupJid, description);
1388
1794
  return { success: true };
1389
1795
  }
1390
1796
  catch (error) {
1391
- this.logger.error('Failed to update group description:', error);
1797
+ this.logger.error("Failed to update group description:", error);
1392
1798
  return {
1393
1799
  success: false,
1394
1800
  error: error.message,
@@ -1404,20 +1810,20 @@ class MiawClient extends events_1.EventEmitter {
1404
1810
  async updateGroupPicture(groupJid, image) {
1405
1811
  try {
1406
1812
  if (!this.socket) {
1407
- throw new Error('Not connected. Call connect() first.');
1813
+ throw new Error("Not connected. Call connect() first.");
1408
1814
  }
1409
- if (this.connectionState !== 'connected') {
1815
+ if (this.connectionState !== "connected") {
1410
1816
  throw new Error(`Cannot update group picture. Connection state: ${this.connectionState}`);
1411
1817
  }
1412
- if (!groupJid.endsWith('@g.us')) {
1413
- throw new Error('Invalid group JID. Must end with @g.us');
1818
+ if (!groupJid.endsWith("@g.us")) {
1819
+ throw new Error("Invalid group JID. Must end with @g.us");
1414
1820
  }
1415
1821
  const imageContent = Buffer.isBuffer(image) ? image : { url: image };
1416
1822
  await this.socket.updateProfilePicture(groupJid, imageContent);
1417
1823
  return { success: true };
1418
1824
  }
1419
1825
  catch (error) {
1420
- this.logger.error('Failed to update group picture:', error);
1826
+ this.logger.error("Failed to update group picture:", error);
1421
1827
  return {
1422
1828
  success: false,
1423
1829
  error: error.message,
@@ -1432,19 +1838,19 @@ class MiawClient extends events_1.EventEmitter {
1432
1838
  async getGroupInviteLink(groupJid) {
1433
1839
  try {
1434
1840
  if (!this.socket) {
1435
- throw new Error('Not connected. Call connect() first.');
1841
+ throw new Error("Not connected. Call connect() first.");
1436
1842
  }
1437
- if (this.connectionState !== 'connected') {
1843
+ if (this.connectionState !== "connected") {
1438
1844
  throw new Error(`Cannot get invite link. Connection state: ${this.connectionState}`);
1439
1845
  }
1440
- if (!groupJid.endsWith('@g.us')) {
1441
- throw new Error('Invalid group JID. Must end with @g.us');
1846
+ if (!groupJid.endsWith("@g.us")) {
1847
+ throw new Error("Invalid group JID. Must end with @g.us");
1442
1848
  }
1443
1849
  const code = await this.socket.groupInviteCode(groupJid);
1444
1850
  return code ? `https://chat.whatsapp.com/${code}` : null;
1445
1851
  }
1446
1852
  catch (error) {
1447
- this.logger.error('Failed to get group invite link:', error);
1853
+ this.logger.error("Failed to get group invite link:", error);
1448
1854
  return null;
1449
1855
  }
1450
1856
  }
@@ -1456,19 +1862,19 @@ class MiawClient extends events_1.EventEmitter {
1456
1862
  async revokeGroupInvite(groupJid) {
1457
1863
  try {
1458
1864
  if (!this.socket) {
1459
- throw new Error('Not connected. Call connect() first.');
1865
+ throw new Error("Not connected. Call connect() first.");
1460
1866
  }
1461
- if (this.connectionState !== 'connected') {
1867
+ if (this.connectionState !== "connected") {
1462
1868
  throw new Error(`Cannot revoke invite. Connection state: ${this.connectionState}`);
1463
1869
  }
1464
- if (!groupJid.endsWith('@g.us')) {
1465
- throw new Error('Invalid group JID. Must end with @g.us');
1870
+ if (!groupJid.endsWith("@g.us")) {
1871
+ throw new Error("Invalid group JID. Must end with @g.us");
1466
1872
  }
1467
1873
  const code = await this.socket.groupRevokeInvite(groupJid);
1468
1874
  return code ? `https://chat.whatsapp.com/${code}` : null;
1469
1875
  }
1470
1876
  catch (error) {
1471
- this.logger.error('Failed to revoke group invite:', error);
1877
+ this.logger.error("Failed to revoke group invite:", error);
1472
1878
  return null;
1473
1879
  }
1474
1880
  }
@@ -1480,21 +1886,21 @@ class MiawClient extends events_1.EventEmitter {
1480
1886
  async acceptGroupInvite(inviteCode) {
1481
1887
  try {
1482
1888
  if (!this.socket) {
1483
- throw new Error('Not connected. Call connect() first.');
1889
+ throw new Error("Not connected. Call connect() first.");
1484
1890
  }
1485
- if (this.connectionState !== 'connected') {
1891
+ if (this.connectionState !== "connected") {
1486
1892
  throw new Error(`Cannot accept invite. Connection state: ${this.connectionState}`);
1487
1893
  }
1488
1894
  // Extract code from URL if full URL was provided
1489
1895
  let code = inviteCode;
1490
- if (inviteCode.includes('chat.whatsapp.com/')) {
1491
- code = inviteCode.split('chat.whatsapp.com/')[1];
1896
+ if (inviteCode.includes("chat.whatsapp.com/")) {
1897
+ code = inviteCode.split("chat.whatsapp.com/")[1];
1492
1898
  }
1493
1899
  const groupJid = await this.socket.groupAcceptInvite(code);
1494
1900
  return groupJid || null;
1495
1901
  }
1496
1902
  catch (error) {
1497
- this.logger.error('Failed to accept group invite:', error);
1903
+ this.logger.error("Failed to accept group invite:", error);
1498
1904
  return null;
1499
1905
  }
1500
1906
  }
@@ -1506,15 +1912,15 @@ class MiawClient extends events_1.EventEmitter {
1506
1912
  async getGroupInviteInfo(inviteCode) {
1507
1913
  try {
1508
1914
  if (!this.socket) {
1509
- throw new Error('Not connected. Call connect() first.');
1915
+ throw new Error("Not connected. Call connect() first.");
1510
1916
  }
1511
- if (this.connectionState !== 'connected') {
1917
+ if (this.connectionState !== "connected") {
1512
1918
  throw new Error(`Cannot get invite info. Connection state: ${this.connectionState}`);
1513
1919
  }
1514
1920
  // Extract code from URL if full URL was provided
1515
1921
  let code = inviteCode;
1516
- if (inviteCode.includes('chat.whatsapp.com/')) {
1517
- code = inviteCode.split('chat.whatsapp.com/')[1];
1922
+ if (inviteCode.includes("chat.whatsapp.com/")) {
1923
+ code = inviteCode.split("chat.whatsapp.com/")[1];
1518
1924
  }
1519
1925
  const metadata = await this.socket.groupGetInviteInfo(code);
1520
1926
  return {
@@ -1526,7 +1932,7 @@ class MiawClient extends events_1.EventEmitter {
1526
1932
  };
1527
1933
  }
1528
1934
  catch (error) {
1529
- this.logger.error('Failed to get group invite info:', error);
1935
+ this.logger.error("Failed to get group invite info:", error);
1530
1936
  return null;
1531
1937
  }
1532
1938
  }
@@ -1541,21 +1947,21 @@ class MiawClient extends events_1.EventEmitter {
1541
1947
  async updateProfilePicture(image) {
1542
1948
  try {
1543
1949
  if (!this.socket) {
1544
- throw new Error('Not connected. Call connect() first.');
1950
+ throw new Error("Not connected. Call connect() first.");
1545
1951
  }
1546
- if (this.connectionState !== 'connected') {
1952
+ if (this.connectionState !== "connected") {
1547
1953
  throw new Error(`Cannot update profile picture. Connection state: ${this.connectionState}`);
1548
1954
  }
1549
1955
  const userJid = this.socket.user?.id;
1550
1956
  if (!userJid) {
1551
- throw new Error('User JID not available');
1957
+ throw new Error("User JID not available");
1552
1958
  }
1553
1959
  const imageContent = Buffer.isBuffer(image) ? image : { url: image };
1554
1960
  await this.socket.updateProfilePicture(userJid, imageContent);
1555
1961
  return { success: true };
1556
1962
  }
1557
1963
  catch (error) {
1558
- this.logger.error('Failed to update profile picture:', error);
1964
+ this.logger.error("Failed to update profile picture:", error);
1559
1965
  return {
1560
1966
  success: false,
1561
1967
  error: error.message,
@@ -1569,20 +1975,20 @@ class MiawClient extends events_1.EventEmitter {
1569
1975
  async removeProfilePicture() {
1570
1976
  try {
1571
1977
  if (!this.socket) {
1572
- throw new Error('Not connected. Call connect() first.');
1978
+ throw new Error("Not connected. Call connect() first.");
1573
1979
  }
1574
- if (this.connectionState !== 'connected') {
1980
+ if (this.connectionState !== "connected") {
1575
1981
  throw new Error(`Cannot remove profile picture. Connection state: ${this.connectionState}`);
1576
1982
  }
1577
1983
  const userJid = this.socket.user?.id;
1578
1984
  if (!userJid) {
1579
- throw new Error('User JID not available');
1985
+ throw new Error("User JID not available");
1580
1986
  }
1581
1987
  await this.socket.removeProfilePicture(userJid);
1582
1988
  return { success: true };
1583
1989
  }
1584
1990
  catch (error) {
1585
- this.logger.error('Failed to remove profile picture:', error);
1991
+ this.logger.error("Failed to remove profile picture:", error);
1586
1992
  return {
1587
1993
  success: false,
1588
1994
  error: error.message,
@@ -1597,19 +2003,19 @@ class MiawClient extends events_1.EventEmitter {
1597
2003
  async updateProfileName(name) {
1598
2004
  try {
1599
2005
  if (!this.socket) {
1600
- throw new Error('Not connected. Call connect() first.');
2006
+ throw new Error("Not connected. Call connect() first.");
1601
2007
  }
1602
- if (this.connectionState !== 'connected') {
2008
+ if (this.connectionState !== "connected") {
1603
2009
  throw new Error(`Cannot update profile name. Connection state: ${this.connectionState}`);
1604
2010
  }
1605
2011
  if (!name || name.trim().length === 0) {
1606
- throw new Error('Profile name cannot be empty');
2012
+ throw new Error("Profile name cannot be empty");
1607
2013
  }
1608
2014
  await this.socket.updateProfileName(name);
1609
2015
  return { success: true };
1610
2016
  }
1611
2017
  catch (error) {
1612
- this.logger.error('Failed to update profile name:', error);
2018
+ this.logger.error("Failed to update profile name:", error);
1613
2019
  return {
1614
2020
  success: false,
1615
2021
  error: error.message,
@@ -1624,16 +2030,16 @@ class MiawClient extends events_1.EventEmitter {
1624
2030
  async updateProfileStatus(status) {
1625
2031
  try {
1626
2032
  if (!this.socket) {
1627
- throw new Error('Not connected. Call connect() first.');
2033
+ throw new Error("Not connected. Call connect() first.");
1628
2034
  }
1629
- if (this.connectionState !== 'connected') {
2035
+ if (this.connectionState !== "connected") {
1630
2036
  throw new Error(`Cannot update profile status. Connection state: ${this.connectionState}`);
1631
2037
  }
1632
2038
  await this.socket.updateProfileStatus(status);
1633
2039
  return { success: true };
1634
2040
  }
1635
2041
  catch (error) {
1636
- this.logger.error('Failed to update profile status:', error);
2042
+ this.logger.error("Failed to update profile status:", error);
1637
2043
  return {
1638
2044
  success: false,
1639
2045
  error: error.message,
@@ -1652,14 +2058,19 @@ class MiawClient extends events_1.EventEmitter {
1652
2058
  async addLabel(label) {
1653
2059
  try {
1654
2060
  if (!this.socket) {
1655
- throw new Error('Not connected. Call connect() first.');
2061
+ throw new Error("Not connected. Call connect() first.");
1656
2062
  }
1657
- if (this.connectionState !== 'connected') {
2063
+ if (this.connectionState !== "connected") {
1658
2064
  throw new Error(`Cannot add label. Connection state: ${this.connectionState}`);
1659
2065
  }
2066
+ // Generate a unique label ID if not provided
2067
+ // WhatsApp Business labels use numeric string IDs starting from 6 (1-5 are predefined)
2068
+ // We use timestamp + random suffix to ensure uniqueness
2069
+ const labelId = label.id ||
2070
+ `${Date.now().toString().slice(-8)}${Math.floor(Math.random() * 1000)}`;
1660
2071
  // Build label action body
1661
2072
  const labelAction = {
1662
- id: label.id,
2073
+ id: labelId,
1663
2074
  name: label.name,
1664
2075
  color: label.color,
1665
2076
  deleted: label.deleted ?? false,
@@ -1668,14 +2079,23 @@ class MiawClient extends events_1.EventEmitter {
1668
2079
  labelAction.predefinedId = label.predefinedId;
1669
2080
  }
1670
2081
  // Use empty string JID for label creation (affects account, not a specific chat)
1671
- await this.socket.addLabel('', labelAction);
2082
+ await this.socket.addLabel("", labelAction);
2083
+ // Store label in labelsStore immediately (don't wait for event)
2084
+ const labelData = {
2085
+ id: labelId,
2086
+ name: label.name,
2087
+ color: label.color,
2088
+ predefinedId: label.predefinedId,
2089
+ deleted: false,
2090
+ };
2091
+ this.labelsStore.set(labelId, labelData);
1672
2092
  return {
1673
2093
  success: true,
1674
- labelId: label.id,
2094
+ labelId: labelId,
1675
2095
  };
1676
2096
  }
1677
2097
  catch (error) {
1678
- this.logger.error('Failed to add label:', error);
2098
+ this.logger.error("Failed to add label:", error);
1679
2099
  return {
1680
2100
  success: false,
1681
2101
  error: error.message,
@@ -1692,17 +2112,17 @@ class MiawClient extends events_1.EventEmitter {
1692
2112
  async addChatLabel(chatJidOrPhone, labelId) {
1693
2113
  try {
1694
2114
  if (!this.socket) {
1695
- throw new Error('Not connected. Call connect() first.');
2115
+ throw new Error("Not connected. Call connect() first.");
1696
2116
  }
1697
- if (this.connectionState !== 'connected') {
2117
+ if (this.connectionState !== "connected") {
1698
2118
  throw new Error(`Cannot add chat label. Connection state: ${this.connectionState}`);
1699
2119
  }
1700
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(chatJidOrPhone);
2120
+ const jid = MessageHandler.formatPhoneToJid(chatJidOrPhone);
1701
2121
  await this.socket.addChatLabel(jid, labelId);
1702
2122
  return { success: true };
1703
2123
  }
1704
2124
  catch (error) {
1705
- this.logger.error('Failed to add chat label:', error);
2125
+ this.logger.error("Failed to add chat label:", error);
1706
2126
  return {
1707
2127
  success: false,
1708
2128
  error: error.message,
@@ -1719,17 +2139,17 @@ class MiawClient extends events_1.EventEmitter {
1719
2139
  async removeChatLabel(chatJidOrPhone, labelId) {
1720
2140
  try {
1721
2141
  if (!this.socket) {
1722
- throw new Error('Not connected. Call connect() first.');
2142
+ throw new Error("Not connected. Call connect() first.");
1723
2143
  }
1724
- if (this.connectionState !== 'connected') {
2144
+ if (this.connectionState !== "connected") {
1725
2145
  throw new Error(`Cannot remove chat label. Connection state: ${this.connectionState}`);
1726
2146
  }
1727
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(chatJidOrPhone);
2147
+ const jid = MessageHandler.formatPhoneToJid(chatJidOrPhone);
1728
2148
  await this.socket.removeChatLabel(jid, labelId);
1729
2149
  return { success: true };
1730
2150
  }
1731
2151
  catch (error) {
1732
- this.logger.error('Failed to remove chat label:', error);
2152
+ this.logger.error("Failed to remove chat label:", error);
1733
2153
  return {
1734
2154
  success: false,
1735
2155
  error: error.message,
@@ -1747,17 +2167,17 @@ class MiawClient extends events_1.EventEmitter {
1747
2167
  async addMessageLabel(chatJidOrPhone, messageId, labelId) {
1748
2168
  try {
1749
2169
  if (!this.socket) {
1750
- throw new Error('Not connected. Call connect() first.');
2170
+ throw new Error("Not connected. Call connect() first.");
1751
2171
  }
1752
- if (this.connectionState !== 'connected') {
2172
+ if (this.connectionState !== "connected") {
1753
2173
  throw new Error(`Cannot add message label. Connection state: ${this.connectionState}`);
1754
2174
  }
1755
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(chatJidOrPhone);
2175
+ const jid = MessageHandler.formatPhoneToJid(chatJidOrPhone);
1756
2176
  await this.socket.addMessageLabel(jid, messageId, labelId);
1757
2177
  return { success: true };
1758
2178
  }
1759
2179
  catch (error) {
1760
- this.logger.error('Failed to add message label:', error);
2180
+ this.logger.error("Failed to add message label:", error);
1761
2181
  return {
1762
2182
  success: false,
1763
2183
  error: error.message,
@@ -1775,17 +2195,17 @@ class MiawClient extends events_1.EventEmitter {
1775
2195
  async removeMessageLabel(chatJidOrPhone, messageId, labelId) {
1776
2196
  try {
1777
2197
  if (!this.socket) {
1778
- throw new Error('Not connected. Call connect() first.');
2198
+ throw new Error("Not connected. Call connect() first.");
1779
2199
  }
1780
- if (this.connectionState !== 'connected') {
2200
+ if (this.connectionState !== "connected") {
1781
2201
  throw new Error(`Cannot remove message label. Connection state: ${this.connectionState}`);
1782
2202
  }
1783
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(chatJidOrPhone);
2203
+ const jid = MessageHandler.formatPhoneToJid(chatJidOrPhone);
1784
2204
  await this.socket.removeMessageLabel(jid, messageId, labelId);
1785
2205
  return { success: true };
1786
2206
  }
1787
2207
  catch (error) {
1788
- this.logger.error('Failed to remove message label:', error);
2208
+ this.logger.error("Failed to remove message label:", error);
1789
2209
  return {
1790
2210
  success: false,
1791
2211
  error: error.message,
@@ -1801,28 +2221,32 @@ class MiawClient extends events_1.EventEmitter {
1801
2221
  * @param limit - Maximum number of products to fetch (default: 10)
1802
2222
  * @param cursor - Pagination cursor for fetching next page
1803
2223
  * @returns ProductCatalog
1804
- * @note Requires WhatsApp Business account
2224
+ * @note Requires WhatsApp Business account with catalog configured
1805
2225
  */
1806
2226
  async getCatalog(businessJidOrPhone, limit = 10, cursor) {
1807
2227
  try {
1808
2228
  if (!this.socket) {
1809
- throw new Error('Not connected. Call connect() first.');
2229
+ throw new Error("Not connected. Call connect() first.");
1810
2230
  }
1811
- if (this.connectionState !== 'connected') {
2231
+ if (this.connectionState !== "connected") {
1812
2232
  throw new Error(`Cannot get catalog. Connection state: ${this.connectionState}`);
1813
2233
  }
1814
- const jid = businessJidOrPhone ? MessageHandler_1.MessageHandler.formatPhoneToJid(businessJidOrPhone) : undefined;
2234
+ const jid = businessJidOrPhone
2235
+ ? MessageHandler.formatPhoneToJid(businessJidOrPhone)
2236
+ : undefined;
1815
2237
  const result = await this.socket.getCatalog({ jid, limit, cursor });
2238
+ // Map Baileys product format to our Product type
2239
+ // Baileys returns: id, name, description, price, currency, retailerId, url, isHidden, imageUrls
1816
2240
  const products = (result.products || []).map((p) => ({
1817
2241
  id: p.id,
1818
2242
  name: p.name,
1819
2243
  description: p.description,
1820
- priceAmount1000: p.priceAmount1000,
2244
+ price: p.price,
2245
+ currency: p.currency,
1821
2246
  retailerId: p.retailerId,
1822
2247
  url: p.url,
1823
2248
  isHidden: p.isHidden,
1824
- images: p.images?.map((img) => ({ url: img.url, caption: img.caption })) || [],
1825
- count: p.count,
2249
+ imageUrls: p.imageUrls || {},
1826
2250
  }));
1827
2251
  return {
1828
2252
  success: true,
@@ -1831,10 +2255,15 @@ class MiawClient extends events_1.EventEmitter {
1831
2255
  };
1832
2256
  }
1833
2257
  catch (error) {
1834
- this.logger.error('Failed to get catalog:', error);
2258
+ this.logger.error("Failed to get catalog:", error);
2259
+ // Provide more helpful error message
2260
+ const errorMsg = error.message;
2261
+ const helpfulError = errorMsg.includes("biz:catalog")
2262
+ ? "Catalog not available. Ensure this is a WhatsApp Business account with catalog enabled."
2263
+ : errorMsg;
1835
2264
  return {
1836
2265
  success: false,
1837
- error: error.message,
2266
+ error: helpfulError,
1838
2267
  };
1839
2268
  }
1840
2269
  }
@@ -1843,17 +2272,20 @@ class MiawClient extends events_1.EventEmitter {
1843
2272
  * @param businessJidOrPhone - Business JID or phone number (default: your own collections)
1844
2273
  * @param limit - Maximum number of collections to fetch (default: 51)
1845
2274
  * @returns Array of ProductCollection
1846
- * @note Requires WhatsApp Business account
2275
+ * @note Requires WhatsApp Business account with collections created via the catalog API.
2276
+ * Collections created in the WhatsApp Business app may not appear here.
1847
2277
  */
1848
2278
  async getCollections(businessJidOrPhone, limit = 51) {
1849
2279
  try {
1850
2280
  if (!this.socket) {
1851
- throw new Error('Not connected. Call connect() first.');
2281
+ throw new Error("Not connected. Call connect() first.");
1852
2282
  }
1853
- if (this.connectionState !== 'connected') {
2283
+ if (this.connectionState !== "connected") {
1854
2284
  throw new Error(`Cannot get collections. Connection state: ${this.connectionState}`);
1855
2285
  }
1856
- const jid = businessJidOrPhone ? MessageHandler_1.MessageHandler.formatPhoneToJid(businessJidOrPhone) : undefined;
2286
+ const jid = businessJidOrPhone
2287
+ ? MessageHandler.formatPhoneToJid(businessJidOrPhone)
2288
+ : undefined;
1857
2289
  const result = await this.socket.getCollections(jid, limit);
1858
2290
  return (result.collections || []).map((col) => ({
1859
2291
  id: col.id,
@@ -1863,48 +2295,59 @@ class MiawClient extends events_1.EventEmitter {
1863
2295
  name: p.name,
1864
2296
  priceAmount1000: p.priceAmount1000,
1865
2297
  retailerId: p.retailerId,
1866
- images: p.images?.map((img) => ({ url: img.url, caption: img.caption })) || [],
2298
+ images: p.images?.map((img) => ({
2299
+ url: img.url,
2300
+ caption: img.caption,
2301
+ })) || [],
1867
2302
  })),
1868
2303
  }));
1869
2304
  }
1870
2305
  catch (error) {
1871
- this.logger.error('Failed to get collections:', error);
2306
+ this.logger.error("Failed to get collections:", error);
1872
2307
  return [];
1873
2308
  }
1874
2309
  }
1875
2310
  /**
1876
2311
  * Create a new product in the catalog
1877
- * @param options - Product options (name, price, images, etc.)
2312
+ * @param options - Product options (name, price, currency, images, etc.)
1878
2313
  * @returns ProductOperationResult with product ID
1879
- * @note Requires WhatsApp Business account
2314
+ * @note Requires WhatsApp Business account with catalog enabled
1880
2315
  */
1881
2316
  async createProduct(options) {
1882
2317
  try {
1883
2318
  if (!this.socket) {
1884
- throw new Error('Not connected. Call connect() first.');
2319
+ throw new Error("Not connected. Call connect() first.");
1885
2320
  }
1886
- if (this.connectionState !== 'connected') {
2321
+ if (this.connectionState !== "connected") {
1887
2322
  throw new Error(`Cannot create product. Connection state: ${this.connectionState}`);
1888
2323
  }
1889
- // Convert price from smallest unit to Baileys format (multiply by 1000)
1890
- const priceAmount1000 = options.price * 10;
2324
+ // Build images array from either buffers or URLs
2325
+ // Buffers are recommended for reliability (URLs require WhatsApp servers to fetch)
2326
+ const images = [];
2327
+ // Prefer buffers if provided (more reliable)
2328
+ if (options.imageBuffers && options.imageBuffers.length > 0) {
2329
+ images.push(...options.imageBuffers);
2330
+ }
2331
+ else if (options.imageUrls && options.imageUrls.length > 0) {
2332
+ // Fall back to URLs (must be publicly accessible)
2333
+ images.push(...options.imageUrls.map((url) => ({ url: new URL(url) })));
2334
+ }
2335
+ // Build product data matching Baileys' ProductCreate format
1891
2336
  const productData = {
1892
2337
  name: options.name,
1893
- priceAmount1000,
2338
+ description: options.description,
2339
+ price: options.price,
2340
+ currency: options.currency,
1894
2341
  isHidden: options.isHidden ?? false,
2342
+ originCountryCode: options.originCountryCode,
2343
+ images,
1895
2344
  };
1896
- if (options.description) {
1897
- productData.description = options.description;
1898
- }
1899
2345
  if (options.retailerId) {
1900
2346
  productData.retailerId = options.retailerId;
1901
2347
  }
1902
2348
  if (options.url) {
1903
2349
  productData.url = options.url;
1904
2350
  }
1905
- if (options.imageUrls && options.imageUrls.length > 0) {
1906
- productData.images = options.imageUrls.map((url) => ({ url }));
1907
- }
1908
2351
  const result = await this.socket.productCreate(productData);
1909
2352
  return {
1910
2353
  success: true,
@@ -1912,7 +2355,7 @@ class MiawClient extends events_1.EventEmitter {
1912
2355
  };
1913
2356
  }
1914
2357
  catch (error) {
1915
- this.logger.error('Failed to create product:', error);
2358
+ this.logger.error("Failed to create product:", error);
1916
2359
  return {
1917
2360
  success: false,
1918
2361
  error: error.message,
@@ -1922,41 +2365,44 @@ class MiawClient extends events_1.EventEmitter {
1922
2365
  /**
1923
2366
  * Update an existing product in the catalog
1924
2367
  * @param productId - Product ID to update
1925
- * @param options - Product options (name, price, images, etc.)
2368
+ * @param options - Product options (name, price, currency, images, etc.)
1926
2369
  * @returns ProductOperationResult
1927
- * @note Requires WhatsApp Business account
2370
+ * @note Requires WhatsApp Business account with catalog enabled
1928
2371
  */
1929
2372
  async updateProduct(productId, options) {
1930
2373
  try {
1931
2374
  if (!this.socket) {
1932
- throw new Error('Not connected. Call connect() first.');
2375
+ throw new Error("Not connected. Call connect() first.");
1933
2376
  }
1934
- if (this.connectionState !== 'connected') {
2377
+ if (this.connectionState !== "connected") {
1935
2378
  throw new Error(`Cannot update product. Connection state: ${this.connectionState}`);
1936
2379
  }
1937
- // Convert price from smallest unit to Baileys format (multiply by 1000)
1938
- const priceAmount1000 = options.price * 10;
1939
- const productData = {
1940
- priceAmount1000,
1941
- };
1942
- if (options.name) {
1943
- productData.name = options.name;
1944
- }
1945
- if (options.description !== undefined) {
1946
- productData.description = options.description;
2380
+ // Build images array from either buffers or URLs
2381
+ // Buffers are recommended for reliability (URLs require WhatsApp servers to fetch)
2382
+ const images = [];
2383
+ // Prefer buffers if provided (more reliable)
2384
+ if (options.imageBuffers && options.imageBuffers.length > 0) {
2385
+ images.push(...options.imageBuffers);
1947
2386
  }
1948
- if (options.isHidden !== undefined) {
1949
- productData.isHidden = options.isHidden;
2387
+ else if (options.imageUrls && options.imageUrls.length > 0) {
2388
+ // Fall back to URLs (must be publicly accessible)
2389
+ images.push(...options.imageUrls.map((url) => ({ url: new URL(url) })));
1950
2390
  }
2391
+ // Build product data matching Baileys' ProductUpdate format
2392
+ const productData = {
2393
+ name: options.name,
2394
+ description: options.description,
2395
+ price: options.price,
2396
+ currency: options.currency,
2397
+ isHidden: options.isHidden,
2398
+ images,
2399
+ };
1951
2400
  if (options.retailerId) {
1952
2401
  productData.retailerId = options.retailerId;
1953
2402
  }
1954
2403
  if (options.url) {
1955
2404
  productData.url = options.url;
1956
2405
  }
1957
- if (options.imageUrls && options.imageUrls.length > 0) {
1958
- productData.images = options.imageUrls.map((url) => ({ url }));
1959
- }
1960
2406
  const result = await this.socket.productUpdate(productId, productData);
1961
2407
  return {
1962
2408
  success: true,
@@ -1964,7 +2410,7 @@ class MiawClient extends events_1.EventEmitter {
1964
2410
  };
1965
2411
  }
1966
2412
  catch (error) {
1967
- this.logger.error('Failed to update product:', error);
2413
+ this.logger.error("Failed to update product:", error);
1968
2414
  return {
1969
2415
  success: false,
1970
2416
  error: error.message,
@@ -1980,13 +2426,13 @@ class MiawClient extends events_1.EventEmitter {
1980
2426
  async deleteProducts(productIds) {
1981
2427
  try {
1982
2428
  if (!this.socket) {
1983
- throw new Error('Not connected. Call connect() first.');
2429
+ throw new Error("Not connected. Call connect() first.");
1984
2430
  }
1985
- if (this.connectionState !== 'connected') {
2431
+ if (this.connectionState !== "connected") {
1986
2432
  throw new Error(`Cannot delete products. Connection state: ${this.connectionState}`);
1987
2433
  }
1988
2434
  if (productIds.length === 0) {
1989
- throw new Error('At least one product ID is required');
2435
+ throw new Error("At least one product ID is required");
1990
2436
  }
1991
2437
  const result = await this.socket.productDelete(productIds);
1992
2438
  return {
@@ -1995,7 +2441,7 @@ class MiawClient extends events_1.EventEmitter {
1995
2441
  };
1996
2442
  }
1997
2443
  catch (error) {
1998
- this.logger.error('Failed to delete products:', error);
2444
+ this.logger.error("Failed to delete products:", error);
1999
2445
  return {
2000
2446
  success: false,
2001
2447
  error: error.message,
@@ -2005,6 +2451,113 @@ class MiawClient extends events_1.EventEmitter {
2005
2451
  // ============================================
2006
2452
  // Newsletter/Channel Methods (v0.9.0)
2007
2453
  // ============================================
2454
+ /**
2455
+ * Send a text message to a newsletter/channel
2456
+ * @param newsletterId - Newsletter JID (e.g., '1234567890@newsletter')
2457
+ * @param text - Message text content
2458
+ * @returns SendMessageResult
2459
+ * @note You must be an admin/owner of the newsletter to send messages
2460
+ */
2461
+ async sendNewsletterMessage(newsletterId, text) {
2462
+ try {
2463
+ if (!this.socket) {
2464
+ throw new Error("Not connected. Call connect() first.");
2465
+ }
2466
+ if (this.connectionState !== "connected") {
2467
+ throw new Error(`Cannot send newsletter message. Connection state: ${this.connectionState}`);
2468
+ }
2469
+ if (!newsletterId.endsWith("@newsletter")) {
2470
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2471
+ }
2472
+ // Baileys sendMessage handles newsletter JIDs automatically
2473
+ const result = await this.socket.sendMessage(newsletterId, { text });
2474
+ return {
2475
+ success: true,
2476
+ messageId: result?.key?.id ?? undefined,
2477
+ };
2478
+ }
2479
+ catch (error) {
2480
+ this.logger.error("Failed to send newsletter message:", error);
2481
+ return {
2482
+ success: false,
2483
+ error: error.message,
2484
+ };
2485
+ }
2486
+ }
2487
+ /**
2488
+ * Send an image to a newsletter/channel
2489
+ * @param newsletterId - Newsletter JID (e.g., '1234567890@newsletter')
2490
+ * @param image - Image source (file path, URL, or Buffer)
2491
+ * @param caption - Optional caption
2492
+ * @returns SendMessageResult
2493
+ * @note You must be an admin/owner of the newsletter to send messages
2494
+ */
2495
+ async sendNewsletterImage(newsletterId, image, caption) {
2496
+ try {
2497
+ if (!this.socket) {
2498
+ throw new Error("Not connected. Call connect() first.");
2499
+ }
2500
+ if (this.connectionState !== "connected") {
2501
+ throw new Error(`Cannot send newsletter image. Connection state: ${this.connectionState}`);
2502
+ }
2503
+ if (!newsletterId.endsWith("@newsletter")) {
2504
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2505
+ }
2506
+ const imageContent = Buffer.isBuffer(image) ? image : { url: image };
2507
+ const result = await this.socket.sendMessage(newsletterId, {
2508
+ image: imageContent,
2509
+ caption,
2510
+ });
2511
+ return {
2512
+ success: true,
2513
+ messageId: result?.key?.id ?? undefined,
2514
+ };
2515
+ }
2516
+ catch (error) {
2517
+ this.logger.error("Failed to send newsletter image:", error);
2518
+ return {
2519
+ success: false,
2520
+ error: error.message,
2521
+ };
2522
+ }
2523
+ }
2524
+ /**
2525
+ * Send a video to a newsletter/channel
2526
+ * @param newsletterId - Newsletter JID (e.g., '1234567890@newsletter')
2527
+ * @param video - Video source (file path, URL, or Buffer)
2528
+ * @param caption - Optional caption
2529
+ * @returns SendMessageResult
2530
+ * @note You must be an admin/owner of the newsletter to send messages
2531
+ */
2532
+ async sendNewsletterVideo(newsletterId, video, caption) {
2533
+ try {
2534
+ if (!this.socket) {
2535
+ throw new Error("Not connected. Call connect() first.");
2536
+ }
2537
+ if (this.connectionState !== "connected") {
2538
+ throw new Error(`Cannot send newsletter video. Connection state: ${this.connectionState}`);
2539
+ }
2540
+ if (!newsletterId.endsWith("@newsletter")) {
2541
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2542
+ }
2543
+ const videoContent = Buffer.isBuffer(video) ? video : { url: video };
2544
+ const result = await this.socket.sendMessage(newsletterId, {
2545
+ video: videoContent,
2546
+ caption,
2547
+ });
2548
+ return {
2549
+ success: true,
2550
+ messageId: result?.key?.id ?? undefined,
2551
+ };
2552
+ }
2553
+ catch (error) {
2554
+ this.logger.error("Failed to send newsletter video:", error);
2555
+ return {
2556
+ success: false,
2557
+ error: error.message,
2558
+ };
2559
+ }
2560
+ }
2008
2561
  /**
2009
2562
  * Create a new newsletter/channel
2010
2563
  * @param name - Newsletter name
@@ -2014,22 +2567,56 @@ class MiawClient extends events_1.EventEmitter {
2014
2567
  async createNewsletter(name, description) {
2015
2568
  try {
2016
2569
  if (!this.socket) {
2017
- throw new Error('Not connected. Call connect() first.');
2570
+ throw new Error("Not connected. Call connect() first.");
2018
2571
  }
2019
- if (this.connectionState !== 'connected') {
2572
+ if (this.connectionState !== "connected") {
2020
2573
  throw new Error(`Cannot create newsletter. Connection state: ${this.connectionState}`);
2021
2574
  }
2022
- const result = await this.socket.newsletterCreate(name, description || '');
2575
+ // Baileys newsletterCreate returns NewsletterMetadata with id property
2576
+ const result = await this.socket.newsletterCreate(name, description || "");
2577
+ // Debug log the result structure
2578
+ this.logger.debug("Newsletter create result:", result);
2579
+ // Baileys returns NewsletterMetadata from parseNewsletterCreateResponse
2580
+ // The id is directly on the result object
2581
+ if (result && typeof result === "object" && "id" in result) {
2582
+ const newsletterId = result.id;
2583
+ if (newsletterId) {
2584
+ return {
2585
+ success: true,
2586
+ newsletterId,
2587
+ };
2588
+ }
2589
+ }
2590
+ // Handle unexpected response format
2591
+ // The newsletter may have been created but response parsing failed
2592
+ this.logger.warn("Newsletter creation returned unexpected format:", JSON.stringify(result, null, 2));
2023
2593
  return {
2024
2594
  success: true,
2025
- newsletterId: result?.id,
2595
+ newsletterId: undefined,
2026
2596
  };
2027
2597
  }
2028
2598
  catch (error) {
2029
- this.logger.error('Failed to create newsletter:', error);
2599
+ const errorMessage = error.message;
2600
+ const errorStack = error.stack;
2601
+ // Log full error for debugging
2602
+ this.logger.debug("Newsletter creation error details:", {
2603
+ message: errorMessage,
2604
+ stack: errorStack,
2605
+ });
2606
+ // Check if this is a response parsing error (newsletter may have been created)
2607
+ // Baileys throws "Cannot read properties of null" when response format is unexpected
2608
+ if (errorMessage.includes("Cannot read properties of null") ||
2609
+ errorMessage.includes("Cannot read properties of undefined")) {
2610
+ this.logger.warn("Newsletter may have been created but response parsing failed:", errorMessage);
2611
+ return {
2612
+ success: true,
2613
+ newsletterId: undefined,
2614
+ };
2615
+ }
2616
+ this.logger.error("Failed to create newsletter:", error);
2030
2617
  return {
2031
2618
  success: false,
2032
- error: error.message,
2619
+ error: errorMessage,
2033
2620
  };
2034
2621
  }
2035
2622
  }
@@ -2041,23 +2628,23 @@ class MiawClient extends events_1.EventEmitter {
2041
2628
  async getNewsletterMetadata(newsletterId) {
2042
2629
  try {
2043
2630
  if (!this.socket) {
2044
- throw new Error('Not connected. Call connect() first.');
2631
+ throw new Error("Not connected. Call connect() first.");
2045
2632
  }
2046
- if (this.connectionState !== 'connected') {
2633
+ if (this.connectionState !== "connected") {
2047
2634
  throw new Error(`Cannot get newsletter metadata. Connection state: ${this.connectionState}`);
2048
2635
  }
2049
- if (!newsletterId.endsWith('@newsletter')) {
2050
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
2636
+ if (!newsletterId.endsWith("@newsletter")) {
2637
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2051
2638
  }
2052
- const meta = await this.socket.newsletterMetadata('jid', newsletterId);
2639
+ const meta = await this.socket.newsletterMetadata("jid", newsletterId);
2053
2640
  if (!meta) {
2054
2641
  return null;
2055
2642
  }
2056
2643
  // Extract picture URL from the picture object if available
2057
- const pictureUrl = typeof meta.picture === 'string' ? meta.picture : meta.picture?.url;
2644
+ const pictureUrl = typeof meta.picture === "string" ? meta.picture : meta.picture?.url;
2058
2645
  return {
2059
2646
  id: meta.id || newsletterId,
2060
- name: meta.name || '',
2647
+ name: meta.name || "",
2061
2648
  description: meta.description,
2062
2649
  pictureUrl,
2063
2650
  subscribers: meta.subscribers,
@@ -2069,7 +2656,7 @@ class MiawClient extends events_1.EventEmitter {
2069
2656
  };
2070
2657
  }
2071
2658
  catch (error) {
2072
- this.logger.error('Failed to get newsletter metadata:', error);
2659
+ this.logger.error("Failed to get newsletter metadata:", error);
2073
2660
  return null;
2074
2661
  }
2075
2662
  }
@@ -2081,19 +2668,19 @@ class MiawClient extends events_1.EventEmitter {
2081
2668
  async followNewsletter(newsletterId) {
2082
2669
  try {
2083
2670
  if (!this.socket) {
2084
- throw new Error('Not connected. Call connect() first.');
2671
+ throw new Error("Not connected. Call connect() first.");
2085
2672
  }
2086
- if (this.connectionState !== 'connected') {
2673
+ if (this.connectionState !== "connected") {
2087
2674
  throw new Error(`Cannot follow newsletter. Connection state: ${this.connectionState}`);
2088
2675
  }
2089
- if (!newsletterId.endsWith('@newsletter')) {
2090
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
2676
+ if (!newsletterId.endsWith("@newsletter")) {
2677
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2091
2678
  }
2092
2679
  await this.socket.newsletterFollow(newsletterId);
2093
2680
  return true;
2094
2681
  }
2095
2682
  catch (error) {
2096
- this.logger.error('Failed to follow newsletter:', error);
2683
+ this.logger.error("Failed to follow newsletter:", error);
2097
2684
  return false;
2098
2685
  }
2099
2686
  }
@@ -2105,19 +2692,19 @@ class MiawClient extends events_1.EventEmitter {
2105
2692
  async unfollowNewsletter(newsletterId) {
2106
2693
  try {
2107
2694
  if (!this.socket) {
2108
- throw new Error('Not connected. Call connect() first.');
2695
+ throw new Error("Not connected. Call connect() first.");
2109
2696
  }
2110
- if (this.connectionState !== 'connected') {
2697
+ if (this.connectionState !== "connected") {
2111
2698
  throw new Error(`Cannot unfollow newsletter. Connection state: ${this.connectionState}`);
2112
2699
  }
2113
- if (!newsletterId.endsWith('@newsletter')) {
2114
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
2700
+ if (!newsletterId.endsWith("@newsletter")) {
2701
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2115
2702
  }
2116
2703
  await this.socket.newsletterUnfollow(newsletterId);
2117
2704
  return true;
2118
2705
  }
2119
2706
  catch (error) {
2120
- this.logger.error('Failed to unfollow newsletter:', error);
2707
+ this.logger.error("Failed to unfollow newsletter:", error);
2121
2708
  return false;
2122
2709
  }
2123
2710
  }
@@ -2129,19 +2716,19 @@ class MiawClient extends events_1.EventEmitter {
2129
2716
  async muteNewsletter(newsletterId) {
2130
2717
  try {
2131
2718
  if (!this.socket) {
2132
- throw new Error('Not connected. Call connect() first.');
2719
+ throw new Error("Not connected. Call connect() first.");
2133
2720
  }
2134
- if (this.connectionState !== 'connected') {
2721
+ if (this.connectionState !== "connected") {
2135
2722
  throw new Error(`Cannot mute newsletter. Connection state: ${this.connectionState}`);
2136
2723
  }
2137
- if (!newsletterId.endsWith('@newsletter')) {
2138
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
2724
+ if (!newsletterId.endsWith("@newsletter")) {
2725
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2139
2726
  }
2140
2727
  await this.socket.newsletterMute(newsletterId);
2141
2728
  return true;
2142
2729
  }
2143
2730
  catch (error) {
2144
- this.logger.error('Failed to mute newsletter:', error);
2731
+ this.logger.error("Failed to mute newsletter:", error);
2145
2732
  return false;
2146
2733
  }
2147
2734
  }
@@ -2153,19 +2740,19 @@ class MiawClient extends events_1.EventEmitter {
2153
2740
  async unmuteNewsletter(newsletterId) {
2154
2741
  try {
2155
2742
  if (!this.socket) {
2156
- throw new Error('Not connected. Call connect() first.');
2743
+ throw new Error("Not connected. Call connect() first.");
2157
2744
  }
2158
- if (this.connectionState !== 'connected') {
2745
+ if (this.connectionState !== "connected") {
2159
2746
  throw new Error(`Cannot unmute newsletter. Connection state: ${this.connectionState}`);
2160
2747
  }
2161
- if (!newsletterId.endsWith('@newsletter')) {
2162
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
2748
+ if (!newsletterId.endsWith("@newsletter")) {
2749
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2163
2750
  }
2164
2751
  await this.socket.newsletterUnmute(newsletterId);
2165
2752
  return true;
2166
2753
  }
2167
2754
  catch (error) {
2168
- this.logger.error('Failed to unmute newsletter:', error);
2755
+ this.logger.error("Failed to unmute newsletter:", error);
2169
2756
  return false;
2170
2757
  }
2171
2758
  }
@@ -2178,19 +2765,19 @@ class MiawClient extends events_1.EventEmitter {
2178
2765
  async updateNewsletterName(newsletterId, name) {
2179
2766
  try {
2180
2767
  if (!this.socket) {
2181
- throw new Error('Not connected. Call connect() first.');
2768
+ throw new Error("Not connected. Call connect() first.");
2182
2769
  }
2183
- if (this.connectionState !== 'connected') {
2770
+ if (this.connectionState !== "connected") {
2184
2771
  throw new Error(`Cannot update newsletter name. Connection state: ${this.connectionState}`);
2185
2772
  }
2186
- if (!newsletterId.endsWith('@newsletter')) {
2187
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
2773
+ if (!newsletterId.endsWith("@newsletter")) {
2774
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2188
2775
  }
2189
2776
  await this.socket.newsletterUpdateName(newsletterId, name);
2190
2777
  return true;
2191
2778
  }
2192
2779
  catch (error) {
2193
- this.logger.error('Failed to update newsletter name:', error);
2780
+ this.logger.error("Failed to update newsletter name:", error);
2194
2781
  return false;
2195
2782
  }
2196
2783
  }
@@ -2203,19 +2790,19 @@ class MiawClient extends events_1.EventEmitter {
2203
2790
  async updateNewsletterDescription(newsletterId, description) {
2204
2791
  try {
2205
2792
  if (!this.socket) {
2206
- throw new Error('Not connected. Call connect() first.');
2793
+ throw new Error("Not connected. Call connect() first.");
2207
2794
  }
2208
- if (this.connectionState !== 'connected') {
2795
+ if (this.connectionState !== "connected") {
2209
2796
  throw new Error(`Cannot update newsletter description. Connection state: ${this.connectionState}`);
2210
2797
  }
2211
- if (!newsletterId.endsWith('@newsletter')) {
2212
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
2798
+ if (!newsletterId.endsWith("@newsletter")) {
2799
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2213
2800
  }
2214
2801
  await this.socket.newsletterUpdateDescription(newsletterId, description);
2215
2802
  return true;
2216
2803
  }
2217
2804
  catch (error) {
2218
- this.logger.error('Failed to update newsletter description:', error);
2805
+ this.logger.error("Failed to update newsletter description:", error);
2219
2806
  return false;
2220
2807
  }
2221
2808
  }
@@ -2228,20 +2815,20 @@ class MiawClient extends events_1.EventEmitter {
2228
2815
  async updateNewsletterPicture(newsletterId, image) {
2229
2816
  try {
2230
2817
  if (!this.socket) {
2231
- throw new Error('Not connected. Call connect() first.');
2818
+ throw new Error("Not connected. Call connect() first.");
2232
2819
  }
2233
- if (this.connectionState !== 'connected') {
2820
+ if (this.connectionState !== "connected") {
2234
2821
  throw new Error(`Cannot update newsletter picture. Connection state: ${this.connectionState}`);
2235
2822
  }
2236
- if (!newsletterId.endsWith('@newsletter')) {
2237
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
2823
+ if (!newsletterId.endsWith("@newsletter")) {
2824
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2238
2825
  }
2239
2826
  const imageContent = Buffer.isBuffer(image) ? image : { url: image };
2240
2827
  await this.socket.newsletterUpdatePicture(newsletterId, imageContent);
2241
2828
  return true;
2242
2829
  }
2243
2830
  catch (error) {
2244
- this.logger.error('Failed to update newsletter picture:', error);
2831
+ this.logger.error("Failed to update newsletter picture:", error);
2245
2832
  return false;
2246
2833
  }
2247
2834
  }
@@ -2253,19 +2840,19 @@ class MiawClient extends events_1.EventEmitter {
2253
2840
  async removeNewsletterPicture(newsletterId) {
2254
2841
  try {
2255
2842
  if (!this.socket) {
2256
- throw new Error('Not connected. Call connect() first.');
2843
+ throw new Error("Not connected. Call connect() first.");
2257
2844
  }
2258
- if (this.connectionState !== 'connected') {
2845
+ if (this.connectionState !== "connected") {
2259
2846
  throw new Error(`Cannot remove newsletter picture. Connection state: ${this.connectionState}`);
2260
2847
  }
2261
- if (!newsletterId.endsWith('@newsletter')) {
2262
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
2848
+ if (!newsletterId.endsWith("@newsletter")) {
2849
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2263
2850
  }
2264
2851
  await this.socket.newsletterRemovePicture(newsletterId);
2265
2852
  return true;
2266
2853
  }
2267
2854
  catch (error) {
2268
- this.logger.error('Failed to remove newsletter picture:', error);
2855
+ this.logger.error("Failed to remove newsletter picture:", error);
2269
2856
  return false;
2270
2857
  }
2271
2858
  }
@@ -2279,19 +2866,19 @@ class MiawClient extends events_1.EventEmitter {
2279
2866
  async reactToNewsletterMessage(newsletterId, messageId, emoji) {
2280
2867
  try {
2281
2868
  if (!this.socket) {
2282
- throw new Error('Not connected. Call connect() first.');
2869
+ throw new Error("Not connected. Call connect() first.");
2283
2870
  }
2284
- if (this.connectionState !== 'connected') {
2871
+ if (this.connectionState !== "connected") {
2285
2872
  throw new Error(`Cannot react to newsletter message. Connection state: ${this.connectionState}`);
2286
2873
  }
2287
- if (!newsletterId.endsWith('@newsletter')) {
2288
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
2874
+ if (!newsletterId.endsWith("@newsletter")) {
2875
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2289
2876
  }
2290
2877
  await this.socket.newsletterReactMessage(newsletterId, messageId, emoji);
2291
2878
  return true;
2292
2879
  }
2293
2880
  catch (error) {
2294
- this.logger.error('Failed to react to newsletter message:', error);
2881
+ this.logger.error("Failed to react to newsletter message:", error);
2295
2882
  return false;
2296
2883
  }
2297
2884
  }
@@ -2306,22 +2893,26 @@ class MiawClient extends events_1.EventEmitter {
2306
2893
  async fetchNewsletterMessages(newsletterId, count = 50, since, after = 0) {
2307
2894
  try {
2308
2895
  if (!this.socket) {
2309
- throw new Error('Not connected. Call connect() first.');
2896
+ throw new Error("Not connected. Call connect() first.");
2310
2897
  }
2311
- if (this.connectionState !== 'connected') {
2898
+ if (this.connectionState !== "connected") {
2312
2899
  throw new Error(`Cannot fetch newsletter messages. Connection state: ${this.connectionState}`);
2313
2900
  }
2314
- if (!newsletterId.endsWith('@newsletter')) {
2315
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
2901
+ if (!newsletterId.endsWith("@newsletter")) {
2902
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2316
2903
  }
2317
2904
  const messages = await this.socket.newsletterFetchMessages(newsletterId, count, since || Date.now(), after);
2318
2905
  const normalizedMessages = (messages || []).map((msg) => ({
2319
- id: msg.key?.id || '',
2906
+ id: msg.key?.id || "",
2320
2907
  newsletterId,
2321
2908
  content: msg.message?.conversation || msg.message?.extendedTextMessage?.text,
2322
2909
  timestamp: msg.messageTimestamp || 0,
2323
2910
  mediaUrl: msg.message?.imageMessage?.url || msg.message?.videoMessage?.url,
2324
- mediaType: msg.message?.imageMessage ? 'image' : msg.message?.videoMessage ? 'video' : undefined,
2911
+ mediaType: msg.message?.imageMessage
2912
+ ? "image"
2913
+ : msg.message?.videoMessage
2914
+ ? "video"
2915
+ : undefined,
2325
2916
  }));
2326
2917
  return {
2327
2918
  success: true,
@@ -2329,7 +2920,7 @@ class MiawClient extends events_1.EventEmitter {
2329
2920
  };
2330
2921
  }
2331
2922
  catch (error) {
2332
- this.logger.error('Failed to fetch newsletter messages:', error);
2923
+ this.logger.error("Failed to fetch newsletter messages:", error);
2333
2924
  return {
2334
2925
  success: false,
2335
2926
  error: error.message,
@@ -2344,19 +2935,19 @@ class MiawClient extends events_1.EventEmitter {
2344
2935
  async subscribeNewsletterUpdates(newsletterId) {
2345
2936
  try {
2346
2937
  if (!this.socket) {
2347
- throw new Error('Not connected. Call connect() first.');
2938
+ throw new Error("Not connected. Call connect() first.");
2348
2939
  }
2349
- if (this.connectionState !== 'connected') {
2940
+ if (this.connectionState !== "connected") {
2350
2941
  throw new Error(`Cannot subscribe to newsletter updates. Connection state: ${this.connectionState}`);
2351
2942
  }
2352
- if (!newsletterId.endsWith('@newsletter')) {
2353
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
2943
+ if (!newsletterId.endsWith("@newsletter")) {
2944
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2354
2945
  }
2355
2946
  await this.socket.subscribeNewsletterUpdates(newsletterId);
2356
2947
  return true;
2357
2948
  }
2358
2949
  catch (error) {
2359
- this.logger.error('Failed to subscribe to newsletter updates:', error);
2950
+ this.logger.error("Failed to subscribe to newsletter updates:", error);
2360
2951
  return false;
2361
2952
  }
2362
2953
  }
@@ -2368,13 +2959,13 @@ class MiawClient extends events_1.EventEmitter {
2368
2959
  async getNewsletterSubscribers(newsletterId) {
2369
2960
  try {
2370
2961
  if (!this.socket) {
2371
- throw new Error('Not connected. Call connect() first.');
2962
+ throw new Error("Not connected. Call connect() first.");
2372
2963
  }
2373
- if (this.connectionState !== 'connected') {
2964
+ if (this.connectionState !== "connected") {
2374
2965
  throw new Error(`Cannot get newsletter subscribers. Connection state: ${this.connectionState}`);
2375
2966
  }
2376
- if (!newsletterId.endsWith('@newsletter')) {
2377
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
2967
+ if (!newsletterId.endsWith("@newsletter")) {
2968
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2378
2969
  }
2379
2970
  const result = await this.socket.newsletterSubscribers(newsletterId);
2380
2971
  return {
@@ -2383,7 +2974,7 @@ class MiawClient extends events_1.EventEmitter {
2383
2974
  };
2384
2975
  }
2385
2976
  catch (error) {
2386
- this.logger.error('Failed to get newsletter subscribers:', error);
2977
+ this.logger.error("Failed to get newsletter subscribers:", error);
2387
2978
  return null;
2388
2979
  }
2389
2980
  }
@@ -2395,19 +2986,19 @@ class MiawClient extends events_1.EventEmitter {
2395
2986
  async getNewsletterAdminCount(newsletterId) {
2396
2987
  try {
2397
2988
  if (!this.socket) {
2398
- throw new Error('Not connected. Call connect() first.');
2989
+ throw new Error("Not connected. Call connect() first.");
2399
2990
  }
2400
- if (this.connectionState !== 'connected') {
2991
+ if (this.connectionState !== "connected") {
2401
2992
  throw new Error(`Cannot get newsletter admin count. Connection state: ${this.connectionState}`);
2402
2993
  }
2403
- if (!newsletterId.endsWith('@newsletter')) {
2404
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
2994
+ if (!newsletterId.endsWith("@newsletter")) {
2995
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2405
2996
  }
2406
2997
  const count = await this.socket.newsletterAdminCount(newsletterId);
2407
2998
  return count || 0;
2408
2999
  }
2409
3000
  catch (error) {
2410
- this.logger.error('Failed to get newsletter admin count:', error);
3001
+ this.logger.error("Failed to get newsletter admin count:", error);
2411
3002
  return null;
2412
3003
  }
2413
3004
  }
@@ -2420,20 +3011,20 @@ class MiawClient extends events_1.EventEmitter {
2420
3011
  async changeNewsletterOwner(newsletterId, newOwnerJid) {
2421
3012
  try {
2422
3013
  if (!this.socket) {
2423
- throw new Error('Not connected. Call connect() first.');
3014
+ throw new Error("Not connected. Call connect() first.");
2424
3015
  }
2425
- if (this.connectionState !== 'connected') {
3016
+ if (this.connectionState !== "connected") {
2426
3017
  throw new Error(`Cannot change newsletter owner. Connection state: ${this.connectionState}`);
2427
3018
  }
2428
- if (!newsletterId.endsWith('@newsletter')) {
2429
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
3019
+ if (!newsletterId.endsWith("@newsletter")) {
3020
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2430
3021
  }
2431
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(newOwnerJid);
3022
+ const jid = MessageHandler.formatPhoneToJid(newOwnerJid);
2432
3023
  await this.socket.newsletterChangeOwner(newsletterId, jid);
2433
3024
  return true;
2434
3025
  }
2435
3026
  catch (error) {
2436
- this.logger.error('Failed to change newsletter owner:', error);
3027
+ this.logger.error("Failed to change newsletter owner:", error);
2437
3028
  return false;
2438
3029
  }
2439
3030
  }
@@ -2446,20 +3037,20 @@ class MiawClient extends events_1.EventEmitter {
2446
3037
  async demoteNewsletterAdmin(newsletterId, adminJid) {
2447
3038
  try {
2448
3039
  if (!this.socket) {
2449
- throw new Error('Not connected. Call connect() first.');
3040
+ throw new Error("Not connected. Call connect() first.");
2450
3041
  }
2451
- if (this.connectionState !== 'connected') {
3042
+ if (this.connectionState !== "connected") {
2452
3043
  throw new Error(`Cannot demote newsletter admin. Connection state: ${this.connectionState}`);
2453
3044
  }
2454
- if (!newsletterId.endsWith('@newsletter')) {
2455
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
3045
+ if (!newsletterId.endsWith("@newsletter")) {
3046
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2456
3047
  }
2457
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(adminJid);
3048
+ const jid = MessageHandler.formatPhoneToJid(adminJid);
2458
3049
  await this.socket.newsletterDemote(newsletterId, jid);
2459
3050
  return true;
2460
3051
  }
2461
3052
  catch (error) {
2462
- this.logger.error('Failed to demote newsletter admin:', error);
3053
+ this.logger.error("Failed to demote newsletter admin:", error);
2463
3054
  return false;
2464
3055
  }
2465
3056
  }
@@ -2471,19 +3062,19 @@ class MiawClient extends events_1.EventEmitter {
2471
3062
  async deleteNewsletter(newsletterId) {
2472
3063
  try {
2473
3064
  if (!this.socket) {
2474
- throw new Error('Not connected. Call connect() first.');
3065
+ throw new Error("Not connected. Call connect() first.");
2475
3066
  }
2476
- if (this.connectionState !== 'connected') {
3067
+ if (this.connectionState !== "connected") {
2477
3068
  throw new Error(`Cannot delete newsletter. Connection state: ${this.connectionState}`);
2478
3069
  }
2479
- if (!newsletterId.endsWith('@newsletter')) {
2480
- throw new Error('Invalid newsletter ID. Must end with @newsletter');
3070
+ if (!newsletterId.endsWith("@newsletter")) {
3071
+ throw new Error("Invalid newsletter ID. Must end with @newsletter");
2481
3072
  }
2482
3073
  await this.socket.newsletterDelete(newsletterId);
2483
3074
  return true;
2484
3075
  }
2485
3076
  catch (error) {
2486
- this.logger.error('Failed to delete newsletter:', error);
3077
+ this.logger.error("Failed to delete newsletter:", error);
2487
3078
  return false;
2488
3079
  }
2489
3080
  }
@@ -2498,12 +3089,12 @@ class MiawClient extends events_1.EventEmitter {
2498
3089
  async addOrEditContact(contact) {
2499
3090
  try {
2500
3091
  if (!this.socket) {
2501
- throw new Error('Not connected. Call connect() first.');
3092
+ throw new Error("Not connected. Call connect() first.");
2502
3093
  }
2503
- if (this.connectionState !== 'connected') {
3094
+ if (this.connectionState !== "connected") {
2504
3095
  throw new Error(`Cannot add/edit contact. Connection state: ${this.connectionState}`);
2505
3096
  }
2506
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(contact.phone);
3097
+ const jid = MessageHandler.formatPhoneToJid(contact.phone);
2507
3098
  // Build contact action for Baileys
2508
3099
  const contactAction = {
2509
3100
  displayName: contact.name,
@@ -2518,7 +3109,7 @@ class MiawClient extends events_1.EventEmitter {
2518
3109
  return { success: true };
2519
3110
  }
2520
3111
  catch (error) {
2521
- this.logger.error('Failed to add/edit contact:', error);
3112
+ this.logger.error("Failed to add/edit contact:", error);
2522
3113
  return {
2523
3114
  success: false,
2524
3115
  error: error.message,
@@ -2533,17 +3124,17 @@ class MiawClient extends events_1.EventEmitter {
2533
3124
  async removeContact(phone) {
2534
3125
  try {
2535
3126
  if (!this.socket) {
2536
- throw new Error('Not connected. Call connect() first.');
3127
+ throw new Error("Not connected. Call connect() first.");
2537
3128
  }
2538
- if (this.connectionState !== 'connected') {
3129
+ if (this.connectionState !== "connected") {
2539
3130
  throw new Error(`Cannot remove contact. Connection state: ${this.connectionState}`);
2540
3131
  }
2541
- const jid = MessageHandler_1.MessageHandler.formatPhoneToJid(phone);
3132
+ const jid = MessageHandler.formatPhoneToJid(phone);
2542
3133
  await this.socket.removeContact(jid);
2543
3134
  return { success: true };
2544
3135
  }
2545
3136
  catch (error) {
2546
- this.logger.error('Failed to remove contact:', error);
3137
+ this.logger.error("Failed to remove contact:", error);
2547
3138
  return {
2548
3139
  success: false,
2549
3140
  error: error.message,
@@ -2556,16 +3147,16 @@ class MiawClient extends events_1.EventEmitter {
2556
3147
  getAudioMimetypeFromFileName(fileName) {
2557
3148
  const ext = path.extname(fileName).toLowerCase();
2558
3149
  const mimeTypes = {
2559
- '.mp3': 'audio/mpeg',
2560
- '.mp4': 'audio/mp4',
2561
- '.m4a': 'audio/mp4',
2562
- '.ogg': 'audio/ogg; codecs=opus',
2563
- '.opus': 'audio/ogg; codecs=opus',
2564
- '.wav': 'audio/wav',
2565
- '.aac': 'audio/aac',
2566
- '.flac': 'audio/flac',
3150
+ ".mp3": "audio/mpeg",
3151
+ ".mp4": "audio/mp4",
3152
+ ".m4a": "audio/mp4",
3153
+ ".ogg": "audio/ogg; codecs=opus",
3154
+ ".opus": "audio/ogg; codecs=opus",
3155
+ ".wav": "audio/wav",
3156
+ ".aac": "audio/aac",
3157
+ ".flac": "audio/flac",
2567
3158
  };
2568
- return mimeTypes[ext] || 'audio/mp4';
3159
+ return mimeTypes[ext] || "audio/mp4";
2569
3160
  }
2570
3161
  /**
2571
3162
  * Get MIME type from file extension
@@ -2573,24 +3164,24 @@ class MiawClient extends events_1.EventEmitter {
2573
3164
  getMimetypeFromFileName(fileName) {
2574
3165
  const ext = path.extname(fileName).toLowerCase();
2575
3166
  const mimeTypes = {
2576
- '.pdf': 'application/pdf',
2577
- '.doc': 'application/msword',
2578
- '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
2579
- '.xls': 'application/vnd.ms-excel',
2580
- '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
2581
- '.ppt': 'application/vnd.ms-powerpoint',
2582
- '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
2583
- '.txt': 'text/plain',
2584
- '.csv': 'text/csv',
2585
- '.json': 'application/json',
2586
- '.xml': 'application/xml',
2587
- '.zip': 'application/zip',
2588
- '.rar': 'application/x-rar-compressed',
2589
- '.7z': 'application/x-7z-compressed',
2590
- '.tar': 'application/x-tar',
2591
- '.gz': 'application/gzip',
3167
+ ".pdf": "application/pdf",
3168
+ ".doc": "application/msword",
3169
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
3170
+ ".xls": "application/vnd.ms-excel",
3171
+ ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
3172
+ ".ppt": "application/vnd.ms-powerpoint",
3173
+ ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
3174
+ ".txt": "text/plain",
3175
+ ".csv": "text/csv",
3176
+ ".json": "application/json",
3177
+ ".xml": "application/xml",
3178
+ ".zip": "application/zip",
3179
+ ".rar": "application/x-rar-compressed",
3180
+ ".7z": "application/x-7z-compressed",
3181
+ ".tar": "application/x-tar",
3182
+ ".gz": "application/gzip",
2592
3183
  };
2593
- return mimeTypes[ext] || 'application/octet-stream';
3184
+ return mimeTypes[ext] || "application/octet-stream";
2594
3185
  }
2595
3186
  /**
2596
3187
  * Disconnect from WhatsApp
@@ -2604,8 +3195,8 @@ class MiawClient extends events_1.EventEmitter {
2604
3195
  await this.socket.logout();
2605
3196
  this.socket = null;
2606
3197
  }
2607
- this.updateConnectionState('disconnected');
2608
- this.logger.info('Disconnected');
3198
+ this.updateConnectionState("disconnected");
3199
+ this.logger.info("Disconnected");
2609
3200
  }
2610
3201
  /**
2611
3202
  * Get current connection state
@@ -2623,7 +3214,7 @@ class MiawClient extends events_1.EventEmitter {
2623
3214
  * Check if connected
2624
3215
  */
2625
3216
  isConnected() {
2626
- return this.connectionState === 'connected';
3217
+ return this.connectionState === "connected";
2627
3218
  }
2628
3219
  // TypeScript event emitter type safety
2629
3220
  on(event, listener) {
@@ -2633,5 +3224,4 @@ class MiawClient extends events_1.EventEmitter {
2633
3224
  return super.emit(event, ...args);
2634
3225
  }
2635
3226
  }
2636
- exports.MiawClient = MiawClient;
2637
3227
  //# sourceMappingURL=MiawClient.js.map