Nexchan commited on
Commit
0ee7b04
·
1 Parent(s): 0e6b5cb

Add application file

Browse files
bot/.gitignore ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ lerna-debug.log*
8
+
9
+ # Diagnostic reports (https://nodejs.org/api/report.html)
10
+ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11
+
12
+ # Runtime data
13
+ pids
14
+ *.pid
15
+ *.seed
16
+ *.pid.lock
17
+
18
+ # Directory for instrumented libs generated by jscoverage/JSCover
19
+ lib-cov
20
+
21
+ # Coverage directory used by tools like istanbul
22
+ coverage
23
+ *.lcov
24
+
25
+ # nyc test coverage
26
+ .nyc_output
27
+
28
+ # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29
+ .grunt
30
+
31
+ # Bower dependency directory (https://bower.io/)
32
+ bower_components
33
+
34
+ # node-waf configuration
35
+ .lock-wscript
36
+
37
+ # Compiled binary addons (https://nodejs.org/api/addons.html)
38
+ build/Release
39
+
40
+ # Dependency directories
41
+ node_modules/
42
+ jspm_packages/
43
+ session/
44
+
45
+ # Snowpack dependency directory (https://snowpack.dev/)
46
+ web_modules/
47
+
48
+ # TypeScript cache
49
+ *.tsbuildinfo
50
+
51
+ # Optional npm cache directory
52
+ .npm
53
+
54
+ # Optional eslint cache
55
+ .eslintcache
56
+
57
+ # Optional stylelint cache
58
+ .stylelintcache
59
+
60
+ # Optional REPL history
61
+ .node_repl_history
62
+
63
+ # Output of 'npm pack'
64
+ *.tgz
65
+
66
+ # Yarn Integrity file
67
+ .yarn-integrity
68
+
69
+ # dotenv environment variable files
70
+ .env
71
+ .env.*
72
+ !.env.example
73
+
74
+ # parcel-bundler cache (https://parceljs.org/)
75
+ .cache
76
+ .parcel-cache
77
+
78
+ # Next.js build output
79
+ .next
80
+ out
81
+
82
+ # Nuxt.js build / generate output
83
+ .nuxt
84
+ dist
85
+
86
+ # Gatsby files
87
+ .cache/
88
+ # Comment in the public line in if your project uses Gatsby and not Next.js
89
+ # https://nextjs.org/blog/next-9-1#public-directory-support
90
+ # public
91
+
92
+ # vuepress build output
93
+ .vuepress/dist
94
+
95
+ # vuepress v2.x temp and cache directory
96
+ .temp
97
+ .cache
98
+
99
+ # Sveltekit cache directory
100
+ .svelte-kit/
101
+
102
+ # vitepress build output
103
+ **/.vitepress/dist
104
+
105
+ # vitepress cache directory
106
+ **/.vitepress/cache
107
+
108
+ # Docusaurus cache and generated files
109
+ .docusaurus
110
+
111
+ # Serverless directories
112
+ .serverless/
113
+
114
+ # FuseBox cache
115
+ .fusebox/
116
+
117
+ # DynamoDB Local files
118
+ .dynamodb/
119
+
120
+ # Firebase cache directory
121
+ .firebase/
122
+
123
+ # TernJS port file
124
+ .tern-port
125
+
126
+ # Stores VSCode versions used for testing VSCode extensions
127
+ .vscode-test
128
+
129
+ # yarn v3
130
+ .pnp.*
131
+ .yarn/*
132
+ !.yarn/patches
133
+ !.yarn/plugins
134
+ !.yarn/releases
135
+ !.yarn/sdks
136
+ !.yarn/versions
137
+
138
+ # Vite logs files
139
+ vite.config.js.timestamp-*
140
+ vite.config.ts.timestamp-*
bot/.nomedia ADDED
File without changes
bot/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Teuku Rizky
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
bot/command/download/facebook.js ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import axios from "axios";
2
+
3
+ async function delay(ms) {
4
+ return new Promise((r) => setTimeout(r, ms));
5
+ }
6
+
7
+ export default {
8
+ command: ["facebook", "fb", "fbdl"],
9
+ description: "Download Facebook video/reel",
10
+ example: "%p%cmd <url>",
11
+ name: "facebook",
12
+ tags: "download",
13
+
14
+ run: async (m, { conn }) => {
15
+ try {
16
+ const url = m.args[0];
17
+ if (!/https?:\/\/(fb\.watch|(www\.|web\.|m\.)?facebook\.com)/i.test(url)) {
18
+ return m.reply(`Example: ${m.prefix + m.command} https://www.facebook.com/...`);
19
+ }
20
+
21
+ m.reply("⏳ Sedang memproses...");
22
+
23
+ const res = await axios.get("https://api.nyxs.pw/dl/fb?url=" + url);
24
+ const result = res.data?.result?.hd;
25
+
26
+ if (!result) return m.reply("Gagal mengambil video 😔");
27
+
28
+ const video = await axios.get(result, { responseType: "arraybuffer" });
29
+ await conn.sendMessage(m.from, { video: Buffer.from(video.data) }, { quoted: m });
30
+ } catch (e) {
31
+ console.error(e);
32
+ await m.reply("Terjadi kesalahan: " + e.message);
33
+ }
34
+ },
35
+ };
bot/command/other/ping.js ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import axios from "axios";
2
+
3
+ async function delay(ms) {
4
+ return new Promise((r) => setTimeout(r, ms));
5
+ }
6
+
7
+ export default {
8
+ command: ["ping", "p"],
9
+ description: "Cek respon bot",
10
+ example: "%p%cmd",
11
+ name: "ping",
12
+ tags: "info",
13
+
14
+ run: async (m, { conn }) => {
15
+ try {
16
+ const start = Date.now();
17
+ m.reply("⏳ Mengukur ping...");
18
+
19
+ // Simulasi delay kecil biar terasa natural
20
+ await delay(200);
21
+
22
+ const end = Date.now();
23
+ const ping = end - start;
24
+
25
+ await conn.sendMessage(
26
+ m.from,
27
+ { text: `🏓 Pong!\n📡 *${ping}ms*` },
28
+ { quoted: m }
29
+ );
30
+ } catch (e) {
31
+ console.error(e);
32
+ await m.reply("Terjadi kesalahan: " + e.message);
33
+ }
34
+ },
35
+ };
bot/index.js ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import makeWASocket, {
4
+ useMultiFileAuthState,
5
+ DisconnectReason,
6
+ makeCacheableSignalKeyStore,
7
+ } from "baileys";
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
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = path.dirname(__filename);
17
+
18
+ async function startBot() {
19
+ const { state, saveCreds } = await useMultiFileAuthState("session");
20
+ const sock = makeWASocket({
21
+ printQRInTerminal: false,
22
+ auth: {
23
+ creds: state.creds,
24
+ keys: makeCacheableSignalKeyStore(state.keys, undefined),
25
+ },
26
+ browser: ["MyBot", "Chrome", "1.0.0"],
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;
36
+ if (qr) {
37
+ console.log("\n=== Scan QR ===\n");
38
+ qrcode.generate(qr, { small: true });
39
+ }
40
+ if (connection === "open") console.log("✅ Bot tersambung!");
41
+ });
42
+
43
+ const commands = await loadCommands(path.join(__dirname, "command"));
44
+ console.log(`${commands.size} command berhasil dimuat`);
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
+
55
+ startBot();
bot/lib/function.js ADDED
@@ -0,0 +1,553 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ }
23
+
24
+ await loadDir(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
+ }
56
+ }
bot/lib/helper.js ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 ADDED
@@ -0,0 +1,1407 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 };
bot/package-lock.json ADDED
The diff for this file is too large to render. See raw diff
 
bot/package.json ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "whatsapp-bot",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "test": "echo \"Error: no test specified\" && exit 1"
9
+ },
10
+ "keywords": [],
11
+ "author": "",
12
+ "license": "ISC",
13
+ "dependencies": {
14
+ "baileys": "7.0.0-rc.6",
15
+ "qrcode-terminal": "^0.12.0"
16
+ },
17
+ "devDependencies": {
18
+ "axios": "^1.13.2",
19
+ "chalk": "^5.6.2",
20
+ "cheerio": "^1.1.2",
21
+ "child_process": "^1.0.2",
22
+ "crypto": "^1.0.1",
23
+ "file-type": "^21.1.0",
24
+ "fluent-ffmpeg": "^2.1.3",
25
+ "form-data": "^4.0.4",
26
+ "jimp": "^1.6.0",
27
+ "libphonenumber-js": "^1.12.26",
28
+ "mime-types": "^3.0.1",
29
+ "moment-timezone": "^0.6.0",
30
+ "node-fetch": "^3.3.2",
31
+ "node-webpmux": "^3.2.1",
32
+ "terminal-kit": "^3.1.2",
33
+ "url": "^0.11.4",
34
+ "util": "^0.12.5"
35
+ }
36
+ }
bot/pnpm-lock.yaml ADDED
@@ -0,0 +1,823 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ lockfileVersion: '9.0'
2
+
3
+ settings:
4
+ autoInstallPeers: true
5
+ excludeLinksFromLockfile: false
6
+
7
+ importers:
8
+
9
+ .:
10
+ dependencies:
11
+ baileys:
12
+ specifier: 7.0.0-rc.6
13
+ version: 7.0.0-rc.6(sharp@0.34.4)
14
+ qrcode-terminal:
15
+ specifier: ^0.12.0
16
+ version: 0.12.0
17
+
18
+ packages:
19
+
20
+ '@borewit/text-codec@0.1.1':
21
+ resolution: {integrity: sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA==}
22
+
23
+ '@borewit/text-codec@0.2.0':
24
+ resolution: {integrity: sha512-X999CKBxGwX8wW+4gFibsbiNdwqmdQEXmUejIWaIqdrHBgS5ARIOOeyiQbHjP9G58xVEPcuvP6VwwH3A0OFTOA==}
25
+
26
+ '@cacheable/memoize@2.0.3':
27
+ resolution: {integrity: sha512-hl9wfQgpiydhQEIv7fkjEzTGE+tcosCXLKFDO707wYJ/78FVOlowb36djex5GdbSyeHnG62pomYLMuV/OT8Pbw==}
28
+
29
+ '@cacheable/memory@2.0.4':
30
+ resolution: {integrity: sha512-cCmJKCKlT1t7hNBI1+gFCwmKFd9I4pS3zqBeNGXTSODnpa0EeDmORHY8oEMTuozfdg3cgsVh8ojLaPYb6eC7Cg==}
31
+
32
+ '@cacheable/node-cache@1.7.4':
33
+ resolution: {integrity: sha512-XU3iQNHcIY2P6GlPCr8iScJV8I4S5hRU6sSQpNOKCLi5Q0VcdMEYa6b6vfNMXyqXI9IFzG44SE+RaxrN+5+ROw==}
34
+ engines: {node: '>=18'}
35
+
36
+ '@cacheable/utils@2.2.0':
37
+ resolution: {integrity: sha512-7xaQayO3msdVcxXLYcLU5wDqJBNdQcPPPHr6mdTEIQI7N7TbtSVVTpWOTfjyhg0L6AQwQdq7miKdWtTDBoBldQ==}
38
+
39
+ '@emnapi/runtime@1.6.0':
40
+ resolution: {integrity: sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA==}
41
+
42
+ '@hapi/boom@9.1.4':
43
+ resolution: {integrity: sha512-Ls1oH8jaN1vNsqcaHVYJrKmgMcKsC1wcp8bujvXrHaAqD2iDYq3HoOwsxwo09Cuda5R5nC0o0IxlrlTuvPuzSw==}
44
+
45
+ '@hapi/hoek@9.3.0':
46
+ resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==}
47
+
48
+ '@img/colour@1.0.0':
49
+ resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==}
50
+ engines: {node: '>=18'}
51
+
52
+ '@img/sharp-darwin-arm64@0.34.4':
53
+ resolution: {integrity: sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==}
54
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
55
+ cpu: [arm64]
56
+ os: [darwin]
57
+
58
+ '@img/sharp-darwin-x64@0.34.4':
59
+ resolution: {integrity: sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==}
60
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
61
+ cpu: [x64]
62
+ os: [darwin]
63
+
64
+ '@img/sharp-libvips-darwin-arm64@1.2.3':
65
+ resolution: {integrity: sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==}
66
+ cpu: [arm64]
67
+ os: [darwin]
68
+
69
+ '@img/sharp-libvips-darwin-x64@1.2.3':
70
+ resolution: {integrity: sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==}
71
+ cpu: [x64]
72
+ os: [darwin]
73
+
74
+ '@img/sharp-libvips-linux-arm64@1.2.3':
75
+ resolution: {integrity: sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==}
76
+ cpu: [arm64]
77
+ os: [linux]
78
+
79
+ '@img/sharp-libvips-linux-arm@1.2.3':
80
+ resolution: {integrity: sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==}
81
+ cpu: [arm]
82
+ os: [linux]
83
+
84
+ '@img/sharp-libvips-linux-ppc64@1.2.3':
85
+ resolution: {integrity: sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==}
86
+ cpu: [ppc64]
87
+ os: [linux]
88
+
89
+ '@img/sharp-libvips-linux-s390x@1.2.3':
90
+ resolution: {integrity: sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==}
91
+ cpu: [s390x]
92
+ os: [linux]
93
+
94
+ '@img/sharp-libvips-linux-x64@1.2.3':
95
+ resolution: {integrity: sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==}
96
+ cpu: [x64]
97
+ os: [linux]
98
+
99
+ '@img/sharp-libvips-linuxmusl-arm64@1.2.3':
100
+ resolution: {integrity: sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==}
101
+ cpu: [arm64]
102
+ os: [linux]
103
+
104
+ '@img/sharp-libvips-linuxmusl-x64@1.2.3':
105
+ resolution: {integrity: sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==}
106
+ cpu: [x64]
107
+ os: [linux]
108
+
109
+ '@img/sharp-linux-arm64@0.34.4':
110
+ resolution: {integrity: sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==}
111
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
112
+ cpu: [arm64]
113
+ os: [linux]
114
+
115
+ '@img/sharp-linux-arm@0.34.4':
116
+ resolution: {integrity: sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==}
117
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
118
+ cpu: [arm]
119
+ os: [linux]
120
+
121
+ '@img/sharp-linux-ppc64@0.34.4':
122
+ resolution: {integrity: sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==}
123
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
124
+ cpu: [ppc64]
125
+ os: [linux]
126
+
127
+ '@img/sharp-linux-s390x@0.34.4':
128
+ resolution: {integrity: sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==}
129
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
130
+ cpu: [s390x]
131
+ os: [linux]
132
+
133
+ '@img/sharp-linux-x64@0.34.4':
134
+ resolution: {integrity: sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==}
135
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
136
+ cpu: [x64]
137
+ os: [linux]
138
+
139
+ '@img/sharp-linuxmusl-arm64@0.34.4':
140
+ resolution: {integrity: sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==}
141
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
142
+ cpu: [arm64]
143
+ os: [linux]
144
+
145
+ '@img/sharp-linuxmusl-x64@0.34.4':
146
+ resolution: {integrity: sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==}
147
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
148
+ cpu: [x64]
149
+ os: [linux]
150
+
151
+ '@img/sharp-wasm32@0.34.4':
152
+ resolution: {integrity: sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==}
153
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
154
+ cpu: [wasm32]
155
+
156
+ '@img/sharp-win32-arm64@0.34.4':
157
+ resolution: {integrity: sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==}
158
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
159
+ cpu: [arm64]
160
+ os: [win32]
161
+
162
+ '@img/sharp-win32-ia32@0.34.4':
163
+ resolution: {integrity: sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==}
164
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
165
+ cpu: [ia32]
166
+ os: [win32]
167
+
168
+ '@img/sharp-win32-x64@0.34.4':
169
+ resolution: {integrity: sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==}
170
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
171
+ cpu: [x64]
172
+ os: [win32]
173
+
174
+ '@keyv/bigmap@1.1.0':
175
+ resolution: {integrity: sha512-MX7XIUNwVRK+hjZcAbNJ0Z8DREo+Weu9vinBOjGU1thEi9F6vPhICzBbk4CCf3eEefKRz7n6TfZXwUFZTSgj8Q==}
176
+ engines: {node: '>= 18'}
177
+ peerDependencies:
178
+ keyv: ^5.5.3
179
+
180
+ '@keyv/serialize@1.1.1':
181
+ resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==}
182
+
183
+ '@pinojs/redact@0.4.0':
184
+ resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==}
185
+
186
+ '@protobufjs/aspromise@1.1.2':
187
+ resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
188
+
189
+ '@protobufjs/base64@1.1.2':
190
+ resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
191
+
192
+ '@protobufjs/codegen@2.0.4':
193
+ resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==}
194
+
195
+ '@protobufjs/eventemitter@1.1.0':
196
+ resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==}
197
+
198
+ '@protobufjs/fetch@1.1.0':
199
+ resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==}
200
+
201
+ '@protobufjs/float@1.0.2':
202
+ resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
203
+
204
+ '@protobufjs/inquire@1.1.0':
205
+ resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==}
206
+
207
+ '@protobufjs/path@1.1.2':
208
+ resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
209
+
210
+ '@protobufjs/pool@1.1.0':
211
+ resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
212
+
213
+ '@protobufjs/utf8@1.1.0':
214
+ resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==}
215
+
216
+ '@tokenizer/inflate@0.2.7':
217
+ resolution: {integrity: sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==}
218
+ engines: {node: '>=18'}
219
+
220
+ '@tokenizer/token@0.3.0':
221
+ resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==}
222
+
223
+ '@types/long@4.0.2':
224
+ resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==}
225
+
226
+ '@types/node@10.17.60':
227
+ resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==}
228
+
229
+ '@types/node@24.10.0':
230
+ resolution: {integrity: sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==}
231
+
232
+ '@whiskeysockets/libsignal-node@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/e81ecfc32eb74951d789ab37f7e341ab66d5fff1':
233
+ resolution: {tarball: https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/e81ecfc32eb74951d789ab37f7e341ab66d5fff1}
234
+ version: 2.0.1
235
+
236
+ async-mutex@0.5.0:
237
+ resolution: {integrity: sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==}
238
+
239
+ atomic-sleep@1.0.0:
240
+ resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
241
+ engines: {node: '>=8.0.0'}
242
+
243
+ baileys@7.0.0-rc.6:
244
+ resolution: {integrity: sha512-Unt58dy39rFQ3dRgTUxT38/AXWInNLYx9zijU7PpHDeoNdJfvgyROnHLtmh9hAglLKA1t374v1JLnfI5Tk/TSQ==}
245
+ engines: {node: '>=20.0.0'}
246
+ peerDependencies:
247
+ audio-decode: ^2.1.3
248
+ jimp: ^1.6.0
249
+ link-preview-js: ^3.0.0
250
+ sharp: '*'
251
+ peerDependenciesMeta:
252
+ audio-decode:
253
+ optional: true
254
+ jimp:
255
+ optional: true
256
+ link-preview-js:
257
+ optional: true
258
+
259
+ cacheable@2.1.1:
260
+ resolution: {integrity: sha512-LmF4AXiSNdiRbI2UjH8pAp9NIXxeQsTotpEaegPiDcnN0YPygDJDV3l/Urc0mL72JWdATEorKqIHEx55nDlONg==}
261
+
262
+ content-type@1.0.5:
263
+ resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
264
+ engines: {node: '>= 0.6'}
265
+
266
+ curve25519-js@0.0.4:
267
+ resolution: {integrity: sha512-axn2UMEnkhyDUPWOwVKBMVIzSQy2ejH2xRGy1wq81dqRwApXfIzfbE3hIX0ZRFBIihf/KDqK158DLwESu4AK1w==}
268
+
269
+ debug@4.4.3:
270
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
271
+ engines: {node: '>=6.0'}
272
+ peerDependencies:
273
+ supports-color: '*'
274
+ peerDependenciesMeta:
275
+ supports-color:
276
+ optional: true
277
+
278
+ detect-libc@2.1.2:
279
+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
280
+ engines: {node: '>=8'}
281
+
282
+ eventemitter3@5.0.1:
283
+ resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
284
+
285
+ fflate@0.8.2:
286
+ resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
287
+
288
+ file-type@21.0.0:
289
+ resolution: {integrity: sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==}
290
+ engines: {node: '>=20'}
291
+
292
+ hookified@1.12.2:
293
+ resolution: {integrity: sha512-aokUX1VdTpI0DUsndvW+OiwmBpKCu/NgRsSSkuSY0zq8PY6Q6a+lmOfAFDXAAOtBqJELvcWY9L1EVtzjbQcMdg==}
294
+
295
+ ieee754@1.2.1:
296
+ resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
297
+
298
+ keyv@5.5.3:
299
+ resolution: {integrity: sha512-h0Un1ieD+HUrzBH6dJXhod3ifSghk5Hw/2Y4/KHBziPlZecrFyE9YOTPU6eOs0V9pYl8gOs86fkr/KN8lUX39A==}
300
+
301
+ long@4.0.0:
302
+ resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==}
303
+
304
+ long@5.3.2:
305
+ resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
306
+
307
+ lru-cache@11.2.2:
308
+ resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==}
309
+ engines: {node: 20 || >=22}
310
+
311
+ media-typer@1.1.0:
312
+ resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==}
313
+ engines: {node: '>= 0.8'}
314
+
315
+ ms@2.1.3:
316
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
317
+
318
+ music-metadata@11.9.0:
319
+ resolution: {integrity: sha512-J7VqD8FY6KRcm75Fzj86FPsckiD/EdvO5OS3P+JiMf/2krP3TcAseZYfkic6eFeJ0iBhhzcdxgfu8hLW95aXXw==}
320
+ engines: {node: '>=18'}
321
+
322
+ on-exit-leak-free@2.1.2:
323
+ resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
324
+ engines: {node: '>=14.0.0'}
325
+
326
+ p-queue@9.0.0:
327
+ resolution: {integrity: sha512-KO1RyxstL9g1mK76530TExamZC/S2Glm080Nx8PE5sTd7nlduDQsAfEl4uXX+qZjLiwvDauvzXavufy3+rJ9zQ==}
328
+ engines: {node: '>=20'}
329
+
330
+ p-timeout@7.0.1:
331
+ resolution: {integrity: sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==}
332
+ engines: {node: '>=20'}
333
+
334
+ pino-abstract-transport@2.0.0:
335
+ resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==}
336
+
337
+ pino-std-serializers@7.0.0:
338
+ resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==}
339
+
340
+ pino@9.14.0:
341
+ resolution: {integrity: sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==}
342
+ hasBin: true
343
+
344
+ process-warning@5.0.0:
345
+ resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==}
346
+
347
+ protobufjs@6.8.8:
348
+ resolution: {integrity: sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==}
349
+ hasBin: true
350
+
351
+ protobufjs@7.5.4:
352
+ resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==}
353
+ engines: {node: '>=12.0.0'}
354
+
355
+ qified@0.5.1:
356
+ resolution: {integrity: sha512-+BtFN3dCP+IaFA6IYNOu/f/uK1B8xD2QWyOeCse0rjtAebBmkzgd2d1OAXi3ikAzJMIBSdzZDNZ3wZKEUDQs5w==}
357
+ engines: {node: '>=20'}
358
+
359
+ qrcode-terminal@0.12.0:
360
+ resolution: {integrity: sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==}
361
+ hasBin: true
362
+
363
+ quick-format-unescaped@4.0.4:
364
+ resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
365
+
366
+ real-require@0.2.0:
367
+ resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
368
+ engines: {node: '>= 12.13.0'}
369
+
370
+ safe-stable-stringify@2.5.0:
371
+ resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
372
+ engines: {node: '>=10'}
373
+
374
+ semver@7.7.3:
375
+ resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}
376
+ engines: {node: '>=10'}
377
+ hasBin: true
378
+
379
+ sharp@0.34.4:
380
+ resolution: {integrity: sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==}
381
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
382
+
383
+ sonic-boom@4.2.0:
384
+ resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==}
385
+
386
+ split2@4.2.0:
387
+ resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
388
+ engines: {node: '>= 10.x'}
389
+
390
+ strtok3@10.3.4:
391
+ resolution: {integrity: sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==}
392
+ engines: {node: '>=18'}
393
+
394
+ thread-stream@3.1.0:
395
+ resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==}
396
+
397
+ token-types@6.1.1:
398
+ resolution: {integrity: sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==}
399
+ engines: {node: '>=14.16'}
400
+
401
+ tslib@2.8.1:
402
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
403
+
404
+ uint8array-extras@1.5.0:
405
+ resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==}
406
+ engines: {node: '>=18'}
407
+
408
+ undici-types@7.16.0:
409
+ resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
410
+
411
+ ws@8.18.3:
412
+ resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
413
+ engines: {node: '>=10.0.0'}
414
+ peerDependencies:
415
+ bufferutil: ^4.0.1
416
+ utf-8-validate: '>=5.0.2'
417
+ peerDependenciesMeta:
418
+ bufferutil:
419
+ optional: true
420
+ utf-8-validate:
421
+ optional: true
422
+
423
+ snapshots:
424
+
425
+ '@borewit/text-codec@0.1.1': {}
426
+
427
+ '@borewit/text-codec@0.2.0': {}
428
+
429
+ '@cacheable/memoize@2.0.3':
430
+ dependencies:
431
+ '@cacheable/utils': 2.2.0
432
+
433
+ '@cacheable/memory@2.0.4':
434
+ dependencies:
435
+ '@cacheable/utils': 2.2.0
436
+ '@keyv/bigmap': 1.1.0(keyv@5.5.3)
437
+ hookified: 1.12.2
438
+ keyv: 5.5.3
439
+
440
+ '@cacheable/node-cache@1.7.4':
441
+ dependencies:
442
+ cacheable: 2.1.1
443
+ hookified: 1.12.2
444
+ keyv: 5.5.3
445
+
446
+ '@cacheable/utils@2.2.0':
447
+ dependencies:
448
+ keyv: 5.5.3
449
+
450
+ '@emnapi/runtime@1.6.0':
451
+ dependencies:
452
+ tslib: 2.8.1
453
+ optional: true
454
+
455
+ '@hapi/boom@9.1.4':
456
+ dependencies:
457
+ '@hapi/hoek': 9.3.0
458
+
459
+ '@hapi/hoek@9.3.0': {}
460
+
461
+ '@img/colour@1.0.0': {}
462
+
463
+ '@img/sharp-darwin-arm64@0.34.4':
464
+ optionalDependencies:
465
+ '@img/sharp-libvips-darwin-arm64': 1.2.3
466
+ optional: true
467
+
468
+ '@img/sharp-darwin-x64@0.34.4':
469
+ optionalDependencies:
470
+ '@img/sharp-libvips-darwin-x64': 1.2.3
471
+ optional: true
472
+
473
+ '@img/sharp-libvips-darwin-arm64@1.2.3':
474
+ optional: true
475
+
476
+ '@img/sharp-libvips-darwin-x64@1.2.3':
477
+ optional: true
478
+
479
+ '@img/sharp-libvips-linux-arm64@1.2.3':
480
+ optional: true
481
+
482
+ '@img/sharp-libvips-linux-arm@1.2.3':
483
+ optional: true
484
+
485
+ '@img/sharp-libvips-linux-ppc64@1.2.3':
486
+ optional: true
487
+
488
+ '@img/sharp-libvips-linux-s390x@1.2.3':
489
+ optional: true
490
+
491
+ '@img/sharp-libvips-linux-x64@1.2.3':
492
+ optional: true
493
+
494
+ '@img/sharp-libvips-linuxmusl-arm64@1.2.3':
495
+ optional: true
496
+
497
+ '@img/sharp-libvips-linuxmusl-x64@1.2.3':
498
+ optional: true
499
+
500
+ '@img/sharp-linux-arm64@0.34.4':
501
+ optionalDependencies:
502
+ '@img/sharp-libvips-linux-arm64': 1.2.3
503
+ optional: true
504
+
505
+ '@img/sharp-linux-arm@0.34.4':
506
+ optionalDependencies:
507
+ '@img/sharp-libvips-linux-arm': 1.2.3
508
+ optional: true
509
+
510
+ '@img/sharp-linux-ppc64@0.34.4':
511
+ optionalDependencies:
512
+ '@img/sharp-libvips-linux-ppc64': 1.2.3
513
+ optional: true
514
+
515
+ '@img/sharp-linux-s390x@0.34.4':
516
+ optionalDependencies:
517
+ '@img/sharp-libvips-linux-s390x': 1.2.3
518
+ optional: true
519
+
520
+ '@img/sharp-linux-x64@0.34.4':
521
+ optionalDependencies:
522
+ '@img/sharp-libvips-linux-x64': 1.2.3
523
+ optional: true
524
+
525
+ '@img/sharp-linuxmusl-arm64@0.34.4':
526
+ optionalDependencies:
527
+ '@img/sharp-libvips-linuxmusl-arm64': 1.2.3
528
+ optional: true
529
+
530
+ '@img/sharp-linuxmusl-x64@0.34.4':
531
+ optionalDependencies:
532
+ '@img/sharp-libvips-linuxmusl-x64': 1.2.3
533
+ optional: true
534
+
535
+ '@img/sharp-wasm32@0.34.4':
536
+ dependencies:
537
+ '@emnapi/runtime': 1.6.0
538
+ optional: true
539
+
540
+ '@img/sharp-win32-arm64@0.34.4':
541
+ optional: true
542
+
543
+ '@img/sharp-win32-ia32@0.34.4':
544
+ optional: true
545
+
546
+ '@img/sharp-win32-x64@0.34.4':
547
+ optional: true
548
+
549
+ '@keyv/bigmap@1.1.0(keyv@5.5.3)':
550
+ dependencies:
551
+ hookified: 1.12.2
552
+ keyv: 5.5.3
553
+
554
+ '@keyv/serialize@1.1.1': {}
555
+
556
+ '@pinojs/redact@0.4.0': {}
557
+
558
+ '@protobufjs/aspromise@1.1.2': {}
559
+
560
+ '@protobufjs/base64@1.1.2': {}
561
+
562
+ '@protobufjs/codegen@2.0.4': {}
563
+
564
+ '@protobufjs/eventemitter@1.1.0': {}
565
+
566
+ '@protobufjs/fetch@1.1.0':
567
+ dependencies:
568
+ '@protobufjs/aspromise': 1.1.2
569
+ '@protobufjs/inquire': 1.1.0
570
+
571
+ '@protobufjs/float@1.0.2': {}
572
+
573
+ '@protobufjs/inquire@1.1.0': {}
574
+
575
+ '@protobufjs/path@1.1.2': {}
576
+
577
+ '@protobufjs/pool@1.1.0': {}
578
+
579
+ '@protobufjs/utf8@1.1.0': {}
580
+
581
+ '@tokenizer/inflate@0.2.7':
582
+ dependencies:
583
+ debug: 4.4.3
584
+ fflate: 0.8.2
585
+ token-types: 6.1.1
586
+ transitivePeerDependencies:
587
+ - supports-color
588
+
589
+ '@tokenizer/token@0.3.0': {}
590
+
591
+ '@types/long@4.0.2': {}
592
+
593
+ '@types/node@10.17.60': {}
594
+
595
+ '@types/node@24.10.0':
596
+ dependencies:
597
+ undici-types: 7.16.0
598
+
599
+ '@whiskeysockets/libsignal-node@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/e81ecfc32eb74951d789ab37f7e341ab66d5fff1':
600
+ dependencies:
601
+ curve25519-js: 0.0.4
602
+ protobufjs: 6.8.8
603
+
604
+ async-mutex@0.5.0:
605
+ dependencies:
606
+ tslib: 2.8.1
607
+
608
+ atomic-sleep@1.0.0: {}
609
+
610
+ baileys@7.0.0-rc.6(sharp@0.34.4):
611
+ dependencies:
612
+ '@cacheable/node-cache': 1.7.4
613
+ '@hapi/boom': 9.1.4
614
+ async-mutex: 0.5.0
615
+ libsignal: '@whiskeysockets/libsignal-node@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/e81ecfc32eb74951d789ab37f7e341ab66d5fff1'
616
+ lru-cache: 11.2.2
617
+ music-metadata: 11.9.0
618
+ p-queue: 9.0.0
619
+ pino: 9.14.0
620
+ protobufjs: 7.5.4
621
+ sharp: 0.34.4
622
+ ws: 8.18.3
623
+ transitivePeerDependencies:
624
+ - bufferutil
625
+ - supports-color
626
+ - utf-8-validate
627
+
628
+ cacheable@2.1.1:
629
+ dependencies:
630
+ '@cacheable/memoize': 2.0.3
631
+ '@cacheable/memory': 2.0.4
632
+ '@cacheable/utils': 2.2.0
633
+ hookified: 1.12.2
634
+ keyv: 5.5.3
635
+ qified: 0.5.1
636
+
637
+ content-type@1.0.5: {}
638
+
639
+ curve25519-js@0.0.4: {}
640
+
641
+ debug@4.4.3:
642
+ dependencies:
643
+ ms: 2.1.3
644
+
645
+ detect-libc@2.1.2: {}
646
+
647
+ eventemitter3@5.0.1: {}
648
+
649
+ fflate@0.8.2: {}
650
+
651
+ file-type@21.0.0:
652
+ dependencies:
653
+ '@tokenizer/inflate': 0.2.7
654
+ strtok3: 10.3.4
655
+ token-types: 6.1.1
656
+ uint8array-extras: 1.5.0
657
+ transitivePeerDependencies:
658
+ - supports-color
659
+
660
+ hookified@1.12.2: {}
661
+
662
+ ieee754@1.2.1: {}
663
+
664
+ keyv@5.5.3:
665
+ dependencies:
666
+ '@keyv/serialize': 1.1.1
667
+
668
+ long@4.0.0: {}
669
+
670
+ long@5.3.2: {}
671
+
672
+ lru-cache@11.2.2: {}
673
+
674
+ media-typer@1.1.0: {}
675
+
676
+ ms@2.1.3: {}
677
+
678
+ music-metadata@11.9.0:
679
+ dependencies:
680
+ '@borewit/text-codec': 0.2.0
681
+ '@tokenizer/token': 0.3.0
682
+ content-type: 1.0.5
683
+ debug: 4.4.3
684
+ file-type: 21.0.0
685
+ media-typer: 1.1.0
686
+ strtok3: 10.3.4
687
+ token-types: 6.1.1
688
+ uint8array-extras: 1.5.0
689
+ transitivePeerDependencies:
690
+ - supports-color
691
+
692
+ on-exit-leak-free@2.1.2: {}
693
+
694
+ p-queue@9.0.0:
695
+ dependencies:
696
+ eventemitter3: 5.0.1
697
+ p-timeout: 7.0.1
698
+
699
+ p-timeout@7.0.1: {}
700
+
701
+ pino-abstract-transport@2.0.0:
702
+ dependencies:
703
+ split2: 4.2.0
704
+
705
+ pino-std-serializers@7.0.0: {}
706
+
707
+ pino@9.14.0:
708
+ dependencies:
709
+ '@pinojs/redact': 0.4.0
710
+ atomic-sleep: 1.0.0
711
+ on-exit-leak-free: 2.1.2
712
+ pino-abstract-transport: 2.0.0
713
+ pino-std-serializers: 7.0.0
714
+ process-warning: 5.0.0
715
+ quick-format-unescaped: 4.0.4
716
+ real-require: 0.2.0
717
+ safe-stable-stringify: 2.5.0
718
+ sonic-boom: 4.2.0
719
+ thread-stream: 3.1.0
720
+
721
+ process-warning@5.0.0: {}
722
+
723
+ protobufjs@6.8.8:
724
+ dependencies:
725
+ '@protobufjs/aspromise': 1.1.2
726
+ '@protobufjs/base64': 1.1.2
727
+ '@protobufjs/codegen': 2.0.4
728
+ '@protobufjs/eventemitter': 1.1.0
729
+ '@protobufjs/fetch': 1.1.0
730
+ '@protobufjs/float': 1.0.2
731
+ '@protobufjs/inquire': 1.1.0
732
+ '@protobufjs/path': 1.1.2
733
+ '@protobufjs/pool': 1.1.0
734
+ '@protobufjs/utf8': 1.1.0
735
+ '@types/long': 4.0.2
736
+ '@types/node': 10.17.60
737
+ long: 4.0.0
738
+
739
+ protobufjs@7.5.4:
740
+ dependencies:
741
+ '@protobufjs/aspromise': 1.1.2
742
+ '@protobufjs/base64': 1.1.2
743
+ '@protobufjs/codegen': 2.0.4
744
+ '@protobufjs/eventemitter': 1.1.0
745
+ '@protobufjs/fetch': 1.1.0
746
+ '@protobufjs/float': 1.0.2
747
+ '@protobufjs/inquire': 1.1.0
748
+ '@protobufjs/path': 1.1.2
749
+ '@protobufjs/pool': 1.1.0
750
+ '@protobufjs/utf8': 1.1.0
751
+ '@types/node': 24.10.0
752
+ long: 5.3.2
753
+
754
+ qified@0.5.1:
755
+ dependencies:
756
+ hookified: 1.12.2
757
+
758
+ qrcode-terminal@0.12.0: {}
759
+
760
+ quick-format-unescaped@4.0.4: {}
761
+
762
+ real-require@0.2.0: {}
763
+
764
+ safe-stable-stringify@2.5.0: {}
765
+
766
+ semver@7.7.3: {}
767
+
768
+ sharp@0.34.4:
769
+ dependencies:
770
+ '@img/colour': 1.0.0
771
+ detect-libc: 2.1.2
772
+ semver: 7.7.3
773
+ optionalDependencies:
774
+ '@img/sharp-darwin-arm64': 0.34.4
775
+ '@img/sharp-darwin-x64': 0.34.4
776
+ '@img/sharp-libvips-darwin-arm64': 1.2.3
777
+ '@img/sharp-libvips-darwin-x64': 1.2.3
778
+ '@img/sharp-libvips-linux-arm': 1.2.3
779
+ '@img/sharp-libvips-linux-arm64': 1.2.3
780
+ '@img/sharp-libvips-linux-ppc64': 1.2.3
781
+ '@img/sharp-libvips-linux-s390x': 1.2.3
782
+ '@img/sharp-libvips-linux-x64': 1.2.3
783
+ '@img/sharp-libvips-linuxmusl-arm64': 1.2.3
784
+ '@img/sharp-libvips-linuxmusl-x64': 1.2.3
785
+ '@img/sharp-linux-arm': 0.34.4
786
+ '@img/sharp-linux-arm64': 0.34.4
787
+ '@img/sharp-linux-ppc64': 0.34.4
788
+ '@img/sharp-linux-s390x': 0.34.4
789
+ '@img/sharp-linux-x64': 0.34.4
790
+ '@img/sharp-linuxmusl-arm64': 0.34.4
791
+ '@img/sharp-linuxmusl-x64': 0.34.4
792
+ '@img/sharp-wasm32': 0.34.4
793
+ '@img/sharp-win32-arm64': 0.34.4
794
+ '@img/sharp-win32-ia32': 0.34.4
795
+ '@img/sharp-win32-x64': 0.34.4
796
+
797
+ sonic-boom@4.2.0:
798
+ dependencies:
799
+ atomic-sleep: 1.0.0
800
+
801
+ split2@4.2.0: {}
802
+
803
+ strtok3@10.3.4:
804
+ dependencies:
805
+ '@tokenizer/token': 0.3.0
806
+
807
+ thread-stream@3.1.0:
808
+ dependencies:
809
+ real-require: 0.2.0
810
+
811
+ token-types@6.1.1:
812
+ dependencies:
813
+ '@borewit/text-codec': 0.1.1
814
+ '@tokenizer/token': 0.3.0
815
+ ieee754: 1.2.1
816
+
817
+ tslib@2.8.1: {}
818
+
819
+ uint8array-extras@1.5.0: {}
820
+
821
+ undici-types@7.16.0: {}
822
+
823
+ ws@8.18.3: {}
bot/products.json ADDED
@@ -0,0 +1,303 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "youtube": {
3
+ "title": "🎵 YouTube Premium",
4
+ "description": "Langganan hemat untuk YouTube Premium dan YouTube Music tanpa iklan 🎧",
5
+ "plans": [
6
+ { "duration": "1 Bulan", "price": "Rp 20.000" },
7
+ { "duration": "2 Bulan", "price": "Rp 35.000" }
8
+ ],
9
+ "notes": [
10
+ "Via Invite Family Pro",
11
+ "Bisa pakai email sendiri",
12
+ "Sudah termasuk YouTube Music Premium"
13
+ ]
14
+ },
15
+ "spotify": {
16
+ "title": "🎶 Spotify Premium Private",
17
+ "description": "Akses musik tanpa batas dan tanpa iklan",
18
+ "plans": [
19
+ { "duration": "1 Bulan", "price": "Rp 25.000" },
20
+ { "duration": "2 Bulan", "price": "Rp 45.000" },
21
+ { "duration": "3 Bulan", "price": "Rp 65.000" }
22
+ ],
23
+ "notes": [
24
+ "Tanpa iklan",
25
+ "Akun baru(private, bukan sharing)",
26
+ "Legal & asli dari Spotify(bukan mod)"
27
+ ]
28
+ },
29
+ "capcut": {
30
+ "title": "🎬 CapCut Pro",
31
+ "description": "Untuk iOS, Android, dan PC (Mac & Windows). Versi berkualitas, 100% siap pakai!",
32
+ "plans": [
33
+ { "duration": "1 Bulan", "price": "Rp 30.000" },
34
+ { "duration": "3 Bulan", "price": "Rp 70.000" },
35
+ { "duration": "1 Tahun", "price": "Rp 240.000" }
36
+ ],
37
+ "notes": [
38
+ "Langsung aktif setelah pembayaran",
39
+ "Tanpa ribet dan tanpa watermark!"
40
+ ]
41
+ },
42
+ "canva": {
43
+ "title": "🎨 Canva Pro Premium",
44
+ "description": "Full fitur • Tanpa batas • Legal & bergaransi",
45
+ "plans": [
46
+ { "duration": "1 Bulan", "price": "Rp 5.000" },
47
+ { "duration": "2 Bulan", "price": "Rp 9.000" },
48
+ { "duration": "3 Bulan", "price": "Rp 14.000" },
49
+ { "duration": "1 Tahun", "price": "Rp 35.000" }
50
+ ],
51
+ "notes": [
52
+ "Langsung aktif setelah pembayaran",
53
+ "Bisa pakai akun sendiri"
54
+ ]
55
+ },
56
+ "loklok": {
57
+ "title": "📱 LOKLOK Sharing",
58
+ "description": "Untuk iOS dan Android",
59
+ "plans": [
60
+ { "duration": "1 Bulan", "price": "Rp 27.000" },
61
+ { "duration": "2 Bulan", "price": "Rp 50.000" }
62
+ ],
63
+ "notes": [
64
+ "Akun login seperti biasa",
65
+ "Dilarang ganti password",
66
+ "Tidak bisa login di TV"
67
+ ]
68
+ },
69
+ "netflix": {
70
+ "title": "📺 Netflix Sharing",
71
+ "description": "Region ID • 1 Profil = 1 Pengguna (tanpa VPN) • Anti Hold | Garansi Aktif | Support HD – 4K",
72
+ "plans": [
73
+ { "duration": "1 Bulan", "price": "Rp 30.000" },
74
+ { "duration": "2 Bulan", "price": "Rp 50.000" },
75
+ { "duration": "3 Bulan", "price": "Rp 70.000" }
76
+ ],
77
+ "notes": [
78
+ "Tidak boleh mengganti email/password atau menambah nomor HP",
79
+ "Tidak boleh mengubah membership/langganan",
80
+ "Melanggar = Garansi otomatis hangus"
81
+ ]
82
+ },
83
+ "alightmotion": {
84
+ "title": "📸 AlightMotion Private",
85
+ "description": "Share (Private Project)",
86
+ "plans": [
87
+ { "duration": "1 Bulan", "price": "Rp 15.000" },
88
+ { "duration": "2 Bulan", "price": "Rp 20.000" },
89
+ { "duration": "3 Bulan", "price": "Rp 25.000" },
90
+ { "duration": "1 Tahun", "price": "Rp 65.000" }
91
+ ],
92
+ "notes": [
93
+ "Login dengan email",
94
+ "Support Android & iOS",
95
+ "Akun private"
96
+ ]
97
+ },
98
+ "amazonprime": {
99
+ "title": "🎥 Amazon Prime Video",
100
+ "description": "Private Akun untuk streaming film dan series eksklusif Prime Video",
101
+ "plans": [
102
+ { "duration": "1 Bulan", "price": "Rp 25.000" },
103
+ { "duration": "2 Bulan", "price": "Rp 45.000" },
104
+ { "duration": "3 Bulan", "price": "Rp 65.000" }
105
+ ],
106
+ "notes": [
107
+ "Bisa login di 3 device",
108
+ "Tanpa perlu VPN, tersedia Subtitle Indonesia",
109
+ "Bisa di semua platform (Android, iOS, Windows) via aplikasi atau web"
110
+ ]
111
+ },
112
+ "icloud": {
113
+ "title": "☁️ iCloud 2TB (2–3 Bulan)",
114
+ "description": "Penyimpanan cloud premium Apple dengan kapasitas besar dan fitur tambahan eksklusif.",
115
+ "plans": [
116
+ { "duration": "2–3 Bulan", "price": "Rp 85.000" }
117
+ ],
118
+ "notes": [
119
+ "Akun pribadi kamu sendiri",
120
+ "Proses 1–60 menit",
121
+ "Bonus fitur: Apple Music, TV, Arcade, Relay, Fitness"
122
+ ]
123
+ },
124
+ "blackbox": {
125
+ "title": "🤖 Blackbox Ai Premium",
126
+ "description": "Akun Sharing",
127
+ "plans": [
128
+ { "duration": "1 Bulan", "price": "Rp 10.000" },
129
+ { "duration": "3 Bulan", "price": "Rp 25.000" },
130
+ { "duration": "6 Bulan", "price": "Rp 35.000" },
131
+ { "duration": "Lifetime", "price": "Rp 60.000" }
132
+ ],
133
+ "notes": [
134
+ "Gratis panduan",
135
+ "Dilarang Ganti Password",
136
+ "Akun lifetime garansi hingga 12 bulan"
137
+ ]
138
+ },
139
+ "bstation": {
140
+ "title": "🎞️ Bstation Premium",
141
+ "description": "Akun Sharing",
142
+ "plans": [
143
+ { "duration": "1 Bulan", "price": "Rp 15.000" },
144
+ { "duration": "3 Bulan", "price": "Rp 30.000" },
145
+ { "duration": "12 Bulan", "price": "Rp 45.000" }
146
+ ],
147
+ "notes": [
148
+ "Tanpa Iklan",
149
+ "Legal & Asli dari Bstation (bukan mod)"
150
+ ]
151
+ },
152
+ "chatgpt": {
153
+ "title": "🧠 ChatGPT Premium",
154
+ "description": "Tersedia dua jenis akun: Sharing & Private dengan akses GPT Premium cepat dan stabil.",
155
+ "plans": [
156
+ { "type": "Akun Sharing", "duration": "1 Bulan (Sharing)", "price": "Rp 20.000" },
157
+ { "type": "Akun Private", "duration": "1 Bulan (Private)", "price": "Rp 55.000" }
158
+ ],
159
+ "notes": [
160
+ "Akun dari seller untuk versi Sharing",
161
+ "Akun pribadi untuk versi Private",
162
+ "Dilarang mengganti password"
163
+ ]
164
+ },
165
+ "gemini": {
166
+ "title": "🌌 Gemini Ai Pro + Veo 3 + Gdrive 2TB",
167
+ "description": "Semi Private • Akses paket kombo Gemini AI dengan Veo 3 dan Google Drive 2TB",
168
+ "plans": [
169
+ { "duration": "1 Bulan", "price": "Rp 20.000" }
170
+ ],
171
+ "notes": [
172
+ "Akun pribadi",
173
+ "Via invite family email"
174
+ ]
175
+ },
176
+ "leonardo": {
177
+ "title": "🎨 Leonardo Ai Premium",
178
+ "description": "Akun Sharing untuk akses AI Generatif Teks ke Gambar tanpa batas",
179
+ "plans": [
180
+ { "duration": "1 Bulan", "price": "Rp 55.000" }
181
+ ],
182
+ "notes": [
183
+ "Akun dari seller",
184
+ "Dilarang mengganti password",
185
+ "Unlimited Generate TEKS to IMAGE"
186
+ ]
187
+ },
188
+ "coreldraw": {
189
+ "title": "🖋️ CorelDRAW V.25.1 - Cracked",
190
+ "description": "(Windows Only)",
191
+ "plans": [
192
+ { "type": "Soft File", "price": "Rp 75.000" },
193
+ { "type": "Soft File + Instalasi via Remote", "price": "Rp 100.000" }
194
+ ],
195
+ "notes": [
196
+ "Tutorial instalasi sudah ada di soft file",
197
+ "Jika beli soft file saja, tidak menerima tutorial berupa tindakan",
198
+ "Garansi seumur hidup jika + instalasi via remote"
199
+ ]
200
+ },
201
+ "disney": {
202
+ "title": "🐭 Disney Plus",
203
+ "description": "Akun Sharing resmi dari Disney+",
204
+ "plans": [
205
+ { "duration": "1 Bulan", "price": "Rp 37.000" }
206
+ ],
207
+ "notes": [
208
+ "Tanpa Iklan - Kualitas 4K UHD",
209
+ "Legal & Asli dari Disney+ (bukan mod)",
210
+ "Support SmartTV"
211
+ ]
212
+ },
213
+ "duolingo": {
214
+ "title": "🦉 DuoLingo",
215
+ "description": "Akun Private untuk belajar bahasa dengan mudah dan menyenangkan",
216
+ "plans": [
217
+ { "duration": "1 Bulan", "price": "Rp 20.000" },
218
+ { "duration": "2–3 Bulan", "price": "Rp 35.000" }
219
+ ],
220
+ "notes": [
221
+ "Bisa akun pribadi"
222
+ ]
223
+ },
224
+ "remini": {
225
+ "title": "📸 Remini Premium",
226
+ "description": "Akun Sharing resmi dari Remini (bukan mod)",
227
+ "plans": [
228
+ { "duration": "1 Bulan", "price": "Rp 35.000" }
229
+ ],
230
+ "notes": [
231
+ "Legal & Asli dari Remini",
232
+ "Support Web/iOS/Android"
233
+ ]
234
+ },
235
+ "vidio": {
236
+ "title": "📺 VIDIO Premium",
237
+ "description": "Streaming tanpa iklan dan kualitas HD resmi dari Vidio",
238
+ "plans": [
239
+ { "type": "Sharing - Mobile / TV", "price": "Rp 35.000" },
240
+ { "type": "Sharing - TV Only", "price": "Rp 17.000" },
241
+ { "type": "Sharing - Mobile Only", "price": "Rp 26.000" },
242
+ { "type": "Private - Mobile / TV", "price": "Rp 50.000" },
243
+ { "type": "Private - TV Only", "price": "Rp 26.000" },
244
+ { "type": "Private - Mobile Only", "price": "Rp 36.000" }
245
+ ],
246
+ "notes": [
247
+ "Tonton tanpa iklan",
248
+ "Kualitas HD",
249
+ "Legal resmi dari Vidio"
250
+ ]
251
+ },
252
+ "tiktok": {
253
+ "title": "🎵 TikTok Services",
254
+ "description": "Layanan followers, likes, views, dan share TikTok cepat & aman",
255
+ "plans": [
256
+ { "type": "Followers", "details": [
257
+ "100 Followers = Rp 25.000",
258
+ "500 Followers = Rp 37.000",
259
+ "1000 Followers = Rp 65.000"
260
+ ]},
261
+ { "type": "Likes", "details": [
262
+ "1000 Like = Rp 15.000",
263
+ "2000 Like = Rp 25.000",
264
+ "3000 Like = Rp 35.000",
265
+ "5000 Like = Rp 45.000"
266
+ ]},
267
+ { "type": "Views", "details": [
268
+ "10.000 View = Rp 15.000",
269
+ "30.000 View = Rp 25.000",
270
+ "50.000 View = Rp 35.000",
271
+ "100.000 View = Rp 70.000",
272
+ "500.000 View = Rp 150.000",
273
+ "1.000.000 View = Rp 250.000"
274
+ ]},
275
+ { "type": "Shares", "details": [
276
+ "1000 Share = Rp 15.000",
277
+ "2000 Share = Rp 25.000",
278
+ "3000 Share = Rp 35.000",
279
+ "5000 Share = Rp 45.000"
280
+ ]}
281
+ ],
282
+ "notes": [
283
+ "Selama proses harap tidak di Private",
284
+ "Jangan ubah username saat pesanan diproses",
285
+ "Proses cepat (maks 1x24 jam)",
286
+ "Cukup kirim username/link"
287
+ ]
288
+ },
289
+ "instagram": {
290
+ "title": "📸 Instagram Followers",
291
+ "description": "Layanan penambah followers cepat dan aman",
292
+ "plans": [
293
+ { "duration": "100 Followers", "price": "Rp 12.000" },
294
+ { "duration": "500 Followers", "price": "Rp 37.000" },
295
+ { "duration": "1000 Followers", "price": "Rp 67.000" }
296
+ ],
297
+ "notes": [
298
+ "Selama proses harap tidak di Private",
299
+ "Jangan ubah username saat pesanan diproses",
300
+ "Country mix world | Asia | Eropa"
301
+ ]
302
+ }
303
+ }