@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.
Potentially problematic release.
This version of @vanzxy/baileys might be problematic. Click here for more details.
- package/NOTICE.md +50 -0
- package/lib/Utils/A2UI.js +217 -0
- package/lib/Utils/MessageBuilder.js +332 -46
- package/lib/Utils/MessageBuilder_d.ts +45 -0
- package/lib/Utils/PersistentStore.js +592 -0
- package/lib/Utils/PersistentStore_d.ts +60 -0
- package/lib/Utils/anti-delete.d.ts +68 -0
- package/lib/Utils/anti-delete.js +185 -0
- package/lib/Utils/auto-reply.d.ts +47 -0
- package/lib/Utils/auto-reply.js +155 -0
- package/lib/Utils/button-helper-utils.js +314 -0
- package/lib/Utils/button-sender.js +817 -0
- package/lib/Utils/chat-history-helpers.d.ts +21 -0
- package/lib/Utils/chat-history-helpers.js +71 -0
- package/lib/Utils/index.d.ts +11 -0
- package/lib/Utils/index.js +16 -0
- package/lib/Utils/media-messages.d.ts +18 -0
- package/lib/Utils/media-messages.js +71 -0
- package/lib/Utils/media-set.d.ts +13 -0
- package/lib/Utils/media-set.js +165 -0
- package/lib/Utils/message-kind.js +139 -0
- package/lib/Utils/message-search.d.ts +44 -0
- package/lib/Utils/message-search.js +174 -0
- package/lib/Utils/scheduling.d.ts +42 -0
- package/lib/Utils/scheduling.js +140 -0
- package/lib/Utils/status.d.ts +50 -0
- package/lib/Utils/status.js +108 -0
- package/lib/Utils/stickerpack.d.ts +51 -0
- package/lib/Utils/stickerpack.js +276 -0
- package/lib/Utils/templates.d.ts +76 -0
- package/lib/Utils/templates.js +151 -0
- package/lib/Utils/use-sqlite-auth-state.js +28 -1
- package/lib/Utils/vcard.d.ts +58 -0
- package/lib/Utils/vcard.js +94 -0
- package/lib/VoIP/audio-feeder.d.ts +15 -0
- package/lib/VoIP/audio-feeder.js +132 -0
- package/lib/VoIP/index.js +277 -0
- package/lib/VoIP/relay-transport.d.ts +43 -0
- package/lib/VoIP/relay-transport.js +559 -0
- package/lib/VoIP/signaling.js +624 -0
- package/lib/VoIP/types.d.ts +69 -0
- package/lib/VoIP/types.js +17 -0
- package/lib/VoIP/wasm-engine.d.ts +103 -0
- package/lib/VoIP/wasm-engine.js +1214 -0
- package/lib/VoIP/worker-bootstrap.js +1042 -0
- package/lib/WABinary/generic-utils.js +8 -0
- package/lib/assets/wasm/loader.js +5 -0
- package/lib/assets/wasm/whatsapp.wasm +0 -0
- package/lib/assets/wasm/worker-modules.js +273 -0
- package/lib/index.js +4 -0
- package/package.json +22 -1
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
// Evernight AI β lib/Utils/button-helper-utils.js / Creator : Vanzxyπ
|
|
2
|
+
// Ported from @queenanya/baileys (Bail-master fork) src/addons/message-utils.ts
|
|
3
|
+
// Original credit inside that file: "Ported from @ryuu-reinzz/button-helper v2.2.5"
|
|
4
|
+
// Converted TS -> JS ESM to match @vanzxy/baileys compiled-lib conventions.
|
|
5
|
+
|
|
6
|
+
import { randomBytes } from 'crypto';
|
|
7
|
+
import { generateWAMessage, generateWAMessageFromContent, normalizeMessageContent } from './messages.js';
|
|
8
|
+
import { getUrlFromDirectPath } from './messages-media.js';
|
|
9
|
+
import { unixTimestampSeconds } from './generics.js';
|
|
10
|
+
import { getBinaryNodeChild, isJidGroup, isJidNewsletter, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
11
|
+
import { QueryIds, XWAPaths } from '../Types/Mex.js';
|
|
12
|
+
|
|
13
|
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
14
|
+
// SECTION 1 β Message Type Detection
|
|
15
|
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
16
|
+
|
|
17
|
+
/** @param {import('../../WAProto/index.js').proto.IMessage} message */
|
|
18
|
+
export function getMediaType(message) {
|
|
19
|
+
if (message.imageMessage) return 'image';
|
|
20
|
+
if (message.videoMessage) return message.videoMessage.gifPlayback ? 'gif' : 'video';
|
|
21
|
+
if (message.audioMessage) return message.audioMessage.ptt ? 'ptt' : 'audio';
|
|
22
|
+
if (message.contactMessage) return 'vcard';
|
|
23
|
+
if (message.documentMessage) return 'document';
|
|
24
|
+
if (message.contactsArrayMessage) return 'contact_array';
|
|
25
|
+
if (message.liveLocationMessage) return 'livelocation';
|
|
26
|
+
if (message.stickerMessage) return 'sticker';
|
|
27
|
+
if (message.listMessage) return 'list';
|
|
28
|
+
if (message.listResponseMessage) return 'list_response';
|
|
29
|
+
if (message.buttonsResponseMessage) return 'buttons_response';
|
|
30
|
+
if (message.orderMessage) return 'order';
|
|
31
|
+
if (message.productMessage) return 'product';
|
|
32
|
+
if (message.interactiveResponseMessage) return 'native_flow_response';
|
|
33
|
+
if (message.groupInviteMessage) return 'url';
|
|
34
|
+
return '';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** @param {import('../../WAProto/index.js').proto.IMessage} message */
|
|
38
|
+
export function getMessageType(message) {
|
|
39
|
+
const normalizedMessage = normalizeMessageContent(message);
|
|
40
|
+
if (!normalizedMessage) return 'text';
|
|
41
|
+
if (normalizedMessage.reactionMessage || normalizedMessage.encReactionMessage) return 'reaction';
|
|
42
|
+
if (
|
|
43
|
+
normalizedMessage.pollCreationMessage ||
|
|
44
|
+
normalizedMessage.pollCreationMessageV2 ||
|
|
45
|
+
normalizedMessage.pollCreationMessageV3 ||
|
|
46
|
+
normalizedMessage.pollUpdateMessage
|
|
47
|
+
)
|
|
48
|
+
return 'poll';
|
|
49
|
+
if (normalizedMessage.eventMessage) return 'event';
|
|
50
|
+
if (getMediaType(normalizedMessage) !== '') return 'media';
|
|
51
|
+
return 'text';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
55
|
+
// SECTION 2 β Button / Biz Node Helpers
|
|
56
|
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
57
|
+
|
|
58
|
+
/** @param {import('../../WAProto/index.js').proto.IMessage} message */
|
|
59
|
+
export function getButtonType(message) {
|
|
60
|
+
const inner = message.viewOnceMessageV2Extension?.message || message;
|
|
61
|
+
if (inner.listMessage) return 'list';
|
|
62
|
+
if (inner.buttonsMessage) return 'buttons';
|
|
63
|
+
if (inner.interactiveMessage?.nativeFlowMessage) return 'native_flow';
|
|
64
|
+
if (inner.interactiveMessage?.carouselMessage) return 'native_flow';
|
|
65
|
+
if (message.viewOnceMessage?.message?.interactiveMessage?.carouselMessage) return 'native_flow';
|
|
66
|
+
if (message.viewOnceMessageV2?.message?.interactiveMessage?.carouselMessage) return 'native_flow';
|
|
67
|
+
if (message.viewOnceMessage?.message?.interactiveMessage?.nativeFlowMessage) return 'native_flow';
|
|
68
|
+
if (message.viewOnceMessageV2?.message?.interactiveMessage?.nativeFlowMessage) return 'native_flow';
|
|
69
|
+
if (message.viewOnceMessageV2Extension?.message?.interactiveMessage?.nativeFlowMessage) return 'native_flow';
|
|
70
|
+
if (message.viewOnceMessageV2Extension?.message?.interactiveMessage?.carouselMessage) return 'native_flow';
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Derive the binary node(s) that must accompany a button/interactive/list
|
|
76
|
+
* message so it renders correctly across WA Messenger + WA Business,
|
|
77
|
+
* Android + iOS.
|
|
78
|
+
* @param {import('../../WAProto/index.js').proto.IMessage} message
|
|
79
|
+
* @returns {import('../WABinary/index.js').BinaryNode}
|
|
80
|
+
*/
|
|
81
|
+
export function getButtonArgs(message) {
|
|
82
|
+
const inner = message.viewOnceMessageV2Extension?.message || message;
|
|
83
|
+
const nativeFlow =
|
|
84
|
+
inner.interactiveMessage?.nativeFlowMessage ||
|
|
85
|
+
message.viewOnceMessage?.message?.interactiveMessage?.nativeFlowMessage ||
|
|
86
|
+
message.viewOnceMessageV2?.message?.interactiveMessage?.nativeFlowMessage;
|
|
87
|
+
const carouselMessage =
|
|
88
|
+
inner.interactiveMessage?.carouselMessage ||
|
|
89
|
+
message.viewOnceMessage?.message?.interactiveMessage?.carouselMessage ||
|
|
90
|
+
message.viewOnceMessageV2?.message?.interactiveMessage?.carouselMessage;
|
|
91
|
+
|
|
92
|
+
const firstButtonName =
|
|
93
|
+
nativeFlow?.buttons?.[0]?.name ||
|
|
94
|
+
carouselMessage?.cards?.[0]?.nativeFlowMessage?.buttons?.[0]?.name;
|
|
95
|
+
const nativeFlowSpecials = [
|
|
96
|
+
'mpm',
|
|
97
|
+
'cta_catalog',
|
|
98
|
+
'send_location',
|
|
99
|
+
'call_permission_request',
|
|
100
|
+
'wa_payment_transaction_details',
|
|
101
|
+
'automated_greeting_message_view_catalog'
|
|
102
|
+
];
|
|
103
|
+
const ts = unixTimestampSeconds().toString();
|
|
104
|
+
if (nativeFlow && (firstButtonName === 'review_and_pay' || firstButtonName === 'payment_info')) {
|
|
105
|
+
return {
|
|
106
|
+
tag: 'biz',
|
|
107
|
+
attrs: { native_flow_name: firstButtonName === 'review_and_pay' ? 'order_details' : firstButtonName }
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (nativeFlow && nativeFlowSpecials.includes(firstButtonName ?? '')) {
|
|
112
|
+
return {
|
|
113
|
+
tag: 'biz',
|
|
114
|
+
attrs: { actual_actors: '2', host_storage: '2', privacy_mode_ts: ts },
|
|
115
|
+
content: [
|
|
116
|
+
{
|
|
117
|
+
tag: 'interactive',
|
|
118
|
+
attrs: { type: 'native_flow', v: '1' },
|
|
119
|
+
content: [{ tag: 'native_flow', attrs: { v: '2', name: firstButtonName } }]
|
|
120
|
+
},
|
|
121
|
+
{ tag: 'quality_control', attrs: { source_type: 'third_party' } }
|
|
122
|
+
]
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (nativeFlow || carouselMessage || message.buttonsMessage) {
|
|
127
|
+
return {
|
|
128
|
+
tag: 'biz',
|
|
129
|
+
attrs: {},
|
|
130
|
+
content: [
|
|
131
|
+
{
|
|
132
|
+
tag: 'interactive',
|
|
133
|
+
attrs: { type: 'native_flow', v: '1' },
|
|
134
|
+
content: [{ tag: 'native_flow', attrs: { v: '9', name: 'mixed' } }]
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (inner.listMessage) {
|
|
141
|
+
return { tag: 'biz', attrs: {}, content: [{ tag: 'list', attrs: { v: '2', type: 'product_list' } }] };
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return { tag: 'biz', attrs: {} };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
148
|
+
// SECTION 3 β WS Extras (mentions, media, MD patch, album, socket extras)
|
|
149
|
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
150
|
+
|
|
151
|
+
/** Build contextInfo for @mention or @all. */
|
|
152
|
+
export const buildMentionContextInfo = (message) => {
|
|
153
|
+
if (message.mentionAll) return { contextInfo: { nonJidMentions: 1 } };
|
|
154
|
+
if (message.mentions?.length) return { contextInfo: { mentionedJid: message.mentions } };
|
|
155
|
+
return { contextInfo: {} };
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/** Extract embedded media from buttons/interactive message (top-level or header-nested). */
|
|
159
|
+
export const extractFromButtonsMessage = (msg) => {
|
|
160
|
+
const header = typeof msg.header === 'object' && msg.header !== null;
|
|
161
|
+
if (header ? msg.header?.imageMessage : msg.imageMessage)
|
|
162
|
+
return { imageMessage: header ? msg.header.imageMessage : msg.imageMessage };
|
|
163
|
+
if (header ? msg.header?.videoMessage : msg.videoMessage)
|
|
164
|
+
return { videoMessage: header ? msg.header.videoMessage : msg.videoMessage };
|
|
165
|
+
if (header ? msg.header?.documentMessage : msg.documentMessage)
|
|
166
|
+
return { documentMessage: header ? msg.header.documentMessage : msg.documentMessage };
|
|
167
|
+
return null;
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
/** Normalise media input: string β { url }, Buffer β as-is, others β as-is. */
|
|
171
|
+
export const normalizeMediaInput = (media) => {
|
|
172
|
+
if (!media) return media;
|
|
173
|
+
if (Buffer.isBuffer(media)) return media;
|
|
174
|
+
if (typeof media === 'string') return { url: media };
|
|
175
|
+
return media;
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/** Wrap buttons/template/list/interactive in viewOnceMessageV2Extension for MD clients. */
|
|
179
|
+
export const patchMessageForMdIfRequired = (message) => {
|
|
180
|
+
if (
|
|
181
|
+
message?.buttonsMessage ||
|
|
182
|
+
message?.templateMessage ||
|
|
183
|
+
message?.listMessage ||
|
|
184
|
+
message?.interactiveMessage?.nativeFlowMessage
|
|
185
|
+
) {
|
|
186
|
+
return {
|
|
187
|
+
viewOnceMessageV2Extension: {
|
|
188
|
+
message: {
|
|
189
|
+
messageContextInfo: { deviceListMetadataVersion: 2, deviceListMetadata: {} },
|
|
190
|
+
...message
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return message;
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Build and relay an album (multi-image/video) message.
|
|
201
|
+
* @param {string} jid
|
|
202
|
+
* @param {Array<object>} albums
|
|
203
|
+
* @param {{ userJid: string, suki: { relayMessage: Function, waUploadToServer: Function } }} options
|
|
204
|
+
* @returns {Promise<Array<object>>} Array of individual media WAMessage objects
|
|
205
|
+
* @example
|
|
206
|
+
* const items = await prepareAlbumMessageContent(jid, [
|
|
207
|
+
* { image: { url: 'https://...' }, caption: 'Photo 1' },
|
|
208
|
+
* { video: { url: 'https://...' }, caption: 'Video 1' }
|
|
209
|
+
* ], { userJid: sock.user.id, suki: sock })
|
|
210
|
+
*/
|
|
211
|
+
export const prepareAlbumMessageContent = async (jid, albums, options) => {
|
|
212
|
+
const messages = [];
|
|
213
|
+
|
|
214
|
+
const albumMsg = generateWAMessageFromContent(
|
|
215
|
+
jid,
|
|
216
|
+
{
|
|
217
|
+
albumMessage: {
|
|
218
|
+
expectedImageCount: albums.filter((item) => 'image' in item).length,
|
|
219
|
+
expectedVideoCount: albums.filter((item) => 'video' in item).length
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
{ userJid: options.userJid }
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
await options.suki.relayMessage(jid, albumMsg.message, { messageId: albumMsg.key.id });
|
|
226
|
+
|
|
227
|
+
for (const media of albums) {
|
|
228
|
+
let mediaMsg;
|
|
229
|
+
const uploadFn = async (encFilePath, opts) => {
|
|
230
|
+
const res = await options.suki.waUploadToServer(encFilePath, {
|
|
231
|
+
...opts,
|
|
232
|
+
newsletter: isJidNewsletter(jid)
|
|
233
|
+
});
|
|
234
|
+
return {
|
|
235
|
+
mediaUrl: res.url ?? '',
|
|
236
|
+
directPath: res.directPath ?? '',
|
|
237
|
+
handle: res.handle,
|
|
238
|
+
mediaKey: res.mediaKey,
|
|
239
|
+
fileEncSha256: res.fileEncSha256,
|
|
240
|
+
fileSha256: res.fileSha256,
|
|
241
|
+
fileLength: res.fileLength
|
|
242
|
+
};
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
const sharedOpts = { userJid: options.userJid, upload: uploadFn };
|
|
246
|
+
|
|
247
|
+
if ('image' in media && media.image) mediaMsg = await generateWAMessage(jid, media, sharedOpts);
|
|
248
|
+
else if ('video' in media && media.video) mediaMsg = await generateWAMessage(jid, media, sharedOpts);
|
|
249
|
+
|
|
250
|
+
if (mediaMsg) {
|
|
251
|
+
mediaMsg.message.messageContextInfo = {
|
|
252
|
+
messageSecret: randomBytes(32),
|
|
253
|
+
messageAssociation: { associationType: 1, parentMessageKey: albumMsg.key }
|
|
254
|
+
};
|
|
255
|
+
messages.push(mediaMsg);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return messages;
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Addon factory for socket-level message extras (profilePictureUrl, getEphemeralGroup).
|
|
264
|
+
* @param {{ query: Function, newsletterWMexQuery?: Function }} ctx
|
|
265
|
+
*/
|
|
266
|
+
export const makeMessageExtrasAddon = (ctx) => {
|
|
267
|
+
const { query, newsletterWMexQuery } = ctx;
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Fetch profile picture URL for any JID, including newsletters.
|
|
271
|
+
* @example
|
|
272
|
+
* const url = await sock.profilePictureUrl('1234567890@s.whatsapp.net')
|
|
273
|
+
*/
|
|
274
|
+
const profilePictureUrl = async (jid) => {
|
|
275
|
+
if (isJidNewsletter(jid) && newsletterWMexQuery) {
|
|
276
|
+
const node = await newsletterWMexQuery(undefined, QueryIds.METADATA, {
|
|
277
|
+
input: { key: jid, type: 'JID', view_role: 'GUEST' },
|
|
278
|
+
fetch_viewer_metadata: true,
|
|
279
|
+
fetch_full_image: true,
|
|
280
|
+
fetch_creation_time: true
|
|
281
|
+
});
|
|
282
|
+
const resultStr = getBinaryNodeChild(node, 'result')?.content?.toString();
|
|
283
|
+
if (!resultStr) return null;
|
|
284
|
+
|
|
285
|
+
const metadata = JSON.parse(resultStr).data[XWAPaths.xwa2_newsletter_metadata];
|
|
286
|
+
return getUrlFromDirectPath(metadata?.thread_metadata?.picture?.direct_path || '');
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const result = await query({
|
|
290
|
+
tag: 'iq',
|
|
291
|
+
attrs: { target: jidNormalizedUser(jid), to: S_WHATSAPP_NET, type: 'get', xmlns: 'w:profile:picture' },
|
|
292
|
+
content: [{ tag: 'picture', attrs: { type: 'image', query: 'url' }, content: undefined }]
|
|
293
|
+
});
|
|
294
|
+
return getBinaryNodeChild(result, 'picture')?.attrs?.url || null;
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Query the ephemeral (disappearing messages) timer for a group.
|
|
299
|
+
* @returns {Promise<number|string>} timer in seconds, or 0 if not set
|
|
300
|
+
* @example
|
|
301
|
+
* const timer = await sock.getEphemeralGroup('120363xxx@g.us')
|
|
302
|
+
*/
|
|
303
|
+
const getEphemeralGroup = async (jid) => {
|
|
304
|
+
if (!isJidGroup(jid)) throw new TypeError('Jid should originate from a group!');
|
|
305
|
+
const result = await query({
|
|
306
|
+
tag: 'iq',
|
|
307
|
+
attrs: { id: `ephemeral-${Date.now()}`, to: jid, type: 'get', xmlns: 'w:g2' },
|
|
308
|
+
content: [{ tag: 'query', attrs: { request: 'interactive' }, content: undefined }]
|
|
309
|
+
});
|
|
310
|
+
return getBinaryNodeChild(getBinaryNodeChild(result, 'group'), 'ephemeral')?.attrs?.expiration || 0;
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
return { profilePictureUrl, getEphemeralGroup };
|
|
314
|
+
};
|