@isaxn/bailyes 1.0.0 → 2.1.3
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.
- package/README.md +271 -23
- package/package.json +24 -12
- package/src/core/baileys-loader.js +16 -0
- package/src/core/client.js +155 -35
- package/src/core/context.js +95 -35
- package/src/core/events.js +14 -2
- package/src/core/handler.js +36 -19
- package/src/core/store.js +209 -0
- package/src/index.js +101 -23
- package/src/message/ai-rich.js +457 -0
- package/src/message/base-builder.js +54 -0
- package/src/message/button-v2.js +104 -0
- package/src/message/button.js +221 -0
- package/src/message/carousel.js +57 -0
- package/src/message/index.js +34 -0
- package/src/message/inline-entities.js +168 -0
- package/src/message/link-preview.js +56 -0
- package/src/message/live-photo.js +59 -0
- package/src/message/live-thumbnail.js +56 -0
- package/src/message/native-flow.js +28 -0
- package/src/message/quick.js +117 -0
- package/src/message/table.js +39 -0
- package/src/message/tokenizer.js +207 -0
- package/src/message/toolkit.js +233 -0
- package/dist/core/client.cjs +0 -65
- package/dist/index.cjs +0 -6
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const crypto = require("crypto");
|
|
4
|
+
const { BaseBuilder } = require("./base-builder.js");
|
|
5
|
+
const { Toolkit } = require("./toolkit.js");
|
|
6
|
+
const { extractIE, waitAllPromises } = require("./inline-entities.js");
|
|
7
|
+
const { tokenize } = require("./tokenizer.js");
|
|
8
|
+
const { toTableMetadata } = require("./table.js");
|
|
9
|
+
|
|
10
|
+
function newLayout(name, data, extra = {}) {
|
|
11
|
+
return {
|
|
12
|
+
...extra,
|
|
13
|
+
view_model: {
|
|
14
|
+
[Array.isArray(data) ? "primitives" : "primitive"]: data,
|
|
15
|
+
__typename: `GenAI${name}LayoutViewModel`
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
class AIRich extends BaseBuilder {
|
|
21
|
+
#client;
|
|
22
|
+
|
|
23
|
+
constructor(client) {
|
|
24
|
+
if (!client) throw new Error("Socket is required");
|
|
25
|
+
|
|
26
|
+
super();
|
|
27
|
+
this.#client = client;
|
|
28
|
+
this._submessages = [];
|
|
29
|
+
this._sections = [];
|
|
30
|
+
this._richResponseSources = [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
addSubmessage(submessage) {
|
|
34
|
+
const items = Array.isArray(submessage) ? submessage : [submessage];
|
|
35
|
+
|
|
36
|
+
for (const item of items) {
|
|
37
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) {
|
|
38
|
+
throw new TypeError("Submessage must be a plain object or array of plain objects");
|
|
39
|
+
}
|
|
40
|
+
this._submessages.push(item);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return this;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
addSection(section) {
|
|
47
|
+
const items = Array.isArray(section) ? section : [section];
|
|
48
|
+
|
|
49
|
+
for (const item of items) {
|
|
50
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) {
|
|
51
|
+
throw new TypeError("Section must be a plain object or array of plain objects");
|
|
52
|
+
}
|
|
53
|
+
this._sections.push(item);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
addText(text, { hyperlink = true, citation = true, latex = true } = {}) {
|
|
60
|
+
if (typeof text !== "string") throw new TypeError("Text must be a string");
|
|
61
|
+
|
|
62
|
+
const { text: extractedText, inline_entities } = extractIE(text, { hyperlink, citation, latex });
|
|
63
|
+
|
|
64
|
+
this._submessages.push({ messageType: 2, messageText: extractedText });
|
|
65
|
+
|
|
66
|
+
this._sections.push(
|
|
67
|
+
newLayout("Single", {
|
|
68
|
+
text: extractedText,
|
|
69
|
+
...(inline_entities.length && { inline_entities }),
|
|
70
|
+
__typename: "GenAIMarkdownTextUXPrimitive"
|
|
71
|
+
})
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
addCode(language, code) {
|
|
78
|
+
if (typeof language !== "string" || typeof code !== "string") {
|
|
79
|
+
throw new TypeError("Language and code must be a string");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const meta = tokenize(code, language);
|
|
83
|
+
|
|
84
|
+
this._submessages.push({
|
|
85
|
+
messageType: 5,
|
|
86
|
+
codeMetadata: { codeLanguage: language, codeBlocks: meta.codeBlock }
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
this._sections.push(
|
|
90
|
+
newLayout("Single", {
|
|
91
|
+
language,
|
|
92
|
+
code_blocks: meta.unified_codeBlock,
|
|
93
|
+
__typename: "GenAICodeUXPrimitive"
|
|
94
|
+
})
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
return this;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
addTable(table, { hyperlink = true, citation = true, latex = true } = {}) {
|
|
101
|
+
if (!Array.isArray(table)) throw new TypeError("Table must be an array");
|
|
102
|
+
|
|
103
|
+
const meta = toTableMetadata(table, { hyperlink, citation, latex });
|
|
104
|
+
|
|
105
|
+
this._submessages.push({
|
|
106
|
+
messageType: 4,
|
|
107
|
+
tableMetadata: { title: meta.title, rows: meta.rows }
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
this._sections.push(
|
|
111
|
+
newLayout("Single", { rows: meta.unified_rows, __typename: "GenATableUXPrimitive" })
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
addSource(sources = []) {
|
|
118
|
+
const isStringArray = Array.isArray(sources) && sources.every((item) => typeof item === "string");
|
|
119
|
+
const isNestedArray =
|
|
120
|
+
Array.isArray(sources) && sources.every((item) => Array.isArray(item) && item.every((v) => typeof v === "string"));
|
|
121
|
+
|
|
122
|
+
if (!(isStringArray || isNestedArray)) {
|
|
123
|
+
throw new TypeError("Sources must be a string array or an array of string arrays");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const normalized = isStringArray ? [sources] : sources;
|
|
127
|
+
|
|
128
|
+
const source = normalized.map(([icon, url, text]) => ({
|
|
129
|
+
source_type: "THIRD_PARTY",
|
|
130
|
+
source_display_name: text ?? "",
|
|
131
|
+
source_subtitle: "AI",
|
|
132
|
+
source_url: url ?? "",
|
|
133
|
+
favicon: {
|
|
134
|
+
url: Toolkit.resolveMedia(this.#client, icon ?? "", "image"),
|
|
135
|
+
mime_type: "image/jpeg",
|
|
136
|
+
width: 16,
|
|
137
|
+
height: 16
|
|
138
|
+
}
|
|
139
|
+
}));
|
|
140
|
+
|
|
141
|
+
this._sections.push(newLayout("Single", { sources: source, __typename: "GenAISearchResultPrimitive" }));
|
|
142
|
+
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
addReels(reelsItems = []) {
|
|
147
|
+
const isSingleObject = reelsItems && typeof reelsItems === "object" && !Array.isArray(reelsItems);
|
|
148
|
+
const isObjectArray =
|
|
149
|
+
Array.isArray(reelsItems) && reelsItems.every((item) => item && typeof item === "object" && !Array.isArray(item));
|
|
150
|
+
|
|
151
|
+
if (!(isSingleObject || isObjectArray)) {
|
|
152
|
+
throw new TypeError("Reels items must be an object or an array of objects");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const items = Array.isArray(reelsItems) ? reelsItems : [reelsItems];
|
|
156
|
+
|
|
157
|
+
const reels = items.map((item) => ({
|
|
158
|
+
...item,
|
|
159
|
+
_avatar: Toolkit.resolveMedia(this.#client, item.profileIconUrl ?? item.profile_url ?? item.profile ?? "", "image"),
|
|
160
|
+
_thumbnail: Toolkit.resolveMedia(this.#client, item.thumbnailUrl ?? item.thumbnail ?? "", "image")
|
|
161
|
+
}));
|
|
162
|
+
|
|
163
|
+
this._submessages.push({
|
|
164
|
+
messageType: 9,
|
|
165
|
+
contentItemsMetadata: {
|
|
166
|
+
contentType: 1,
|
|
167
|
+
itemsMetadata: reels.map((item) => ({
|
|
168
|
+
reelItem: {
|
|
169
|
+
title: item.username ?? "",
|
|
170
|
+
profileIconUrl: item._avatar,
|
|
171
|
+
thumbnailUrl: item._thumbnail,
|
|
172
|
+
videoUrl: item.videoUrl ?? item.url ?? ""
|
|
173
|
+
}
|
|
174
|
+
}))
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
reels.forEach((item, idx) => {
|
|
179
|
+
this._richResponseSources.push({
|
|
180
|
+
provider: "NIXEL",
|
|
181
|
+
thumbnailCDNURL: item._thumbnail,
|
|
182
|
+
sourceProviderURL: item.videoUrl ?? item.url ?? "",
|
|
183
|
+
sourceQuery: "",
|
|
184
|
+
faviconCDNURL: item._avatar,
|
|
185
|
+
citationNumber: idx + 1,
|
|
186
|
+
sourceTitle: item.username ?? ""
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
this._sections.push(
|
|
191
|
+
newLayout(
|
|
192
|
+
"HScroll",
|
|
193
|
+
reels.map((item) => ({
|
|
194
|
+
reels_url: item.videoUrl ?? item.url ?? "",
|
|
195
|
+
thumbnail_url: item._thumbnail,
|
|
196
|
+
creator: item.username ?? item.title ?? "",
|
|
197
|
+
avatar_url: item._avatar,
|
|
198
|
+
reels_title: item.reels_title ?? item.title ?? "",
|
|
199
|
+
likes_count: item.likes_count ?? item.like ?? 0,
|
|
200
|
+
shares_count: item.shares_count ?? item.share ?? 0,
|
|
201
|
+
view_count: item.view_count ?? item.view ?? 0,
|
|
202
|
+
reel_source: item.reel_source ?? item.source ?? "IG",
|
|
203
|
+
is_verified: Boolean(item.is_verified || item.verified),
|
|
204
|
+
__typename: "GenAIReelPrimitive"
|
|
205
|
+
}))
|
|
206
|
+
)
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
return this;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
addImage(imageUrl, { resolveUrl = false } = {}) {
|
|
213
|
+
const isValid =
|
|
214
|
+
typeof imageUrl === "string" ||
|
|
215
|
+
Buffer.isBuffer(imageUrl) ||
|
|
216
|
+
(Array.isArray(imageUrl) && imageUrl.every((v) => typeof v === "string" || Buffer.isBuffer(v)));
|
|
217
|
+
|
|
218
|
+
if (!isValid) {
|
|
219
|
+
throw new TypeError("imageUrl must be string | buffer | array of string/buffer");
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const items = Array.isArray(imageUrl) ? imageUrl : [imageUrl];
|
|
223
|
+
|
|
224
|
+
const list = items.map((v) => {
|
|
225
|
+
const url = Toolkit.resolveMedia(this.#client, v, "image", { resolveUrl });
|
|
226
|
+
return { imagePreviewUrl: url, imageHighResUrl: url, sourceUrl: url };
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
this._submessages.push({
|
|
230
|
+
messageType: 1,
|
|
231
|
+
gridImageMetadata: {
|
|
232
|
+
gridImageUrl: { imagePreviewUrl: list[0]?.imagePreviewUrl },
|
|
233
|
+
imageUrls: list
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
list.forEach(({ imagePreviewUrl }) => {
|
|
238
|
+
this._sections.push(
|
|
239
|
+
newLayout("Single", {
|
|
240
|
+
media: { url: imagePreviewUrl, mime_type: "image/png" },
|
|
241
|
+
imagine_type: "IMAGE",
|
|
242
|
+
status: { status: "READY" },
|
|
243
|
+
__typename: "GenAIImaginePrimitive"
|
|
244
|
+
})
|
|
245
|
+
);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
return this;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
addVideo(videoUrl, { autoFill = true } = {}) {
|
|
252
|
+
const isObjectVideo = (v) => v && typeof v === "object" && v.url;
|
|
253
|
+
|
|
254
|
+
const isValid =
|
|
255
|
+
typeof videoUrl === "string" ||
|
|
256
|
+
Buffer.isBuffer(videoUrl) ||
|
|
257
|
+
isObjectVideo(videoUrl) ||
|
|
258
|
+
(Array.isArray(videoUrl) && videoUrl.every((v) => typeof v === "string" || Buffer.isBuffer(v) || isObjectVideo(v)));
|
|
259
|
+
|
|
260
|
+
if (!isValid) {
|
|
261
|
+
throw new TypeError("videoUrl must be string | buffer | object | array");
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const items = Array.isArray(videoUrl) ? videoUrl : [videoUrl];
|
|
265
|
+
|
|
266
|
+
this._submessages.push({ messageType: 2, messageText: "[ CANNOT_LOAD_VIDEO - NIXEL ]" });
|
|
267
|
+
|
|
268
|
+
items.forEach((item) => {
|
|
269
|
+
const isObject = isObjectVideo(item);
|
|
270
|
+
const url = isObject ? Toolkit.resolveMedia(this.#client, item.url ?? "", "video") : Toolkit.resolveMedia(this.#client, item, "video");
|
|
271
|
+
|
|
272
|
+
const bufferPromise = autoFill ? Promise.resolve(url).then((u) => Toolkit.fetchBuffer(u)) : null;
|
|
273
|
+
|
|
274
|
+
const file_length =
|
|
275
|
+
isObject && item.file_length != null ? item.file_length : autoFill ? bufferPromise.then((b) => b?.length ?? 0) : 0;
|
|
276
|
+
|
|
277
|
+
const duration =
|
|
278
|
+
isObject && item.duration != null
|
|
279
|
+
? item.duration
|
|
280
|
+
: autoFill
|
|
281
|
+
? bufferPromise.then((b) => Toolkit.getMp4Duration(b, { silent: true }))
|
|
282
|
+
: 0;
|
|
283
|
+
|
|
284
|
+
const thumbnail =
|
|
285
|
+
isObject && item.thumbnail
|
|
286
|
+
? Toolkit.resolveMedia(this.#client, item.thumbnail, "image", { result: "base64", resize: true, width: 300, height: 300 })
|
|
287
|
+
: autoFill && bufferPromise
|
|
288
|
+
? bufferPromise.then((b) => Toolkit.getMp4Preview(b, { time: 0, result: "base64" }))
|
|
289
|
+
: null;
|
|
290
|
+
|
|
291
|
+
this._sections.push(
|
|
292
|
+
newLayout("Single", {
|
|
293
|
+
media: { url, mime_type: isObject ? item.mime_type ?? "video/mp4" : "video/mp4", file_length, duration },
|
|
294
|
+
imagine_type: "ANIMATE",
|
|
295
|
+
status: { status: "READY" },
|
|
296
|
+
thumbnail: { raw_media: thumbnail },
|
|
297
|
+
__typename: "GenAIImaginePrimitive"
|
|
298
|
+
})
|
|
299
|
+
);
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
return this;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
addProduct(data = {}) {
|
|
306
|
+
const isSingleObject = data && typeof data === "object" && !Array.isArray(data);
|
|
307
|
+
const isObjectArray = Array.isArray(data) && data.every((item) => item && typeof item === "object" && !Array.isArray(item));
|
|
308
|
+
|
|
309
|
+
if (!(isSingleObject || isObjectArray)) {
|
|
310
|
+
throw new TypeError("Product items must be an object or an array of objects");
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
this._submessages.push({ messageType: 2, messageText: "[ CANNOT_LOAD_PRODUCT - NIXEL ]" });
|
|
314
|
+
|
|
315
|
+
const items = Array.isArray(data) ? data : [data];
|
|
316
|
+
|
|
317
|
+
const product = items.map((item) => ({
|
|
318
|
+
title: item.title,
|
|
319
|
+
brand: item.brand,
|
|
320
|
+
price: item.price,
|
|
321
|
+
sale_price: item.sale_price,
|
|
322
|
+
product_url: item.product_url ?? item.url,
|
|
323
|
+
image: { url: Toolkit.resolveMedia(this.#client, item.image_url ?? item.image, "image") },
|
|
324
|
+
additional_images: [{ url: Toolkit.resolveMedia(this.#client, item.icon_url ?? item.icon, "image") }],
|
|
325
|
+
__typename: "GenAIProductItemCardPrimitive"
|
|
326
|
+
}));
|
|
327
|
+
|
|
328
|
+
this._sections.push(newLayout(Array.isArray(data) ? "HScroll" : "Single", Array.isArray(data) ? product : product[0]));
|
|
329
|
+
|
|
330
|
+
return this;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
addPost(data = {}) {
|
|
334
|
+
const isSingleObject = data && typeof data === "object" && !Array.isArray(data);
|
|
335
|
+
const isObjectArray = Array.isArray(data) && data.every((item) => item && typeof item === "object" && !Array.isArray(item));
|
|
336
|
+
|
|
337
|
+
if (!(isSingleObject || isObjectArray)) {
|
|
338
|
+
throw new TypeError("Post items must be an object or an array of objects");
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const posts = Array.isArray(data) ? data : [data];
|
|
342
|
+
|
|
343
|
+
this._submessages.push({ messageType: 2, messageText: "[ CANNOT_LOAD_POST - NIXEL ]" });
|
|
344
|
+
|
|
345
|
+
const primitives = posts.map((p) => ({
|
|
346
|
+
title: p.title ?? "",
|
|
347
|
+
subtitle: p.subtitle ?? "",
|
|
348
|
+
username: p.username ?? "",
|
|
349
|
+
profile_picture_url: Toolkit.resolveMedia(this.#client, p.profile_picture_url ?? p.profile_url ?? p.profile ?? "", "image"),
|
|
350
|
+
is_verified: Boolean(p.is_verified || p.verified),
|
|
351
|
+
thumbnail_url: Toolkit.resolveMedia(this.#client, p.thumbnail_url ?? p.thumbnail ?? "", "image"),
|
|
352
|
+
post_caption: p.post_caption ?? p.caption ?? "",
|
|
353
|
+
likes_count: p.likes_count ?? p.like ?? 0,
|
|
354
|
+
comments_count: p.comments_count ?? p.comment ?? 0,
|
|
355
|
+
shares_count: p.shares_count ?? p.share ?? 0,
|
|
356
|
+
post_url: p.post_url ?? p.url ?? "",
|
|
357
|
+
post_deeplink: p.post_deeplink ?? p.deeplink ?? "",
|
|
358
|
+
source_app: p.source_app || p.source || "INSTAGRAM",
|
|
359
|
+
footer_label: p.footer_label ?? p.footer ?? "",
|
|
360
|
+
footer_icon: Toolkit.resolveMedia(this.#client, p.footer_icon ?? p.icon ?? "", "image"),
|
|
361
|
+
is_carousel: posts.length > 1,
|
|
362
|
+
orientation: p.orientation ?? "LANDSCAPE",
|
|
363
|
+
post_type: p.post_type ?? "VIDEO",
|
|
364
|
+
__typename: "GenAIPostPrimitive"
|
|
365
|
+
}));
|
|
366
|
+
|
|
367
|
+
this._sections.push(newLayout("HScroll", primitives));
|
|
368
|
+
|
|
369
|
+
return this;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
addTip(text) {
|
|
373
|
+
this._submessages.push({ messageType: 2, messageText: text });
|
|
374
|
+
this._sections.push(newLayout("Single", { text, __typename: "GenAIMetadataTextPrimitive" }));
|
|
375
|
+
return this;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
addSuggest(suggestion, { scroll = true, layout } = {}) {
|
|
379
|
+
const isValid =
|
|
380
|
+
typeof suggestion === "string" || (Array.isArray(suggestion) && suggestion.every((v) => typeof v === "string"));
|
|
381
|
+
|
|
382
|
+
if (!isValid) throw new TypeError("Suggestion must be a string or array of strings");
|
|
383
|
+
|
|
384
|
+
const suggest = Array.isArray(suggestion)
|
|
385
|
+
? suggestion.map((text) => ({ prompt_text: text, prompt_type: "SUGGESTED_PROMPT", __typename: "GenAIFollowUpSuggestionPillPrimitive" }))
|
|
386
|
+
: [{ prompt_text: suggestion, prompt_type: "SUGGESTED_PROMPT", __typename: "GenAIFollowUpSuggestionPillPrimitive" }];
|
|
387
|
+
|
|
388
|
+
const type = layout ?? (suggest.length === 1 ? "Single" : scroll ? "HScroll" : "ActionRow");
|
|
389
|
+
|
|
390
|
+
this._sections.push(newLayout(type, type === "Single" ? suggest[0] : suggest, { __typename: "GenAIUnifiedResponseSection" }));
|
|
391
|
+
|
|
392
|
+
return this;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
async build({ forwarded = true, notification = false, includesUnifiedResponse = true, includesSubmessages = true, quoted, quotedParticipant, ...options } = {}) {
|
|
396
|
+
const forward = forwarded
|
|
397
|
+
? { forwardingScore: 1, isForwarded: true, forwardedAiBotMessageInfo: { botJid: "0@bot" }, forwardOrigin: 4 }
|
|
398
|
+
: {};
|
|
399
|
+
|
|
400
|
+
const notif = notification
|
|
401
|
+
? {
|
|
402
|
+
sessionTransparencyMetadata: {
|
|
403
|
+
disclaimerText: this._footer || "AI generated response",
|
|
404
|
+
hcaId: `hca_${Date.now()}`,
|
|
405
|
+
sessionTransparencyType: 1
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
: {};
|
|
409
|
+
|
|
410
|
+
const qObj = quoted
|
|
411
|
+
? {
|
|
412
|
+
stanzaId: quoted?.key?.id || quoted?.id,
|
|
413
|
+
participant: quotedParticipant || quoted?.key?.participant || quoted?.key?.remoteJid,
|
|
414
|
+
quotedType: 0,
|
|
415
|
+
quotedMessage: typeof quoted === "object" && quoted !== null ? quoted.message ?? quoted : undefined
|
|
416
|
+
}
|
|
417
|
+
: {};
|
|
418
|
+
|
|
419
|
+
const sections = this._footer
|
|
420
|
+
? [...(await waitAllPromises(this._sections)), newLayout("Single", { text: this._footer, __typename: "GenAIMetadataTextPrimitive" })]
|
|
421
|
+
: [...(await waitAllPromises(this._sections))];
|
|
422
|
+
|
|
423
|
+
return {
|
|
424
|
+
messageContextInfo: {
|
|
425
|
+
deviceListMetadata: {},
|
|
426
|
+
deviceListMetadataVersion: 2,
|
|
427
|
+
botMetadata: {
|
|
428
|
+
messageDisclaimerText: this._title,
|
|
429
|
+
richResponseSourcesMetadata: { sources: this._richResponseSources },
|
|
430
|
+
...notif
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
...this._extraPayload,
|
|
434
|
+
botForwardedMessage: {
|
|
435
|
+
message: {
|
|
436
|
+
richResponseMessage: {
|
|
437
|
+
messageType: 1,
|
|
438
|
+
submessages: includesSubmessages ? await waitAllPromises(this._submessages) : [],
|
|
439
|
+
unifiedResponse: {
|
|
440
|
+
data: includesUnifiedResponse
|
|
441
|
+
? Buffer.from(JSON.stringify({ response_id: crypto.randomUUID(), sections })).toString("base64")
|
|
442
|
+
: ""
|
|
443
|
+
},
|
|
444
|
+
contextInfo: { ...forward, ...qObj, ...this._contextInfo }
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
async send(jid, { forwarded, notification, includesUnifiedResponse, includesSubmessages, ...options } = {}) {
|
|
452
|
+
const msg = await this.build({ forwarded, notification, includesUnifiedResponse, includesSubmessages, ...options });
|
|
453
|
+
return this.#client.relayMessage(jid, msg, { ...options });
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
module.exports = { AIRich };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
class BaseBuilder {
|
|
4
|
+
constructor() {
|
|
5
|
+
this._title = "";
|
|
6
|
+
this._subtitle = "";
|
|
7
|
+
this._body = "";
|
|
8
|
+
this._footer = "";
|
|
9
|
+
this._contextInfo = {};
|
|
10
|
+
this._extraPayload = {};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
setTitle(title) {
|
|
14
|
+
if (typeof title !== "string") throw new TypeError("Title must be a string");
|
|
15
|
+
this._title = title;
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
setSubtitle(subtitle) {
|
|
20
|
+
if (typeof subtitle !== "string") throw new TypeError("Subtitle must be a string");
|
|
21
|
+
this._subtitle = subtitle;
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
setBody(body) {
|
|
26
|
+
if (typeof body !== "string") throw new TypeError("Body must be a string");
|
|
27
|
+
this._body = body;
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
setFooter(footer) {
|
|
32
|
+
if (typeof footer !== "string") throw new TypeError("Footer must be a string");
|
|
33
|
+
this._footer = footer;
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setContextInfo(obj) {
|
|
38
|
+
if (typeof obj !== "object" || obj === null || Array.isArray(obj)) {
|
|
39
|
+
throw new TypeError("ContextInfo must be a plain object");
|
|
40
|
+
}
|
|
41
|
+
this._contextInfo = obj;
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
addPayload(obj) {
|
|
46
|
+
if (typeof obj !== "object" || obj === null || Array.isArray(obj)) {
|
|
47
|
+
throw new TypeError("Payload must be a plain object");
|
|
48
|
+
}
|
|
49
|
+
Object.assign(this._extraPayload, obj);
|
|
50
|
+
return this;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = { BaseBuilder };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const crypto = require("crypto");
|
|
4
|
+
const { getBaileys } = require("../core/baileys-loader.js");
|
|
5
|
+
const { BaseBuilder } = require("./base-builder.js");
|
|
6
|
+
const { Toolkit } = require("./toolkit.js");
|
|
7
|
+
const { relayInteractive } = require("./native-flow.js");
|
|
8
|
+
|
|
9
|
+
class ButtonV2 extends BaseBuilder {
|
|
10
|
+
#client;
|
|
11
|
+
|
|
12
|
+
constructor(client) {
|
|
13
|
+
super();
|
|
14
|
+
if (!client) throw new Error("Socket is required");
|
|
15
|
+
|
|
16
|
+
this.#client = client;
|
|
17
|
+
this._image = undefined;
|
|
18
|
+
this._data = undefined;
|
|
19
|
+
this._buttons = [];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
addButton(displayText = "", buttonId) {
|
|
23
|
+
this._buttons.push({
|
|
24
|
+
buttonId: buttonId ?? crypto.randomUUID(),
|
|
25
|
+
buttonText: { displayText },
|
|
26
|
+
type: 1
|
|
27
|
+
});
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
addRawButton(obj) {
|
|
32
|
+
if (typeof obj !== "object" || obj === null || Array.isArray(obj)) {
|
|
33
|
+
throw new TypeError("Buttons must be a plain object");
|
|
34
|
+
}
|
|
35
|
+
this._buttons.push(obj);
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
setThumbnail(mediaPath) {
|
|
40
|
+
if (!mediaPath) throw new Error("Url or buffer needed");
|
|
41
|
+
this._image = mediaPath;
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setMedia(obj) {
|
|
46
|
+
if (typeof obj !== "object" || obj === null || Array.isArray(obj)) {
|
|
47
|
+
throw new TypeError("Media must be a plain object");
|
|
48
|
+
}
|
|
49
|
+
this._data = obj;
|
|
50
|
+
return this;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async build(jid, options = {}) {
|
|
54
|
+
const { generateWAMessageFromContent } = await getBaileys();
|
|
55
|
+
|
|
56
|
+
const thumbnail = this._image
|
|
57
|
+
? await Toolkit.resize(
|
|
58
|
+
Buffer.isBuffer(this._image) ? this._image : await Toolkit.fetchBuffer(this._image, {}, { silent: true }),
|
|
59
|
+
300,
|
|
60
|
+
300
|
|
61
|
+
)
|
|
62
|
+
: null;
|
|
63
|
+
|
|
64
|
+
const header = this._data
|
|
65
|
+
? this._data
|
|
66
|
+
: {
|
|
67
|
+
headerType: 6,
|
|
68
|
+
locationMessage: {
|
|
69
|
+
degreesLatitude: 0,
|
|
70
|
+
degreesLongitude: 0,
|
|
71
|
+
name: this._title,
|
|
72
|
+
address: this._subtitle,
|
|
73
|
+
jpegThumbnail: thumbnail
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
return generateWAMessageFromContent(
|
|
78
|
+
jid,
|
|
79
|
+
{
|
|
80
|
+
...this._extraPayload,
|
|
81
|
+
buttonsMessage: {
|
|
82
|
+
contentText: this._body,
|
|
83
|
+
footerText: this._footer,
|
|
84
|
+
...header,
|
|
85
|
+
viewOnce: true,
|
|
86
|
+
contextInfo: this._contextInfo,
|
|
87
|
+
buttons: [...this._buttons]
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
{ ...options }
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async send(jid, options = {}) {
|
|
95
|
+
if (this._buttons.length < 1) {
|
|
96
|
+
throw new Error("ButtonV2 requires at least one button");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const msg = await this.build(jid, options);
|
|
100
|
+
return relayInteractive(this.#client, msg, options);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = { ButtonV2 };
|