Nexchan commited on
Commit
72ee6f0
·
1 Parent(s): 804b45d
bot/command/other/ping.js CHANGED
@@ -9,7 +9,7 @@ export default {
9
  description: "Cek respon bot",
10
  example: "%p%cmd",
11
  name: "ping",
12
- tags: "info",
13
 
14
  run: async (m, { conn }) => {
15
  try {
 
9
  description: "Cek respon bot",
10
  example: "%p%cmd",
11
  name: "ping",
12
+ tags: "other",
13
 
14
  run: async (m, { conn }) => {
15
  try {
bot/index.js CHANGED
@@ -8,7 +8,7 @@ import makeWASocket, {
8
  import qrcode from "qrcode-terminal";
9
  import { fileURLToPath } from "url";
10
  import { loadCommands, handleCommand } from "./lib/handler.js";
11
- import { Client, Serialize } from "./lib/serialize.js";
12
  global.prefix = /^[°•π÷×¶∆£¢€¥®™+✓_=|/~!?@#%^&.©^]/i;
13
 
14
  // __dirname untuk ESM
@@ -27,9 +27,7 @@ async function startBot() {
27
  });
28
 
29
  sock.ev.on("creds.update", saveCreds);
30
-
31
- await Client({ sock, store });
32
- global.conn = conn;
33
 
34
  sock.ev.on("connection.update", (update) => {
35
  const { connection, qr } = update;
@@ -45,10 +43,9 @@ async function startBot() {
45
 
46
  sock.ev.on("messages.upsert", async (message) => {
47
  if (!message.messages) return;
48
- const m = await Serialize(conn, message.messages[0]);
49
  const msg = message.messages[0];
50
  if (!msg.message || msg.key.fromMe) return;
51
- await handleCommand(sock, m, msg, commands);
52
  });
53
  }
54
 
 
8
  import qrcode from "qrcode-terminal";
9
  import { fileURLToPath } from "url";
10
  import { loadCommands, handleCommand } from "./lib/handler.js";
11
+ // import { Client, Serialize } from "./lib/serialize.js";
12
  global.prefix = /^[°•π÷×¶∆£¢€¥®™+✓_=|/~!?@#%^&.©^]/i;
13
 
14
  // __dirname untuk ESM
 
27
  });
28
 
29
  sock.ev.on("creds.update", saveCreds);
30
+ // global.conn = conn;
 
 
31
 
32
  sock.ev.on("connection.update", (update) => {
33
  const { connection, qr } = update;
 
43
 
44
  sock.ev.on("messages.upsert", async (message) => {
45
  if (!message.messages) return;
 
46
  const msg = message.messages[0];
47
  if (!msg.message || msg.key.fromMe) return;
48
+ await handleCommand(sock, msg, commands);
49
  });
50
  }
51
 
bot/lib/function.js DELETED
@@ -1,553 +0,0 @@
1
- import fs from "fs";
2
- import os from "os";
3
- import path from "path";
4
- import Jimp from "jimp";
5
- import axios from "axios";
6
- import chalk from "chalk";
7
- import * as cheerio from "cheerio";
8
- import { format } from "util";
9
- import { platform } from "os";
10
- import term from "terminal-kit";
11
- import mimes from "mime-types";
12
- import FormData from "form-data";
13
- import { exec } from "child_process";
14
- import moment from "moment-timezone";
15
- import baileys from "baileys";
16
- import { fileTypeFromBuffer } from "file-type";
17
- import { fileURLToPath, pathToFileURL } from "url";
18
-
19
- export default new (class Function {
20
- constructor() {
21
- this.axios = axios;
22
- this.cheerio = cheerio;
23
- this.fs = fs;
24
- this.path = path;
25
- this.baileys = baileys;
26
- this.FormData = FormData;
27
- this.upload = {
28
- telegra: this.telegra.bind(this),
29
- pomf: this.pomf.bind(this),
30
- hari: this.hari.bind(this),
31
- tmp: this.tmp.bind(this),
32
- freeimage: this.freeimage.bind(this),
33
- };
34
- }
35
-
36
- __filename(pathURL = import.meta, rmPrefix = platform() !== "win32") {
37
- const path = pathURL?.url || pathURL;
38
-
39
- return rmPrefix
40
- ? /file:\/\/\//.test(path)
41
- ? fileURLToPath(path)
42
- : path
43
- : /file:\/\/\//.test(path)
44
- ? path
45
- : pathToFileURL(path).href;
46
- }
47
-
48
- __dirname(pathURL) {
49
- const dir = this.__filename(pathURL, true);
50
- const regex = /\/$/;
51
-
52
- return regex.test(dir)
53
- ? dir
54
- : fs.existsSync(dir) && fs.statSync(dir).isDirectory
55
- ? dir.replace(regex, "")
56
- : path.dirname(dir);
57
- }
58
-
59
- async dirSize(directory) {
60
- const files = await fs.readdirSync(directory);
61
- const stats = files.map((file) => fs.statSync(path.join(directory, file)));
62
-
63
- return (await Promise.all(stats)).reduce(
64
- (accumulator, { size }) => accumulator + size,
65
- 0,
66
- );
67
- }
68
-
69
- sleep(ms) {
70
- return new Promise((a) => setTimeout(a, ms));
71
- }
72
-
73
- format(str) {
74
- return format(str);
75
- }
76
-
77
- Format(str) {
78
- return JSON.stringify(str, null, 2);
79
- }
80
-
81
- jam(numer, options = {}) {
82
- let format = options.format ? options.format : "HH:mm";
83
- let jam = options?.timeZone
84
- ? moment(numer).tz(options.timeZone).format(format)
85
- : moment(numer).format(format);
86
-
87
- return `${jam}`;
88
- }
89
-
90
- tanggal(numer, timeZone = "") {
91
- const myMonths = [
92
- "Januari",
93
- "Februari",
94
- "Maret",
95
- "April",
96
- "Mei",
97
- "Juni",
98
- "Juli",
99
- "Agustus",
100
- "September",
101
- "Oktober",
102
- "November",
103
- "Desember",
104
- ];
105
- const myDays = [
106
- "Minggu",
107
- "Senin",
108
- "Selasa",
109
- "Rabu",
110
- "Kamis",
111
- "Jum’at",
112
- "Sabtu",
113
- ];
114
- var tgl = new Date(numer);
115
- timeZone ? tgl.toLocaleString("en", { timeZone }) : "";
116
- var day = tgl.getDate();
117
- var bulan = tgl.getMonth();
118
- var thisDay = tgl.getDay(),
119
- thisDay = myDays[thisDay];
120
- var yy = tgl.getYear();
121
- var year = yy < 1000 ? yy + 1900 : yy;
122
-
123
- return `${thisDay}, ${day} ${myMonths[bulan]} ${year}`;
124
- }
125
-
126
- async getFile(PATH, save) {
127
- try {
128
- let filename = null;
129
- let data = await this.fetchBuffer(PATH);
130
-
131
- if (data?.data && save) {
132
- filename = path.join(
133
- os.tmpdir(),
134
- Date.now() + "." + data.ext,
135
- );
136
- fs.promises.writeFile(filename, data?.data);
137
- }
138
- return {
139
- filename: data?.name ? data.name : filename,
140
- ...data,
141
- };
142
- } catch (e) {
143
- throw e;
144
- }
145
- }
146
-
147
- async fetchJson(url, options = {}) {
148
- try {
149
- let data = await axios.get(url, {
150
- headers: {
151
- ...(!!options.headers ? options.headers : {}),
152
- },
153
- responseType: "json",
154
- ...options,
155
- });
156
-
157
- return await data?.data;
158
- } catch (e) {
159
- throw e;
160
- }
161
- }
162
-
163
- fetchBuffer(string, options = {}) {
164
- return new Promise(async (resolve, reject) => {
165
- try {
166
- if (/^https?:\/\//i.test(string)) {
167
- let data = await axios.get(string, {
168
- headers: {
169
- ...(!!options.headers ? options.headers : {}),
170
- },
171
- responseType: "arraybuffer",
172
- ...options,
173
- });
174
-
175
- let buffer = await data?.data;
176
- let name = /filename/i.test(data.headers?.get("content-disposition"))
177
- ? data.headers
178
- ?.get("content-disposition")
179
- ?.match(/filename=(.*)/)?.[1]
180
- ?.replace(/[""]/g, "")
181
- : "";
182
- let mime =
183
- mimes.lookup(name) ||
184
- data.headers.get("content-type") ||
185
- (await fileTypeFromBuffer(buffer))?.mime;
186
-
187
- resolve({
188
- data: buffer,
189
- size: Buffer.byteLength(buffer),
190
- sizeH: this.formatSize(Buffer.byteLength(buffer)),
191
- name,
192
- mime,
193
- ext: mimes.extension(mime),
194
- });
195
- } else if (/^data:.*?\/.*?base64,/i.test(string)) {
196
- let data = Buffer.from(string.split`,`[1], "base64");
197
- let size = Buffer.byteLength(data);
198
-
199
- resolve({
200
- data,
201
- size,
202
- sizeH: this.formatSize(size),
203
- ...((await fileTypeFromBuffer(data)) || {
204
- mime: "application/octet-stream",
205
- ext: ".bin",
206
- }),
207
- });
208
- } else if (fs.existsSync(string) && fs.statSync(string).isFile()) {
209
- let data = fs.readFileSync(string);
210
- let size = Buffer.byteLength(data);
211
-
212
- resolve({
213
- data,
214
- size,
215
- sizeH: this.formatSize(size),
216
- ...((await fileTypeFromBuffer(data)) || {
217
- mime: "application/octet-stream",
218
- ext: ".bin",
219
- }),
220
- });
221
- } else if (Buffer.isBuffer(string)) {
222
- let size = Buffer?.byteLength(string) || 0;
223
-
224
- resolve({
225
- data: string,
226
- size,
227
- sizeH: this.formatSize(size),
228
- ...((await fileTypeFromBuffer(string)) || {
229
- mime: "application/octet-stream",
230
- ext: ".bin",
231
- }),
232
- });
233
- } else if (/^[a-zA-Z0-9+/]={0,2}$/i.test(string)) {
234
- let data = Buffer.from(string, "base64");
235
- let size = Buffer.byteLength(data);
236
-
237
- resolve({
238
- data,
239
- size,
240
- sizeH: this.formatSize(size),
241
- ...((await fileTypeFromBuffer(data)) || {
242
- mime: "application/octet-stream",
243
- ext: ".bin",
244
- }),
245
- });
246
- } else {
247
- let buffer = Buffer.alloc(20);
248
- let size = Buffer.byteLength(buffer);
249
-
250
- resolve({
251
- data: buffer,
252
- size,
253
- sizeH: this.formatSize(size),
254
- ...((await fileTypeFromBuffer(buffer)) || {
255
- mime: "application/octet-stream",
256
- ext: ".bin",
257
- }),
258
- });
259
- }
260
- } catch (e) {
261
- reject(new Error(e?.message || e));
262
- }
263
- });
264
- }
265
-
266
- mime(name) {
267
- let mimetype = mimes.lookup(name);
268
- if (!mimetype) return mimes.extension(name);
269
- return { mime: mimetype, ext: mimes.extension(mimetype) };
270
- }
271
-
272
- isUrl(url) {
273
- let regex = new RegExp(
274
- /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/,
275
- "gi",
276
- );
277
- if (!regex.test(url)) return false;
278
- return url.match(regex);
279
- }
280
-
281
- escapeRegExp(string) {
282
- return string.replace(/[.*=+:\-?^${}()|[\]\\]|\s/g, "\\$&");
283
- }
284
-
285
- toUpper(query) {
286
- const arr = query.split(" ");
287
- for (var i = 0; i < arr.length; i++) {
288
- arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].slice(1);
289
- }
290
-
291
- return arr.join(" ");
292
- }
293
-
294
- getRandom(ext = "", length = "10") {
295
- var result = "";
296
- var character =
297
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
298
- var characterLength = character.length;
299
-
300
- for (var i = 0; i < length; i++) {
301
- result += character.charAt(Math.floor(Math.random() * characterLength));
302
- }
303
-
304
- return `${result}${ext ? `.${ext}` : ""}`;
305
- }
306
-
307
- formatSize(bytes, si = true, dp = 2) {
308
- const thresh = si ? 1000 : 1024;
309
-
310
- if (Math.abs(bytes) < thresh) {
311
- return `${bytes} B`;
312
- }
313
-
314
- const units = si
315
- ? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
316
- : ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
317
- const r = 10 ** dp;
318
- let u = -1;
319
-
320
- do {
321
- bytes /= thresh;
322
- ++u;
323
- } while (
324
- Math.round(Math.abs(bytes) * r) / r >= thresh &&
325
- u < units.length - 1
326
- );
327
-
328
- return `${bytes.toFixed(dp)} ${units[u]}`;
329
- }
330
-
331
- async resizeImage(buffer, height) {
332
- buffer = (await this.getFile(buffer)).data;
333
-
334
- return new Promise((resolve, reject) => {
335
- Jimp.read(buffer, (err, image) => {
336
- if (err) {
337
- reject(err);
338
- return;
339
- }
340
-
341
- image
342
- .resize(Jimp.AUTO, height)
343
- .getBuffer(Jimp.MIME_PNG, (err, resizedBuffer) => {
344
- if (err) {
345
- reject(err);
346
- return;
347
- }
348
- resolve(resizedBuffer);
349
- });
350
- });
351
- });
352
- }
353
-
354
- runtime(seconds) {
355
- seconds = Number(seconds);
356
- var d = Math.floor(seconds / (3600 * 24));
357
- var h = Math.floor((seconds % (3600 * 24)) / 3600);
358
- var m = Math.floor((seconds % 3600) / 60);
359
- var s = Math.floor(seconds % 60);
360
- var dDisplay = d > 0 ? d + (d == 1 ? " day, " : " days, ") : "";
361
- var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : "";
362
- var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : "";
363
- var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : "";
364
- return dDisplay + hDisplay + mDisplay + sDisplay;
365
- }
366
-
367
- loading() {
368
- var { terminal } = term;
369
- var progressBar,
370
- progress = 0;
371
-
372
- function doProgress() {
373
- progress += Math.random() / 10;
374
- progressBar.update(progress);
375
- if (progress >= 1) {
376
- setTimeout(function () {
377
- console.clear(),
378
- exec(`screenfetch - A Deepin`, (error, stdout, stderr) => {
379
- console.log(stdout),
380
- console.log(chalk.bgGray("Bot WhatsApp By Alisa & Ahyad"));
381
- });
382
- }, 200);
383
- } else {
384
- setTimeout(doProgress, 90 + Math.random() * 200);
385
- }
386
- }
387
-
388
- progressBar = terminal.progressBar({
389
- width: 80,
390
- title: "\n\nLoad this script....",
391
- eta: true,
392
- percent: true,
393
- });
394
-
395
- doProgress();
396
- }
397
-
398
- reloadPlugin(type, file) {
399
- const filename = (file) => file.replace(/^.*[\\\/]/, "");
400
-
401
- switch (type) {
402
- case "delete":
403
- return delete global.plugins[file];
404
- break;
405
- case "add":
406
- case "change":
407
- try {
408
- (async () => {
409
- const module = await import(`${file}?update=${Date.now()}`);
410
- global.plugins[file] = module.default || module;
411
- })();
412
- } catch (e) {
413
- conn.logger.error(
414
- `Error require plugin "${filename(file)}\n${format(e)}"`,
415
- );
416
- } finally {
417
- global.plugins = Object.fromEntries(
418
- Object.entries(global.plugins).sort(([a], [b]) =>
419
- a.localeCompare(b),
420
- ),
421
- );
422
- }
423
- break;
424
- }
425
- }
426
-
427
- timeSpeech() {
428
- let ucapanWaktu = "";
429
- let wakt = moment.tz("Asia/Jakarta").format("HH:mm");
430
-
431
- if (wakt < "23:59") ucapanWaktu = "Selamat Malam";
432
- if (wakt < "19:00") ucapanWaktu = "Selamat Petang";
433
- if (wakt < "18:00") ucapanWaktu = "Selamat Sore";
434
- if (wakt < "15:00") ucapanWaktu = "Selamat Siang";
435
- if (wakt < "10:00") ucapanWaktu = "Selamat Pagi";
436
- if (wakt < "05:00") ucapanWaktu = "Selamat Subuh";
437
- if (wakt < "03:00") ucapanWaktu = "Selamat Tengah Malam";
438
-
439
- return ucapanWaktu;
440
- }
441
-
442
- pomf(media) {
443
- return new Promise(async (resolve, reject) => {
444
- let mime = await fileTypeFromBuffer(media);
445
- let form = new FormData();
446
-
447
- form.append("files[]", media, `file-${Date.now()}.${mime.ext}`);
448
-
449
- axios
450
- .post("https://pomf.lain.la/upload.php", form, {
451
- headers: {
452
- "User-Agent":
453
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0",
454
- ...form.getHeaders(),
455
- },
456
- })
457
- .then(({ data }) => resolve(data.files[0].url))
458
- .catch(reject);
459
- });
460
- }
461
-
462
- telegra(media) {
463
- return new Promise(async (resolve, reject) => {
464
- let mime = await fileTypeFromBuffer(media);
465
- let form = new FormData();
466
-
467
- form.append("file", media, `file-${Date.now()}.${mime.ext}`);
468
-
469
- axios
470
- .post("https://telegra.ph/upload", form, {
471
- headers: {
472
- "User-Agent":
473
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0",
474
- ...form.getHeaders(),
475
- },
476
- })
477
- .then(({ data }) => resolve("https://telegra.ph" + data[0].src))
478
- .catch(reject);
479
- });
480
- }
481
-
482
- hari(media) {
483
- return new Promise(async (resolve, reject) => {
484
- let mime = await fileTypeFromBuffer(media);
485
- let form = new FormData();
486
-
487
- form.append("file", media, `file-${Date.now()}.${mime.ext}`);
488
-
489
- axios
490
- .post("https://hari.christmas/upload", form, {
491
- headers: {
492
- "User-Agent":
493
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0",
494
- ...form.getHeaders(),
495
- },
496
- })
497
- .then(({ data }) => resolve(data.downloadUrl))
498
- .catch(reject);
499
- });
500
- }
501
-
502
- tmp(media) {
503
- return new Promise(async (resolve, reject) => {
504
- let mime = await fileTypeFromBuffer(media);
505
- let form = new FormData();
506
-
507
- form.append("file", media, `file-${Date.now()}.${mime.ext}`);
508
-
509
- axios
510
- .post("https://tmpfiles.org/api/v1/upload", form, {
511
- headers: {
512
- "User-Agent":
513
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0",
514
- ...form.getHeaders(),
515
- },
516
- })
517
- .then(({ data }) => {
518
- const url = data.data.url.match(/https:\/\/tmpfiles.org\/(.*)/)[1];
519
- const hasil = "https://tmpfiles.org/dl/" + url;
520
- resolve(hasil);
521
- })
522
- .catch(reject);
523
- });
524
- }
525
-
526
- async freeimage(buffer) {
527
- const { data: html } = await axios
528
- .get("https://freeimage.host/")
529
- .catch(() => null);
530
- const token = html.match(/PF.obj.config.auth_token = "(.+?)";/)[1];
531
- let mime = await fileTypeFromBuffer(buffer);
532
- let form = new FormData();
533
-
534
- form.append("source", buffer, `file-${Date.now()}.${mime.ext}`);
535
-
536
- const options = {
537
- type: "file",
538
- action: "upload",
539
- timestamp: (Date.now() / 1000).toString(),
540
- auth_token: token,
541
- nsfw: "0",
542
- };
543
- for (const [key, value] of Object.entries(options)) {
544
- form.append(key, value);
545
- }
546
- const { data } = await axios.post("https://freeimage.host/json", form, {
547
- headers: {
548
- "Content-Type": "multipart/form-data",
549
- },
550
- });
551
- return data.image.url;
552
- }
553
- })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bot/lib/handler.js CHANGED
@@ -1,22 +1,51 @@
 
1
  import fs from "fs";
2
  import path from "path";
 
3
 
 
 
 
 
 
 
 
 
 
4
  export async function loadCommands(dir) {
5
  const commands = new Map();
6
 
7
  async function loadDir(folder) {
8
  const files = fs.readdirSync(folder);
 
9
  for (const file of files) {
10
  const full = path.join(folder, file);
11
  const stat = fs.statSync(full);
12
- if (stat.isDirectory()) await loadDir(full);
13
- else if (file.endsWith(".js")) {
14
- const cmdModule = (await import("file://" + full)).default;
15
- if (cmdModule && cmdModule.command) {
16
- cmdModule.command.forEach((alias) => {
17
- commands.set(alias.toLowerCase(), cmdModule);
18
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
 
 
20
  }
21
  }
22
  }
@@ -25,31 +54,131 @@ export async function loadCommands(dir) {
25
  return commands;
26
  }
27
 
28
- export async function handleCommand(sock, m, msg, commands) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  try {
30
  const from = msg.key.remoteJid;
31
  const isGroup = from.endsWith("@g.us");
 
32
 
33
- let text =
34
- msg.message.conversation ||
35
- msg.message.extendedTextMessage?.text ||
36
- msg.message.imageMessage?.caption ||
37
- msg.message.videoMessage?.caption ||
38
- "";
39
 
40
- const prefix = text.match(global.prefix)?.[0];
41
- if (!prefix) return; // bukan command
 
 
 
 
 
42
 
43
- const [cmd, ...args] = text
 
 
 
 
44
  .slice(prefix.length)
45
  .trim()
46
  .split(/\s+/);
47
- const command = cmd.toLowerCase();
48
 
 
 
 
49
  const plugin = commands.get(command);
50
  if (!plugin) return;
51
 
52
- await plugin.run(m, { conn: sock });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  } catch (e) {
54
  console.error("❌ Error handleCommand:", e);
55
  }
 
1
+ // command-handler.js
2
  import fs from "fs";
3
  import path from "path";
4
+ import { pathToFileURL } from "url";
5
 
6
+ /**
7
+ * Load semua command dari folder (rekursif)
8
+ * Struktur file command:
9
+ * export default {
10
+ * command: ["ping", "p"],
11
+ * description: "...",
12
+ * run: async (m, { conn }) => {}
13
+ * }
14
+ */
15
  export async function loadCommands(dir) {
16
  const commands = new Map();
17
 
18
  async function loadDir(folder) {
19
  const files = fs.readdirSync(folder);
20
+
21
  for (const file of files) {
22
  const full = path.join(folder, file);
23
  const stat = fs.statSync(full);
24
+
25
+ if (stat.isDirectory()) {
26
+ // masuk folder lagi (rekursif)
27
+ await loadDir(full);
28
+ continue;
29
+ }
30
+
31
+ if (!file.endsWith(".js")) continue;
32
+
33
+ try {
34
+ const fileUrl = pathToFileURL(full).href;
35
+ const cmdModule = (await import(fileUrl)).default;
36
+
37
+ if (!cmdModule || !cmdModule.command) continue;
38
+
39
+ const aliases = Array.isArray(cmdModule.command)
40
+ ? cmdModule.command
41
+ : [cmdModule.command];
42
+
43
+ for (const alias of aliases) {
44
+ const key = String(alias).toLowerCase();
45
+ commands.set(key, cmdModule);
46
  }
47
+ } catch (err) {
48
+ console.error(`❌ Gagal load command: ${full}`, err);
49
  }
50
  }
51
  }
 
54
  return commands;
55
  }
56
 
57
+ /**
58
+ * Helper untuk ambil teks utama dari message
59
+ */
60
+ function getMessageText(msg) {
61
+ return (
62
+ msg.message?.conversation ||
63
+ msg.message?.extendedTextMessage?.text ||
64
+ msg.message?.imageMessage?.caption ||
65
+ msg.message?.videoMessage?.caption ||
66
+ msg.message?.buttonsResponseMessage?.selectedButtonId ||
67
+ msg.message?.listResponseMessage?.singleSelectReply?.selectedRowId ||
68
+ ""
69
+ );
70
+ }
71
+
72
+ /**
73
+ * Handler utama command
74
+ * - parsing prefix, command, args
75
+ * - bikin wrapper "m" dengan m.reply, m.send, dll
76
+ * - jalanin plugin.run(...)
77
+ */
78
+ export async function handleCommand(sock, msg, commands) {
79
  try {
80
  const from = msg.key.remoteJid;
81
  const isGroup = from.endsWith("@g.us");
82
+ const sender = msg.key.participant || msg.key.remoteJid;
83
 
84
+ const body = getMessageText(msg);
85
+ if (!body) return;
 
 
 
 
86
 
87
+ // global.prefix bisa string / regex
88
+ const prefixMatch =
89
+ typeof global.prefix === "string"
90
+ ? body.startsWith(global.prefix)
91
+ ? [global.prefix]
92
+ : null
93
+ : body.match(global.prefix);
94
 
95
+ if (!prefixMatch) return; // bukan command
96
+
97
+ const prefix = prefixMatch[0];
98
+
99
+ const [rawCmd, ...args] = body
100
  .slice(prefix.length)
101
  .trim()
102
  .split(/\s+/);
 
103
 
104
+ if (!rawCmd) return;
105
+
106
+ const command = rawCmd.toLowerCase();
107
  const plugin = commands.get(command);
108
  if (!plugin) return;
109
 
110
+ // Data tambahan
111
+ const quoted =
112
+ msg.message?.extendedTextMessage?.contextInfo?.quotedMessage || null;
113
+ const mentionedJid =
114
+ msg.message?.extendedTextMessage?.contextInfo?.mentionedJid || [];
115
+
116
+ // =========================================
117
+ // Wrapper "m" untuk dikirim ke plugin
118
+ // =========================================
119
+ const m = {
120
+ ...msg,
121
+ from,
122
+ sender,
123
+ isGroup,
124
+ body,
125
+ text: body,
126
+ args,
127
+ prefix,
128
+ command,
129
+ quoted,
130
+ mentionedJid,
131
+
132
+ /**
133
+ * Reply text sederhana
134
+ * @param {string} text
135
+ * @param {object} options - opsi tambahan sendMessage
136
+ */
137
+ reply: async (text, options = {}) => {
138
+ return sock.sendMessage(
139
+ from,
140
+ { text: String(text) },
141
+ { quoted: msg, ...options }
142
+ );
143
+ },
144
+
145
+ /**
146
+ * Kirim pesan custom / media
147
+ * contoh:
148
+ * m.send({ image: buffer, caption: "hai" })
149
+ */
150
+ send: async (content, options = {}) => {
151
+ return sock.sendMessage(from, content, { quoted: msg, ...options });
152
+ },
153
+
154
+ /**
155
+ * React ke pesan
156
+ * @param {string} emoji
157
+ */
158
+ react: async (emoji) => {
159
+ try {
160
+ return sock.sendMessage(from, {
161
+ react: { text: emoji, key: msg.key },
162
+ });
163
+ } catch (err) {
164
+ console.error("❌ Gagal react:", err);
165
+ }
166
+ },
167
+
168
+ /**
169
+ * Reply error dengan format rapi
170
+ */
171
+ error: async (err) => {
172
+ console.error("❌ Plugin error:", err);
173
+ const message =
174
+ typeof err === "string" ? err : err?.message || "Terjadi kesalahan";
175
+ return m.reply("⚠️ Error: " + message);
176
+ },
177
+ };
178
+ // =========================================
179
+
180
+ // Jalankan plugin
181
+ await plugin.run(m, { conn: sock, sock });
182
  } catch (e) {
183
  console.error("❌ Error handleCommand:", e);
184
  }
bot/lib/helper.js DELETED
@@ -1,134 +0,0 @@
1
- // @ts-check
2
- import os from "os";
3
- import path from "path";
4
- import { fileURLToPath, pathToFileURL } from "url";
5
- import { createRequire } from "module";
6
- import fs from "fs";
7
- import Stream, { Readable } from "stream";
8
-
9
- /**
10
- * @param {ImportMeta | string} pathURL
11
- * @param {boolean?} rmPrefix if value is `'true'`, it will remove `'file://'` prefix, if windows it will automatically false
12
- */
13
- const __filename = function filename(
14
- pathURL = import.meta,
15
- rmPrefix = os.platform() !== "win32",
16
- ) {
17
- const path =
18
- /** @type {ImportMeta} */ (pathURL).url || /** @type {String} */ (pathURL);
19
- return rmPrefix
20
- ? /file:\/\/\//.test(path)
21
- ? fileURLToPath(path)
22
- : path
23
- : /file:\/\/\//.test(path)
24
- ? path
25
- : pathToFileURL(path).href;
26
- };
27
-
28
- /** @param {ImportMeta | string} pathURL */
29
- const __dirname = function dirname(pathURL) {
30
- const dir = __filename(pathURL, true);
31
- const regex = /\/$/;
32
- return regex.test(dir)
33
- ? dir
34
- : fs.existsSync(dir) && fs.statSync(dir).isDirectory()
35
- ? dir.replace(regex, "")
36
- : path.dirname(dir); // windows
37
- };
38
-
39
- /** @param {ImportMeta | string} dir */
40
- const __require = function require(dir = import.meta) {
41
- const path =
42
- /** @type {ImportMeta} */ (dir).url || /** @type {String} */ (dir);
43
- return createRequire(path);
44
- };
45
- /** @param {string} file */
46
- const checkFileExists = (file) =>
47
- fs.promises
48
- .access(file, fs.constants.F_OK)
49
- .then(() => true)
50
- .catch(() => false);
51
-
52
- /**
53
- * @param {Readable} stream
54
- * @param {string} file
55
- * @returns {Promise<void>}
56
- */
57
- const saveStreamToFile = (stream, file) =>
58
- new Promise((resolve, reject) => {
59
- const writable = stream.pipe(fs.createWriteStream(file));
60
- writable.once("finish", () => {
61
- resolve();
62
- writable.destroy();
63
- });
64
- writable.once("error", () => {
65
- reject();
66
- writable.destroy();
67
- });
68
- });
69
-
70
- const kDestroyed = Symbol("kDestroyed");
71
- const kIsReadable = Symbol("kIsReadable");
72
- const isReadableNodeStream = (obj, strict = false) => {
73
- return !!(
74
- (
75
- obj &&
76
- typeof obj.pipe === "function" &&
77
- typeof obj.on === "function" &&
78
- (!strict ||
79
- (typeof obj.pause === "function" &&
80
- typeof obj.resume === "function")) &&
81
- (!obj._writableState || obj._readableState?.readable !== false) && // Duplex
82
- (!obj._writableState || obj._readableState)
83
- ) // Writable has .pipe.
84
- );
85
- };
86
- const isNodeStream = (obj) => {
87
- return (
88
- obj &&
89
- (obj._readableState ||
90
- obj._writableState ||
91
- (typeof obj.write === "function" && typeof obj.on === "function") ||
92
- (typeof obj.pipe === "function" && typeof obj.on === "function"))
93
- );
94
- };
95
- const isDestroyed = (stream) => {
96
- if (!isNodeStream(stream)) return null;
97
- const wState = stream._writableState;
98
- const rState = stream._readableState;
99
- const state = wState || rState;
100
- return !!(stream.destroyed || stream[kDestroyed] || state?.destroyed);
101
- };
102
- const isReadableFinished = (stream, strict) => {
103
- if (!isReadableNodeStream(stream)) return null;
104
- const rState = stream._readableState;
105
- if (rState?.errored) return false;
106
- if (typeof rState?.endEmitted !== "boolean") return null;
107
- return !!(
108
- rState.endEmitted ||
109
- (strict === false && rState.ended === true && rState.length === 0)
110
- );
111
- };
112
- const isReadableStream = (stream) => {
113
- if (typeof Stream.isReadable === "function") return Stream.isReadable(stream);
114
- if (stream && stream[kIsReadable] != null) return stream[kIsReadable];
115
- if (typeof stream?.readable !== "boolean") return null;
116
- if (isDestroyed(stream)) return false;
117
- return (
118
- (isReadableNodeStream(stream) &&
119
- !!stream.readable &&
120
- !isReadableFinished(stream)) ||
121
- stream instanceof fs.ReadStream ||
122
- stream instanceof Readable
123
- );
124
- };
125
-
126
- export default {
127
- __filename,
128
- __dirname,
129
- __require,
130
- checkFileExists,
131
-
132
- saveStreamToFile,
133
- isReadableStream,
134
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bot/lib/serialize.js DELETED
@@ -1,1407 +0,0 @@
1
- import Function from "./function.js";
2
- import { writeExif } from "./sticker.js";
3
-
4
- import path from 'path'
5
- import fs from "fs";
6
- import util from "util";
7
- import chalk from "chalk";
8
- import Crypto from "crypto";
9
- import baileys from "baileys";
10
- import { parsePhoneNumber } from "libphonenumber-js";
11
- import { fileTypeFromBuffer } from 'file-type'
12
- import { format } from 'util'
13
- import fetch from 'node-fetch'
14
-
15
- const {
16
- generateWAMessageFromContent,
17
- proto,
18
- prepareWAMessageMedia,
19
- jidNormalizedUser,
20
- WA_DEFAULT_EPHEMERAL,
21
- downloadContentFromMessage,
22
- jidDecode,
23
- areJidsSameUser,
24
- generateForwardMessageContent,
25
- WAMessageStubType,
26
- extractMessageContent,
27
- } = baileys;
28
-
29
- import { fileURLToPath } from 'url'
30
- import os from "os";
31
- const __dirname = path.dirname(fileURLToPath(import.meta.url))
32
-
33
-
34
- import { promises } from 'fs'
35
- import { join } from 'path'
36
- import { spawn } from 'child_process'
37
-
38
- function ffmpeg(buffer, args = [], ext = '', ext2 = '') {
39
- return new Promise(async (resolve, reject) => {
40
- try {
41
- let tmp = join(os.tmpdir(), '/temp', + new Date + '.' + ext)
42
- let out = tmp + '.' + ext2
43
- await promises.writeFile(tmp, buffer)
44
- spawn('ffmpeg', [
45
- '-y',
46
- '-i', tmp,
47
- ...args,
48
- out
49
- ])
50
- .on('error', reject)
51
- .on('close', async (code) => {
52
- try {
53
- await promises.unlink(tmp)
54
- if (code !== 0) return reject(code)
55
- resolve({
56
- data: await promises.readFile(out),
57
- filename: out,
58
- delete() {
59
- return promises.unlink(out)
60
- }
61
- })
62
- } catch (e) {
63
- reject(e)
64
- }
65
- })
66
- } catch (e) {
67
- reject(e)
68
- }
69
- })
70
- }
71
-
72
- /**
73
- * Convert Audio to Playable WhatsApp Audio
74
- * @param {Buffer} buffer Audio Buffer
75
- * @param {String} ext File Extension
76
- * @returns {Promise<{data: Buffer, filename: String, delete: Function}>}
77
- */
78
- function toPTT(buffer, ext) {
79
- return ffmpeg(buffer, [
80
- '-vn',
81
- '-c:a', 'libopus',
82
- '-b:a', '128k',
83
- '-vbr', 'on',
84
- ], ext, 'ogg')
85
- }
86
-
87
- /**
88
- * Convert Audio to Playable WhatsApp PTT
89
- * @param {Buffer} buffer Audio Buffer
90
- * @param {String} ext File Extension
91
- * @returns {Promise<{data: Buffer, filename: String, delete: Function}>}
92
- */
93
- function toAudio(buffer, ext) {
94
- return ffmpeg(buffer, [
95
- '-vn',
96
- '-c:a', 'libopus',
97
- '-b:a', '128k',
98
- '-vbr', 'on',
99
- '-compression_level', '10'
100
- ], ext, 'opus')
101
- }
102
-
103
- /**
104
- * Convert Audio to Playable WhatsApp Video
105
- * @param {Buffer} buffer Video Buffer
106
- * @param {String} ext File Extension
107
- * @returns {Promise<{data: Buffer, filename: String, delete: Function}>}
108
- */
109
- function toVideo(buffer, ext) {
110
- return ffmpeg(buffer, [
111
- '-c:v', 'libx264',
112
- '-c:a', 'aac',
113
- '-ab', '128k',
114
- '-ar', '44100',
115
- '-crf', '32',
116
- '-preset', 'slow'
117
- ], ext, 'mp4')
118
- }
119
-
120
- function hasEmojis(input) {
121
- const emojiRegex = /\p{Emoji}/u; // Unicode property escapes for emoji
122
- return emojiRegex.test(input);
123
- }
124
-
125
- function getFirstEmoji(input) {
126
- if (!hasEmojis(input)) return false;
127
- const emojiRegex = /\p{Emoji}/u; // Unicode property escapes for emoji
128
- const match = input.match(emojiRegex);
129
- return match ? match[0] : false;
130
- }
131
-
132
- function hasSingleEmoji(input) {
133
- const emojiRegex = /^(\p{Emoji})$/u; // Unicode property escapes for emoji
134
- return emojiRegex.test(input);
135
- }
136
-
137
-
138
-
139
-
140
-
141
- export function Client({ conn, store }) {
142
- delete store.groupMetadata;
143
-
144
- for (let v in store) {
145
- conn[v] = store[v];
146
- }
147
-
148
- const client = Object.defineProperties(conn, {
149
- appenTextMessage: {
150
- async value(m, text, chatUpdate) {
151
- let messages = await baileys.generateWAMessage(
152
- m.chat,
153
- { text: text, mentions: m.mentionedJid },
154
- { userJid: conn.user.id, quoted: m.quoted && m.quoted.fakeObj },
155
- );
156
-
157
- messages.key.fromMe = baileys.areJidsSameUser(m.sender, conn.user.id);
158
- messages.key.id = m.key.id;
159
- messages.pushName = m.pushName;
160
-
161
- if (m.isGroup) messages.participant = m.sender;
162
-
163
- let msg = {
164
- ...chatUpdate,
165
- messages: [baileys.proto.WebMessageInfo.fromObject(messages)],
166
- type: "append",
167
- };
168
-
169
- conn.ev.emit("messages.upsert", msg);
170
- },
171
- },
172
-
173
- logger: {
174
- get() {
175
- return {
176
- info(...args) {
177
- console.log(
178
- chalk.bold.bgRgb(51, 204, 51)("INFO "),
179
- chalk.cyan(util.format(...args)),
180
- );
181
- },
182
- error(...args) {
183
- console.log(
184
- chalk.bold.bgRgb(247, 38, 33)("ERROR "),
185
- chalk.rgb(255, 38, 0)(util.format(...args)),
186
- );
187
- },
188
- warn(...args) {
189
- console.log(
190
- chalk.bold.bgRgb(255, 153, 0)("WARNING "),
191
- chalk.redBright(util.format(...args)),
192
- );
193
- },
194
- trace(...args) {
195
- console.log(
196
- chalk.grey("TRACE "),
197
- chalk.white(util.format(...args)),
198
- );
199
- },
200
- debug(...args) {
201
- console.log(
202
- chalk.bold.bgRgb(66, 167, 245)("DEBUG "),
203
- chalk.white(util.format(...args)),
204
- );
205
- },
206
- };
207
- },
208
- enumerable: true,
209
- },
210
-
211
- getContentType: {
212
- value(content) {
213
- if (content) {
214
- const keys = Object.keys(content);
215
- const key = keys.find(
216
- (k) =>
217
- (k === "conversation" ||
218
- k.endsWith("Message") ||
219
- k.endsWith("V2") ||
220
- k.endsWith("V3")) &&
221
- k !== "senderKeyDistributionMessage",
222
- );
223
- return key;
224
- }
225
- },
226
- enumerable: true,
227
- },
228
-
229
- decodeJid: {
230
- value(jid) {
231
- if (/:\d+@/gi.test(jid)) {
232
- const decode = baileys.jidNormalizedUser(jid);
233
- return decode;
234
- } else return jid;
235
- },
236
- },
237
-
238
- generateMessageID: {
239
- value(id = "3EB0", length = 18) {
240
- return id + Crypto.randomBytes(length).toString("hex").toUpperCase();
241
- },
242
- },
243
-
244
- getFile: {
245
- /**
246
- * getBuffer hehe
247
- * @param {fs.PathLike} PATH
248
- * @param {Boolean} saveToFile
249
- */
250
- async value(PATH, saveToFile = false) {
251
- let res, filename;
252
- // Determine the source of PATH and convert it to Buffer
253
- const data = Buffer.isBuffer(PATH) ? PATH :
254
- PATH instanceof ArrayBuffer ? Buffer.from(PATH) :
255
- /^data:.*?\/.*?;base64,/i.test(PATH) ? Buffer.from(PATH.split(',')[1], 'base64') :
256
- /^https?:\/\//.test(PATH) ? await (async () => {
257
- res = await axios.get(PATH, { responseType: 'arraybuffer' });
258
- return Buffer.from(res.data);
259
- })() :
260
- fs.existsSync(PATH) ? (filename = PATH, fs.readFileSync(PATH)) :
261
- typeof PATH === 'string' ? Buffer.from(PATH) :
262
- Buffer.alloc(0);
263
-
264
- // Ensure the result is a Buffer
265
- if (!Buffer.isBuffer(data)) throw new TypeError('Result is not a buffer');
266
-
267
- // Detect file type
268
- const type = await fileTypeFromBuffer(data) || {
269
- mime: 'application/octet-stream',
270
- ext: '.bin'
271
- };
272
-
273
- // Save to file if required
274
- if (data && saveToFile && !filename) {
275
- filename = path.join(os.tmpdir(), `temp${Date.now()}.${type.ext}`);
276
- await fs.promises.writeFile(filename, data);
277
- }
278
-
279
- // Return the result with additional information
280
- return {
281
- res,
282
- filename,
283
- ...type,
284
- data,
285
- async deleteFile() {
286
- if (filename) await fs.promises.unlink(filename);
287
- }
288
- };
289
- },
290
- enumerable: true
291
- },
292
- sendFile: {
293
- /**
294
- * Send Media/File with Automatic Type Specifier
295
- * @param {String} jid
296
- * @param {String|Buffer} path
297
- * @param {String} filename
298
- * @param {String} caption
299
- * @param {import('@adiwajshing/baileys').proto.WebMessageInfo} quoted
300
- * @param {Boolean} ptt
301
- * @param {Object} options
302
- */
303
- async value(jid, path, filename = '', caption = '', quoted, ptt = false, options = {}) {
304
- let type = await conn.getFile(path, true)
305
- let { res, data: file, filename: pathFile } = type
306
- if (res && res.status !== 200 || file.length <= 65536) {
307
- try { throw { json: JSON.parse(file.toString()) } }
308
- catch (e) { if (e.json) throw e.json }
309
- }
310
- const fileSize = fs.statSync(pathFile).size / 1024 / 1024
311
- if (fileSize >= 100) throw new Error('File size is too big!')
312
- let opt = {}
313
- if (quoted) opt.quoted = quoted
314
- if (!type) options.asDocument = true
315
- let mtype = '', mimetype = options.mimetype || type.mime, convert
316
- if (/webp/.test(type.mime) || (/image/.test(type.mime) && options.asSticker)) mtype = 'sticker'
317
- else if (/image/.test(type.mime) || (/webp/.test(type.mime) && options.asImage)) mtype = 'image'
318
- else if (/video/.test(type.mime)) mtype = 'video'
319
- else if (/audio/.test(type.mime)) (
320
- convert = await toAudio(file, type.ext),
321
- file = convert.data,
322
- pathFile = convert.filename,
323
- mtype = 'audio',
324
- mimetype = options.mimetype || 'audio/ogg; codecs=opus'
325
- )
326
- else mtype = 'document'
327
- if (options.asDocument) mtype = 'document'
328
-
329
- delete options.asSticker
330
- delete options.asLocation
331
- delete options.asVideo
332
- delete options.asDocument
333
- delete options.asImage
334
-
335
- let message = {
336
- ...options,
337
- caption,
338
- ptt,
339
- [mtype]: { url: pathFile },
340
- mimetype,
341
- fileName: filename || pathFile.split('/').pop()
342
- }
343
- /**
344
- * @type {import('@adiwajshing/baileys').proto.WebMessageInfo}
345
- */
346
- let m
347
- try {
348
- m = await conn.sendMessage(jid, message, { ...opt, ...options })
349
- } catch (e) {
350
- console.error(e)
351
- m = null
352
- } finally {
353
- if (!m) m = await conn.sendMessage(jid, { ...message, [mtype]: file }, { ...opt, ...options })
354
- file = null // releasing the memory
355
- return m
356
- }
357
- },
358
- enumerable: true
359
- },
360
- loadMessage: {
361
- /**
362
- *
363
- * @param {String} messageID
364
- * @returns {import('@adiwajshing/baileys').proto.WebMessageInfo}
365
- */
366
- value(messageID) {
367
- return Object.entries(conn.chats)
368
- .filter(([_, { messages }]) => typeof messages === 'object')
369
- .find(([_, { messages }]) => Object.entries(messages)
370
- .find(([k, v]) => (k === messageID || v.key?.id === messageID)))
371
- ?.[1].messages?.[messageID]
372
- },
373
- enumerable: true
374
- },
375
-
376
- getName: {
377
- value(jid) {
378
- let id = conn.decodeJid(jid),
379
- v;
380
-
381
- if (id?.endsWith("@g.us")) {
382
- return new Promise(async (resolve) => {
383
- v =
384
- conn.contacts[id] ||
385
- conn.messages["status@broadcast"]?.array?.find(
386
- (a) => a?.key?.participant === id,
387
- );
388
- if (!(v.name || v.subject)) v = conn.groupMetadata[id] || {};
389
- resolve(
390
- v?.name ||
391
- v?.subject ||
392
- v?.pushName ||
393
- parsePhoneNumber("+" + id.replace("@g.us", "")).format(
394
- "INTERNATIONAL",
395
- ),
396
- );
397
- });
398
- } else {
399
- v =
400
- id === "0@s.whatsapp.net"
401
- ? {
402
- id,
403
- name: "WhatsApp",
404
- }
405
- : id === conn.decodeJid(conn?.user?.id)
406
- ? conn.user
407
- : conn.contacts[id] || {};
408
- }
409
-
410
- return (
411
- v?.name ||
412
- v?.subject ||
413
- v?.pushName ||
414
- v?.verifiedName ||
415
- parsePhoneNumber("+" + id.replace("@s.whatsapp.net", "")).format(
416
- "INTERNATIONAL",
417
- )
418
- );
419
- },
420
- },
421
-
422
- sendContact: {
423
- async value(jid, number, quoted, options = {}) {
424
- let list = [];
425
-
426
- for (let v of number) {
427
- list.push({
428
- displayName: await conn.getName(v),
429
- vcard: `BEGIN:VCARD\nVERSION:3.0\nN:${await conn.getName(
430
- v + "@s.whatsapp.net",
431
- )}\nFN:${await conn.getName(
432
- v + "@s.whatsapp.net",
433
- )}\nitem1.TEL;waid=${v}:${v}\nitem1.X-ABLabel:Ponsel\nitem2.EMAIL;type=INTERNET:alisaadev@gmail.com\nitem2.X-ABLabel:Email\nitem3.URL:https://nhentai.net\nitem3.X-ABLabel:Instagram\nitem4.ADR:;;Indonesia;;;;\nitem4.X-ABLabel:Region\nEND:VCARD`,
434
- });
435
- }
436
-
437
- return conn.sendMessage(
438
- jid,
439
- {
440
- contacts: {
441
- displayName: `${list.length} Contact`,
442
- contacts: list,
443
- },
444
- mentions: quoted?.participant
445
- ? [conn.decodeJid(quoted?.participant)]
446
- : [conn.decodeJid(conn.user?.id)],
447
- ...options,
448
- },
449
- { quoted, ...options },
450
- );
451
- },
452
- enumerable: true,
453
- },
454
-
455
- parseMention: {
456
- value(text) {
457
- return (
458
- [...text.matchAll(/@([0-9]{5,16}|0)/g)].map(
459
- (v) => v[1] + "@s.whatsapp.net",
460
- ) || []
461
- );
462
- },
463
- },
464
-
465
- downloadMediaMessage: {
466
- async value(message, filename) {
467
- let mime = {
468
- imageMessage: "image",
469
- videoMessage: "video",
470
- stickerMessage: "sticker",
471
- documentMessage: "document",
472
- audioMessage: "audio",
473
- ptvMessage: "video",
474
- }[message.type];
475
-
476
- if ("thumbnailDirectPath" in message.msg && !("url" in message.msg)) {
477
- message = {
478
- directPath: message.msg.thumbnailDirectPath,
479
- mediaKey: message.msg.mediaKey,
480
- };
481
- mime = "thumbnail-link";
482
- } else {
483
- message = message.msg;
484
- }
485
-
486
- return await baileys.toBuffer(
487
- await baileys.downloadContentFromMessage(message, mime),
488
- );
489
- },
490
- enumerable: true,
491
- },
492
-
493
- serializeM: {
494
- /**
495
- * Serialize Message, so it easier to manipulate
496
- * @param {import('@adiwajshing/baileys').proto.WebMessageInfo} m
497
- */
498
- value(m) {
499
- return smsg(conn, m)
500
- }
501
- },
502
-
503
- send5button: {
504
- async value(jid, message, footer, header, buttons, quoted, options = {}) {
505
- let headerData = {
506
- hasMediaAttachment: false,
507
- ...header,
508
- };
509
-
510
- if (header.url) {
511
- let { mime, data: buffer } = await Function.getFile(header.url);
512
-
513
- if (/image|video/i.test(mime)) {
514
- let media;
515
- if (/image/i.test(mime)) {
516
- media = await prepareWAMessageMedia(
517
- { image: buffer },
518
- { upload: conn.waUploadToServer },
519
- );
520
- } else if (/video/i.test(mime)) {
521
- media = await prepareWAMessageMedia(
522
- { video: buffer },
523
- { upload: conn.waUploadToServer },
524
- );
525
- }
526
-
527
- headerData = {
528
- ...headerData,
529
- hasMediaAttachment: true,
530
- ...media,
531
- };
532
- }
533
- }
534
-
535
- // Menginisialisasi array kosong untuk menyimpan tombol-tombol yang diformat
536
- let formattedButtons = [];
537
-
538
- // Iterasi melalui setiap tombol
539
- for (let button of buttons) {
540
- let formattedButton;
541
-
542
- // Mendeteksi tipe tombol
543
- if (button.name === "single_select") {
544
- formattedButton = {
545
- name: button.name,
546
- buttonParamsJson: {
547
- title: button.buttonParamsJson.title || "Default Title",
548
- sections: button.buttonParamsJson.sections || [],
549
- },
550
- };
551
- } else if (button.name === "quick_reply") {
552
- formattedButton = {
553
- name: button.name,
554
- buttonParamsJson: {
555
- display_text: button.buttonParamsJson.display_text || "Quick Reply",
556
- id: button.buttonParamsJson.id || "quick_reply_id",
557
- },
558
- };
559
- } else if (button.name.startsWith("cta_")) {
560
- // Cek untuk tombol cta_ yang mungkin memiliki berbagai tipe
561
- formattedButton = {
562
- name: button.name,
563
- buttonParamsJson: {
564
- display_text: button.buttonParamsJson.display_text || "CTA Button",
565
- id: button.buttonParamsJson.id || "cta_button_id",
566
- // tambahkan properti tambahan sesuai kebutuhan
567
- },
568
- };
569
- } else {
570
- // Menangani tombol yang tidak diketahui
571
- formattedButton = {
572
- name: button.name,
573
- buttonParamsJson: button.buttonParamsJson || {},
574
- };
575
- }
576
-
577
- // Tambahkan tombol yang diformat ke dalam array formattedButtons
578
- formattedButtons.push(formattedButton);
579
- }
580
-
581
- // Membangun pesan menggunakan fungsi generateWAMessageFromContent
582
- let msg = generateWAMessageFromContent(
583
- jid,
584
- {
585
- viewOnceMessage: {
586
- message: {
587
- messageContextInfo: {
588
- deviceListMetadata: {},
589
- deviceListMetadataVersion: 2,
590
- },
591
- interactiveMessage: proto.Message.InteractiveMessage.create({
592
- body: proto.Message.InteractiveMessage.Body.create({
593
- text: message,
594
- }),
595
- footer: proto.Message.InteractiveMessage.Footer.create({
596
- text: footer,
597
- }),
598
- header: proto.Message.InteractiveMessage.Header.create(headerData),
599
- nativeFlowMessage: proto.Message.InteractiveMessage.NativeFlowMessage.create({
600
- buttons: formattedButtons, // Menggunakan tombol yang sudah diformat ulang
601
- }),
602
- }),
603
- },
604
- },
605
- },
606
- { quoted, userJid: quoted.key.remoteJid },
607
- );
608
-
609
- // Mengirim pesan menggunakan conn.relayMessage
610
- conn.relayMessage(jid, msg.message, {
611
- messageId: msg.key.id,
612
- });
613
- },
614
- enumerable: true,
615
- writable: true,
616
- },
617
-
618
- sendMedia: {
619
- async value(jid, url, quoted = "", options = {}) {
620
- let { mime, data: buffer, ext, size } = await Function.getFile(url);
621
- mime = options?.mimetype ? options.mimetype : mime;
622
- let data = { text: "" },
623
- mimetype = /audio/i.test(mime) ? "audio/mpeg" : mime;
624
-
625
- if (size > 45000000)
626
- data = {
627
- document: buffer,
628
- mimetype: mime,
629
- fileName: options?.fileName
630
- ? options.fileName
631
- : `${conn.user?.name} (${new Date()}).${ext}`,
632
- ...options,
633
- };
634
- else if (options.asDocument)
635
- data = {
636
- document: buffer,
637
- mimetype: mime,
638
- fileName: options?.fileName
639
- ? options.fileName
640
- : `${conn.user?.name} (${new Date()}).${ext}`,
641
- ...options,
642
- };
643
- else if (options.asSticker || /webp/.test(mime)) {
644
- let pathFile = await writeExif(
645
- { mimetype, data: buffer },
646
- { ...options },
647
- );
648
- data = {
649
- sticker: fs.readFileSync(pathFile),
650
- mimetype: "image/webp",
651
- ...options,
652
- };
653
- fs.existsSync(pathFile) ? await fs.promises.unlink(pathFile) : "";
654
- } else if (/image/.test(mime))
655
- data = {
656
- image: buffer,
657
- mimetype: options?.mimetype ? options.mimetype : "image/png",
658
- ...options,
659
- };
660
- else if (/video/.test(mime))
661
- data = {
662
- video: buffer,
663
- mimetype: options?.mimetype ? options.mimetype : "video/mp4",
664
- ...options,
665
- };
666
- else if (/audio/.test(mime))
667
- data = {
668
- audio: buffer,
669
- mimetype: options?.mimetype ? options.mimetype : "audio/mpeg",
670
- ...options,
671
- };
672
- else
673
- data = {
674
- document: buffer,
675
- mimetype: mime,
676
- ...options,
677
- };
678
-
679
- return await conn.sendMessage(jid, data, {
680
- quoted,
681
- ...options,
682
- });
683
- },
684
- enumerable: true,
685
- },
686
-
687
- cMod: {
688
- value(jid, copy, text = "", sender = conn.user.id, options = {}) {
689
- let mtype = conn.getContentType(copy.message);
690
- let content = copy.message[mtype];
691
-
692
- if (typeof content === "string") copy.message[mtype] = text || content;
693
- else if (content.caption) content.caption = text || content.text;
694
- else if (content.text) content.text = text || content.text;
695
- if (typeof content !== "string") {
696
- copy.message[mtype] = { ...content, ...options };
697
- copy.message[mtype].contextInfo = {
698
- ...(content.contextInfo || {}),
699
- mentionedJid:
700
- options.mentions || content.contextInfo?.mentionedJid || [],
701
- };
702
- }
703
-
704
- if (copy.key.participant)
705
- sender = copy.key.participant = sender || copy.key.participant;
706
- if (copy.key.remoteJid.includes("@s.whatsapp.net"))
707
- sender = sender || copy.key.remoteJid;
708
- else if (copy.key.remoteJid.includes("@broadcast"))
709
- sender = sender || copy.key.remoteJid;
710
- copy.key.remoteJid = jid;
711
- copy.key.fromMe = baileys.areJidsSameUser(sender, conn.user.id);
712
- return baileys.proto.WebMessageInfo.fromObject(copy);
713
- },
714
- },
715
-
716
- sendPoll: {
717
- async value(chatId, name, values, options = {}) {
718
- let selectableCount = options?.selectableCount
719
- ? options.selectableCount
720
- : 1;
721
-
722
- return await conn.sendMessage(
723
- chatId,
724
- {
725
- poll: {
726
- name,
727
- values,
728
- selectableCount,
729
- },
730
- ...options,
731
- },
732
- { ...options },
733
- );
734
- },
735
- enumerable: true,
736
- },
737
-
738
- setProfilePicture: {
739
- async value(jid, media, type = "full") {
740
- let { data } = await Function.getFile(media);
741
-
742
- if (/full/i.test(type)) {
743
- data = await Function.resizeImage(media, 720);
744
- await conn.query({
745
- tag: "iq",
746
- attrs: {
747
- to: await conn.decodeJid(jid),
748
- type: "set",
749
- xmlns: "w:profile:picture",
750
- },
751
- content: [
752
- {
753
- tag: "picture",
754
- attrs: {
755
- type: "image",
756
- },
757
- content: data,
758
- },
759
- ],
760
- });
761
- } else {
762
- data = await Function.resizeImage(media, 640);
763
- await conn.query({
764
- tag: "iq",
765
- attrs: {
766
- to: await conn.decodeJid(jid),
767
- type: "set",
768
- xmlns: "w:profile:picture",
769
- },
770
- content: [
771
- {
772
- tag: "picture",
773
- attrs: {
774
- type: "image",
775
- },
776
- content: data,
777
- },
778
- ],
779
- });
780
- }
781
- },
782
- enumerable: true,
783
- },
784
-
785
- sendGroupV4Invite: {
786
- async value(
787
- jid,
788
- groupJid,
789
- inviteCode,
790
- inviteExpiration,
791
- groupName,
792
- jpegThumbnail,
793
- caption = "Invitation to join my WhatsApp Group",
794
- options = {},
795
- ) {
796
- const media = await baileys.prepareWAMessageMedia(
797
- {
798
- image: (await Function.getFile(jpegThumbnail)).data,
799
- },
800
- {
801
- upload: conn.waUploadToServer,
802
- },
803
- );
804
-
805
- const message = baileys.proto.Message.fromObject({
806
- groupJid,
807
- inviteCode,
808
- inviteExpiration: inviteExpiration
809
- ? parseInt(inviteExpiration)
810
- : +new Date(new Date() + 3 * 86400000),
811
- groupName,
812
- jpegThumbnail: media.imageMessage?.jpegThumbnail || jpegThumbnail,
813
- caption,
814
- });
815
-
816
- const m = baileys.generateWAMessageFromContent(jid, message, {
817
- userJid: conn.user?.id,
818
- });
819
-
820
- await conn.relayMessage(jid, m.message, {
821
- messageId: m.key.id,
822
- });
823
-
824
- return m;
825
- },
826
- enumerable: true,
827
- },
828
-
829
- sendListM: {
830
- async value(jid, text, footer, list, url, quoted, options = {}) {
831
- let header = {
832
- hasMediaAttachment: false,
833
- };
834
-
835
- let { mime, data: buffer, ext, size } = await Function.getFile(url);
836
-
837
- if (/image|video/i.test(mime)) {
838
- let media;
839
- if (/image/i.test(mime)) {
840
- media = await prepareWAMessageMedia(
841
- { image: buffer },
842
- { upload: conn.waUploadToServer },
843
- );
844
- } else if (/video/i.test(mime)) {
845
- media = await prepareWAMessageMedia(
846
- { video: buffer },
847
- { upload: conn.waUploadToServer },
848
- );
849
- }
850
-
851
- header = {
852
- hasMediaAttachment: true,
853
- ...media,
854
- };
855
- }
856
-
857
- let msg = generateWAMessageFromContent(
858
- jid,
859
- {
860
- viewOnceMessage: {
861
- message: {
862
- messageContextInfo: {
863
- deviceListMetadata: {},
864
- deviceListMetadataVersion: 2,
865
- },
866
- interactiveMessage: proto.Message.InteractiveMessage.create({
867
- body: proto.Message.InteractiveMessage.Body.create({
868
- text: text,
869
- }),
870
- footer: proto.Message.InteractiveMessage.Footer.create({
871
- text: footer,
872
- }),
873
- header:
874
- proto.Message.InteractiveMessage.Header.create(header),
875
- nativeFlowMessage:
876
- proto.Message.InteractiveMessage.NativeFlowMessage.create({
877
- buttons: [
878
- {
879
- name: "single_select",
880
- buttonParamsJson: JSON.stringify({
881
- title: "Click Here",
882
- sections: list,
883
- }),
884
- },
885
- ],
886
- }),
887
- contextInfo: options.contextInfo || {},
888
- }),
889
- },
890
- },
891
- },
892
- { quoted, userJid: quoted.key.remoteJid },
893
- );
894
-
895
- conn.relayMessage(jid, msg.message, {
896
- messageId: msg.key.id,
897
- });
898
- },
899
- enumerable: true,
900
- writable: true,
901
- },
902
- sendQuick: {
903
- async value(
904
- jid,
905
- message,
906
- footer,
907
- media = null,
908
- buttons,
909
- quoted,
910
- options = {},
911
- ) {
912
- let header = {
913
- hasMediaAttachment: false,
914
- };
915
-
916
- let { mime, data: buffer, ext, size } = await Function.getFile(media);
917
-
918
- if (/image|video/i.test(mime)) {
919
- let media;
920
- if (/image/i.test(mime)) {
921
- media = await prepareWAMessageMedia(
922
- { image: buffer },
923
- { upload: conn.waUploadToServer },
924
- );
925
- } else if (/video/i.test(mime)) {
926
- media = await prepareWAMessageMedia(
927
- { video: buffer },
928
- { upload: conn.waUploadToServer },
929
- );
930
- }
931
-
932
- header = {
933
- hasMediaAttachment: true,
934
- ...media,
935
- };
936
- }
937
-
938
- let buttonsArray = buttons.map(([buttonText, quickText]) => ({
939
- name: "quick_reply",
940
- buttonParamsJson: JSON.stringify({
941
- display_text: buttonText,
942
- id: quickText,
943
- }),
944
- }));
945
- let content = {
946
- viewOnceMessage: {
947
- message: {
948
- messageContextInfo: {
949
- deviceListMetadata: {},
950
- deviceListMetadataVersion: 2,
951
- },
952
- interactiveMessage: proto.Message.InteractiveMessage.create({
953
- body: proto.Message.InteractiveMessage.Body.create({
954
- text: message,
955
- }),
956
- footer: proto.Message.InteractiveMessage.Footer.create({
957
- text: footer,
958
- }),
959
- header: proto.Message.InteractiveMessage.Header.create(header),
960
- nativeFlowMessage:
961
- proto.Message.InteractiveMessage.NativeFlowMessage.create({
962
- buttons: buttonsArray,
963
- }),
964
- contextInfo: options.contextInfo || {},
965
- }),
966
- },
967
- },
968
- };
969
- let msg = generateWAMessageFromContent(
970
- jid,
971
- content,
972
- { quoted: quoted, ephemeralExpiration: WA_DEFAULT_EPHEMERAL },
973
- { quoted, userJid: quoted.key.remoteJid },
974
- );
975
- await conn.relayMessage(jid, msg.message, {
976
- messageId: msg.key.id,
977
- });
978
- },
979
- enumerable: true,
980
- writable: true,
981
- },
982
- });
983
-
984
- if (conn.user?.id) conn.user.jid = conn.decodeJid(conn.user?.id);
985
- return conn;
986
- }
987
-
988
- export function smsg(conn, m, hasParent) {
989
- if (!m) return m
990
- /**
991
- * @type {import('@adiwajshing/baileys').proto.WebMessageInfo}
992
- */
993
- let M = proto.WebMessageInfo
994
- m = M.fromObject(m)
995
- m.conn = conn
996
- let protocolMessageKey
997
- if (m.message) {
998
- if (m.mtype == 'protocolMessage' && m.msg.key) {
999
- protocolMessageKey = m.msg.key
1000
- if (protocolMessageKey == 'status@broadcast') protocolMessageKey.remoteJid = m.chat
1001
- if (!protocolMessageKey.participant || protocolMessageKey.participant == 'status_me') protocolMessageKey.participant = m.sender
1002
- protocolMessageKey.fromMe = conn.decodeJid(protocolMessageKey.participant) === conn.decodeJid(conn.user.id)
1003
- if (!protocolMessageKey.fromMe && protocolMessageKey.remoteJid === conn.decodeJid(conn.user.id)) protocolMessageKey.remoteJid = m.sender
1004
- }
1005
- if (m.quoted) if (!m.quoted.mediaMessage) delete m.quoted.download
1006
- }
1007
- if (!m.mediaMessage) delete m.download
1008
-
1009
- try {
1010
- if (protocolMessageKey && m.mtype == 'protocolMessage') conn.ev.emit('message.delete', protocolMessageKey)
1011
- } catch (e) {
1012
- console.error(e)
1013
- }
1014
- return m
1015
- }
1016
-
1017
- export async function Serialize(conn, msg) {
1018
- const m = {};
1019
- const botNumber = conn.decodeJid(conn.user?.id);
1020
-
1021
- if (!msg.message) return;
1022
- if (msg.key && msg.key.remoteJid == "status@broadcast") return;
1023
-
1024
- m.message = baileys.extractMessageContent(msg.message);
1025
-
1026
- if (msg.key) {
1027
- m.key = msg.key;
1028
- m.chat = m.key.remoteJid.startsWith("status")
1029
- ? jidNormalizedUser(m.key.participant)
1030
- : jidNormalizedUser(m.key.remoteJid);
1031
- m.fromMe = m.key.fromMe;
1032
- m.from = m.chat;
1033
- m.id = m.key.id;
1034
- m.isBaileys =
1035
- (m.id?.startsWith("3EB0") && m.id?.length === 22) ||
1036
- m.id?.length === 16 ||
1037
- false;
1038
- m.isGroup = m.chat.endsWith("@g.us");
1039
- m.participant = !m.isGroup ? false : m.key.participant;
1040
- m.sender = conn.decodeJid(
1041
- m.fromMe ? conn.user.id : m.isGroup ? m.participant : m.chat,
1042
- );
1043
- }
1044
-
1045
- m.pushName = msg.pushName;
1046
- m.isOwner =
1047
- m.sender &&
1048
- [...global.owner, botNumber.split("@")[0]].includes(
1049
- m.sender.replace(/\D+/g, ""),
1050
- );
1051
-
1052
- if (m.isGroup) {
1053
- m.metadata = await conn.groupMetadata(m.chat);
1054
- m.admins = m.metadata.participants.reduce(
1055
- (memberAdmin, memberNow) =>
1056
- (memberNow.admin
1057
- ? memberAdmin.push({ id: memberNow.id, admin: memberNow.admin })
1058
- : [...memberAdmin]) && memberAdmin,
1059
- [],
1060
- );
1061
- m.isAdmin = !!m.admins.find((member) => member.id === m.sender);
1062
- m.isBotAdmin = !!m.admins.find((member) => member.id === botNumber);
1063
- }
1064
-
1065
- if (m.message) {
1066
- m.type = conn.getContentType(m.message) || Object.keys(m.message)[0];
1067
- m.msg =
1068
- baileys.extractMessageContent(m.message[m.type]) || m.message[m.type];
1069
- m.mentions = m.msg?.contextInfo?.mentionedJid || [];
1070
- m.body =
1071
- m.msg?.text ||
1072
- m.msg?.conversation ||
1073
- m.msg?.caption ||
1074
- m.message?.conversation ||
1075
- m.msg?.selectedButtonId ||
1076
- m.msg?.singleSelectReply?.selectedRowId ||
1077
- m.msg?.selectedId ||
1078
- m.msg?.contentText ||
1079
- m.msg?.selectedDisplayText ||
1080
- m.msg?.title ||
1081
- m.msg?.name ||
1082
- "";
1083
- // respon btn
1084
- if (m.type === "interactiveResponseMessage") {
1085
- let msg = m.message[m.type] || m.msg;
1086
- if (msg.nativeFlowResponseMessage && !m.isBot) {
1087
- let { id } = JSON.parse(msg.nativeFlowResponseMessage.paramsJson) || {};
1088
- if (id) {
1089
- let emit_msg = {
1090
- key: {
1091
- ...m.key,
1092
- },
1093
- message: {
1094
- extendedTextMessage: {
1095
- text: id,
1096
- },
1097
- },
1098
- pushName: m.pushName,
1099
- messageTimestamp: m.messageTimestamp || 754785898978,
1100
- };
1101
- return conn.ev.emit("messages.upsert", {
1102
- messages: [emit_msg],
1103
- type: "notify",
1104
- });
1105
- }
1106
- }
1107
- }
1108
- m.prefix = global.prefix.test(m.body)
1109
- ? m.body.match(global.prefix)[0]
1110
- : ".";
1111
- m.command =
1112
- m.body && m.body.replace(m.prefix, "").trim().split(/ +/).shift();
1113
- m.arg =
1114
- m.body
1115
- .trim()
1116
- .split(/ +/)
1117
- .filter((a) => a) || [];
1118
- m.args =
1119
- m.body
1120
- .trim()
1121
- .replace(new RegExp("^" + Function.escapeRegExp(m.prefix), "i"), "")
1122
- .replace(m.command, "")
1123
- .split(/ +/)
1124
- .filter((a) => a) || [];
1125
- m.text = m.args.join(" ");
1126
- m.expiration = m.msg?.contextInfo?.expiration || 0;
1127
- m.timestamp =
1128
- (typeof msg.messageTimestamp === "number"
1129
- ? msg.messageTimestamp
1130
- : msg.messageTimestamp.low
1131
- ? msg.messageTimestamp.low
1132
- : msg.messageTimestamp.high) || m.msg.timestampMs * 1000;
1133
- m.isMedia = !!m.msg?.mimetype || !!m.msg?.thumbnailDirectPath;
1134
-
1135
- if (m.isMedia) {
1136
- m.mime = m.msg?.mimetype;
1137
- m.size = m.msg?.fileLength;
1138
- m.height = m.msg?.height || "";
1139
- m.width = m.msg?.width || "";
1140
-
1141
- if (/webp/i.test(m.mime)) {
1142
- m.isAnimated = m.msg?.isAnimated;
1143
- }
1144
- }
1145
-
1146
- m.reply = async (text, options = {}) => {
1147
- let chatId = options?.from ? options.from : m.chat;
1148
- let quoted = options?.quoted ? options.quoted : m;
1149
-
1150
- if (
1151
- Buffer.isBuffer(text) ||
1152
- /^data:.?\/.*?;base64,/i.test(text) ||
1153
- /^https?:\/\//.test(text) ||
1154
- fs.existsSync(text)
1155
- ) {
1156
- let data = await Function.getFile(text);
1157
-
1158
- if (
1159
- !options.mimetype &&
1160
- (/utf-8|json/i.test(data.mime) || data.ext == ".bin" || !data.ext)
1161
- ) {
1162
- return conn.sendMessage(
1163
- chatId,
1164
- {
1165
- text,
1166
- mentions: [m.sender, ...conn.parseMention(text)],
1167
- ...options,
1168
- },
1169
- { quoted, ephemeralExpiration: m.expiration, ...options },
1170
- );
1171
- } else {
1172
- return conn.sendMedia(m.chat, data.data, quoted, {
1173
- ephemeralExpiration: m.expiration,
1174
- ...options,
1175
- });
1176
- }
1177
- } else {
1178
- if (!!global.msg[text]) text = global.msg[text];
1179
- return conn.sendMessage(
1180
- chatId,
1181
- {
1182
- text,
1183
- mentions: [m.sender, ...conn.parseMention(text)],
1184
- ...options,
1185
- },
1186
- { quoted, ephemeralExpiration: m.expiration, ...options },
1187
- );
1188
- }
1189
- };
1190
-
1191
- m.react = (emoji) => {
1192
- const firstEmoji = getFirstEmoji(emoji);
1193
- if (hasSingleEmoji(firstEmoji)) {
1194
- return conn.sendMessage(m.from, { react: { text: firstEmoji, key: m.key } });
1195
- }
1196
- };
1197
-
1198
- m.download = (filepath) => {
1199
- if (filepath) return conn.downloadMediaMessage(m, filepath);
1200
- else return conn.downloadMediaMessage(m);
1201
- };
1202
- }
1203
-
1204
- // quoted line
1205
- m.isQuoted = false;
1206
-
1207
- if (m.msg?.contextInfo?.quotedMessage) {
1208
- m.isQuoted = true;
1209
- m.quoted = {};
1210
- m.quoted.message = baileys.extractMessageContent(
1211
- m.msg?.contextInfo?.quotedMessage,
1212
- );
1213
-
1214
- if (m.quoted.message) {
1215
- m.quoted.type =
1216
- conn.getContentType(m.quoted.message) ||
1217
- Object.keys(m.quoted.message)[0];
1218
- m.quoted.msg =
1219
- baileys.extractMessageContent(m.quoted.message[m.quoted.type]) ||
1220
- m.quoted.message[m.quoted.type];
1221
- m.quoted.key = {
1222
- remoteJid: m.msg?.contextInfo?.remoteJid || m.chat,
1223
- participant: m.msg?.contextInfo?.remoteJid?.endsWith("g.us")
1224
- ? conn.decodeJid(m.msg?.contextInfo?.participant)
1225
- : false,
1226
- fromMe: baileys.areJidsSameUser(
1227
- conn.decodeJid(m.msg?.contextInfo?.participant),
1228
- conn.decodeJid(conn.user?.id),
1229
- ),
1230
- id: m.msg?.contextInfo?.stanzaId,
1231
- };
1232
-
1233
- m.quoted.from = m.quoted.key.remoteJid;
1234
- m.quoted.fromMe = m.quoted.key.fromMe;
1235
- m.quoted.id = m.msg?.contextInfo?.stanzaId;
1236
- m.quoted.isBaileys =
1237
- (m.quoted?.id?.startsWith("3EB0") && m.quoted?.id?.length === 22) ||
1238
- m.quoted?.id?.length === 16 ||
1239
- false;
1240
- m.quoted.isGroup = m.quoted.from.endsWith("@g.us");
1241
- m.quoted.participant = m.quoted.key.participant;
1242
- m.quoted.sender = conn.decodeJid(m.msg?.contextInfo?.participant);
1243
- m.quoted.isOwner =
1244
- m.quoted.sender &&
1245
- [...global.owner, botNumber.split("@")[0]].includes(
1246
- m.quoted.sender.replace(/\D+/g, ""),
1247
- );
1248
-
1249
- if (m.quoted.isGroup) {
1250
- m.quoted.metadata = await conn.groupMetadata(m.quoted.from);
1251
- m.quoted.admins = m.quoted.metadata.participants.reduce(
1252
- (memberAdmin, memberNow) =>
1253
- (memberNow.admin
1254
- ? memberAdmin.push({ id: memberNow.id, admin: memberNow.admin })
1255
- : [...memberAdmin]) && memberAdmin,
1256
- [],
1257
- );
1258
- m.quoted.isAdmin = !!m.quoted.admins.find(
1259
- (member) => member.id === m.quoted.sender,
1260
- );
1261
- m.quoted.isBotAdmin = !!m.quoted.admins.find(
1262
- (member) => member.id === botNumber,
1263
- );
1264
- }
1265
-
1266
- m.quoted.mentions = m.quoted.msg?.contextInfo?.mentionedJid || [];
1267
- m.quoted.body =
1268
- m.quoted.msg?.text ||
1269
- m.quoted.msg?.caption ||
1270
- m.quoted?.message?.conversation ||
1271
- m.quoted.msg?.selectedButtonId ||
1272
- m.quoted.msg?.singleSelectReply?.selectedRowId ||
1273
- m.quoted.msg?.selectedId ||
1274
- m.quoted.msg?.contentText ||
1275
- m.quoted.msg?.selectedDisplayText ||
1276
- m.quoted.msg?.title ||
1277
- m.quoted?.msg?.name ||
1278
- "";
1279
- m.quoted.prefix = global.prefix.test(m.quoted.body)
1280
- ? m.quoted.body.match(global.prefix)[0]
1281
- : ".";
1282
- m.quoted.command =
1283
- m.quoted.body &&
1284
- m.quoted.body.replace(m.quoted.prefix, "").trim().split(/ +/).shift();
1285
- m.quoted.arg =
1286
- m.quoted.body
1287
- .trim()
1288
- .split(/ +/)
1289
- .filter((a) => a) || [];
1290
- m.quoted.args =
1291
- m.quoted.body
1292
- .trim()
1293
- .replace(
1294
- new RegExp("^" + Function.escapeRegExp(m.quoted.prefix), "i"),
1295
- "",
1296
- )
1297
- .replace(m.quoted.command, "")
1298
- .split(/ +/)
1299
- .filter((a) => a) || [];
1300
- m.quoted.text = m.quoted.args.join(" ");
1301
- m.quoted.isMedia =
1302
- !!m.quoted.msg?.mimetype || !!m.quoted.msg?.thumbnailDirectPath;
1303
-
1304
- if (m.quoted.isMedia) {
1305
- m.quoted.mime = m.quoted.msg?.mimetype;
1306
- m.quoted.size = m.quoted.msg?.fileLength;
1307
- m.quoted.height = m.quoted.msg?.height || "";
1308
- m.quoted.width = m.quoted.msg?.width || "";
1309
- if (/webp/i.test(m.quoted.mime)) {
1310
- m.quoted.isAnimated = m?.quoted?.msg?.isAnimated || false;
1311
- }
1312
- }
1313
-
1314
- m.quoted.delete = () => {
1315
- if (m.quoted.fromMe) return conn.sendMessage(m.from, {delete: m.quoted.key})
1316
- }
1317
-
1318
- m.quoted.reply = (text, options = {}) => {
1319
- return m.reply(text, { quoted: m.quoted, ...options });
1320
- };
1321
-
1322
- m.quoted.react = (emoji) => {
1323
- const firstEmoji = getFirstEmoji(emoji);
1324
- if (hasSingleEmoji(firstEmoji)) {
1325
- return conn.sendMessage(m.from, { react: { text: firstEmoji, key: m.quoted.key } });
1326
- }
1327
- }
1328
-
1329
- m.quoted.download = (filepath) => {
1330
- if (filepath) return conn.downloadMediaMessage(m.quoted, filepath);
1331
- else return conn.downloadMediaMessage(m.quoted);
1332
- };
1333
- }
1334
- }
1335
-
1336
- return m;
1337
- }
1338
-
1339
- export function protoType() {
1340
- Buffer.prototype.toArrayBuffer = function toArrayBufferV2() {
1341
- const ab = new ArrayBuffer(this.length);
1342
- const view = new Uint8Array(ab);
1343
- for (let i = 0; i < this.length; ++i) {
1344
- view[i] = this[i];
1345
- }
1346
- return ab;
1347
- };
1348
- Buffer.prototype.toArrayBufferV2 = function toArrayBuffer() {
1349
- return this.buffer.slice(
1350
- this.byteOffset,
1351
- this.byteOffset + this.byteLength,
1352
- );
1353
- };
1354
- ArrayBuffer.prototype.toBuffer = function toBuffer() {
1355
- return Buffer.from(new Uint8Array(this));
1356
- };
1357
- Uint8Array.prototype.getFileType =
1358
- ArrayBuffer.prototype.getFileType =
1359
- Buffer.prototype.getFileType =
1360
- async function getFileType() {
1361
- return await fileTypeFromBuffer(this);
1362
- };
1363
- String.prototype.isNumber = Number.prototype.isNumber = isNumber;
1364
- String.prototype.capitalize = function capitalize() {
1365
- return this.charAt(0).toUpperCase() + this.slice(1, this.length);
1366
- };
1367
- String.prototype.capitalizeV2 = function capitalizeV2() {
1368
- const str = this.split(" ");
1369
- return str.map((v) => v.capitalize()).join(" ");
1370
- };
1371
- String.prototype.decodeJid = function decodeJid() {
1372
- if (/:\d+@/gi.test(this)) {
1373
- const decode = baileys.jidDecode(this) || {};
1374
- return (
1375
- (decode.user && decode.server && decode.user + "@" + decode.server) ||
1376
- this
1377
- ).trim();
1378
- } else return this.trim();
1379
- };
1380
- Number.prototype.toTimeString = function toTimeString() {
1381
- const seconds = Math.floor((this / 1000) % 60);
1382
- const minutes = Math.floor((this / (60 * 1000)) % 60);
1383
- const hours = Math.floor((this / (60 * 60 * 1000)) % 24);
1384
- const days = Math.floor(this / (24 * 60 * 60 * 1000));
1385
- return (
1386
- (days ? `${days} day(s) ` : "") +
1387
- (hours ? `${hours} hour(s) ` : "") +
1388
- (minutes ? `${minutes} minute(s) ` : "") +
1389
- (seconds ? `${seconds} second(s)` : "")
1390
- ).trim();
1391
- };
1392
- Number.prototype.getRandom =
1393
- String.prototype.getRandom =
1394
- Array.prototype.getRandom =
1395
- getRandom;
1396
- }
1397
-
1398
- function isNumber() {
1399
- const int = parseInt(this);
1400
- return typeof int === "number" && !isNaN(int);
1401
- }
1402
-
1403
- function getRandom() {
1404
- if (Array.isArray(this) || this instanceof String)
1405
- return this[Math.floor(Math.random() * this.length)];
1406
- return Math.floor(Math.random() * this);
1407
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bot/lib/sticker.js DELETED
@@ -1,260 +0,0 @@
1
- import Func from "./function.js";
2
-
3
- import fs from "fs";
4
- import path from "path";
5
- import axios from "axios";
6
- import Crypto from "crypto";
7
- import ff from "fluent-ffmpeg";
8
- import webp from "node-webpmux";
9
- import { fileTypeFromBuffer } from "file-type";
10
- import os from "os";
11
- import * as cheerio from "cheerio";
12
- import FormData from "form-data"
13
-
14
-
15
- async function imageToWebp(media) {
16
- const tmpFileOut = path.join(
17
- os.tmpdir(),
18
- await Func.getRandom("webp"),
19
- );
20
- const tmpFileIn = path.join(
21
- os.tmpdir(),
22
- await Func.getRandom("jpg"),
23
- );
24
-
25
- fs.writeFileSync(tmpFileIn, media);
26
-
27
- await new Promise((resolve, reject) => {
28
- ff(tmpFileIn)
29
- .on("error", reject)
30
- .on("end", () => resolve(true))
31
- .addOutputOptions([
32
- "-vcodec",
33
- "libwebp",
34
- "-vf",
35
- "scale='min(320,iw)':min'(320,ih)':force_original_aspect_ratio=decrease,fps=15, pad=320:320:-1:-1:color=white@0.0, split [a][b]; [a] palettegen=reserve_transparent=on:transparency_color=ffffff [p]; [b][p] paletteuse",
36
- ])
37
- .toFormat("webp")
38
- .save(tmpFileOut);
39
- });
40
-
41
- const buff = fs.readFileSync(tmpFileOut);
42
- fs.promises.unlink(tmpFileOut);
43
- fs.promises.unlink(tmpFileIn);
44
- return buff;
45
- }
46
-
47
- async function videoToWebp(media) {
48
- const tmpFileOut = path.join(
49
- os.tmpdir(),
50
- await Func.getRandom("webp"),
51
- );
52
- const tmpFileIn = path.join(
53
- os.tmpdir(),
54
- await Func.getRandom("mp4"),
55
- );
56
-
57
- fs.writeFileSync(tmpFileIn, media);
58
-
59
- await new Promise((resolve, reject) => {
60
- ff(tmpFileIn)
61
- .on("error", reject)
62
- .on("end", () => resolve(true))
63
- .addOutputOptions([
64
- "-vcodec",
65
- "libwebp",
66
- "-vf",
67
- "scale='min(320,iw)':min'(320,ih)':force_original_aspect_ratio=decrease,fps=15, pad=320:320:-1:-1:color=white@0.0, split [a][b]; [a] palettegen=reserve_transparent=on:transparency_color=ffffff [p]; [b][p] paletteuse",
68
- "-loop",
69
- "0",
70
- "-ss",
71
- "00:00:00.0",
72
- "-t",
73
- "00:00:05.0",
74
- "-preset",
75
- "default",
76
- "-an",
77
- "-vsync",
78
- "0",
79
- ])
80
- .toFormat("webp")
81
- .save(tmpFileOut);
82
- });
83
-
84
- const buff = fs.readFileSync(tmpFileOut);
85
- fs.promises.unlink(tmpFileOut);
86
- fs.promises.unlink(tmpFileIn);
87
- return buff;
88
- }
89
-
90
- async function writeExif(media, metadata) {
91
- let wMedia = /webp/.test(media.mimetype)
92
- ? media.data
93
- : /image/.test(media.mimetype)
94
- ? await imageToWebp(media.data)
95
- : /video/.test(media.mimetype)
96
- ? await videoToWebp(media.data)
97
- : "";
98
- const tmpFileOut = path.join(
99
- os.tmpdir(),
100
- await Func.getRandom("webp"),
101
- );
102
- const tmpFileIn = path.join(
103
- os.tmpdir(),
104
- await Func.getRandom("webp", "15"),
105
- );
106
-
107
- fs.writeFileSync(tmpFileIn, wMedia);
108
-
109
- if (Object.keys(metadata).length != 0) {
110
- const img = new webp.Image();
111
- const opt = {
112
- packId: metadata?.packId ? metadata.packId : "https://nhentai.net",
113
- packName: metadata?.packName ? metadata.packName : "Stiker dibuat oleh :",
114
- packPublish: metadata?.packPublish ? metadata.packPublish : "Nex - The Fallen Knight",
115
- packEmail: metadata?.packEmail
116
- ? metadata.packEmail
117
- : "arifzyn906@gmail.com",
118
- packWebsite: metadata?.packWebsite
119
- ? metadata.packWebsite
120
- : "https://nhentai.net",
121
- androidApp: metadata?.androidApp
122
- ? metadata.androidApp
123
- : "https://play.google.com/store/apps/details?id=com.bitsmedia.android.muslimpro",
124
- iOSApp: metadata?.iOSApp
125
- ? metadata.iOSApp
126
- : "https://apps.apple.com/id/app/muslim-pro-al-quran-adzan/id388389451?|=id",
127
- emojis: metadata?.emojis ? metadata.emojis : [],
128
- isAvatar: metadata?.isAvatar ? metadata.isAvatar : 0,
129
- };
130
- const json = {
131
- "sticker-pack-id": opt.packId,
132
- "sticker-pack-name": opt.packName,
133
- "sticker-pack-publisher": opt.packPublish,
134
- "sticker-pack-publisher-email": opt.packEmail,
135
- "sticker-pack-publisher-website": opt.packWebsite,
136
- "android-app-store-link": opt.androidApp,
137
- "ios-app-store-link": opt.iOSApp,
138
- emojis: opt.emojis,
139
- "is-avatar-sticker": opt.isAvatar,
140
- "is-ai-sticker":1,
141
- };
142
- const exifAttr = Buffer.from([
143
- 0x49, 0x49, 0x2a, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x41, 0x57,
144
- 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
145
- ]);
146
- const jsonBuff = Buffer.from(JSON.stringify(json), "utf-8");
147
- const exif = Buffer.concat([exifAttr, jsonBuff]);
148
-
149
- exif.writeUIntLE(jsonBuff.length, 14, 4);
150
- await img.load(tmpFileIn);
151
- fs.promises.unlink(tmpFileIn);
152
- img.exif = exif;
153
- await img.save(tmpFileOut);
154
-
155
- return tmpFileOut;
156
- }
157
- }
158
-
159
- async function webp2mp4File(source) {
160
- return new Promise((resolve, reject) => {
161
- const form = new Func.FormData();
162
- let isUrl = typeof source === "string" && /https?:\/\//.test(source);
163
-
164
- form.append("new-image-url", isUrl ? source : "");
165
- form.append("new-image", isUrl ? "" : source, Date.now() + "-image.webp");
166
- Func.axios({
167
- method: "post",
168
- url: "https://s6.ezgif.com/webp-to-mp4",
169
- data: form,
170
- headers: {
171
- "Content-Type": `multipart/form-data; boundary=${form._boundary}`,
172
- },
173
- })
174
- .then(({ data }) => {
175
- const bodyFormThen = new Func.FormData();
176
- const $ = Func.cheerio.load(data);
177
- const file = $("input[name='file']").attr("value");
178
- const token = $("input[name='token']").attr("value");
179
- const convert = $("input[name='file']").attr("value");
180
-
181
- bodyFormThen.append("file", file);
182
- bodyFormThen.append("convert", "Convert WebP to MP4!");
183
- Func.axios({
184
- method: "post",
185
- url: "https://ezgif.com/webp-to-mp4/" + file,
186
- data: bodyFormThen,
187
- headers: {
188
- "Content-Type": `multipart/form-data; boundary=${bodyFormThen._boundary}`,
189
- },
190
- })
191
- .then(({ data }) => {
192
- const $ = Func.cheerio.load(data);
193
- const result =
194
- "https:" +
195
- $("div#output > p.outfile > video > source").attr("src");
196
-
197
- resolve(result);
198
- })
199
- .catch(reject);
200
- })
201
- .catch(reject);
202
- });
203
- }
204
-
205
- async function webp2mp4FileV2(media_source) {
206
- return new Promise(async (resolve, reject) => {
207
- try {
208
- const formData = new FormData();
209
- // Check if media_source is a string (URL) or buffer
210
- if (typeof media_source === 'string') {
211
- formData.append('new-image-url', media_source);
212
- } else {
213
- // Assuming media_source is a buffer
214
- formData.append('new-image', media_source, { filename: Date.now() + '.webp' });
215
- }
216
-
217
- const response = await axios.post('https://ezgif.com/webp-to-mp4', formData, {
218
- headers: {
219
- ...formData.getHeaders()
220
- }
221
- });
222
-
223
- const $ = cheerio.load(response.data);
224
- const srcValue = $('#target').attr('src').split('.com/tmp/')[1];
225
-
226
- const formData2 = new FormData();
227
- formData2.append('file', srcValue);
228
-
229
- const response2 = await axios.post(`https://ezgif.com/webp-to-mp4/${srcValue}?ajax=true`, formData2, {
230
- headers: {
231
- ...formData2.getHeaders()
232
- }
233
- });
234
-
235
- const $2 = cheerio.load(response2.data);
236
- const mp4URL = $2('video source').attr('src');
237
- const absoluteURL = mp4URL.startsWith('//') ? 'https:' + mp4URL : mp4URL;
238
- resolve(absoluteURL);
239
- } catch (error) {
240
- reject(error.message);
241
- }
242
- });
243
- }
244
-
245
- async function uploadFile(buffer) {
246
- const form = new Func.FormData();
247
- const { ext } = await fileTypeFromBuffer(buffer);
248
-
249
- form.append("file", buffer, await Func.getRandom(ext));
250
- let a = await axios.post("https://filezone.my.id/upload", form, {
251
- headers: {
252
- accept: "*/*",
253
- "accept-language": "en-US,en;q=0.9,id;q=0.8",
254
- "content-type": `multipart/form-data; boundary=${form._boundary}`,
255
- },
256
- });
257
- return a.data.result;
258
- }
259
-
260
- export { uploadFile, imageToWebp, videoToWebp, writeExif, webp2mp4File, webp2mp4FileV2 };