@arcaelas/whatsapp 8.0.0 → 8.2.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.
@@ -4,7 +4,6 @@
4
4
  * Chat entity — individual and group conversations.
5
5
  */
6
6
  import type { WASocket } from 'baileys';
7
- import type Contact from '../../lib/contact';
8
7
  import type Message from '../../lib/message';
9
8
  import { type Engine } from '../../lib/store';
10
9
  import type WhatsApp from '../../lib/whatsapp';
@@ -87,7 +86,7 @@ export declare function chat(init: {
87
86
  * @param limit - Tamaño de página / Page size
88
87
  * @returns Página de contactos / Contact page
89
88
  */
90
- members(offset?: number, limit?: number): Promise<Contact[]>;
89
+ members(offset?: number, limit?: number): Promise<InstanceType<typeof init.wa.Contact>[]>;
91
90
  /**
92
91
  * Descripción: el asunto del grupo o, en un 1:1, la bio del contacto. Es asíncrono
93
92
  * porque ninguna de las dos vive en el documento del chat.
@@ -221,7 +220,7 @@ export declare function chat(init: {
221
220
  * @param limit - Tamaño de página / Page size
222
221
  * @returns Página de contactos / Contact page
223
222
  */
224
- members(offset?: number, limit?: number): Promise<Contact[]>;
223
+ members(offset?: number, limit?: number): Promise<InstanceType<typeof init.wa.Contact>[]>;
225
224
  /**
226
225
  * Descripción: el asunto del grupo o, en un 1:1, la bio del contacto. Es asíncrono
227
226
  * porque ninguna de las dos vive en el documento del chat.
@@ -354,7 +353,7 @@ export declare function chat(init: {
354
353
  * @param limit - Tamaño de página / Page size
355
354
  * @returns Página de contactos / Contact page
356
355
  */
357
- members(offset?: number, limit?: number): Promise<Contact[]>;
356
+ members(offset?: number, limit?: number): Promise<InstanceType<typeof init.wa.Contact>[]>;
358
357
  /**
359
358
  * Descripción: el asunto del grupo o, en un 1:1, la bio del contacto. Es asíncrono
360
359
  * porque ninguna de las dos vive en el documento del chat.
@@ -76,6 +76,13 @@ export declare function contact(init: Init): {
76
76
  img_url?: string | null;
77
77
  status?: string | null;
78
78
  }): {
79
+ /**
80
+ * true cuando este contacto es la propia cuenta. La comparación cubre JID y LID porque
81
+ * la cuenta se anuncia por cualquiera de los dos según el chat.
82
+ * true when this contact is the account itself. The comparison covers JID and LID
83
+ * because the account announces itself through either depending on the chat.
84
+ */
85
+ get me(): boolean;
79
86
  /**
80
87
  * Chat 1:1 del contacto: el persistido, o una instancia mínima.
81
88
  * The contact's 1:1 chat: the persisted one, or a minimal instance.
@@ -132,6 +139,13 @@ export declare function contact(init: Init): {
132
139
  * @returns Contacto, o null si no existe en WhatsApp / Contact, or null when not on WhatsApp
133
140
  */
134
141
  get(uid: string | number): Promise<{
142
+ /**
143
+ * true cuando este contacto es la propia cuenta. La comparación cubre JID y LID porque
144
+ * la cuenta se anuncia por cualquiera de los dos según el chat.
145
+ * true when this contact is the account itself. The comparison covers JID and LID
146
+ * because the account announces itself through either depending on the chat.
147
+ */
148
+ get me(): boolean;
135
149
  /**
136
150
  * Chat 1:1 del contacto: el persistido, o una instancia mínima.
137
151
  * The contact's 1:1 chat: the persisted one, or a minimal instance.
@@ -187,6 +201,13 @@ export declare function contact(init: Init): {
187
201
  * @returns Página de contactos / Contact page
188
202
  */
189
203
  list(offset?: number, limit?: number): Promise<{
204
+ /**
205
+ * true cuando este contacto es la propia cuenta. La comparación cubre JID y LID porque
206
+ * la cuenta se anuncia por cualquiera de los dos según el chat.
207
+ * true when this contact is the account itself. The comparison covers JID and LID
208
+ * because the account announces itself through either depending on the chat.
209
+ */
210
+ get me(): boolean;
190
211
  /**
191
212
  * Chat 1:1 del contacto: el persistido, o una instancia mínima.
192
213
  * The contact's 1:1 chat: the persisted one, or a minimal instance.
@@ -58,6 +58,17 @@ exports.default = Contact;
58
58
  */
59
59
  function contact(init) {
60
60
  class _Contact extends Contact {
61
+ /**
62
+ * true cuando este contacto es la propia cuenta. La comparación cubre JID y LID porque
63
+ * la cuenta se anuncia por cualquiera de los dos según el chat.
64
+ * true when this contact is the account itself. The comparison covers JID and LID
65
+ * because the account announces itself through either depending on the chat.
66
+ */
67
+ get me() {
68
+ const user = init.socket.user;
69
+ const mine = [user?.id, user?.lid].filter((id) => Boolean(id)).map((id) => (id.split(':')[0] ?? '').split('@')[0]);
70
+ return [this.jid, this.lid, this._raw.id].some((id) => id && mine.includes((id.split('@')[0] ?? '')));
71
+ }
61
72
  /**
62
73
  * Chat 1:1 del contacto: el persistido, o una instancia mínima.
63
74
  * The contact's 1:1 chat: the persisted one, or a minimal instance.
@@ -63,6 +63,12 @@ export default class Message {
63
63
  emoji: string;
64
64
  at: number;
65
65
  }[];
66
+ responses?: {
67
+ author: string;
68
+ response: 'going' | 'not_going' | 'maybe';
69
+ guests: number;
70
+ at: number;
71
+ }[];
66
72
  viewed?: boolean | null;
67
73
  raw: WAMessage;
68
74
  };
@@ -402,6 +408,20 @@ export declare class VCard extends Message {
402
408
  export declare class Event extends Message {
403
409
  /** @internal Bloque del evento en el raw. / Raw event block. */
404
410
  get _event(): proto.Message.IEventMessage | null | undefined;
411
+ /** Asistentes confirmados, acompañantes incluidos. / Confirmed attendees, companions included. */
412
+ get going(): number;
413
+ /**
414
+ * Respuestas de asistencia al evento, con el nombre resuelto de cada contacto y en orden
415
+ * de llegada — la última es la más reciente.
416
+ * Attendance responses, with each contact's resolved name, in arrival order — the last one
417
+ * is the most recent.
418
+ */
419
+ attendees(): Promise<{
420
+ name: string;
421
+ contact: string;
422
+ response: 'going' | 'not_going' | 'maybe';
423
+ guests: number;
424
+ }[]>;
405
425
  /** Nombre del evento. / Event name. */
406
426
  get name(): string;
407
427
  /** Inicio en ISO UTC. / Start as ISO UTC. */
@@ -460,6 +480,12 @@ export declare function message(init: Init): {
460
480
  emoji: string;
461
481
  at: number;
462
482
  }[];
483
+ responses?: {
484
+ author: string;
485
+ response: "going" | "not_going" | "maybe";
486
+ guests: number;
487
+ at: number;
488
+ }[];
463
489
  viewed?: boolean | null;
464
490
  raw: WAMessage;
465
491
  };
@@ -677,6 +677,25 @@ exports.VCard = VCard;
677
677
  class Event extends Message {
678
678
  /** @internal Bloque del evento en el raw. / Raw event block. */
679
679
  get _event() { return this._raw.raw.message?.eventMessage; }
680
+ /** Asistentes confirmados, acompañantes incluidos. / Confirmed attendees, companions included. */
681
+ get going() {
682
+ return (this._raw.responses ?? []).filter((entry) => entry.response === 'going').reduce((sum, entry) => sum + 1 + entry.guests, 0);
683
+ }
684
+ /**
685
+ * Respuestas de asistencia al evento, con el nombre resuelto de cada contacto y en orden
686
+ * de llegada — la última es la más reciente.
687
+ * Attendance responses, with each contact's resolved name, in arrival order — the last one
688
+ * is the most recent.
689
+ */
690
+ async attendees() {
691
+ const rows = [];
692
+ for (const entry of this._raw.responses ?? []) {
693
+ const who = await this._init.wa.Contact.get(entry.author).catch(() => null);
694
+ const contact = (who?.phone ?? entry.author.split('@')[0].split(':')[0]);
695
+ rows.push({ name: who?.name ?? contact, contact, response: entry.response, guests: entry.guests });
696
+ }
697
+ return rows;
698
+ }
680
699
  /** Nombre del evento. / Event name. */
681
700
  get name() { return this._event?.name ?? ''; }
682
701
  /** Inicio en ISO UTC. / Start as ISO UTC. */
@@ -109,7 +109,7 @@ interface EventMap {
109
109
  'message:created': [Message, ChatInstance, WhatsApp];
110
110
  'message:updated': [Message, ChatInstance, WhatsApp];
111
111
  'message:deleted': [Message, ChatInstance, WhatsApp];
112
- 'message:reacted': [Message, ChatInstance, string, WhatsApp];
112
+ 'message:reacted': [Message, ChatInstance, string, ContactInstance, WhatsApp];
113
113
  'message:starred': [Message, ChatInstance, WhatsApp];
114
114
  'message:unstarred': [Message, ChatInstance, WhatsApp];
115
115
  'message:forwarded': [Message, ChatInstance, WhatsApp];
@@ -578,7 +578,15 @@ class WhatsApp {
578
578
  ];
579
579
  await engine.set(found.path, (0, store_1.serialize)(found.doc), found.doc.created_at);
580
580
  const instance = new message_1.default(init, found.doc);
581
- this.emit('message:reacted', instance, await instance.chat(), emoji, this);
581
+ // Quién reaccionó viaja en el evento: sin él, distinguir la
582
+ // reacción del usuario del eco de una propia obligaba a cada
583
+ // consumidor a llevar su propio registro de ecos con timeouts.
584
+ // Who reacted travels in the event: without it, telling the
585
+ // user's reaction from the echo of an own one forced every
586
+ // consumer to keep its own echo ledger with timeouts.
587
+ const who = await canonical(author);
588
+ const card = (0, store_1.deserialize)(await engine.get(`/contact/${who}`));
589
+ this.emit('message:reacted', instance, await instance.chat(), emoji, new this.Contact(card ?? { id: who, lid: null, name: null, notify: null, verified_name: null, img_url: null, status: null }), this);
582
590
  }
583
591
  continue;
584
592
  }
@@ -634,6 +642,45 @@ class WhatsApp {
634
642
  this.emit('feed:created', new status_1.Feed(init, doc), this);
635
643
  continue;
636
644
  }
645
+ if (kind === 'encEventResponseMessage') {
646
+ const enc = msg.message?.encEventResponseMessage;
647
+ const key = enc?.eventCreationMessageKey;
648
+ const found = key?.id && key.remoteJid ? await locate(key.remoteJid, key.id) : null;
649
+ const raw_secret = found?.doc.raw.message?.messageContextInfo?.messageSecret;
650
+ const secret = typeof raw_secret === 'string' ? Buffer.from(raw_secret, 'base64') : raw_secret;
651
+ if (found && secret && enc?.encPayload && enc.encIv) {
652
+ const mine = [socket.user?.lid, socket.user?.id];
653
+ const theirs = (from) => [from.remoteJid, from.participant, from.remoteJidAlt];
654
+ const responders = (msg.key.fromMe ? mine : theirs(msg.key)).filter((id) => Boolean(id));
655
+ const creators = (found.doc.raw.key?.fromMe ? mine : theirs(found.doc.raw.key ?? {})).filter((id) => Boolean(id));
656
+ for (const pair of responders.flatMap((who) => creators.map((creator) => [who, creator]))) {
657
+ try {
658
+ const parsed = (0, baileys_1.decryptEventResponse)({ encPayload: enc.encPayload, encIv: enc.encIv }, {
659
+ eventCreatorJid: (0, baileys_1.jidNormalizedUser)(pair[1]),
660
+ eventMsgId: found.doc.id,
661
+ eventEncKey: secret,
662
+ responderJid: (0, baileys_1.jidNormalizedUser)(pair[0]),
663
+ });
664
+ const response = { 1: 'going', 2: 'not_going', 3: 'maybe' }[parsed.response];
665
+ if (response) {
666
+ const author = await canonical((0, baileys_1.jidNormalizedUser)((msg.key.fromMe ? socket.user?.id : msg.key.participant ?? cid) ?? cid));
667
+ found.doc.responses = [
668
+ ...(found.doc.responses ?? []).filter((entry) => entry.author !== author),
669
+ { author, response, guests: Number(parsed.extraGuestCount ?? 0), at: (Number(msg.messageTimestamp) || Math.floor(Date.now() / 1_000)) * 1_000 },
670
+ ];
671
+ await engine.set(found.path, (0, store_1.serialize)(found.doc), found.doc.created_at);
672
+ const instance = new message_1.default(init, found.doc);
673
+ this.emit('message:updated', instance, await instance.chat(), this);
674
+ }
675
+ break;
676
+ }
677
+ catch {
678
+ /* identidad equivocada / wrong identity */
679
+ }
680
+ }
681
+ }
682
+ continue;
683
+ }
637
684
  if (kind === 'pollUpdateMessage') {
638
685
  const key = msg.message?.pollUpdateMessage?.pollCreationMessageKey;
639
686
  const vote = msg.message?.pollUpdateMessage?.vote;
@@ -4,7 +4,6 @@
4
4
  * Chat entity — individual and group conversations.
5
5
  */
6
6
  import type { WASocket } from 'baileys';
7
- import type Contact from '../../lib/contact/index.js';
8
7
  import type Message from '../../lib/message/index.js';
9
8
  import { type Engine } from '../../lib/store/index.js';
10
9
  import type WhatsApp from '../../lib/whatsapp/index.js';
@@ -87,7 +86,7 @@ export declare function chat(init: {
87
86
  * @param limit - Tamaño de página / Page size
88
87
  * @returns Página de contactos / Contact page
89
88
  */
90
- members(offset?: number, limit?: number): Promise<Contact[]>;
89
+ members(offset?: number, limit?: number): Promise<InstanceType<typeof init.wa.Contact>[]>;
91
90
  /**
92
91
  * Descripción: el asunto del grupo o, en un 1:1, la bio del contacto. Es asíncrono
93
92
  * porque ninguna de las dos vive en el documento del chat.
@@ -221,7 +220,7 @@ export declare function chat(init: {
221
220
  * @param limit - Tamaño de página / Page size
222
221
  * @returns Página de contactos / Contact page
223
222
  */
224
- members(offset?: number, limit?: number): Promise<Contact[]>;
223
+ members(offset?: number, limit?: number): Promise<InstanceType<typeof init.wa.Contact>[]>;
225
224
  /**
226
225
  * Descripción: el asunto del grupo o, en un 1:1, la bio del contacto. Es asíncrono
227
226
  * porque ninguna de las dos vive en el documento del chat.
@@ -354,7 +353,7 @@ export declare function chat(init: {
354
353
  * @param limit - Tamaño de página / Page size
355
354
  * @returns Página de contactos / Contact page
356
355
  */
357
- members(offset?: number, limit?: number): Promise<Contact[]>;
356
+ members(offset?: number, limit?: number): Promise<InstanceType<typeof init.wa.Contact>[]>;
358
357
  /**
359
358
  * Descripción: el asunto del grupo o, en un 1:1, la bio del contacto. Es asíncrono
360
359
  * porque ninguna de las dos vive en el documento del chat.
@@ -76,6 +76,13 @@ export declare function contact(init: Init): {
76
76
  img_url?: string | null;
77
77
  status?: string | null;
78
78
  }): {
79
+ /**
80
+ * true cuando este contacto es la propia cuenta. La comparación cubre JID y LID porque
81
+ * la cuenta se anuncia por cualquiera de los dos según el chat.
82
+ * true when this contact is the account itself. The comparison covers JID and LID
83
+ * because the account announces itself through either depending on the chat.
84
+ */
85
+ get me(): boolean;
79
86
  /**
80
87
  * Chat 1:1 del contacto: el persistido, o una instancia mínima.
81
88
  * The contact's 1:1 chat: the persisted one, or a minimal instance.
@@ -132,6 +139,13 @@ export declare function contact(init: Init): {
132
139
  * @returns Contacto, o null si no existe en WhatsApp / Contact, or null when not on WhatsApp
133
140
  */
134
141
  get(uid: string | number): Promise<{
142
+ /**
143
+ * true cuando este contacto es la propia cuenta. La comparación cubre JID y LID porque
144
+ * la cuenta se anuncia por cualquiera de los dos según el chat.
145
+ * true when this contact is the account itself. The comparison covers JID and LID
146
+ * because the account announces itself through either depending on the chat.
147
+ */
148
+ get me(): boolean;
135
149
  /**
136
150
  * Chat 1:1 del contacto: el persistido, o una instancia mínima.
137
151
  * The contact's 1:1 chat: the persisted one, or a minimal instance.
@@ -187,6 +201,13 @@ export declare function contact(init: Init): {
187
201
  * @returns Página de contactos / Contact page
188
202
  */
189
203
  list(offset?: number, limit?: number): Promise<{
204
+ /**
205
+ * true cuando este contacto es la propia cuenta. La comparación cubre JID y LID porque
206
+ * la cuenta se anuncia por cualquiera de los dos según el chat.
207
+ * true when this contact is the account itself. The comparison covers JID and LID
208
+ * because the account announces itself through either depending on the chat.
209
+ */
210
+ get me(): boolean;
190
211
  /**
191
212
  * Chat 1:1 del contacto: el persistido, o una instancia mínima.
192
213
  * The contact's 1:1 chat: the persisted one, or a minimal instance.
@@ -53,6 +53,17 @@ export default class Contact {
53
53
  */
54
54
  export function contact(init) {
55
55
  class _Contact extends Contact {
56
+ /**
57
+ * true cuando este contacto es la propia cuenta. La comparación cubre JID y LID porque
58
+ * la cuenta se anuncia por cualquiera de los dos según el chat.
59
+ * true when this contact is the account itself. The comparison covers JID and LID
60
+ * because the account announces itself through either depending on the chat.
61
+ */
62
+ get me() {
63
+ const user = init.socket.user;
64
+ const mine = [user?.id, user?.lid].filter((id) => Boolean(id)).map((id) => (id.split(':')[0] ?? '').split('@')[0]);
65
+ return [this.jid, this.lid, this._raw.id].some((id) => id && mine.includes((id.split('@')[0] ?? '')));
66
+ }
56
67
  /**
57
68
  * Chat 1:1 del contacto: el persistido, o una instancia mínima.
58
69
  * The contact's 1:1 chat: the persisted one, or a minimal instance.
@@ -63,6 +63,12 @@ export default class Message {
63
63
  emoji: string;
64
64
  at: number;
65
65
  }[];
66
+ responses?: {
67
+ author: string;
68
+ response: 'going' | 'not_going' | 'maybe';
69
+ guests: number;
70
+ at: number;
71
+ }[];
66
72
  viewed?: boolean | null;
67
73
  raw: WAMessage;
68
74
  };
@@ -402,6 +408,20 @@ export declare class VCard extends Message {
402
408
  export declare class Event extends Message {
403
409
  /** @internal Bloque del evento en el raw. / Raw event block. */
404
410
  get _event(): proto.Message.IEventMessage | null | undefined;
411
+ /** Asistentes confirmados, acompañantes incluidos. / Confirmed attendees, companions included. */
412
+ get going(): number;
413
+ /**
414
+ * Respuestas de asistencia al evento, con el nombre resuelto de cada contacto y en orden
415
+ * de llegada — la última es la más reciente.
416
+ * Attendance responses, with each contact's resolved name, in arrival order — the last one
417
+ * is the most recent.
418
+ */
419
+ attendees(): Promise<{
420
+ name: string;
421
+ contact: string;
422
+ response: 'going' | 'not_going' | 'maybe';
423
+ guests: number;
424
+ }[]>;
405
425
  /** Nombre del evento. / Event name. */
406
426
  get name(): string;
407
427
  /** Inicio en ISO UTC. / Start as ISO UTC. */
@@ -460,6 +480,12 @@ export declare function message(init: Init): {
460
480
  emoji: string;
461
481
  at: number;
462
482
  }[];
483
+ responses?: {
484
+ author: string;
485
+ response: "going" | "not_going" | "maybe";
486
+ guests: number;
487
+ at: number;
488
+ }[];
463
489
  viewed?: boolean | null;
464
490
  raw: WAMessage;
465
491
  };
@@ -660,6 +660,25 @@ export class VCard extends Message {
660
660
  export class Event extends Message {
661
661
  /** @internal Bloque del evento en el raw. / Raw event block. */
662
662
  get _event() { return this._raw.raw.message?.eventMessage; }
663
+ /** Asistentes confirmados, acompañantes incluidos. / Confirmed attendees, companions included. */
664
+ get going() {
665
+ return (this._raw.responses ?? []).filter((entry) => entry.response === 'going').reduce((sum, entry) => sum + 1 + entry.guests, 0);
666
+ }
667
+ /**
668
+ * Respuestas de asistencia al evento, con el nombre resuelto de cada contacto y en orden
669
+ * de llegada — la última es la más reciente.
670
+ * Attendance responses, with each contact's resolved name, in arrival order — the last one
671
+ * is the most recent.
672
+ */
673
+ async attendees() {
674
+ const rows = [];
675
+ for (const entry of this._raw.responses ?? []) {
676
+ const who = await this._init.wa.Contact.get(entry.author).catch(() => null);
677
+ const contact = (who?.phone ?? entry.author.split('@')[0].split(':')[0]);
678
+ rows.push({ name: who?.name ?? contact, contact, response: entry.response, guests: entry.guests });
679
+ }
680
+ return rows;
681
+ }
663
682
  /** Nombre del evento. / Event name. */
664
683
  get name() { return this._event?.name ?? ''; }
665
684
  /** Inicio en ISO UTC. / Start as ISO UTC. */
@@ -109,7 +109,7 @@ interface EventMap {
109
109
  'message:created': [Message, ChatInstance, WhatsApp];
110
110
  'message:updated': [Message, ChatInstance, WhatsApp];
111
111
  'message:deleted': [Message, ChatInstance, WhatsApp];
112
- 'message:reacted': [Message, ChatInstance, string, WhatsApp];
112
+ 'message:reacted': [Message, ChatInstance, string, ContactInstance, WhatsApp];
113
113
  'message:starred': [Message, ChatInstance, WhatsApp];
114
114
  'message:unstarred': [Message, ChatInstance, WhatsApp];
115
115
  'message:forwarded': [Message, ChatInstance, WhatsApp];
@@ -1,4 +1,4 @@
1
- import { Browsers, decryptPollVote, DisconnectReason, downloadMediaMessage, fetchLatestBaileysVersion, getContentType, initAuthCreds, jidNormalizedUser, makeWASocket, proto, updateMessageWithPollUpdate, } from 'baileys';
1
+ import { Browsers, decryptEventResponse, decryptPollVote, DisconnectReason, downloadMediaMessage, fetchLatestBaileysVersion, getContentType, initAuthCreds, jidNormalizedUser, makeWASocket, proto, updateMessageWithPollUpdate, } from 'baileys';
2
2
  import { EventEmitter } from 'node:events';
3
3
  import pino from 'pino';
4
4
  import * as QRCode from 'qrcode';
@@ -540,7 +540,15 @@ export default class WhatsApp {
540
540
  ];
541
541
  await engine.set(found.path, serialize(found.doc), found.doc.created_at);
542
542
  const instance = new Message(init, found.doc);
543
- this.emit('message:reacted', instance, await instance.chat(), emoji, this);
543
+ // Quién reaccionó viaja en el evento: sin él, distinguir la
544
+ // reacción del usuario del eco de una propia obligaba a cada
545
+ // consumidor a llevar su propio registro de ecos con timeouts.
546
+ // Who reacted travels in the event: without it, telling the
547
+ // user's reaction from the echo of an own one forced every
548
+ // consumer to keep its own echo ledger with timeouts.
549
+ const who = await canonical(author);
550
+ const card = deserialize(await engine.get(`/contact/${who}`));
551
+ this.emit('message:reacted', instance, await instance.chat(), emoji, new this.Contact(card ?? { id: who, lid: null, name: null, notify: null, verified_name: null, img_url: null, status: null }), this);
544
552
  }
545
553
  continue;
546
554
  }
@@ -596,6 +604,45 @@ export default class WhatsApp {
596
604
  this.emit('feed:created', new Feed(init, doc), this);
597
605
  continue;
598
606
  }
607
+ if (kind === 'encEventResponseMessage') {
608
+ const enc = msg.message?.encEventResponseMessage;
609
+ const key = enc?.eventCreationMessageKey;
610
+ const found = key?.id && key.remoteJid ? await locate(key.remoteJid, key.id) : null;
611
+ const raw_secret = found?.doc.raw.message?.messageContextInfo?.messageSecret;
612
+ const secret = typeof raw_secret === 'string' ? Buffer.from(raw_secret, 'base64') : raw_secret;
613
+ if (found && secret && enc?.encPayload && enc.encIv) {
614
+ const mine = [socket.user?.lid, socket.user?.id];
615
+ const theirs = (from) => [from.remoteJid, from.participant, from.remoteJidAlt];
616
+ const responders = (msg.key.fromMe ? mine : theirs(msg.key)).filter((id) => Boolean(id));
617
+ const creators = (found.doc.raw.key?.fromMe ? mine : theirs(found.doc.raw.key ?? {})).filter((id) => Boolean(id));
618
+ for (const pair of responders.flatMap((who) => creators.map((creator) => [who, creator]))) {
619
+ try {
620
+ const parsed = decryptEventResponse({ encPayload: enc.encPayload, encIv: enc.encIv }, {
621
+ eventCreatorJid: jidNormalizedUser(pair[1]),
622
+ eventMsgId: found.doc.id,
623
+ eventEncKey: secret,
624
+ responderJid: jidNormalizedUser(pair[0]),
625
+ });
626
+ const response = { 1: 'going', 2: 'not_going', 3: 'maybe' }[parsed.response];
627
+ if (response) {
628
+ const author = await canonical(jidNormalizedUser((msg.key.fromMe ? socket.user?.id : msg.key.participant ?? cid) ?? cid));
629
+ found.doc.responses = [
630
+ ...(found.doc.responses ?? []).filter((entry) => entry.author !== author),
631
+ { author, response, guests: Number(parsed.extraGuestCount ?? 0), at: (Number(msg.messageTimestamp) || Math.floor(Date.now() / 1_000)) * 1_000 },
632
+ ];
633
+ await engine.set(found.path, serialize(found.doc), found.doc.created_at);
634
+ const instance = new Message(init, found.doc);
635
+ this.emit('message:updated', instance, await instance.chat(), this);
636
+ }
637
+ break;
638
+ }
639
+ catch {
640
+ /* identidad equivocada / wrong identity */
641
+ }
642
+ }
643
+ }
644
+ continue;
645
+ }
599
646
  if (kind === 'pollUpdateMessage') {
600
647
  const key = msg.message?.pollUpdateMessage?.pollCreationMessageKey;
601
648
  const vote = msg.message?.pollUpdateMessage?.vote;
package/package.json CHANGED
@@ -72,7 +72,7 @@
72
72
  "release": "npm publish --access public"
73
73
  },
74
74
  "types": "./build/esm/index.d.ts",
75
- "version": "8.0.0",
75
+ "version": "8.2.0",
76
76
  "engines": {
77
77
  "node": ">=20"
78
78
  },