@vanzxy/baileys 1.6.2 → 1.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/NOTICE.md +50 -0
  2. package/lib/Utils/A2UI.js +217 -0
  3. package/lib/Utils/MessageBuilder.js +332 -46
  4. package/lib/Utils/MessageBuilder_d.ts +45 -0
  5. package/lib/Utils/PersistentStore.js +592 -0
  6. package/lib/Utils/PersistentStore_d.ts +60 -0
  7. package/lib/Utils/anti-delete.d.ts +68 -0
  8. package/lib/Utils/anti-delete.js +185 -0
  9. package/lib/Utils/auto-reply.d.ts +47 -0
  10. package/lib/Utils/auto-reply.js +155 -0
  11. package/lib/Utils/button-helper-utils.js +314 -0
  12. package/lib/Utils/button-sender.js +817 -0
  13. package/lib/Utils/chat-history-helpers.d.ts +21 -0
  14. package/lib/Utils/chat-history-helpers.js +71 -0
  15. package/lib/Utils/index.d.ts +11 -0
  16. package/lib/Utils/index.js +16 -0
  17. package/lib/Utils/media-messages.d.ts +18 -0
  18. package/lib/Utils/media-messages.js +71 -0
  19. package/lib/Utils/media-set.d.ts +13 -0
  20. package/lib/Utils/media-set.js +165 -0
  21. package/lib/Utils/message-kind.js +139 -0
  22. package/lib/Utils/message-search.d.ts +44 -0
  23. package/lib/Utils/message-search.js +174 -0
  24. package/lib/Utils/scheduling.d.ts +42 -0
  25. package/lib/Utils/scheduling.js +140 -0
  26. package/lib/Utils/status.d.ts +50 -0
  27. package/lib/Utils/status.js +108 -0
  28. package/lib/Utils/stickerpack.d.ts +51 -0
  29. package/lib/Utils/stickerpack.js +276 -0
  30. package/lib/Utils/templates.d.ts +76 -0
  31. package/lib/Utils/templates.js +151 -0
  32. package/lib/Utils/use-sqlite-auth-state.js +28 -1
  33. package/lib/Utils/vcard.d.ts +58 -0
  34. package/lib/Utils/vcard.js +94 -0
  35. package/lib/VoIP/audio-feeder.d.ts +15 -0
  36. package/lib/VoIP/audio-feeder.js +132 -0
  37. package/lib/VoIP/index.js +277 -0
  38. package/lib/VoIP/relay-transport.d.ts +43 -0
  39. package/lib/VoIP/relay-transport.js +559 -0
  40. package/lib/VoIP/signaling.js +624 -0
  41. package/lib/VoIP/types.d.ts +69 -0
  42. package/lib/VoIP/types.js +17 -0
  43. package/lib/VoIP/wasm-engine.d.ts +103 -0
  44. package/lib/VoIP/wasm-engine.js +1214 -0
  45. package/lib/VoIP/worker-bootstrap.js +1042 -0
  46. package/lib/WABinary/generic-utils.js +8 -0
  47. package/lib/assets/wasm/loader.js +5 -0
  48. package/lib/assets/wasm/whatsapp.wasm +0 -0
  49. package/lib/assets/wasm/worker-modules.js +273 -0
  50. package/lib/index.js +4 -0
  51. package/package.json +22 -1
@@ -0,0 +1,21 @@
1
+ import type { WAMessage } from '../Types/index.js';
2
+ import type { AnyMediaMessageContent, WAMediaUploadFunction } from '../Types/Message.js';
3
+ import type { ILogger } from './logger.js';
4
+ import type { MediaType } from '../Defaults/index.js';
5
+ /** The object returned by `makeInMemoryStore()` (see lib/Store/make-in-memory-store.js). */
6
+ export interface InMemoryStoreLike {
7
+ messages?: Record<string, {
8
+ array: WAMessage[];
9
+ } | undefined>;
10
+ }
11
+ export declare const getLastMessageInChat: (store: InMemoryStoreLike, jid: string) => WAMessage | undefined;
12
+ export declare const getOldestMessageInChat: (store: InMemoryStoreLike, jid: string) => WAMessage | undefined;
13
+ export declare const copyNForward: (sock: {
14
+ sendMessage: (jid: string, content: unknown) => Promise<WAMessage | undefined>;
15
+ }, jid: string, message: WAMessage, forceForward?: boolean) => Promise<WAMessage | undefined>;
16
+ export declare const uploadMediaToWhatsApp: (sock: {
17
+ waUploadToServer: WAMediaUploadFunction;
18
+ }, message: AnyMediaMessageContent, opts?: {
19
+ logger?: ILogger;
20
+ mediaTypeOverride?: MediaType;
21
+ }) => Promise<any>;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Vanz@Add --- ported from Bail-master addons/chat-history-helpers.ts.
3
+ *
4
+ * NOTE: Bail-master's original version was written against ITS OWN
5
+ * `in-memory-store.ts` addon (a plain `Map<jid, WAMessage[]>`), which this fork
6
+ * does not have. `@vanzxy/baileys` already ships a full `makeInMemoryStore`
7
+ * (see lib/Store/make-in-memory-store.js), whose `store.messages[jid]` is a
8
+ * KeyedDB-backed ordered dictionary exposing `.array` — NOT a plain array or
9
+ * Map. getLastMessageInChat / getOldestMessageInChat below are rewritten
10
+ * against that shape so they work with this fork's real store out of the box.
11
+ * copyNForward and uploadMediaToWhatsApp are store-independent and ported as-is.
12
+ */
13
+ import { generateForwardMessageContent, prepareWAMessageMedia } from './messages.js';
14
+ /**
15
+ * Get the most recently stored message in a chat.
16
+ * `store` is the object returned by `makeInMemoryStore()`, kept in sync via
17
+ * `store.bind(sock.ev)`.
18
+ */
19
+ export const getLastMessageInChat = (store, jid) => {
20
+ const list = store.messages?.[jid];
21
+ const arr = list?.array;
22
+ if (!arr || arr.length === 0)
23
+ return undefined;
24
+ return arr[arr.length - 1];
25
+ };
26
+ /**
27
+ * Get the oldest stored message in a chat (useful as the `oldestMsgKey`
28
+ * cursor for `sock.fetchMessageHistory(...)`, which pages backwards from it).
29
+ */
30
+ export const getOldestMessageInChat = (store, jid) => {
31
+ const list = store.messages?.[jid];
32
+ const arr = list?.array;
33
+ if (!arr || arr.length === 0)
34
+ return undefined;
35
+ return arr[0];
36
+ };
37
+ /**
38
+ * Re-send ("copy-forward") an existing message to a (possibly different) jid.
39
+ * Thin wrapper around generateForwardMessageContent + sock.sendMessage —
40
+ * strips the original sender's quoting/context the same way WhatsApp's own
41
+ * "Forward" action does, and marks the copy as forwarded.
42
+ *
43
+ * Usage: await copyNForward(sock, targetJid, originalMessage)
44
+ */
45
+ export const copyNForward = async (sock, jid, message, forceForward = false) => {
46
+ const content = generateForwardMessageContent(message, forceForward);
47
+ return sock.sendMessage(jid, content);
48
+ };
49
+ /**
50
+ * Upload media directly to WhatsApp's own encrypted media CDN and get back
51
+ * a ready-to-send message-content object (with mediaKey, url/directPath,
52
+ * fileEncSha256, etc).
53
+ *
54
+ * IMPORTANT: WhatsApp clients only accept media that lives on WhatsApp's own
55
+ * CDN, encrypted with a mediaKey the recipient can derive — there is no way
56
+ * to point a WAMessage at an arbitrary third-party URL and have it render.
57
+ * This wrapper does the real, official upload (same path prepareWAMessageMedia
58
+ * / sock.waUploadToServer use internally) — it does not accept or return an
59
+ * arbitrary external URL.
60
+ *
61
+ * Usage: const media = await uploadMediaToWhatsApp(sock, { image: buffer })
62
+ * await sock.sendMessage(jid, media)
63
+ */
64
+ export const uploadMediaToWhatsApp = async (sock, message, opts) => {
65
+ return prepareWAMessageMedia(message, {
66
+ upload: sock.waUploadToServer,
67
+ logger: opts?.logger,
68
+ mediaTypeOverride: opts?.mediaTypeOverride
69
+ });
70
+ };
71
+ //# sourceMappingURL=chat-history-helpers.js.map
@@ -22,3 +22,14 @@ export * from "./browser-utils.js";
22
22
  export * from "./companion-reg-client-utils.js";
23
23
  export * from "./identity-change-handler.js";
24
24
  export * from "./stanza-ack.js";
25
+ export * from "./anti-delete.js";
26
+ export * from "./message-search.js";
27
+ export * from "./chat-history-helpers.js";
28
+ export * from "./scheduling.js";
29
+ export * from "./auto-reply.js";
30
+ export * from "./templates.js";
31
+ export * from "./vcard.js";
32
+ export * from "./media-messages.js";
33
+ export * from "./stickerpack.js";
34
+ export * from "./media-set.js";
35
+ export * from "./status.js";
@@ -18,9 +18,25 @@ export * from './event-buffer.js';
18
18
  export * from './process-message.js';
19
19
  export * from './rich-message-utils.js';
20
20
  export * from './MessageBuilder.js';
21
+ export * from './A2UI.js';
22
+ export * from './PersistentStore.js';
23
+ export * from './message-kind.js';
21
24
  export * from './message-retry-manager.js';
22
25
  export * from './browser-utils.js';
23
26
  export * from './companion-reg-client-utils.js';
24
27
  export * from './identity-change-handler.js';
25
28
  export * from './stanza-ack.js';
29
+ export * from './button-helper-utils.js';
30
+ export * from './button-sender.js';
31
+ export * from './anti-delete.js';
32
+ export * from './message-search.js';
33
+ export * from './chat-history-helpers.js';
34
+ export * from './scheduling.js';
35
+ export * from './auto-reply.js';
36
+ export * from './templates.js';
37
+ export * from './vcard.js';
38
+ export * from './media-messages.js';
39
+ export * from './stickerpack.js';
40
+ export * from './media-set.js';
41
+ export * from './status.js';
26
42
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,18 @@
1
+ import type { WAMediaUpload } from '../Types/index.js';
2
+ export declare const generateProfilePictureFull: (img: Buffer | string) => Promise<{
3
+ img: Buffer;
4
+ }>;
5
+ export declare const changeprofileFull: (img: Buffer | string) => Promise<{
6
+ img: Buffer;
7
+ }>;
8
+ export declare const generateProfilePictureFP: (buffer: Buffer | string) => Promise<{
9
+ img: Buffer;
10
+ preview: Buffer;
11
+ }>;
12
+ export declare const generatePP: (buffer: Buffer | string) => Promise<{
13
+ img: Buffer;
14
+ preview: Buffer;
15
+ }>;
16
+ export declare const generateProfilePicturee: (mediaUpload: WAMediaUpload) => Promise<{
17
+ img: Buffer;
18
+ }>;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Vanz@Add --- ported from Bail-master addons/media-messages.ts.
3
+ * Jimp-based profile-picture image generators (square + panoramic/wide).
4
+ * Deduplicated aliases kept intact: generateProfilePictureFull ===
5
+ * changeprofileFull, generateProfilePictureFP === generatePP (source had
6
+ * these as byte-identical pairs under different names).
7
+ */
8
+ import { Jimp, JimpMime } from 'jimp';
9
+ const toBuffer = async (stream) => {
10
+ const chunks = [];
11
+ for await (const chunk of stream) {
12
+ chunks.push(chunk);
13
+ }
14
+ stream.destroy?.();
15
+ return Buffer.concat(chunks);
16
+ };
17
+ /**
18
+ * Generates a panoramic/wide profile picture buffer — landscape images are
19
+ * scaled down to a 720px-wide target, portrait images to a 324px-wide
20
+ * target, preserving aspect ratio throughout.
21
+ */
22
+ const generateWideProfilePicture = async (img) => {
23
+ const jimp = await Jimp.read(img);
24
+ const width = jimp.bitmap.width;
25
+ const height = jimp.bitmap.height;
26
+ const ratio = width > height ? width / 720 : width / 324;
27
+ const targetWidth = Math.round(width / ratio);
28
+ const targetHeight = Math.round(height / ratio);
29
+ const buffer = await jimp.resize({ w: targetWidth, h: targetHeight }).getBuffer(JimpMime.jpeg, { quality: 100 });
30
+ return { img: buffer };
31
+ };
32
+ export const generateProfilePictureFull = generateWideProfilePicture;
33
+ export const changeprofileFull = generateWideProfilePicture;
34
+ /**
35
+ * Generates a square profile picture buffer (main image, scaled to fit
36
+ * within 720x720) plus a normalized preview buffer.
37
+ */
38
+ const generateSquareProfilePicture = async (buffer) => {
39
+ const jimp = await Jimp.read(buffer);
40
+ const img = await jimp.clone().scaleToFit({ w: 720, h: 720 }).getBuffer(JimpMime.jpeg);
41
+ const preview = await jimp.clone().normalize().getBuffer(JimpMime.jpeg);
42
+ return { img, preview };
43
+ };
44
+ export const generateProfilePictureFP = generateSquareProfilePicture;
45
+ export const generatePP = generateSquareProfilePicture;
46
+ /**
47
+ * Generates a profile picture buffer from a flexible input source — a raw
48
+ * Buffer, a `{ url }` media-upload descriptor, or a `{ stream }`
49
+ * media-upload descriptor. Resizes the longer dimension down to 720px,
50
+ * preserving aspect ratio on the other.
51
+ */
52
+ export const generateProfilePicturee = async (mediaUpload) => {
53
+ let bufferOrFilePath;
54
+ if (Buffer.isBuffer(mediaUpload)) {
55
+ bufferOrFilePath = mediaUpload;
56
+ }
57
+ else if ('url' in mediaUpload) {
58
+ bufferOrFilePath = mediaUpload.url.toString();
59
+ }
60
+ else {
61
+ bufferOrFilePath = await toBuffer(mediaUpload.stream);
62
+ }
63
+ const jimp = await Jimp.read(bufferOrFilePath);
64
+ const { width, height } = jimp.bitmap;
65
+ const resized = width > height
66
+ ? jimp.resize({ w: 720, h: Math.round((height / width) * 720) })
67
+ : jimp.resize({ w: Math.round((width / height) * 720), h: 720 });
68
+ const img = await resized.getBuffer(JimpMime.jpeg, { quality: 100 });
69
+ return { img };
70
+ };
71
+ //# sourceMappingURL=media-messages.js.map
@@ -0,0 +1,13 @@
1
+ import type { AnyMessageContent } from '../Types/index.js';
2
+ import type makeWASocket from '../Socket/index.js';
3
+ type WASocket = ReturnType<typeof makeWASocket>;
4
+ export declare const updateProfilePictureFull: (jid: string, content: Buffer | string, sock: WASocket) => Promise<any>;
5
+ export declare const updateProfilePictureFull2: (jid: string, content: Buffer | string, sock: WASocket) => Promise<any>;
6
+ type GroupStatusContent = AnyMessageContent & {
7
+ backgroundColor?: string;
8
+ };
9
+ export declare const groupStatus: (jid: string, content: GroupStatusContent, sock: WASocket) => Promise<any>;
10
+ export declare const groupStatusV2: (jids: string[], content: GroupStatusContent, sock: WASocket) => Promise<any[]>;
11
+ export declare const groupSetMemberLabel: (jid: string, memberLabel: string, sock: WASocket) => Promise<any>;
12
+ export declare const groupLabel: (jid: string, text: string, sock: WASocket) => Promise<void>;
13
+ export {};
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Vanz@Add --- ported from Bail-master addons/media-set.ts.
3
+ * Profile-picture setters (full/panoramic variants) and group-status /
4
+ * member-label senders. Depends on this fork's own media-messages.js
5
+ * (also ported this batch) and its existing generateWAMessageContent /
6
+ * generateWAMessageFromContent / unixTimestampSeconds / S_WHATSAPP_NET.
7
+ *
8
+ * NOTE ON DUPLICATE-LOOKING SETTERS: `updateProfilePictureFull` and
9
+ * `updateProfilePictureFull2` are genuinely different, not duplicates —
10
+ * the first sends the `img` buffer from `generateProfilePictureFP`
11
+ * (scaled-to-fit 720x720 main image), the second sends the `preview`
12
+ * buffer from `generatePP` (normalized preview). Both are kept.
13
+ */
14
+ import { randomBytes } from 'node:crypto';
15
+ import { generateWAMessageContent, generateWAMessageFromContent, unixTimestampSeconds } from './messages.js';
16
+ import { S_WHATSAPP_NET } from '../WABinary/index.js';
17
+ import { generatePP, generateProfilePictureFP } from './media-messages.js';
18
+ /** Update the profile picture for yourself or a group — sends the main (scaled-to-fit) image. */
19
+ export const updateProfilePictureFull = async (jid, content, sock) => {
20
+ const { query } = sock;
21
+ const { img } = await generateProfilePictureFP(content);
22
+ const media = await query({
23
+ tag: 'iq',
24
+ attrs: {
25
+ target: jid,
26
+ to: S_WHATSAPP_NET,
27
+ type: 'set',
28
+ xmlns: 'w:profile:picture'
29
+ },
30
+ content: [
31
+ {
32
+ tag: 'picture',
33
+ attrs: { type: 'image' },
34
+ content: img
35
+ }
36
+ ]
37
+ });
38
+ return media;
39
+ };
40
+ /** Update the profile picture for yourself or a group — sends the normalized preview image. */
41
+ export const updateProfilePictureFull2 = async (jid, content, sock) => {
42
+ const { query } = sock;
43
+ const { preview } = await generatePP(content);
44
+ const media = await query({
45
+ tag: 'iq',
46
+ attrs: {
47
+ target: jid,
48
+ to: S_WHATSAPP_NET,
49
+ type: 'set',
50
+ xmlns: 'w:profile:picture'
51
+ },
52
+ content: [
53
+ {
54
+ tag: 'picture',
55
+ attrs: { type: 'image' },
56
+ content: preview
57
+ }
58
+ ]
59
+ });
60
+ return media;
61
+ };
62
+ /** Send a group status (status update visible only within a group's members). */
63
+ export const groupStatus = async (jid, content, sock) => {
64
+ const { backgroundColor, ...rest } = content;
65
+ const inside = await generateWAMessageContent(rest, {
66
+ upload: sock.waUploadToServer,
67
+ backgroundColor
68
+ });
69
+ const messageSecret = randomBytes(32);
70
+ const m = generateWAMessageFromContent(jid, {
71
+ messageContextInfo: { messageSecret },
72
+ groupStatusMessageV2: {
73
+ message: {
74
+ ...inside,
75
+ messageContextInfo: { messageSecret }
76
+ }
77
+ }
78
+ }, {});
79
+ await sock.relayMessage(jid, m.message, { messageId: m.key.id });
80
+ return m;
81
+ };
82
+ /** Send the same group status to multiple groups at once. */
83
+ export const groupStatusV2 = async (jids, content, sock) => {
84
+ const { backgroundColor, ...rest } = content;
85
+ const inside = await generateWAMessageContent(rest, {
86
+ upload: sock.waUploadToServer,
87
+ backgroundColor
88
+ });
89
+ const messageSecret = randomBytes(32);
90
+ const results = [];
91
+ for (const id of jids) {
92
+ const m = generateWAMessageFromContent(id, {
93
+ messageContextInfo: { messageSecret },
94
+ groupStatusMessageV2: {
95
+ message: {
96
+ ...inside,
97
+ messageContextInfo: { messageSecret }
98
+ }
99
+ }
100
+ }, {});
101
+ await sock.relayMessage(id, m.message, { messageId: m.key.id });
102
+ results.push(m);
103
+ }
104
+ return results;
105
+ };
106
+ /**
107
+ * Set/update a member's label in a group (awaits the relay and returns the result).
108
+ * Label is truncated to 30 characters (WA's limit).
109
+ */
110
+ export const groupSetMemberLabel = async (jid, memberLabel, sock) => {
111
+ const result = await sock.relayMessage(jid, {
112
+ protocolMessage: {
113
+ type: 30,
114
+ memberLabel: {
115
+ label: memberLabel.slice(0, 30),
116
+ labelTimestamp: unixTimestampSeconds() || Date.now()
117
+ }
118
+ }
119
+ }, {
120
+ additionalNodes: [
121
+ {
122
+ tag: 'meta',
123
+ attrs: {
124
+ tag_reason: 'user_update',
125
+ appdata: 'member_tag'
126
+ },
127
+ content: undefined
128
+ }
129
+ ]
130
+ });
131
+ return result;
132
+ };
133
+ /**
134
+ * Set/update a member's label in a group — fire-and-forget variant (errors
135
+ * are swallowed, matching the source's behavior; prefer
136
+ * `groupSetMemberLabel` if you need to await/observe failures).
137
+ */
138
+ export const groupLabel = async (jid, text, sock) => {
139
+ try {
140
+ void sock.relayMessage(jid, {
141
+ protocolMessage: {
142
+ type: 30,
143
+ memberLabel: {
144
+ label: text.slice(0, 30),
145
+ labelTimestamp: Date.now()
146
+ }
147
+ }
148
+ }, {
149
+ additionalNodes: [
150
+ {
151
+ tag: 'meta',
152
+ attrs: {
153
+ tag_reason: 'user_update',
154
+ appdata: 'member_tag'
155
+ },
156
+ content: undefined
157
+ }
158
+ ]
159
+ });
160
+ }
161
+ catch {
162
+ // intentionally swallowed — matches source behavior
163
+ }
164
+ };
165
+ //# sourceMappingURL=media-set.js.map
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Evernight AI — lib/Utils/message-kind.js / Creator : Vanzxy🍃
3
+ *
4
+ * Addon-kind resolution logic adapted from zapo-js (MIT, © vinikjkkj)
5
+ * <https://github.com/vinikjkkj/zapo>, ported to this Baileys fork's
6
+ * message-content shape. The normalized reply parser below is original,
7
+ * written to cover this fork's own buttonsResponseMessage /
8
+ * listResponseMessage / interactiveResponseMessage / templateButtonReplyMessage
9
+ * send-side shapes (see messages.js).
10
+ */
11
+
12
+ /**
13
+ * Unwraps ephemeral/viewOnce/edited wrappers to get at the real content.
14
+ * Mirrors the wrapper set already handled by normalizeMessageContent()
15
+ * in messages.js, kept local here to avoid a circular import.
16
+ */
17
+ const unwrapMessage = (message) => {
18
+ let content = message;
19
+ for (let i = 0; i < 5; i++) {
20
+ const inner = content?.ephemeralMessage?.message ||
21
+ content?.viewOnceMessage?.message ||
22
+ content?.viewOnceMessageV2?.message ||
23
+ content?.viewOnceMessageV2Extension?.message ||
24
+ content?.documentWithCaptionMessage?.message ||
25
+ content?.editedMessage?.message;
26
+ if (!inner) {
27
+ break;
28
+ }
29
+ content = inner;
30
+ }
31
+ return content;
32
+ };
33
+
34
+ /**
35
+ * Companion "addon kind" for list / native-flow style messages.
36
+ * Ported from zapo-js's resolveButtonAddonKind (src/message/encode/content.ts).
37
+ * @typedef {'list' | 'interactive' | 'payment_info' | 'order_details'} WaButtonAddonKind
38
+ */
39
+
40
+ const resolveNativeFlowAddonKind = (nativeFlow) => {
41
+ const firstButtonName = nativeFlow?.buttons?.[0]?.name;
42
+ if (firstButtonName === 'payment_info')
43
+ return 'payment_info';
44
+ if (firstButtonName === 'review_and_pay')
45
+ return 'order_details';
46
+ return 'interactive';
47
+ };
48
+
49
+ /**
50
+ * Resolves which kind of button/list addon an outgoing message carries.
51
+ * Returns null if the message has no button/list/native-flow content.
52
+ * @param {import('../../WAProto').proto.IMessage} message
53
+ * @returns {WaButtonAddonKind | null}
54
+ */
55
+ export const resolveButtonAddonKind = (message) => {
56
+ const msg = unwrapMessage(message);
57
+ if (!msg)
58
+ return null;
59
+ if (msg.listMessage)
60
+ return 'list';
61
+ if (msg.buttonsMessage)
62
+ return 'interactive';
63
+ const nativeFlow = msg.interactiveMessage?.nativeFlowMessage;
64
+ if (nativeFlow)
65
+ return resolveNativeFlowAddonKind(nativeFlow);
66
+ return null;
67
+ };
68
+
69
+ /**
70
+ * Normalized shape returned by parseInteractiveReply, regardless of which
71
+ * underlying WhatsApp reply type produced it.
72
+ * @typedef {Object} NormalizedInteractiveReply
73
+ * @property {'buttons_response'|'list_response'|'native_flow_response'|'template_button_reply'|null} kind
74
+ * @property {string|null} id - the button/row/native-flow id the user selected
75
+ * @property {string|null} displayText - visible text of the selection, if present
76
+ * @property {Object|null} params - parsed paramsJson for native-flow responses, or null
77
+ */
78
+
79
+ /**
80
+ * Reads whatever a user tapped (button, list row, or native-flow reply) and
81
+ * returns one consistent shape, so plugin authors don't need a different
82
+ * branch per response type. Safe against malformed paramsJson (returns null
83
+ * instead of throwing).
84
+ * @param {import('../../WAProto').proto.IMessage} message
85
+ * @returns {NormalizedInteractiveReply}
86
+ */
87
+ export const parseInteractiveReply = (message) => {
88
+ const msg = unwrapMessage(message);
89
+ const empty = { kind: null, id: null, displayText: null, params: null };
90
+ if (!msg)
91
+ return empty;
92
+ if (msg.buttonsResponseMessage) {
93
+ const r = msg.buttonsResponseMessage;
94
+ return {
95
+ kind: 'buttons_response',
96
+ id: r.selectedButtonId || null,
97
+ displayText: r.selectedDisplayText || null,
98
+ params: null
99
+ };
100
+ }
101
+ if (msg.listResponseMessage) {
102
+ const r = msg.listResponseMessage;
103
+ return {
104
+ kind: 'list_response',
105
+ id: r.singleSelectReply?.selectedRowId || null,
106
+ displayText: r.title || r.description || null,
107
+ params: null
108
+ };
109
+ }
110
+ if (msg.interactiveResponseMessage) {
111
+ const r = msg.interactiveResponseMessage;
112
+ let params = null;
113
+ if (r.nativeFlowResponseMessage?.paramsJson) {
114
+ try {
115
+ params = JSON.parse(r.nativeFlowResponseMessage.paramsJson);
116
+ }
117
+ catch {
118
+ params = null;
119
+ }
120
+ }
121
+ return {
122
+ kind: 'native_flow_response',
123
+ id: params?.id ?? r.nativeFlowResponseMessage?.name ?? null,
124
+ displayText: r.body?.text || null,
125
+ params
126
+ };
127
+ }
128
+ if (msg.templateButtonReplyMessage) {
129
+ const r = msg.templateButtonReplyMessage;
130
+ return {
131
+ kind: 'template_button_reply',
132
+ id: r.selectedId || null,
133
+ displayText: r.selectedDisplayText || null,
134
+ params: null
135
+ };
136
+ }
137
+ return empty;
138
+ };
139
+ //# sourceMappingURL=message-kind.js.map
@@ -0,0 +1,44 @@
1
+ import type { WAMessage } from '../Types/index.js';
2
+ export type SearchMessageType = 'text' | 'image' | 'video' | 'document' | 'audio' | 'sticker' | 'location' | 'contact' | 'other';
3
+ export interface SearchOptions {
4
+ jid?: string;
5
+ fromDate?: Date;
6
+ toDate?: Date;
7
+ fromSender?: string;
8
+ fromMe?: boolean;
9
+ messageTypes?: SearchMessageType[];
10
+ limit?: number;
11
+ caseSensitive?: boolean;
12
+ }
13
+ export interface SearchResult {
14
+ message: WAMessage;
15
+ matchedText: string;
16
+ matchPosition: number;
17
+ relevanceScore: number;
18
+ }
19
+ export interface RegexSearchOptions {
20
+ jid?: string;
21
+ fromSender?: string;
22
+ fromMe?: boolean;
23
+ messageTypes?: SearchMessageType[];
24
+ limit?: number;
25
+ }
26
+ export declare const extractMessageText: (message: WAMessage) => string;
27
+ export declare const calculateRelevance: (query: string, text: string, position: number) => number;
28
+ export declare const searchMessages: (messages: WAMessage[], query: string, options?: SearchOptions) => SearchResult[];
29
+ export declare const searchMessagesRegex: (messages: WAMessage[], pattern: RegExp, options?: RegexSearchOptions) => SearchResult[];
30
+ export declare class MessageSearchManager {
31
+ private messages;
32
+ private messageIndex;
33
+ addMessages(messages: WAMessage[]): void;
34
+ removeMessages(messageIds: string[]): void;
35
+ clear(): void;
36
+ get count(): number;
37
+ search(query: string, options?: SearchOptions): SearchResult[];
38
+ searchRegex(pattern: RegExp, options?: RegexSearchOptions): SearchResult[];
39
+ getByJid(jid: string): WAMessage[];
40
+ getBySender(sender: string): WAMessage[];
41
+ getByType(type: SearchMessageType): WAMessage[];
42
+ getById(id: string): WAMessage | undefined;
43
+ }
44
+ export declare const createMessageSearch: () => MessageSearchManager;