@arcaelas/whatsapp 1.4.0 → 2.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.
Files changed (41) hide show
  1. package/build/cjs/Chat.d.ts +199 -217
  2. package/build/cjs/Chat.js +151 -274
  3. package/build/cjs/Chat.js.map +1 -1
  4. package/build/cjs/Contact.d.ts +455 -148
  5. package/build/cjs/Contact.js +74 -103
  6. package/build/cjs/Contact.js.map +1 -1
  7. package/build/cjs/Message.d.ts +587 -265
  8. package/build/cjs/Message.js +304 -254
  9. package/build/cjs/Message.js.map +1 -1
  10. package/build/cjs/WhatsApp.d.ts +19 -7
  11. package/build/cjs/WhatsApp.js +88 -80
  12. package/build/cjs/WhatsApp.js.map +1 -1
  13. package/build/cjs/index.d.ts +2 -2
  14. package/build/cjs/store/driver/FileEngine.d.ts +13 -2
  15. package/build/cjs/store/driver/FileEngine.js +15 -19
  16. package/build/cjs/store/driver/FileEngine.js.map +1 -1
  17. package/build/cjs/store/driver/RedisEngine.d.ts +13 -4
  18. package/build/cjs/store/driver/RedisEngine.js +23 -22
  19. package/build/cjs/store/driver/RedisEngine.js.map +1 -1
  20. package/build/cjs/store/engine.d.ts +9 -10
  21. package/build/esm/Chat.d.ts +199 -217
  22. package/build/esm/Chat.js +151 -273
  23. package/build/esm/Chat.js.map +1 -1
  24. package/build/esm/Contact.d.ts +455 -148
  25. package/build/esm/Contact.js +74 -102
  26. package/build/esm/Contact.js.map +1 -1
  27. package/build/esm/Message.d.ts +587 -265
  28. package/build/esm/Message.js +305 -254
  29. package/build/esm/Message.js.map +1 -1
  30. package/build/esm/WhatsApp.d.ts +19 -7
  31. package/build/esm/WhatsApp.js +91 -83
  32. package/build/esm/WhatsApp.js.map +1 -1
  33. package/build/esm/index.d.ts +2 -2
  34. package/build/esm/store/driver/FileEngine.d.ts +13 -2
  35. package/build/esm/store/driver/FileEngine.js +15 -19
  36. package/build/esm/store/driver/FileEngine.js.map +1 -1
  37. package/build/esm/store/driver/RedisEngine.d.ts +13 -4
  38. package/build/esm/store/driver/RedisEngine.js +23 -22
  39. package/build/esm/store/driver/RedisEngine.js.map +1 -1
  40. package/build/esm/store/engine.d.ts +9 -10
  41. package/package.json +2 -2
@@ -6,24 +6,26 @@ import { BufferJSON, downloadMediaMessage, generateForwardMessageContent, genera
6
6
  import { Readable } from 'node:stream';
7
7
  /**
8
8
  * @description Estados de un mensaje.
9
+ * Message delivery statuses.
9
10
  */
10
11
  export var MESSAGE_STATUS;
11
12
  (function (MESSAGE_STATUS) {
12
- /** Error al enviar */
13
+ /** Error al enviar / Send error */
13
14
  MESSAGE_STATUS[MESSAGE_STATUS["ERROR"] = 0] = "ERROR";
14
- /** Mensaje pendiente de envío */
15
+ /** Mensaje pendiente de envío / Pending send */
15
16
  MESSAGE_STATUS[MESSAGE_STATUS["PENDING"] = 1] = "PENDING";
16
- /** Servidor recibió el mensaje */
17
+ /** Servidor recibió el mensaje / Server acknowledged */
17
18
  MESSAGE_STATUS[MESSAGE_STATUS["SERVER_ACK"] = 2] = "SERVER_ACK";
18
- /** Mensaje entregado al destinatario */
19
+ /** Mensaje entregado al destinatario / Delivered */
19
20
  MESSAGE_STATUS[MESSAGE_STATUS["DELIVERED"] = 3] = "DELIVERED";
20
- /** Mensaje leído por el destinatario */
21
+ /** Mensaje leído por el destinatario / Read */
21
22
  MESSAGE_STATUS[MESSAGE_STATUS["READ"] = 4] = "READ";
22
- /** Mensaje reproducido (audio/video) */
23
+ /** Mensaje reproducido (audio/video) / Played */
23
24
  MESSAGE_STATUS[MESSAGE_STATUS["PLAYED"] = 5] = "PLAYED";
24
25
  })(MESSAGE_STATUS || (MESSAGE_STATUS = {}));
25
26
  /**
26
27
  * @description Mapeo de tipos de contenido de Baileys a MessageType.
28
+ * Baileys content type to MessageType mapping.
27
29
  */
28
30
  export const MESSAGE_TYPE_MAP = {
29
31
  conversation: 'text',
@@ -39,41 +41,33 @@ export const MESSAGE_TYPE_MAP = {
39
41
  };
40
42
  /**
41
43
  * @description Construye IMessageIndex desde WAMessage.
42
- * @param raw WAMessage del protocolo.
43
- * @param edited Si el mensaje fue editado.
44
- * @returns IMessageIndex normalizado.
44
+ * Builds IMessageIndex from WAMessage.
45
45
  */
46
- export function build_message_index(raw, edited = false) {
46
+ function build_message_index(raw, edited = false) {
47
+ const key = raw.key ?? {};
47
48
  const content_type = getContentType(raw.message ?? {});
48
49
  const msg_type = MESSAGE_TYPE_MAP[content_type ?? ''] ?? 'text';
49
50
  const msg_content = raw.message?.[content_type];
50
51
  const context_info = msg_content?.contextInfo;
51
- // Calcular MIME
52
+ const ephemeral_duration = raw.ephemeralDuration ?? context_info?.expiration;
53
+ const deleted_at = raw.ephemeralStartTimestamp && ephemeral_duration ? (Number(raw.ephemeralStartTimestamp) + ephemeral_duration) * 1000 : null;
52
54
  let mime = 'text/plain';
53
- if (msg_type === 'location' || msg_type === 'poll') {
55
+ if (msg_type === 'location' || msg_type === 'poll')
54
56
  mime = 'application/json';
55
- }
56
- else if (msg_type !== 'text' && typeof msg_content === 'object') {
57
+ else if (msg_type !== 'text' && typeof msg_content === 'object')
57
58
  mime = msg_content?.mimetype ?? 'application/octet-stream';
58
- }
59
- // Calcular caption
60
59
  let caption = '';
61
- if (typeof msg_content === 'string') {
60
+ if (typeof msg_content === 'string')
62
61
  caption = msg_content;
63
- }
64
- else if (msg_content) {
62
+ else if (msg_content)
65
63
  caption = msg_content.caption ?? msg_content.text ?? msg_content.name ?? '';
66
- }
67
- // Calcular deleted_at
68
- const ephemeral_duration = raw.ephemeralDuration ?? context_info?.expiration;
69
- const deleted_at = raw.ephemeralStartTimestamp && ephemeral_duration ? (Number(raw.ephemeralStartTimestamp) + ephemeral_duration) * 1000 : null;
70
64
  return {
71
- id: raw.key.id,
72
- cid: raw.key.remoteJid,
65
+ id: key.id ?? '',
66
+ cid: key.remoteJidAlt || key.remoteJid || '',
73
67
  mid: context_info?.stanzaId ?? null,
74
- me: raw.key.fromMe ?? false,
68
+ me: key.fromMe ?? false,
75
69
  type: msg_type,
76
- author: raw.key.participant ?? raw.key.remoteJid,
70
+ author: key.participant || key.remoteJid || '',
77
71
  status: raw.status ?? MESSAGE_STATUS.PENDING,
78
72
  starred: raw.starred ?? false,
79
73
  forwarded: context_info?.isForwarded ?? false,
@@ -87,79 +81,51 @@ export function build_message_index(raw, edited = false) {
87
81
  /**
88
82
  * @description
89
83
  * Clase base para representar un mensaje de WhatsApp.
90
- * Expone getters sobre el índice, raw accesible para operaciones avanzadas.
84
+ * Base class representing a WhatsApp message.
91
85
  */
92
86
  export class Message {
93
87
  constructor(data) {
94
88
  this.index = data.index;
95
89
  this.raw = data.raw;
96
90
  }
97
- /** ID único del mensaje */
98
- get id() {
99
- return this.index.id;
100
- }
101
- /** JID del chat al que pertenece */
102
- get cid() {
103
- return this.index.cid;
104
- }
105
- /** ID del mensaje padre (reply) */
106
- get mid() {
107
- return this.index.mid;
108
- }
109
- /** true si el mensaje fue enviado por el usuario autenticado */
110
- get me() {
111
- return this.index.me;
112
- }
113
- /** Autor del mensaje */
114
- get author() {
115
- return this.index.author;
116
- }
117
- /** true si el mensaje fue editado */
118
- get edited() {
119
- return this.index.edited;
120
- }
121
- /** Tipo de contenido del mensaje */
122
- get type() {
123
- return this.index.type;
124
- }
125
- /** Texto o caption del mensaje */
126
- get caption() {
127
- return this.index.caption;
128
- }
129
- /** Tipo MIME del contenido */
130
- get mime() {
131
- return this.index.mime;
132
- }
133
- /** Estado del mensaje */
134
- get status() {
135
- return this.index.status;
136
- }
137
- /** true si el mensaje está destacado */
138
- get starred() {
139
- return this.index.starred;
140
- }
141
- /** true si el mensaje fue reenviado */
142
- get forwarded() {
143
- return this.index.forwarded;
144
- }
145
- /** Timestamp de creación (ms) */
146
- get created_at() {
147
- return this.index.created_at;
148
- }
149
- /** Timestamp de expiración (ms) o null */
150
- get deleted_at() {
151
- return this.index.deleted_at;
152
- }
91
+ /** ID único del mensaje / Unique message ID */
92
+ get id() { return this.index.id; }
93
+ /** JID del chat al que pertenece / Chat JID */
94
+ get cid() { return this.index.cid; }
95
+ /** ID del mensaje padre (reply) / Parent message ID (reply) */
96
+ get mid() { return this.index.mid; }
97
+ /** true si el mensaje fue enviado por el usuario autenticado / true if sent by authenticated user */
98
+ get me() { return this.index.me; }
99
+ /** Autor del mensaje / Message author */
100
+ get author() { return this.index.author; }
101
+ /** true si el mensaje fue editado / true if edited */
102
+ get edited() { return this.index.edited; }
103
+ /** Tipo de contenido del mensaje / Message content type */
104
+ get type() { return this.index.type; }
105
+ /** Texto o caption del mensaje / Message text or caption */
106
+ get caption() { return this.index.caption; }
107
+ /** Tipo MIME del contenido / Content MIME type */
108
+ get mime() { return this.index.mime; }
109
+ /** Estado del mensaje / Message status */
110
+ get status() { return this.index.status; }
111
+ /** true si el mensaje está destacado / true if starred */
112
+ get starred() { return this.index.starred; }
113
+ /** true si el mensaje fue reenviado / true if forwarded */
114
+ get forwarded() { return this.index.forwarded; }
115
+ /** Timestamp de creación (ms) / Creation timestamp (ms) */
116
+ get created_at() { return this.index.created_at; }
117
+ /** Timestamp de expiración (ms) o null / Expiration timestamp (ms) or null */
118
+ get deleted_at() { return this.index.deleted_at; }
153
119
  /**
154
120
  * @description Obtiene el contenido como Readable stream.
155
- * @returns Readable stream (vacío en clase base).
121
+ * Gets content as Readable stream.
156
122
  */
157
123
  stream() {
158
124
  return Promise.resolve(Readable.from(Buffer.alloc(0)));
159
125
  }
160
126
  /**
161
127
  * @description Obtiene el contenido del mensaje como Buffer.
162
- * @returns Buffer con el contenido (vacío en clase base).
128
+ * Gets message content as Buffer.
163
129
  */
164
130
  content() {
165
131
  return Promise.resolve(Buffer.alloc(0));
@@ -167,122 +133,271 @@ export class Message {
167
133
  }
168
134
  /**
169
135
  * @description Factory que retorna la clase Message enlazada al contexto.
136
+ * Factory that returns the Message class bound to context.
170
137
  * @param wa Instancia de WhatsApp.
171
- * @returns Clase _Message que extiende Message.
172
138
  */
173
139
  export function message(wa) {
174
- /** Subscribers para watch() */
175
140
  const _watchers = new Map();
176
- /** Función interna para envío de mensajes */
177
- async function _send(cid, content, binary) {
178
- if (!wa.socket)
141
+ /**
142
+ * @description Agrega un mensaje al índice del chat (interno).
143
+ * Adds a message to the chat index (internal).
144
+ */
145
+ async function _add_to_index(cid, mid, timestamp) {
146
+ const key = `chat/${cid}/messages`;
147
+ const line = `${timestamp} ${mid}`;
148
+ const current = await wa.engine.get(key);
149
+ await wa.engine.set(key, current ? `${line}\n${current}` : line);
150
+ }
151
+ /**
152
+ * @description Elimina un mensaje del índice del chat (interno).
153
+ * Removes a message from the chat index (internal).
154
+ */
155
+ async function _remove_from_index(cid, mid) {
156
+ const key = `chat/${cid}/messages`;
157
+ const content = await wa.engine.get(key);
158
+ if (!content)
159
+ return;
160
+ const filtered = content.trim().split('\n').filter((line) => !line.endsWith(` ${mid}`)).join('\n');
161
+ await wa.engine.set(key, filtered || null);
162
+ }
163
+ /**
164
+ * @description Notifica a los watchers de un mensaje (interno).
165
+ * Notifies message watchers (internal).
166
+ */
167
+ function _notify(cid, mid) {
168
+ const handlers = _watchers.get(`${cid}:${mid}`);
169
+ handlers?.forEach((h) => _Message.get(cid, mid).then((msg) => msg && h(msg)));
170
+ }
171
+ async function _send(cid, content, binary, reply_to) {
172
+ const jid = await wa.resolveJID(cid);
173
+ if (!jid || !wa.socket)
179
174
  return null;
180
- const raw = await wa.socket.sendMessage(cid, content);
181
- if (!raw?.key?.id)
175
+ let quoted;
176
+ if (reply_to) {
177
+ const ref = await _Message.get(jid, reply_to);
178
+ if (ref)
179
+ quoted = ref.raw;
180
+ }
181
+ const raw = await wa.socket.sendMessage(jid, { ...content, ...(quoted && { quoted }) });
182
+ const sent_id = raw?.key?.id;
183
+ if (!raw || !sent_id)
182
184
  return null;
183
185
  const index = build_message_index(raw);
184
- await wa.engine.set(`chat/${cid}/message/${raw.key.id}/index`, JSON.stringify(index, BufferJSON.replacer));
185
- await wa.engine.set(`chat/${cid}/message/${raw.key.id}/raw`, JSON.stringify(raw, BufferJSON.replacer));
186
+ await wa.engine.set(`chat/${jid}/message/${sent_id}/index`, JSON.stringify(index, BufferJSON.replacer));
187
+ await wa.engine.set(`chat/${jid}/message/${sent_id}/raw`, JSON.stringify(raw, BufferJSON.replacer));
186
188
  if (binary)
187
- await wa.engine.set(`chat/${cid}/message/${raw.key.id}/content`, binary.toString('base64'));
188
- await wa.Chat.add_message(cid, raw.key.id, index.created_at);
189
+ await wa.engine.set(`chat/${jid}/message/${sent_id}/content`, binary.toString('base64'));
190
+ await _add_to_index(jid, sent_id, index.created_at);
189
191
  return new _Message({ index, raw });
190
192
  }
191
193
  const _Message = class extends Message {
192
194
  /**
193
195
  * @description Obtiene un mensaje por CID y MID.
194
- * @param cid ID del chat.
195
- * @param mid ID del mensaje.
196
- * @returns Mensaje o null si no existe.
196
+ * Retrieves a message by CID and MID.
197
197
  */
198
198
  static async get(cid, mid) {
199
- const stored_index = await wa.engine.get(`chat/${cid}/message/${mid}/index`);
199
+ const jid = await wa.resolveJID(cid);
200
+ if (!jid)
201
+ return null;
202
+ const stored_index = await wa.engine.get(`chat/${jid}/message/${mid}/index`);
200
203
  if (!stored_index)
201
204
  return null;
202
205
  const index = JSON.parse(stored_index, BufferJSON.reviver);
203
- // Obtener raw si existe
204
- const stored_raw = await wa.engine.get(`chat/${cid}/message/${mid}/raw`);
205
- const raw = stored_raw ? JSON.parse(stored_raw, BufferJSON.reviver) : { key: { remoteJid: cid, id: mid, fromMe: index.me } };
206
+ const stored_raw = await wa.engine.get(`chat/${jid}/message/${mid}/raw`);
207
+ const raw = stored_raw ? JSON.parse(stored_raw, BufferJSON.reviver) : { key: { remoteJid: jid, id: mid, fromMe: index.me } };
206
208
  return new _Message({ index, raw });
207
209
  }
208
210
  /**
209
- * @description Reacciona a un mensaje.
210
- * @param cid ID del chat.
211
- * @param mid ID del mensaje.
212
- * @param emoji Emoji de reacción (vacío para quitar).
213
- * @returns true si se envió correctamente.
211
+ * @description Lista mensajes de un chat (paginado).
212
+ * Lists messages from a chat (paginated).
213
+ */
214
+ static async list(cid, offset = 0, limit = 50) {
215
+ const jid = await wa.resolveJID(cid);
216
+ if (!jid)
217
+ return [];
218
+ const content = await wa.engine.get(`chat/${jid}/messages`);
219
+ if (!content)
220
+ return [];
221
+ const ids = content.trim().split('\n').slice(offset, offset + limit).map((line) => line.split(' ')[1]).filter(Boolean);
222
+ const messages = [];
223
+ for (const mid of ids) {
224
+ const msg = await _Message.get(jid, mid);
225
+ if (msg)
226
+ messages.push(msg);
227
+ }
228
+ return messages;
229
+ }
230
+ /**
231
+ * @description Cuenta mensajes de un chat.
232
+ * Counts messages in a chat.
233
+ */
234
+ static async count(cid) {
235
+ const jid = await wa.resolveJID(cid);
236
+ if (!jid)
237
+ return 0;
238
+ const content = await wa.engine.get(`chat/${jid}/messages`);
239
+ if (!content)
240
+ return 0;
241
+ return content.trim().split('\n').filter(Boolean).length;
242
+ }
243
+ /**
244
+ * @description Envía un mensaje de texto.
245
+ * Sends a text message.
246
+ */
247
+ static async text(cid, text, mid) {
248
+ return _send(cid, { text }, undefined, mid);
249
+ }
250
+ /**
251
+ * @description Envía una imagen.
252
+ * Sends an image.
253
+ */
254
+ static async image(cid, buffer, caption, mid) {
255
+ return _send(cid, { image: buffer, caption }, buffer, mid);
256
+ }
257
+ /**
258
+ * @description Envía un video.
259
+ * Sends a video.
260
+ */
261
+ static async video(cid, buffer, caption, mid) {
262
+ return _send(cid, { video: buffer, caption }, buffer, mid);
263
+ }
264
+ /**
265
+ * @description Envía un audio.
266
+ * Sends an audio.
267
+ * @param ptt true para nota de voz (default true) / true for voice note (default true).
268
+ */
269
+ static async audio(cid, buffer, ptt = true, mid) {
270
+ return _send(cid, { audio: buffer, ptt }, buffer, mid);
271
+ }
272
+ /**
273
+ * @description Envía una ubicación.
274
+ * Sends a location.
275
+ */
276
+ static async location(cid, opts, mid) {
277
+ return _send(cid, { location: { degreesLatitude: opts.lat, degreesLongitude: opts.lng } }, undefined, mid);
278
+ }
279
+ /**
280
+ * @description Envía una encuesta.
281
+ * Sends a poll.
282
+ */
283
+ static async poll(cid, opts, mid) {
284
+ return _send(cid, { poll: { name: opts.content, values: opts.options.map((o) => o.content), selectableCount: 1 } }, undefined, mid);
285
+ }
286
+ /**
287
+ * @description Edita un mensaje por CID y MID.
288
+ * Edits a message by CID and MID.
289
+ */
290
+ static async edit(cid, mid, text) {
291
+ const msg = await _Message.get(cid, mid);
292
+ return msg ? msg.edit(text) : false;
293
+ }
294
+ /**
295
+ * @description Elimina un mensaje por CID y MID.
296
+ * Deletes a message by CID and MID.
297
+ */
298
+ static async remove(cid, mid) {
299
+ const msg = await _Message.get(cid, mid);
300
+ return msg ? msg.remove() : false;
301
+ }
302
+ /**
303
+ * @description Reacciona a un mensaje por CID y MID.
304
+ * Reacts to a message by CID and MID.
214
305
  */
215
306
  static async react(cid, mid, emoji) {
216
- if (!wa.socket)
217
- return false;
218
307
  const msg = await _Message.get(cid, mid);
219
- if (!msg)
308
+ return msg ? msg.react(emoji) : false;
309
+ }
310
+ /**
311
+ * @description Reenvía un mensaje por CID y MID a otro chat.
312
+ * Forwards a message by CID and MID to another chat.
313
+ */
314
+ static async forward(cid, mid, to_cid) {
315
+ const msg = await _Message.get(cid, mid);
316
+ return msg ? msg.forward(to_cid) : false;
317
+ }
318
+ /**
319
+ * @description Observa cambios en un mensaje específico.
320
+ * Watches changes on a specific message.
321
+ * @returns Función para dejar de observar / Unsubscribe function.
322
+ */
323
+ static watch(cid, mid, handler) {
324
+ const key = `${cid}:${mid}`;
325
+ if (!_watchers.has(key))
326
+ _watchers.set(key, new Set());
327
+ _watchers.get(key)?.add(handler);
328
+ return () => {
329
+ _watchers.get(key)?.delete(handler);
330
+ if (_watchers.get(key)?.size === 0)
331
+ _watchers.delete(key);
332
+ };
333
+ }
334
+ /**
335
+ * @description Edita el mensaje (solo texto o caption, solo mensajes propios).
336
+ * Edits the message (text or caption only, own messages only).
337
+ */
338
+ async edit(text) {
339
+ if (!wa.socket || !this.me)
220
340
  return false;
221
- await wa.socket.sendMessage(cid, {
222
- react: { text: emoji, key: { remoteJid: cid, id: mid, fromMe: msg.me } },
341
+ await wa.socket.sendMessage(this.cid, {
342
+ text,
343
+ edit: { remoteJid: this.cid, id: this.id, fromMe: true },
223
344
  });
345
+ const content_type = getContentType(this.raw.message ?? {});
346
+ if (content_type === 'conversation') {
347
+ this.raw.message = { conversation: text };
348
+ }
349
+ else if (content_type === 'extendedTextMessage') {
350
+ this.raw.message = { extendedTextMessage: { text } };
351
+ }
352
+ this.index.caption = text;
353
+ this.index.edited = true;
354
+ await wa.engine.set(`chat/${this.cid}/message/${this.id}/index`, JSON.stringify(this.index, BufferJSON.replacer));
355
+ await wa.engine.set(`chat/${this.cid}/message/${this.id}/raw`, JSON.stringify(this.raw, BufferJSON.replacer));
224
356
  return true;
225
357
  }
226
358
  /**
227
- * @description Elimina un mensaje para todos.
228
- * @param cid ID del chat.
229
- * @param mid ID del mensaje.
230
- * @returns true si se eliminó correctamente.
359
+ * @description Elimina el mensaje para todos.
360
+ * Deletes the message for everyone.
231
361
  */
232
- static async remove(cid, mid) {
362
+ async remove() {
233
363
  if (!wa.socket)
234
364
  return false;
235
- const msg = await _Message.get(cid, mid);
236
- if (!msg)
237
- return false;
238
- await wa.socket.sendMessage(cid, { delete: { remoteJid: cid, id: mid, fromMe: msg.me } });
239
- // Eliminar del índice del chat
240
- await wa.Chat.remove_message(cid, mid);
241
- // Eliminar archivos
242
- await wa.engine.set(`chat/${cid}/message/${mid}/index`, null);
243
- await wa.engine.set(`chat/${cid}/message/${mid}/content`, null);
244
- await wa.engine.set(`chat/${cid}/message/${mid}/raw`, null);
365
+ await wa.socket.sendMessage(this.cid, { delete: { remoteJid: this.cid, id: this.id, fromMe: this.me } });
366
+ await _remove_from_index(this.cid, this.id);
367
+ await wa.engine.set(`chat/${this.cid}/message/${this.id}`, null);
245
368
  return true;
246
369
  }
247
370
  /**
248
- * @description Reenvía un mensaje a otro chat.
249
- * @param cid ID del chat origen.
250
- * @param mid ID del mensaje.
251
- * @param to_cid ID del chat destino.
252
- * @returns true si se reenvió correctamente.
371
+ * @description Reenvía el mensaje a otro chat.
372
+ * Forwards the message to another chat.
253
373
  */
254
- static async forward(cid, mid, to_cid) {
374
+ async forward(to_cid) {
255
375
  if (!wa.socket)
256
376
  return false;
257
- const msg = await _Message.get(cid, mid);
258
- if (!msg)
259
- return false;
260
- // Forward nativo con raw
261
- if (msg.raw.message) {
377
+ if (this.raw.message) {
262
378
  try {
263
- const wa_msg = generateWAMessageFromContent(to_cid, generateForwardMessageContent(msg.raw, false), { userJid: wa.socket.user?.id ?? '' });
379
+ const wa_msg = generateWAMessageFromContent(to_cid, generateForwardMessageContent(this.raw, false), { userJid: wa.socket.user?.id ?? '' });
380
+ if (!wa_msg.message || !wa_msg.key?.id)
381
+ return false;
264
382
  await wa.socket.relayMessage(to_cid, wa_msg.message, { messageId: wa_msg.key.id });
265
383
  return true;
266
384
  }
267
- catch {
268
- // Fallback si falla el forward nativo
269
- }
385
+ catch { /* fallback below */ }
270
386
  }
271
- // Fallback: obtener contenido y reenviar
272
- const content = await msg.content();
273
- if (!content.length)
387
+ const buf = await this.content();
388
+ if (!buf.length)
274
389
  return false;
275
- if (msg.type === 'text')
276
- return (await _Message.text(to_cid, content.toString())) !== null;
277
- if (msg.type === 'image')
278
- return (await _Message.image(to_cid, content, msg.caption || undefined)) !== null;
279
- if (msg.type === 'video')
280
- return (await _Message.video(to_cid, content, msg.caption || undefined)) !== null;
281
- if (msg.type === 'audio')
282
- return (await _Message.audio(to_cid, content)) !== null;
283
- if (msg.type === 'location') {
390
+ if (this.type === 'text')
391
+ return (await _Message.text(to_cid, buf.toString())) !== null;
392
+ if (this.type === 'image')
393
+ return (await _Message.image(to_cid, buf, this.caption || undefined)) !== null;
394
+ if (this.type === 'video')
395
+ return (await _Message.video(to_cid, buf, this.caption || undefined)) !== null;
396
+ if (this.type === 'audio')
397
+ return (await _Message.audio(to_cid, buf)) !== null;
398
+ if (this.type === 'location') {
284
399
  try {
285
- return (await _Message.location(to_cid, JSON.parse(content.toString()))) !== null;
400
+ return (await _Message.location(to_cid, JSON.parse(buf.toString()))) !== null;
286
401
  }
287
402
  catch {
288
403
  return false;
@@ -291,126 +406,63 @@ export function message(wa) {
291
406
  return false;
292
407
  }
293
408
  /**
294
- * @description Edita un mensaje (solo texto o caption).
295
- * @param cid ID del chat.
296
- * @param mid ID del mensaje.
297
- * @param text Nuevo contenido.
298
- * @returns true si se editó correctamente.
409
+ * @description Reacciona al mensaje.
410
+ * Reacts to the message.
411
+ * @param emoji Emoji de reacción (vacío para quitar) / Reaction emoji (empty to remove).
299
412
  */
300
- static async edit(cid, mid, text) {
413
+ async react(emoji) {
301
414
  if (!wa.socket)
302
415
  return false;
303
- const msg = await _Message.get(cid, mid);
304
- if (!msg?.me)
305
- return false;
306
- await wa.socket.sendMessage(cid, {
307
- text,
308
- edit: { remoteJid: cid, id: mid, fromMe: true },
416
+ await wa.socket.sendMessage(this.cid, {
417
+ react: { text: emoji, key: { remoteJid: this.cid, id: this.id, fromMe: this.me } },
309
418
  });
310
- // Actualizar el mensaje almacenado con el nuevo contenido
311
- const content_type = getContentType(msg.raw.message ?? {});
312
- if (content_type === 'conversation') {
313
- msg.raw.message = { conversation: text };
314
- }
315
- else if (content_type === 'extendedTextMessage') {
316
- msg.raw.message = { extendedTextMessage: { text } };
317
- }
318
- // Actualizar índice
319
- msg.index.caption = text;
320
- msg.index.edited = true;
321
- await wa.engine.set(`chat/${cid}/message/${mid}/index`, JSON.stringify(msg.index, BufferJSON.replacer));
322
- await wa.engine.set(`chat/${cid}/message/${mid}/raw`, JSON.stringify(msg.raw, BufferJSON.replacer));
323
419
  return true;
324
420
  }
325
421
  /**
326
- * @description Envía un mensaje de texto.
327
- * @param cid ID del chat destino.
328
- * @param text Contenido del mensaje.
329
- * @returns Mensaje enviado o null.
422
+ * @description Responde con un mensaje de texto.
423
+ * Replies with a text message.
330
424
  */
331
- static async text(cid, text) {
332
- return _send(cid, { text });
425
+ async text(content) {
426
+ return _Message.text(this.cid, content, this.id);
333
427
  }
334
428
  /**
335
- * @description Envía una imagen.
336
- * @param cid ID del chat destino.
337
- * @param buffer Buffer de la imagen.
338
- * @param caption Caption opcional.
339
- * @returns Mensaje enviado o null.
429
+ * @description Responde con una imagen.
430
+ * Replies with an image.
340
431
  */
341
- static async image(cid, buffer, caption) {
342
- return _send(cid, { image: buffer, caption }, buffer);
432
+ async image(buffer, caption) {
433
+ return _Message.image(this.cid, buffer, caption, this.id);
343
434
  }
344
435
  /**
345
- * @description Envía un video.
346
- * @param cid ID del chat destino.
347
- * @param buffer Buffer del video.
348
- * @param caption Caption opcional.
349
- * @returns Mensaje enviado o null.
436
+ * @description Responde con un video.
437
+ * Replies with a video.
350
438
  */
351
- static async video(cid, buffer, caption) {
352
- return _send(cid, { video: buffer, caption }, buffer);
439
+ async video(buffer, caption) {
440
+ return _Message.video(this.cid, buffer, caption, this.id);
353
441
  }
354
442
  /**
355
- * @description Envía un audio.
356
- * @param cid ID del chat destino.
357
- * @param buffer Buffer del audio.
358
- * @param ptt true para nota de voz (default true).
359
- * @returns Mensaje enviado o null.
443
+ * @description Responde con un audio.
444
+ * Replies with an audio.
360
445
  */
361
- static async audio(cid, buffer, ptt = true) {
362
- return _send(cid, { audio: buffer, ptt }, buffer);
446
+ async audio(buffer, ptt = true) {
447
+ return _Message.audio(this.cid, buffer, ptt, this.id);
363
448
  }
364
449
  /**
365
- * @description Envía una ubicación.
366
- * @param cid ID del chat destino.
367
- * @param opts Opciones de ubicación (lat, lng, live).
368
- * @returns Mensaje enviado o null.
450
+ * @description Responde con una ubicacion.
451
+ * Replies with a location.
369
452
  */
370
- static async location(cid, opts) {
371
- return _send(cid, { location: { degreesLatitude: opts.lat, degreesLongitude: opts.lng } });
372
- }
373
- /**
374
- * @description Envía una encuesta.
375
- * @param cid ID del chat destino.
376
- * @param opts Opciones de encuesta (content, options).
377
- * @returns Mensaje enviado o null.
378
- */
379
- static async poll(cid, opts) {
380
- return _send(cid, { poll: { name: opts.content, values: opts.options.map((o) => o.content), selectableCount: 1 } });
381
- }
382
- /**
383
- * @description Observa cambios en un mensaje específico.
384
- * @param cid ID del chat.
385
- * @param mid ID del mensaje.
386
- * @param handler Callback con el mensaje actualizado.
387
- * @returns Función para dejar de observar.
388
- */
389
- static watch(cid, mid, handler) {
390
- const key = `${cid}:${mid}`;
391
- if (!_watchers.has(key))
392
- _watchers.set(key, new Set());
393
- _watchers.get(key).add(handler);
394
- return () => {
395
- _watchers.get(key)?.delete(handler);
396
- if (_watchers.get(key)?.size === 0)
397
- _watchers.delete(key);
398
- };
453
+ async location(opts) {
454
+ return _Message.location(this.cid, opts, this.id);
399
455
  }
400
456
  /**
401
- * @description Notifica a los watchers de un mensaje.
402
- * @param cid ID del chat.
403
- * @param mid ID del mensaje.
457
+ * @description Responde con una encuesta.
458
+ * Replies with a poll.
404
459
  */
405
- static notify(cid, mid) {
406
- const handlers = _watchers.get(`${cid}:${mid}`);
407
- handlers?.forEach((h) => _Message.get(cid, mid).then((msg) => msg && h(msg)));
460
+ async poll(opts) {
461
+ return _Message.poll(this.cid, opts, this.id);
408
462
  }
409
463
  /**
410
464
  * @description Obtiene el contenido como Readable stream.
411
- * Para media (image/video/audio) retorna stream directo de Baileys sin cargar en memoria.
412
- * Para text/location/poll retorna stream desde buffer pequeño.
413
- * @returns Readable stream con el contenido.
465
+ * Gets content as Readable stream.
414
466
  */
415
467
  async stream() {
416
468
  if (this.type === 'text') {
@@ -436,8 +488,7 @@ export function message(wa) {
436
488
  }
437
489
  /**
438
490
  * @description Obtiene el contenido del mensaje como Buffer.
439
- * Usa stream() internamente y cachea el resultado en el engine.
440
- * @returns Buffer con el contenido.
491
+ * Gets message content as Buffer.
441
492
  */
442
493
  async content() {
443
494
  const cached = await wa.engine.get(`chat/${this.cid}/message/${this.id}/content`);
@@ -454,6 +505,6 @@ export function message(wa) {
454
505
  return buffer;
455
506
  }
456
507
  };
457
- return _Message;
508
+ return Object.assign(_Message, { _add_to_index, _remove_from_index, _notify, _build_index: build_message_index });
458
509
  }
459
510
  //# sourceMappingURL=Message.js.map