├── utils ├── getRandomInt.js ├── sleep.js ├── getRandomString.js ├── formatDate.js ├── formatCurrency.js ├── getTime.js ├── pickRandom.js ├── getDate.js ├── store.js ├── execPromise.js ├── formatSize.js ├── getBuffer.js ├── imageProcessing.js ├── logger.js ├── prototype.js ├── api.js ├── msg.js └── fetcher.js ├── system └── plugins │ ├── say.js │ ├── anime │ ├── picre.js │ ├── cosplay.js │ ├── loli.js │ └── kuronime.js │ ├── events │ ├── _button-resp.js │ ├── antilink.js │ ├── autobio.js │ ├── _eval.js │ └── autoshalat.js │ ├── nsfw │ ├── boobs.js │ ├── korean.js │ └── fantox.js │ ├── random │ └── bluearchive.js │ ├── group │ ├── setpp.js │ ├── setnamegc.js │ ├── setdesc.js │ ├── revoke.js │ ├── linkgc.js │ ├── promote.js │ ├── group.js │ ├── kick.js │ ├── demote.js │ ├── set.js │ ├── askot.js │ ├── settings.js │ └── add.js │ ├── tools │ ├── forward.js │ ├── remini.js │ ├── tourl.js │ ├── removebg.js │ ├── hikagen.js │ ├── pixiv.js │ ├── kalender.js │ ├── npm.js │ ├── whatmusic.js │ └── get.js │ ├── ai │ ├── aoyo.js │ └── felo.js │ ├── owner │ ├── self.js │ ├── clearchat.js │ ├── join.js │ ├── setpp.js │ ├── example.js │ ├── upsw.js │ ├── broadcast.js │ ├── scrape.js │ └── plugins.js │ ├── info │ ├── listgroup.js │ └── ping.js │ ├── downloader │ ├── sfile.js │ ├── instagram.js │ ├── mediafire.js │ ├── ttsearch.js │ ├── rednote.js │ ├── videy-dl.js │ ├── spotify.js │ ├── snackvideo.js │ ├── gitclone.js │ ├── applemusic.js │ └── soundcloud.js │ ├── rpg │ ├── levelup.js │ ├── gajian.js │ ├── mulung.js │ ├── gojek.js │ ├── taxy.js │ ├── bansos.js │ ├── bank.js │ └── merampok.js │ ├── sfw │ ├── nekos.js │ ├── waifuim.js │ └── waifupics.js │ ├── game │ ├── genshin-stalk.js │ ├── blue-archive.js │ └── wuthering-waves.js │ └── islam │ └── alif.js ├── library ├── database │ └── badwords.json ├── leveling.js ├── logger.js ├── queque.js ├── case.js └── converter.js ├── scrapers ├── source │ ├── remini.js │ ├── translate.js │ ├── libur.js │ ├── pixiv.js │ ├── aio.js │ ├── removebg.js │ ├── anoboy.js │ ├── mediafire.js │ ├── rvnoise.js │ ├── gptlogic.js │ ├── videodl.js │ ├── findsong.js │ ├── uploader.js │ ├── whatmusic.js │ ├── metaai.js │ ├── facebook.js │ ├── aoyoai.js │ ├── yousearch.js │ ├── feloai.js │ ├── steam.js │ ├── xbox.js │ ├── furry.js │ ├── sfile.js │ ├── rednote.js │ ├── kuronime.js │ ├── terabox.js │ ├── doodstream.js │ ├── snackvideo.js │ ├── photoaid.js │ └── swapface.js └── index.js ├── events ├── calls.js └── messages.js └── package.json /utils/getRandomInt.js: -------------------------------------------------------------------------------- 1 | module.exports = (max) => Math.floor(Math.random(), max); 2 | -------------------------------------------------------------------------------- /utils/sleep.js: -------------------------------------------------------------------------------- 1 | module.exports = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); 2 | -------------------------------------------------------------------------------- /utils/getRandomString.js: -------------------------------------------------------------------------------- 1 | const crypto = require("crypto"); 2 | 3 | module.exports = (size) => crypto.randomBytes(size).toString("hex"); 4 | -------------------------------------------------------------------------------- /utils/formatDate.js: -------------------------------------------------------------------------------- 1 | module.exports = (date) => 2 | new Date(date).toLocaleDateString(global.locale, { 3 | day: "numeric", 4 | month: "long", 5 | year: "numeric", 6 | }); 7 | -------------------------------------------------------------------------------- /utils/formatCurrency.js: -------------------------------------------------------------------------------- 1 | module.exports = (number, currency) => 2 | new Intl.NumberFormat(global.locale, { 3 | style: "currency", 4 | currency, 5 | maximumFractionDigits: 0, 6 | }).format(number); 7 | -------------------------------------------------------------------------------- /utils/getTime.js: -------------------------------------------------------------------------------- 1 | const moment = require("moment-timezone"); 2 | module.exports = () => { 3 | moment.locale(global.locale || "id-ID"); 4 | return moment.tz(global.timezone || "id-ID").format("HH:mm:ss"); 5 | }; 6 | -------------------------------------------------------------------------------- /utils/pickRandom.js: -------------------------------------------------------------------------------- 1 | const pickRandom = (arr) => { 2 | if (!Array.isArray(arr) || arr.length === 0) return null; 3 | return arr[Math.floor(Math.random() * arr.length)]; 4 | }; 5 | 6 | module.exports = pickRandom; 7 | -------------------------------------------------------------------------------- /utils/getDate.js: -------------------------------------------------------------------------------- 1 | const moment = require("moment-timezone"); 2 | 3 | module.exports = () => { 4 | moment.locale(global.locale || "id-ID"); 5 | return moment.tz(global.timezone || "id-ID").format("dddd, DD MMMM YYYY"); 6 | }; 7 | -------------------------------------------------------------------------------- /utils/store.js: -------------------------------------------------------------------------------- 1 | const { makeInMemoryStore } = require("@whiskeysockets/baileys"); 2 | const pino = require("pino"); 3 | 4 | const store = makeInMemoryStore({ 5 | logger: pino().child({ level: "fatal", stream: "store" }), 6 | }); 7 | 8 | module.exports = store; 9 | -------------------------------------------------------------------------------- /utils/execPromise.js: -------------------------------------------------------------------------------- 1 | const { exec } = require("child_process"); 2 | 3 | module.exports = (command) => 4 | new Promise((resolve, reject) => 5 | exec(command, (error, stdout, stderr) => { 6 | if (error) reject(error); 7 | if (stderr) reject(stderr); 8 | resolve(stdout); 9 | }), 10 | ); 11 | -------------------------------------------------------------------------------- /utils/formatSize.js: -------------------------------------------------------------------------------- 1 | async function formatSize(bytes) { 2 | const sizes = ["Bytes", "KB", "MB", "GB", "TB"]; 3 | if (bytes === 0) return "0 Bytes"; 4 | const i = Math.floor(Math.log(bytes) / Math.log(1024)); 5 | return (bytes / Math.pow(1024, i)).toFixed(2) + " " + sizes[i]; 6 | } 7 | 8 | module.exports = { formatSize }; 9 | -------------------------------------------------------------------------------- /system/plugins/say.js: -------------------------------------------------------------------------------- 1 | class Commands { 2 | constructor() { 3 | this.command = ["say"]; 4 | this.alias = ["say"]; 5 | this.description = ["Toold kirim text"]; 6 | this.loading = true; 7 | } 8 | 9 | async run(m, { sock }) { 10 | if (!m.text) return m.reply("Masukan Textnya!"); 11 | m.reply(m.text); 12 | } 13 | } 14 | 15 | module.exports = new Commands(); 16 | -------------------------------------------------------------------------------- /system/plugins/anime/picre.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "picre", 3 | alias: ["pcr"], 4 | category: ["anime"], 5 | async run(m, { sock, config }) { 6 | try { 7 | await m.reply({ 8 | image: { url: "https://pic.re/image" }, 9 | caption: config.messages.success, 10 | }); 11 | } catch (e) { 12 | await m.reply(`${e}`); 13 | } 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /system/plugins/events/_button-resp.js: -------------------------------------------------------------------------------- 1 | async function events(m, { sock }) { 2 | if (m.type === "interactiveResponseMessage" && m.quoted.fromMe) { 3 | sock.appendTextMessage( 4 | m, 5 | JSON.parse(m.msg.nativeFlowResponseMessage.paramsJson).id, 6 | m, 7 | ); 8 | } 9 | if (m.type === "templateButtonReplyMessage" && m.quoted.fromMe) { 10 | sock.appendTextMessage(m, m.msg.selectedId, m); 11 | } 12 | } 13 | 14 | module.exports = { 15 | events, 16 | }; 17 | -------------------------------------------------------------------------------- /utils/getBuffer.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | const getBuffer = async (url, options = {}) => { 4 | try { 5 | const res = await axios({ 6 | method: "get", 7 | url, 8 | headers: { 9 | DNT: 1, 10 | "Upgrade-Insecure-Request": 1, 11 | }, 12 | ...options, 13 | responseType: "arraybuffer", 14 | }); 15 | return res.data; 16 | } catch (err) { 17 | throw err; 18 | } 19 | }; 20 | 21 | module.exports = { getBuffer }; 22 | -------------------------------------------------------------------------------- /system/plugins/anime/cosplay.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | module.exports = { 4 | command: "cosplay", 5 | alias: ["cp"], 6 | category: ["anime"], 7 | async run(m, { sock, config, Api }) { 8 | try { 9 | const result = Api.createUrl("archive", `/asupan/cosplay`); 10 | await m.reply({ 11 | image: { url: result }, 12 | caption: config.messages.success, 13 | }); 14 | } catch (e) { 15 | await m.reply(`${e}`); 16 | } 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /system/plugins/nsfw/boobs.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | module.exports = { 4 | command: "boobs", 5 | alias: ["boobs"], 6 | category: ["nsfw", "random"], 7 | async run(m, { Api, sock, config }) { 8 | try { 9 | const result = Api.createUrl("delirius", `/nsfw/boobs`); 10 | await m.reply({ 11 | image: { url: result }, 12 | caption: config.messages.success, 13 | }); 14 | } catch (e) { 15 | await m.reply(`${e}`); 16 | } 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /system/plugins/nsfw/korean.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | module.exports = { 4 | command: "korean", 5 | alias: ["korean"], 6 | category: ["nsfw", "random"], 7 | async run(m, { Api, sock, config }) { 8 | try { 9 | const result = Api.createUrl("delirius", `/nsfw/corean`); 10 | await m.reply({ 11 | image: { url: result }, 12 | caption: config.messages.success, 13 | }); 14 | } catch (e) { 15 | await m.reply(`${e}`); 16 | } 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /system/plugins/random/bluearchive.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | module.exports = { 4 | command: "ba", 5 | alias: ["ba"], 6 | category: ["anime", "game", "random"], 7 | async run(m, { Api, sock, config }) { 8 | try { 9 | const result = Api.createUrl("apizell", `/random/ba`); 10 | await m.reply({ 11 | image: { url: result }, 12 | caption: config.messages.success, 13 | }); 14 | } catch (e) { 15 | await m.reply(`${e}`); 16 | } 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /library/database/badwords.json: -------------------------------------------------------------------------------- 1 | [ 2 | "seksi", 3 | "adult", 4 | "naked", 5 | "ngentot", 6 | "telanjang", 7 | "seks", 8 | "kelamin", 9 | "vagina", 10 | "payudara", 11 | "nenen", 12 | "tetek", 13 | "pantat", 14 | "memek", 15 | "horny", 16 | "susu", 17 | "bugil", 18 | "loli", 19 | "hentai", 20 | "anal", 21 | "blow job", 22 | "onani", 23 | "kontol", 24 | "tobrut", 25 | "slot", 26 | "situs", 27 | "jackpot", 28 | "vicidor", 29 | "cipokan", 30 | "kokop", 31 | "lesbi", 32 | "lesby" 33 | ] 34 | -------------------------------------------------------------------------------- /scrapers/source/remini.js: -------------------------------------------------------------------------------- 1 | async function Upscale(imageBuffer) { 2 | try { 3 | const response = await fetch("https://lexica.qewertyy.dev/upscale", { 4 | body: JSON.stringify({ 5 | image_data: Buffer.from(imageBuffer, "base64"), 6 | format: "binary", 7 | }), 8 | headers: { 9 | "Content-Type": "application/json", 10 | }, 11 | method: "POST", 12 | }); 13 | return Buffer.from(await response.arrayBuffer()); 14 | } catch { 15 | return null; 16 | } 17 | } 18 | 19 | module.exports = Upscale; 20 | -------------------------------------------------------------------------------- /system/plugins/anime/loli.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | module.exports = { 4 | command: "loli", 5 | alias: ["loli"], 6 | category: ["anime"], 7 | async run(m, { sock, config }) { 8 | try { 9 | const res = await axios.get( 10 | "https://api.lolicon.app/setu/v2?num=1&r18=0&tag=lolicon", 11 | ); 12 | const result = await res.data.data[0].urls.original; 13 | await m.reply({ 14 | image: { url: result }, 15 | caption: config.messages.success, 16 | }); 17 | } catch (e) { 18 | await m.reply(`${e}`); 19 | } 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /system/plugins/group/setpp.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "setppgroup", 3 | alias: ["setppgc"], 4 | category: ["group"], 5 | settings: { 6 | group: true, 7 | admin: true, 8 | botAdmin: true, 9 | }, 10 | description: "📸 Mengubah foto profil grup", 11 | async run(m, { sock }) { 12 | let q = m.quoted ? m.quoted : m; 13 | if (!q.isMedia) 14 | throw "⚠️ *Silakan kirim atau reply foto yang ingin dijadikan foto profil grup!*"; 15 | 16 | let buffer = await q.download(); 17 | await sock 18 | .updateProfilePicture(m.cht, buffer) 19 | .then(() => m.reply("> ✅ *Foto profil grup berhasil diperbarui!*")); 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /events/calls.js: -------------------------------------------------------------------------------- 1 | const config = require("@configuration"); 2 | 3 | module.exports = (sock) => { 4 | const lastCall = new Map(); 5 | 6 | sock.ev.on("call", async (callData) => { 7 | if (!config.settings.antiCall) return; 8 | 9 | for (const call of callData) { 10 | const now = Date.now(); 11 | const lastCallTime = lastCall.get(call.from) || 0; 12 | 13 | if (now - lastCallTime > 5000) { 14 | lastCall.set(call.from, now); 15 | 16 | await sock.rejectCall(call.id, call.from); 17 | await sock.sendMessage(call.from, { 18 | text: `🚫 ${config.messages.call}`, 19 | mentions: [call.from] 20 | }); 21 | } 22 | } 23 | }); 24 | }; -------------------------------------------------------------------------------- /scrapers/source/translate.js: -------------------------------------------------------------------------------- 1 | async function translate(query = "", lang) { 2 | if (!query.trim()) return ""; 3 | const url = new URL("https://translate.googleapis.com/translate_a/single"); 4 | url.searchParams.append("client", "gtx"); 5 | url.searchParams.append("sl", "auto"); 6 | url.searchParams.append("dt", "t"); 7 | url.searchParams.append("tl", lang); 8 | url.searchParams.append("q", query); 9 | 10 | try { 11 | const response = await fetch(url.href); 12 | const data = await response.json(); 13 | if (data) { 14 | return [data[0]].map(([[a]]) => a).join(" "); 15 | } else { 16 | return ""; 17 | } 18 | } catch (err) { 19 | throw err; 20 | } 21 | } 22 | 23 | module.exports = translate; 24 | -------------------------------------------------------------------------------- /system/plugins/group/setnamegc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "setnamegroup", 3 | alias: ["setnamegc"], 4 | category: ["group"], 5 | settings: { 6 | group: true, 7 | admin: true, 8 | botAdmin: true, 9 | }, 10 | description: "📝 Mengubah nama grup ke nama yang baru", 11 | async run(m, { sock, text }) { 12 | if (!text) 13 | throw "⚠️ *Silakan masukkan nama grup baru!*\n\n💡 Contoh: setnamegc Grup Santai."; 14 | if (text.length > 20) 15 | throw "❌ *Nama grup terlalu panjang!*\nMaksimal 20 karakter."; 16 | 17 | await sock.groupUpdateSubject(m.cht, text.trim()); 18 | m.reply( 19 | `✅ *Nama grup berhasil diubah!* \n\n📝 *Nama Grup Baru:*\n${text.trim()}`, 20 | ); 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /system/plugins/group/setdesc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "setdeskripsi", 3 | alias: ["setdesc"], 4 | category: ["group"], 5 | settings: { 6 | group: true, 7 | admin: true, 8 | botAdmin: true, 9 | }, 10 | description: "📝 Mengganti deskripsi grup dengan teks baru", 11 | async run(m, { sock, text }) { 12 | if (!text) 13 | throw "⚠️ *Silakan masukkan deskripsi grup baru!*\n\n💡 Contoh: setdesc Grup Diskusi Seru."; 14 | if (text.length > 200) 15 | throw "❌ *Deskripsi terlalu panjang!*\nMaksimal 200 karakter."; 16 | 17 | await sock.groupUpdateDescription(m.cht, text.trim()); 18 | m.reply( 19 | `✅ *Deskripsi Grup Berhasil Diperbarui!*\n\n📝 *Deskripsi Baru:*\n${text.trim()}`, 20 | ); 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /system/plugins/group/revoke.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "resetlink", 3 | alias: ["revoke"], 4 | category: ["group"], 5 | settings: { 6 | group: true, 7 | admin: true, 8 | botAdmin: true, 9 | }, 10 | description: "🔗 Mereset ulang link undangan grup", 11 | async run(m, { sock }) { 12 | try { 13 | const newLink = await sock.groupRevokeInvite(m.cht); 14 | m.reply( 15 | `*✅ Link Grup Berhasil Direset!*\n\n> 🔗 *Link Baru:* https://chat.whatsapp.com/${newLink}\n\n📌 _Silakan bagikan link ini kepada anggota baru._`, 16 | ); 17 | } catch (err) { 18 | m.reply( 19 | `*❌ Gagal Mereset Link!*\n\n> Pastikan bot memiliki hak admin untuk melakukan perubahan ini.`, 20 | ); 21 | } 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /scrapers/source/libur.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const cheerio = require("cheerio"); 3 | 4 | async function libur(year) { 5 | return new Promise(async (resolve, reject) => { 6 | await axios 7 | .get(`https://publicholidays.co.id/id/${year}-dates/`) 8 | .then((a) => { 9 | let $ = cheerio.load(a.data); 10 | let array = []; 11 | $("table.publicholidays") 12 | .eq(0) 13 | .find("tbody .even") 14 | .each((a, i) => { 15 | array.push({ 16 | date: $(i).find("td").eq(0).text(), 17 | day: $(i).find("td").eq(1).text(), 18 | name: $(i).find("td").eq(2).text().trim(), 19 | }); 20 | }); 21 | resolve(array); 22 | }); 23 | }); 24 | } 25 | 26 | module.exports = libur; 27 | -------------------------------------------------------------------------------- /system/plugins/tools/forward.js: -------------------------------------------------------------------------------- 1 | const path = require("node:path"); 2 | const serialize = require(path.resolve("./library/serialize.js")); 3 | 4 | module.exports = { 5 | command: "quoted", 6 | alias: ["q"], 7 | category: ["tools"], 8 | settings: { 9 | limit: true, 10 | }, 11 | description: "🔁 Meneruskan pesan yang dibalas oleh pengguna", 12 | async run(m, { sock, store }) { 13 | if (!m.quoted) throw "> ❌ Balas pesan yang ingin diteruskan"; 14 | 15 | let loadMsg = await store.loadMessage(m.cht, m.quoted.id); 16 | if (!loadMsg?.message) throw "> ❌ Tidak ada pesan yang diteruskan"; 17 | 18 | let data = await serialize(loadMsg, sock, store); 19 | if (!data?.quoted) throw "> ❌ Tidak ada pesan yang diteruskan"; 20 | 21 | sock.copyNForward(m.sender, data.quoted, true); 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /scrapers/source/pixiv.js: -------------------------------------------------------------------------------- 1 | async function pixiv(q, r18) { 2 | return new Promise(async (resolve, reject) => { 3 | axios 4 | .get( 5 | `https://api.lolicon.app/setu/v1?r18=${r18 ? 1 : 0}&excludeAi=true&size=original&size=regular&keyword=${q}&limit=20`, 6 | ) 7 | .then((response) => { 8 | const array = []; 9 | const data = response.data; 10 | for (let i of data.data) { 11 | array.push({ 12 | title: i.title, 13 | author: i.author, 14 | tags: i.tags, 15 | images: i.url, 16 | }); 17 | } 18 | resolve(array); 19 | }) 20 | .catch((e) => { 21 | reject({ 22 | error: "Sorry I can't get data from pixiv.net", 23 | }); 24 | }); 25 | }); 26 | } 27 | 28 | module.exports = pixiv; 29 | -------------------------------------------------------------------------------- /scrapers/source/aio.js: -------------------------------------------------------------------------------- 1 | const { fetch } = require("node-fetch"); 2 | 3 | async function aio(url) { 4 | try { 5 | const response = await fetch( 6 | "https://anydownloader.com/wp-json/aio-dl/video-data/", 7 | { 8 | method: "POST", 9 | headers: { 10 | "Content-Type": "application/x-www-form-urlencoded", 11 | Referer: "https://anydownloader.com/", 12 | Token: 13 | "5b64d1dc13a4b859f02bcf9e572b66ea8e419f4b296488b7f32407f386571a0d", 14 | }, 15 | body: new URLSearchParams({ 16 | url, 17 | }), 18 | }, 19 | ); 20 | const data = await response.json(); 21 | if (!data.url) return data; 22 | return data; 23 | } catch (error) { 24 | console.error("Error fetching data:"); 25 | throw error; 26 | } 27 | } 28 | 29 | module.exports = aio; 30 | -------------------------------------------------------------------------------- /scrapers/source/removebg.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | async function removebg(buffer) { 4 | try { 5 | return await new Promise(async (resolve, reject) => { 6 | const image = buffer.toString("base64"); 7 | let res = await axios.post( 8 | "https://us-central1-ai-apps-prod.cloudfunctions.net/restorePhoto", 9 | { 10 | image: `data:image/png;base64,${image}`, 11 | model: 12 | "fb8af171cfa1616ddcf1242c093f9c46bcada5ad4cf6f2fbe8b81b330ec5c003", 13 | }, 14 | ); 15 | const data = res.data?.replace(`"`, ""); 16 | console.log(res.status, data); 17 | if (!data) return reject("failed removebg image"); 18 | resolve(data); 19 | }); 20 | } catch (e) { 21 | return { 22 | msg: e, 23 | }; 24 | } 25 | } 26 | 27 | module.exports = removebg; 28 | -------------------------------------------------------------------------------- /system/plugins/events/antilink.js: -------------------------------------------------------------------------------- 1 | const { getUrlInfo } = require("baileys"); 2 | 3 | async function events(m, { sock, Func }) { 4 | if (!m.isGroup) return; 5 | let group = db.list().group[m.cht]; 6 | if (Func.isUrl(m.body) && /chat.whatsapp.com/.test(m.body)) { 7 | if (!m.isBotAdmin || m.isAdmin) return; 8 | let msg = `*🚫 Link Grup Terdeteksi!*\n\n`; 9 | msg += m.isAdmin 10 | ? `> Anda aman karena Anda adalah admin dari grup *${m.metadata.subject}*.\n\nTerima kasih telah mematuhi aturan grup! 😊` 11 | : `> Maaf, mengirim link grup lain tidak diperbolehkan di grup *${m.metadata.subject}*.\n\nPesan Anda akan dihapus untuk menjaga keamanan dan kenyamanan bersama. Terima kasih atas pengertiannya! 🙏`; 12 | 13 | await m.reply(msg); 14 | await sock.sendMessage(m.cht, { delete: m.key }); 15 | } 16 | } 17 | 18 | module.exports = { 19 | events, 20 | }; 21 | -------------------------------------------------------------------------------- /system/plugins/events/autobio.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const config = require("@configuration"); 3 | 4 | async function events(m, { sock }) { 5 | if (config.settings.autoBio) { 6 | let uptime = clockString(process.uptime() * 1000); 7 | 8 | try { 9 | await sock.updateProfileStatus( 10 | `Takeshi-WaBot | Runtime: ${uptime} | Mode: ${config.settings["groupOnly"] ? "Group" : "Publik"}`, 11 | ); 12 | } catch (err) { 13 | console.error("Gagal memperbarui bio:", err); 14 | } 15 | } 16 | } 17 | 18 | module.exports = { 19 | events, 20 | }; 21 | 22 | function clockString(ms) { 23 | let h = isNaN(ms) ? "--" : Math.floor(ms / 3600000); 24 | let m = isNaN(ms) ? "--" : Math.floor(ms / 60000) % 60; 25 | let s = isNaN(ms) ? "--" : Math.floor(ms / 1000) % 60; 26 | return [h, m, s].map((v) => v.toString().padStart(2, "0")).join(":"); 27 | } 28 | -------------------------------------------------------------------------------- /system/plugins/group/linkgc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "link", 3 | alias: ["linkgc"], 4 | category: ["group"], 5 | settings: { 6 | group: true, 7 | botAdmin: true, 8 | }, 9 | description: "🔗 Mendapatkan tautan undangan grup", 10 | async run(m, { sock }) { 11 | try { 12 | let link = 13 | "https://chat.whatsapp.com/" + (await sock.groupInviteCode(m.cht)); 14 | let caption = `*– 乂 Informasi Tautan Grup*\n\n`; 15 | caption += `> *- Nama Grup :* ${m.metadata.subject}\n`; 16 | caption += `> *- Tautan :* ${link}\n\n`; 17 | caption += `📌 _Gunakan tautan ini dengan bijak untuk menjaga keamanan grup._`; 18 | 19 | m.reply(caption); 20 | } catch (error) { 21 | m.reply( 22 | `*❌ Gagal Mendapatkan Link!*\n\n> Pastikan bot memiliki hak admin untuk membuat tautan grup.`, 23 | ); 24 | } 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /scrapers/source/anoboy.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const cheerio = require("cheerio"); 3 | 4 | class AnoBoy { 5 | latest = async function latest() { 6 | return new Promise(async (resolve, reject) => { 7 | await axios.get("https://anoboy.io/").then((a) => { 8 | let $ = cheerio.load(a.data); 9 | let array = []; 10 | $(".listupd .bs .bsx").each((a, i) => { 11 | array.push({ 12 | title: $(i).find("a").attr("title"), 13 | type: $(i).find("a .limit .typez").text().trim(), 14 | thumbnail: 15 | $(i).find("a .limit img").attr("data-lazy-src") || 16 | "https://files.catbox.moe/qflij6.png", 17 | url: $(i).find("a").attr("href"), 18 | }); 19 | }); 20 | resolve(array); 21 | }); 22 | }); 23 | }; 24 | } 25 | 26 | module.exports = new AnoBoy(); 27 | -------------------------------------------------------------------------------- /system/plugins/ai/aoyo.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | module.exports = { 4 | command: "aoyo", 5 | alias: ["ao"], 6 | category: ["ai"], 7 | description: "Jawab semua pertanyaan mu dengan Aoyo AI", 8 | loading: true, 9 | async run(m, { text, sock, Api, Msg, config }) { 10 | if (!text) 11 | return m.reply( 12 | `${Msg.generateInstruction(["send"], ["text"])}\n` + 13 | Msg.generateCommandExample( 14 | m.prefix, 15 | m.command, 16 | "Apa itu bot whatsapp?", 17 | ), 18 | ); 19 | try { 20 | const apiUrl = Api.createUrl("fast", "/aiexperience/aoyo", { 21 | ask: text, 22 | }); 23 | const result = (await axios.get(apiUrl)).data.result.answer; 24 | 25 | return await m.reply(result); 26 | } catch (error) { 27 | m.reply(error); 28 | if (error.status !== 200) return await m.reply(config.messages.notFound); 29 | } 30 | }, 31 | }; 32 | -------------------------------------------------------------------------------- /system/plugins/ai/felo.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | module.exports = { 4 | command: "felo", 5 | alias: ["fl"], 6 | category: ["ai"], 7 | description: "Jawab semua pertanyaan mu dengan Felo AI", 8 | loading: true, 9 | async run(m, { text, sock, Api, Msg, config }) { 10 | if (!text) 11 | return m.reply( 12 | `${Msg.generateInstruction(["send"], ["text"])}\n` + 13 | Msg.generateCommandExample( 14 | m.prefix, 15 | m.command, 16 | "Apa itu bot whatsapp?", 17 | ), 18 | ); 19 | try { 20 | const apiUrl = Api.createUrl("fast", "/aiexperience/felo", { 21 | ask: text, 22 | }); 23 | const result = (await axios.get(apiUrl)).data.result.answer; 24 | 25 | return await m.reply(result); 26 | } catch (error) { 27 | m.reply(error); 28 | if (error.status !== 200) return await m.reply(config.messages.notFound); 29 | } 30 | }, 31 | }; 32 | -------------------------------------------------------------------------------- /system/plugins/tools/remini.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "remini", 3 | alias: ["hdr", "hd"], 4 | category: ["tools"], 5 | settings: { 6 | limit: true, 7 | }, 8 | description: "Jernihkan dan tingkatkan kualitas foto favoritmu dengan mudah!", 9 | loading: true, 10 | async run(m, { Scraper, Func }) { 11 | let target = m.quoted ? m.quoted : m; 12 | if (!/image/.test(target.msg.mimetype) || !target.isMedia) 13 | throw "⚠️ *Oops!* Harap kirim atau balas sebuah foto yang ingin dijernihkan."; 14 | 15 | let buffer = await target.download(); 16 | let enhancedImage = await Scraper.remini(buffer); 17 | let size = Func.formatSize(enhancedImage.length); 18 | 19 | m.reply({ 20 | image: enhancedImage, 21 | caption: `✨ *Remini - Photo Enhancer* ✨\n\n🖼️ *Foto telah berhasil dijernihkan!*\n📂 *Ukuran file hasil:* ${size}\n\n💡 *Tips:* Gunakan foto dengan kualitas dasar yang cukup baik untuk hasil terbaik.`, 22 | }); 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /system/plugins/owner/self.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "self", 3 | alias: [], 4 | category: ["owner"], 5 | settings: { 6 | owner: true, 7 | }, 8 | description: "🔇 Ubah bot menjadi mode senyap (Self Mode)", 9 | async run(m, { sock, text }) { 10 | if (!text) 11 | return m.reply({ 12 | poll: { 13 | name: `*– 乂 Cara Penggunaan Fitur Mode Senyap (Self Mode)*\n\n> *\`0\`* - Untuk mematikan fitur self mode (Bot aktif di grup)\n> *\`1\`* - Untuk menghidupkan fitur self mode (Bot hanya aktif di private chat)`, 14 | values: [`self 0`, `self 1`], 15 | selectableCount: 1, 16 | }, 17 | }); 18 | 19 | let settings = db.list().settings; 20 | settings.self = parseInt(text) > 0 ? true : false; 21 | 22 | m.reply( 23 | `> ✅ Fitur *Self Mode* berhasil ${text < 1 ? "dimatikan" : "diaktifkan"}. Bot akan ${text < 1 ? "kembali bergabung ke grup" : "hanya dapat digunakan melalui pesan pribadi"}.`, 24 | ); 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /utils/imageProcessing.js: -------------------------------------------------------------------------------- 1 | const sharp = require("sharp"); 2 | const { fromBuffer } = require("file-type"); 3 | 4 | /** 5 | * Resize image to buffer or base64 6 | * @param {Buffer} bufferdata 7 | * @param {Boolean} encode 8 | * @param {String} mimType 9 | */ 10 | // eslint-disable-next-line no-async-promise-executor 11 | module.exports = resizeImage = (buff, encode) => 12 | new Promise(async (resolve, reject) => { 13 | console.log("Resizeing image..."); 14 | const { mime } = await fromBuffer(buff); 15 | sharp(buff, { failOnError: false }) 16 | .resize(512, 512) 17 | .toBuffer() 18 | .then((resizedImageBuffer) => { 19 | if (!encode) return resolve(resizedImageBuffer); 20 | console.log("Create base64 from resizedImageBuffer..."); 21 | const resizedImageData = resizedImageBuffer.toString("base64"); 22 | const resizedBase64 = `data:${mime};base64,${resizedImageData}`; 23 | resolve(resizedBase64); 24 | }) 25 | .catch((error) => reject(error)); 26 | }); 27 | -------------------------------------------------------------------------------- /system/plugins/tools/tourl.js: -------------------------------------------------------------------------------- 1 | class Command { 2 | constructor() { 3 | this.command = "tourl"; 4 | this.alias = ["upload"]; 5 | this.category = ["tools"]; 6 | this.settings = { 7 | limit: true, 8 | }; 9 | this.description = "Ubah media menjadi link dengan cepat dan mudah!"; 10 | this.loading = true; 11 | } 12 | 13 | run = async (m, { Uploader, Func }) => { 14 | let target = m.quoted ? m.quoted : m; 15 | if (!target.msg.mimetype) 16 | throw "⚠️ *Oops!* Harap kirim atau balas media (gambar/video) yang ingin diubah menjadi tautan."; 17 | 18 | let buffer = await target.download(); 19 | let url = await Uploader.catbox(buffer); 20 | 21 | let caption = `✨ *Media to URL Uploader* ✨\n\n`; 22 | caption += `📂 *Ukuran media:* ${Func.formatSize(buffer.length)}\n`; 23 | caption += `🔗 *Tautan hasil:* ${url}\n\n`; 24 | caption += `💡 *Tips:* Gunakan fitur ini untuk berbagi media dengan lebih mudah tanpa perlu mengunggah ulang.`; 25 | 26 | m.reply(caption); 27 | }; 28 | } 29 | 30 | module.exports = new Command(); 31 | -------------------------------------------------------------------------------- /utils/logger.js: -------------------------------------------------------------------------------- 1 | const chalk = require("chalk"); 2 | 3 | // Logger class 4 | class Logger { 5 | info(...args) { 6 | console.log(chalk.green.bold("[ INFORMATION ]"), ...args); 7 | } 8 | 9 | warn(...args) { 10 | console.log(chalk.yellow.bold("[ WARNING ]"), ...args); 11 | } 12 | 13 | run(...args) { 14 | console.log(chalk.cyan.bold("[ RUNNING ]"), ...args); 15 | } 16 | 17 | success(...args) { 18 | console.log(chalk.green.bold("[ SUCCESS ]"), ...args); 19 | } 20 | 21 | error(...args) { 22 | console.log(chalk.red.bold("[ ERROR ]"), ...args); 23 | } 24 | 25 | debug(...args) { 26 | console.log(chalk.gray.bold("[ DEBUG ]"), ...args); 27 | } 28 | 29 | critical(...args) { 30 | console.log(chalk.bgRed.white.bold("[ CRITICAL ]"), ...args); 31 | } 32 | 33 | event(...args) { 34 | console.log(chalk.magenta.bold("[ EVENT ]"), ...args); 35 | } 36 | 37 | start() { 38 | console.clear(); 39 | console.log(chalk.magenta.bold("[ SYSTEM STARTED ]")); 40 | } 41 | } 42 | 43 | module.exports = { 44 | logger: new Logger(), 45 | }; 46 | -------------------------------------------------------------------------------- /library/leveling.js: -------------------------------------------------------------------------------- 1 | const growth = Math.pow(Math.PI / Math.E, 1.618) * Math.E * 0.75; 2 | 3 | function xpRange(level, multiplier = global.multiplier || 1) { 4 | if (level < 0) { 5 | throw new TypeError("Level tidak boleh negatif"); 6 | } 7 | const min = 8 | level === 0 ? 0 : Math.round(Math.pow(level, growth) * multiplier) + 1; 9 | const max = Math.round(Math.pow(level + 1, growth) * multiplier); 10 | return { min, max, xp: max - min }; 11 | } 12 | 13 | function findLevel(xp, multiplier = global.multiplier || 1) { 14 | if (xp === 1 / 0) return 1 / 0; 15 | if (isNaN(xp)) return NaN; 16 | if (xp <= 0) return -1; 17 | let level = 0; 18 | do { 19 | level++; 20 | } while (xpRange(level, multiplier).min <= xp); 21 | return --level; 22 | } 23 | 24 | function canLevelUp(level, xp, multiplier = global.multiplier || 1) { 25 | return ( 26 | level >= 0 && 27 | (xp === 1 / 0 || 28 | (!isNaN(xp) && xp > 0 && level < findLevel(xp, multiplier))) 29 | ); 30 | } 31 | 32 | module.exports = { 33 | growth, 34 | xpRange, 35 | findLevel, 36 | canLevelUp, 37 | }; 38 | -------------------------------------------------------------------------------- /library/logger.js: -------------------------------------------------------------------------------- 1 | const color = require("chalk"); 2 | 3 | module.exports = (m) => { 4 | const tag = color.green.bold("[ WHATSAPP ]"); 5 | const divider = color.magenta.bold("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); 6 | 7 | let info = `\n${tag} ${color.cyan.bold("NEW MESSAGE RECEIVED")}\n`; 8 | info += `${divider}\n`; 9 | info += 10 | color.white.bold("🗨️Dari : ") + 11 | color.green.bold(m.isGroup ? "Group Chat" : "Private Chat") + 12 | "\n"; 13 | 14 | if (m.isGroup) { 15 | info += 16 | color.white.bold("👥 Group Name: ") + 17 | color.yellow.bold(m.metadata.subject) + 18 | "\n"; 19 | } 20 | 21 | info += color.white.bold("📂 Tipe : ") + color.blue.bold(m.type) + "\n"; 22 | info += 23 | color.white.bold("🙋 Nama : ") + color.magenta.bold(m.pushName) + "\n"; 24 | info += `${divider}\n`; 25 | 26 | const body = m.body 27 | ? color.bgYellow.black.bold(` ✏️ Pesan: ${m.body} `) 28 | : color.bgBlue.white.bold(` 📂 Media/File Terkirim `); 29 | 30 | info += `${body}\n`; 31 | info += `${divider}\n`; 32 | 33 | console.log(info); 34 | }; 35 | -------------------------------------------------------------------------------- /system/plugins/info/listgroup.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "listgroup", 3 | alias: ["gcl", "listgroup"], 4 | category: ["info"], 5 | settings: { 6 | limit: true, 7 | owner: true, 8 | }, 9 | description: "📋 Menampilkan daftar grup yang dikelola oleh bot", 10 | async run(m, { sock, Func, store }) { 11 | let data = Object.values(store.groupMetadata); 12 | let cap = "*– 乂 Daftar Group Bot*\n\n"; 13 | cap += `> 📊 *Total Grup:* ${data.length}\n\n`; 14 | 15 | if (data.length === 0) { 16 | return m.reply("> ❌ *Tidak ada grup yang terdaftar di bot ini.*"); 17 | } 18 | 19 | cap += data 20 | .sort((a, b) => b.creation - a.creation) 21 | .map((a, i) => { 22 | let owner = a.owner ? "@" + a.owner.split("@")[0] : "Tidak ada pemilik"; 23 | return ( 24 | `> *${i + 1}.* ${a.subject}\n` + 25 | `> ⏳ *Dibuat:* ${Func.ago(a.creation * 1000)}\n` + 26 | `> 👥 *Jumlah Member:* ${a.size}\n` + 27 | `> 👑 *Pemilik:* ${owner}` 28 | ); 29 | }) 30 | .join("\n\n"); 31 | 32 | m.reply(cap); 33 | }, 34 | }; 35 | -------------------------------------------------------------------------------- /system/plugins/owner/clearchat.js: -------------------------------------------------------------------------------- 1 | class Command { 2 | constructor() { 3 | this.command = "clearchat"; 4 | this.alias = []; 5 | this.category = ["owner"]; 6 | this.settings = { owner: true }; 7 | this.description = "Membersihkan semua pesan di grup"; 8 | this.loading = true; 9 | } 10 | 11 | run = async (m, { sock, store }) => { 12 | const groupIds = Object.keys(store.groupMetadata); 13 | if (groupIds.length === 0) { 14 | throw `*❌ Tidak ada grup ditemukan untuk membersihkan pesan.*`; 15 | } 16 | let successCount = 0; 17 | for (let id of groupIds) { 18 | try { 19 | await sock.clearMessage(id, m.key, m.timestamps); 20 | successCount++; 21 | } catch (err) { 22 | console.error(`❌ Gagal membersihkan chat grup ${id}:`, err.message); 23 | } 24 | } 25 | 26 | m.reply( 27 | `*╭──[ 乂 CLEAR CHAT - GRUP ]* 28 | ᎒⊸ Total Grup: *${groupIds.length}* 29 | ᎒⊸ Berhasil Dibersihkan: *${successCount}* 30 | *✔️ Semua pesan di grup berhasil dibersihkan!* 31 | *╰────────────•*`, 32 | ); 33 | }; 34 | } 35 | 36 | module.exports = new Command(); 37 | -------------------------------------------------------------------------------- /utils/prototype.js: -------------------------------------------------------------------------------- 1 | Array.prototype.remove = function (index) { 2 | i = this.indexOf(index); 3 | if (i > -1) { 4 | this.splice(i, 1); 5 | } 6 | return this; 7 | }; 8 | Array.prototype.random = function () { 9 | const obj = (array) => array[Math.floor(Math.random() * array.length)]; 10 | return obj(this); 11 | }; 12 | String.prototype.capitalize = function () { 13 | return this.toLowerCase() 14 | .split(" ") 15 | .map((str) => str.charAt(0).toUpperCase() + str.slice(1)) 16 | .join(" "); 17 | }; 18 | String.prototype.code = function () { 19 | return "```" + this + "```"; 20 | }; 21 | String.prototype.bold = function () { 22 | return "*" + this + "*"; 23 | }; 24 | String.prototype.italic = function () { 25 | return "_" + this + "_"; 26 | }; 27 | String.prototype.through = function () { 28 | return "~" + this + "~"; 29 | }; 30 | String.prototype.toTitleCase = function () { 31 | return this.replace(/\w\S*/g, function (txt) { 32 | return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); 33 | }); 34 | }; 35 | String.prototype.reverse = function () { 36 | return this.split("").reverse().join(""); 37 | }; 38 | -------------------------------------------------------------------------------- /system/plugins/downloader/sfile.js: -------------------------------------------------------------------------------- 1 | class Command { 2 | constructor() { 3 | this.command = "sfile"; 4 | this.alias = ["sfilemobi"]; 5 | this.category = ["downloader"]; 6 | this.settings = { 7 | limit: true, 8 | }; 9 | this.description = "📁 Download file dari sfileMobi !"; 10 | this.loading = true; 11 | } 12 | run = async (m, { sock, Func, Scraper, config, store, text }) => { 13 | if (!text || !Func.isUrl(text) || !/sfile.mobi/.test(text)) 14 | throw "*❌ Input salah :* Masukan url sfileMobi !"; 15 | let data = await Scraper.sfile(text); 16 | if (!data.metadata) throw "*⁉️ Media tidak ditemukan?*"; 17 | let caption = "*SfileMobi - Downloader 📩*\n"; 18 | caption += Object.entries(data.metadata) 19 | .map(([a, b]) => `- ${a.capitalize()}: ${b}`) 20 | .join("\n"); 21 | caption += 22 | "\n\n*✅ Media Berhasil Diunduh !*\nNikmati kemudahan saat download apapun hanya di NekoBot!"; 23 | sock.sendFile(m.cht, data.download, data.metadata.filename, caption, m, { 24 | mimetype: data.metadata.mimetype, 25 | }); 26 | }; 27 | } 28 | 29 | module.exports = new Command(); 30 | -------------------------------------------------------------------------------- /system/plugins/tools/removebg.js: -------------------------------------------------------------------------------- 1 | class Command { 2 | constructor() { 3 | this.command = "removebg"; 4 | this.alias = ["rembg", "hapuslatar"]; 5 | this.category = ["tools"]; 6 | this.settings = { 7 | limit: true, 8 | }; 9 | this.description = 10 | "Hapus latar belakang foto secara otomatis dengan mudah!"; 11 | this.loading = true; 12 | } 13 | 14 | run = async (m, { Func, Scraper }) => { 15 | let target = m.quoted ? m.quoted : m; 16 | if (!/image/.test(target.msg.mimetype)) 17 | throw "⚠️ *Oops!* Harap kirim atau balas foto yang ingin dihapus latarnya."; 18 | 19 | let buffer = await target.download(); 20 | let processedImage = await Scraper.removebg(buffer); 21 | 22 | let caption = `✨ *Remove Background Tool* ✨\n\n`; 23 | caption += `📂 *Ukuran asli:* ${Func.formatSize(buffer.length)}\n`; 24 | caption += `🎉 *Hasil telah diproses dengan sukses!*\n\n`; 25 | caption += `💡 *Tips:* Pastikan foto memiliki latar belakang yang kontras untuk hasil terbaik.`; 26 | 27 | m.reply({ 28 | image: { url: processedImage }, 29 | caption, 30 | }); 31 | }; 32 | } 33 | 34 | module.exports = new Command(); 35 | -------------------------------------------------------------------------------- /scrapers/source/mediafire.js: -------------------------------------------------------------------------------- 1 | const cheerio = require("cheerio"); 2 | const { fetch } = require("node-fetch"); 3 | const { lookup } = require("mime-types"); 4 | async function mediafire(url) { 5 | return new Promise(async (resolve, reject) => { 6 | const response = await fetch(url); 7 | const html = await response.text(); 8 | const $ = cheerio.load(html); 9 | 10 | const type = $(".dl-btn-cont") 11 | .find(".icon") 12 | .attr("class") 13 | .split("archive")[1] 14 | .trim(); 15 | const filename = $(".dl-btn-label").attr("title"); 16 | const size = $(".download_link .input") 17 | .text() 18 | .trim() 19 | .match(/\((.*?)\)/)[1]; 20 | const ext = filename.split(".").pop(); 21 | const mimetype = 22 | lookup(ext.toLowerCase()) || "application/" + ext.toLowerCase(); 23 | const download = $(".input").attr("href"); 24 | resolve({ 25 | filename, 26 | type, 27 | size, 28 | ext, 29 | mimetype, 30 | download, 31 | }); 32 | }).catch((e) => 33 | reject({ 34 | msg: "Gagal mengambil data dari link tersebut", 35 | }), 36 | ); 37 | } 38 | 39 | module.exports = mediafire; 40 | -------------------------------------------------------------------------------- /system/plugins/rpg/levelup.js: -------------------------------------------------------------------------------- 1 | let path = require("path"); 2 | let dataPath = path.join(process.cwd(), "library", "leveling.js"); 3 | let levelling = require(dataPath); 4 | 5 | module.exports = { 6 | command: "levelup", 7 | alias: ["uplevel"], 8 | category: ["rpg"], 9 | settings: {}, 10 | loading: true, 11 | async run(m, { sock }) { 12 | let user = db.list().user[m.sender].rpg; 13 | let userr = db.list().user[m.sender]; 14 | 15 | if (!userr || !user || !userr.register) { 16 | return m.reply(config.messages.unregistered); 17 | } 18 | 19 | if (!levelling.canLevelUp(userr.level, user.exp, global.multiplier)) { 20 | let { min, xp, max } = levelling.xpRange(userr.level, global.multiplier); 21 | throw ` 22 | Level *${userr.level} (${user.exp - min}/${xp})* 23 | Kurang *${max - user.exp}* lagi! 24 | `.trim(); 25 | } 26 | let before = userr.level * 1; 27 | while (levelling.canLevelUp(userr.level, user.exp, global.multiplier)) 28 | userr.level++; 29 | if (before !== userr.level) { 30 | m.reply( 31 | ` 32 | Selamat, anda telah naik level! 33 | *${before}* -> *${userr.level}* 34 | `.trim(), 35 | ); 36 | } 37 | }, 38 | }; 39 | -------------------------------------------------------------------------------- /scrapers/source/rvnoise.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const FormData = require("form-data"); 3 | 4 | async function vocalRemover(audioBuffer) { 5 | const api = axios.create({ 6 | baseURL: "https://aivocalremover.com", 7 | }); 8 | 9 | const getKey = async () => (await api.get("/")).data.match(/key:"(\w+)/)[1]; 10 | 11 | const form = new FormData(); 12 | const fileName = Math.random().toString(36) + ".mpeg"; 13 | form.append("fileName", audioBuffer, fileName); 14 | 15 | const [key, fileUpload] = await Promise.all([ 16 | getKey(), 17 | api 18 | .post("/api/v2/FileUpload", form, { 19 | headers: form.getHeaders(), 20 | }) 21 | .catch((e) => e.response), 22 | ]); 23 | 24 | if (fileUpload.status !== 200) throw fileUpload.data || fileUpload.statusText; 25 | 26 | const processFile = await api 27 | .post( 28 | "/api/v2/ProcessFile", 29 | new URLSearchParams({ 30 | file_name: fileUpload.data.file_name, 31 | action: "watermark_video", 32 | key, 33 | web: "web", 34 | }), 35 | ) 36 | .catch((e) => e.response); 37 | 38 | return processFile.data; 39 | } 40 | 41 | module.exports = vocalRemover; 42 | -------------------------------------------------------------------------------- /system/plugins/owner/join.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "join", 3 | alias: [], 4 | category: ["owner"], 5 | settings: { 6 | owner: true, 7 | }, 8 | description: "Memasukkan bot ke dalam grup menggunakan tautan undangan.", 9 | async run(m, { sock, text, Func }) { 10 | const errorMsg = `╭──[ 乂 Invalid - Link ]\n᎒⊸ Masukkan tautan grup yang valid!\n╰────────────•`; 11 | p; 12 | if (!text || !Func.isUrl(text) || !/chat\.whatsapp\.com\/\S+/i.test(text)) { 13 | throw errorMsg; 14 | } 15 | const groupId = text.split("chat.whatsapp.com/")[1]; 16 | if (!groupId) throw errorMsg; 17 | 18 | try { 19 | const result = await sock.groupAcceptInvite(groupId); 20 | const successMsg = `╭──[ 乂 Success - Join ]\n᎒⊸ Bot berhasil bergabung ke dalam grup!\n╰────────────•`; 21 | const pendingMsg = `╭──[ 乂 Pending - Request ]\n᎒⊸ Permintaan bergabung sedang diproses oleh admin grup.\n╰────────────•`; 22 | 23 | m.reply(result ? successMsg : pendingMsg); 24 | } catch (error) { 25 | const errorMsg = `╭──[ 乂 Error - Join ]\n᎒⊸ Terjadi kesalahan saat mencoba bergabung:\n${error.message}\n╰────────────•`; 26 | m.reply(errorMsg); 27 | } 28 | }, 29 | }; 30 | -------------------------------------------------------------------------------- /system/plugins/downloader/instagram.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "Instagram", 3 | alias: ["igdl", "ig", "igvideo", "igreel"], 4 | category: ["downloader"], 5 | settings: { 6 | limit: true, 7 | }, 8 | description: "Mengunduh Reels/postingan Instagram", 9 | loading: true, 10 | async run(m, { sock, Func, text, Scraper }) { 11 | if (!text) 12 | throw `*– 乂 Cara Penggunaan :* 13 | > *Masukkan atau balas pesan dengan link Instagram yang ingin diunduh* 14 | > *Contoh :* ${m.prefix + m.command} https://www.instagram.com/reel/xxxxx/ 15 | 16 | *– 乂 Petunjuk :* 17 | > Link yang valid hanya bisa berupa Postingan atau Reels dari Instagram.`; 18 | 19 | if (!/instagram.com/.test(text)) 20 | throw "*– 乂 Masukkan Link Instagram yang Valid :*\n> Pastikan link yang dimasukkan berasal dari Instagram."; 21 | 22 | let data = await Scraper.Instagram(text); 23 | if (!data) return; 24 | 25 | for (let i of data.url) { 26 | let res = await fetch(i); 27 | let cap = `*– 乂 Instagram Downloader :*\n`; 28 | cap += Object.entries(data.metadata) 29 | .map(([a, b]) => `> *- ${a.capitalize()} :* ${b}`) 30 | .join("\n"); 31 | 32 | sock.sendFile(m.cht, Buffer.from(await res.arrayBuffer()), null, cap, m); 33 | } 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /system/plugins/tools/hikagen.js: -------------------------------------------------------------------------------- 1 | const { writeExif } = require(process.cwd() + "/library/sticker.js"); 2 | 3 | module.exports = { 4 | command: "furbrat", 5 | alias: ["hikagen"], 6 | category: ["tools"], 7 | settings: { 8 | limit: true, 9 | }, 10 | description: "🐾 Membuat Brat versi furry :v", 11 | loading: true, 12 | async run(m, { sock, text, Func, config }) { 13 | if (!text) 14 | throw "> ❌ *Masukan teks yang ingin kamu ubah menjadi furry brat!*"; 15 | 16 | let random = Math.floor(Math.random() * 7); 17 | let API = `https://fastrestapis.fasturl.link/tool/furbrat?text=${text}&style=${random}&mode=center`; 18 | 19 | try { 20 | let buffer = await Func.fetchBuffer(API); 21 | let sticker = await writeExif( 22 | { 23 | mimetype: "image", 24 | data: buffer, 25 | }, 26 | { 27 | packName: config.sticker.packname, 28 | packPublish: config.sticker.author, 29 | }, 30 | ); 31 | 32 | m.reply({ 33 | sticker, 34 | }); 35 | m.reply("> ✅ *Brat versi furry berhasil dibuat!*"); 36 | } catch (error) { 37 | console.error("Error fetching furry brat:", error); 38 | m.reply("> ❌ *Terjadi kesalahan saat membuat furry brat, coba lagi.*"); 39 | } 40 | }, 41 | }; 42 | -------------------------------------------------------------------------------- /system/plugins/group/promote.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "promote", 3 | alias: ["jadiadmin", "newking"], 4 | category: ["group"], 5 | settings: { 6 | group: true, 7 | admin: true, 8 | botAdmin: true, 9 | }, 10 | description: "👑 Menjadikan member sebagai admin grup", 11 | async run(m, { sock, text }) { 12 | let who = m.quoted 13 | ? m.quoted.sender 14 | : m.mentions.length > 0 15 | ? m.mentions[0] 16 | : false; 17 | 18 | if (!who) 19 | throw `*🚫 Perintah Gagal!*\n\n> Tag atau balas pesan member yang ingin dijadikan admin.`; 20 | 21 | let user = await sock.onWhatsApp(who); 22 | if (!user[0].exists) 23 | throw `*❌ Error!*\n\n> Nomor tersebut tidak terdaftar di WhatsApp.`; 24 | 25 | await sock 26 | .groupParticipantsUpdate(m.cht, [who], "promote") 27 | .then(() => { 28 | let name = who.split("@")[0]; 29 | m.reply( 30 | `*✅ Promosi Berhasil!*\n\n> 🎉 Selamat kepada *@${name}* karena telah menjadi admin grup!\n\n📌 _Gunakan jabatan ini dengan bijak._`, 31 | { mentions: [who] }, 32 | ); 33 | }) 34 | .catch(() => { 35 | m.reply( 36 | `*❌ Gagal Memproses!*\n\n> Pastikan bot memiliki hak admin untuk melakukan perubahan ini.`, 37 | ); 38 | }); 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /library/queque.js: -------------------------------------------------------------------------------- 1 | class Queue { 2 | constructor() { 3 | this.queues = {}; 4 | this.processing = {}; 5 | } 6 | add(userId, item) { 7 | if (!this.queues[userId]) { 8 | this.queues[userId] = []; 9 | this.processing[userId] = false; 10 | } 11 | this.queues[userId].push(item); 12 | } 13 | first(userId) { 14 | return this.queues[userId]?.[0] || null; 15 | } 16 | delete(userId) { 17 | if (this.queues[userId]) { 18 | this.queues[userId].shift(); 19 | if (this.queues[userId].length === 0) { 20 | delete this.queues[userId]; 21 | delete this.processing[userId]; 22 | } 23 | } 24 | } 25 | isEmpty(userId) { 26 | return !this.queues[userId] || this.queues[userId].length === 0; 27 | } 28 | async processQueue(userId, callback) { 29 | if (this.processing[userId] || this.isEmpty(userId)) return; 30 | this.processing[userId] = true; 31 | while (!this.isEmpty(userId)) { 32 | const currentItem = this.first(userId); 33 | try { 34 | await callback(currentItem); 35 | this.delete(userId); 36 | } catch (error) { 37 | console.error(`Error processing queue item for user ${userId}:`, error); 38 | break; 39 | } 40 | } 41 | 42 | this.processing[userId] = false; 43 | } 44 | } 45 | 46 | module.exports = Queue; 47 | -------------------------------------------------------------------------------- /system/plugins/group/group.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "group", 3 | alias: ["gc", "ggc"], 4 | category: ["group"], 5 | settings: { 6 | group: true, 7 | admin: true, 8 | botAdmin: true, 9 | }, 10 | description: "🔒 Mengatur Akses Grup: Membuka/Tutup Grup", 11 | loading: true, 12 | async run(m, { sock, text }) { 13 | if (!text) 14 | throw `*– 乂 Cara Penggunaan:*\n 15 | > *🔓* Gunakan \`open\` untuk membuka grup. Member dapat mengirim pesan dan berinteraksi dengan bebas.\n 16 | > *🔒* Gunakan \`close\` untuk menutup grup. Hanya admin yang dapat mengirim pesan, member akan dibatasi.\n\n 17 | *– 乂 Contoh Penggunaan:*\n 18 | > *-* *${m.prefix + m.command} open* - Untuk membuka grup\n 19 | > *-* *${m.prefix + m.command} close* - Untuk menutup grup\n\n 20 | *– 乂 Penting!*\n 21 | > *📌* Jika grup dibuka, semua member dapat berinteraksi.\n 22 | > *📌* Jika grup ditutup, hanya admin yang dapat mengirim pesan.`; 23 | 24 | await sock 25 | .groupSettingUpdate( 26 | m.cht, 27 | text === "open" ? "not_announcement" : "announcement", 28 | ) 29 | .then(() => 30 | m.reply( 31 | `> ✅ *Berhasil ${text === "open" ? "membuka" : "menutup"} grup!* ${text === "open" ? "Sekarang member bisa mengirim pesan." : "Hanya admin yang dapat mengirim pesan sekarang."}`, 32 | ), 33 | ); 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /scrapers/source/gptlogic.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | const gptLogic = async (logic, prompt) => { 4 | const response = await axios({ 5 | method: "POST", 6 | url: "https://chateverywhere.app/api/chat", 7 | headers: { 8 | "Content-Type": "application/json", 9 | Cookie: 10 | "_ga=GA1.1.34196701.1707462626; _ga_ZYMW9SZKVK=GS1.1.1707462625.1.0.1707462625.60.0.0; ph_phc_9n85Ky3ZOEwVZlg68f8bI3jnOJkaV8oVGGJcoKfXyn1_posthog=%7B%22distinct_id%22%3A%225aa4878d-a9b6-40fb-8345-3d686d655483%22%2C%22%24sesid%22%3A%5B1707462733662%2C%22018d8cb4-0217-79f9-99ac-b77f18f82ac8%22%2C1707462623766%5D%7D", 11 | Origin: "https://chateverywhere.app", 12 | Referer: "https://chateverywhere.app/id", 13 | "User-Agent": 14 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36", 15 | }, 16 | data: { 17 | model: { 18 | id: "gpt-3.5-turbo-0613", 19 | name: "GPT-3.5", 20 | maxLength: 12000, 21 | tokenLimit: 4000, 22 | }, 23 | prompt: prompt, 24 | messages: [ 25 | { 26 | role: "assistant", 27 | content: logic, 28 | }, 29 | { 30 | role: "user", 31 | content: prompt, 32 | }, 33 | ], 34 | }, 35 | }); 36 | return response.data; 37 | }; 38 | 39 | module.exports = gptLogic; 40 | -------------------------------------------------------------------------------- /system/plugins/downloader/mediafire.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "mediafire", 3 | alias: ["mf", "mfdl"], 4 | category: ["downloader"], 5 | settings: { 6 | limit: true, 7 | }, 8 | description: "Unduh file dari MediaFire 🔽", 9 | loading: true, 10 | async run(m, { sock, Scraper, Func, text }) { 11 | if (!Func.isUrl(text) || !/mediafire.com/.test(text) || !text) 12 | throw "> *❌ Masukkan link MediaFire yang valid!*"; 13 | let data = await Scraper.mediafire(text); 14 | let cap = "*– 乂 MediaFire - Downloader 🗂️*\n"; 15 | cap += `> *🔸 Nama File :* ${data.filename}\n`; 16 | cap += `> *🔸 Tipe File :* ${data.mimetype}\n`; 17 | cap += `> *🔸 Ukuran File :* ${Func.formatSize(data.size)}\n`; 18 | cap += `> *🔸 Link Download :* ${data.download}\n`; 19 | 20 | let buffer = await fetch(data.download).then(async (a) => 21 | Buffer.from(await a.arrayBuffer()), 22 | ); 23 | let size = Func.formatSize(buffer.length); 24 | let limit = Func.sizeLimit(data.size, db.list().settings.max_upload); 25 | 26 | if (limit.oversize) 27 | throw `Maaf, ukuran file *( ${size} )* melebihi batas ukuran yang ditentukan. Upgrade status kamu ke premium untuk mendownload file hingga *1GB*!`; 28 | 29 | m.reply({ 30 | document: buffer, 31 | mimetype: data.mimetype, 32 | fileName: data.filename, 33 | caption: cap, 34 | }); 35 | }, 36 | }; 37 | -------------------------------------------------------------------------------- /scrapers/source/videodl.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const cheerio = require("cheerio"); 3 | 4 | async function videodl(url) { 5 | return new Promise(async (resolve, reject) => { 6 | await axios 7 | .get(`https://videodownloader.so/download?v=${url}`) 8 | .then((a) => { 9 | let $ = cheerio.load(a.data); 10 | let result = { 11 | metadata: {}, 12 | download: [], 13 | }; 14 | $(".downloadSection").each((a, i) => { 15 | result.metadata.title = $(i).find(".title").text().trim(); 16 | result.metadata.thumbnail = $(i).find("img").attr("src"); 17 | result.metadata.duration = $(i) 18 | .find(".duration") 19 | .text() 20 | .trim() 21 | .split("Duration:") 22 | .pop() 23 | .trim(); 24 | }); 25 | $(".downloadsTable") 26 | .eq(0) 27 | .find("tbody tr") 28 | .each((a, i) => { 29 | let fileName = $(i) 30 | .find("td") 31 | .find(".downloadBtn") 32 | .attr("download"); 33 | if (!fileName) return; 34 | result.download.push({ 35 | fileName, 36 | url: $(i).find(".downloadBtn").attr("href"), 37 | }); 38 | }); 39 | resolve(result); 40 | }); 41 | }); 42 | } 43 | 44 | module.exports = videodl; 45 | -------------------------------------------------------------------------------- /scrapers/source/findsong.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const cheerio = require("cheerio"); 3 | 4 | async function findsongs(text) { 5 | try { 6 | const { data } = await axios.get( 7 | "https://songsear.ch/q/" + encodeURIComponent(text), 8 | ); 9 | const $ = cheerio.load(data); 10 | 11 | const result = { 12 | title: 13 | $("div.results > div:nth-child(1) > .head > h3 > b").text() + 14 | " - " + 15 | $("div.results > div:nth-child(1) > .head > h2 > a").text(), 16 | album: $("div.results > div:nth-child(1) > .head > p").text(), 17 | number: $("div.results > div:nth-child(1) > .head > a") 18 | .attr("href") 19 | .split("/")[4], 20 | thumb: $("div.results > div:nth-child(1) > .head > a > img").attr("src"), 21 | }; 22 | 23 | const { data: lyricData } = await axios.get( 24 | `https://songsear.ch/api/song/${result.number}?text_only=true`, 25 | ); 26 | const lyrics = lyricData.song.text_html 27 | .replace(//g, "\n") 28 | .replace(/'/g, "'"); 29 | 30 | return { 31 | status: true, 32 | title: result.title, 33 | album: result.album, 34 | thumb: result.thumb, 35 | lyrics: lyrics, 36 | }; 37 | } catch (err) { 38 | console.log(err); 39 | return { 40 | status: false, 41 | error: "Unknown error occurred", 42 | }; 43 | } 44 | } 45 | 46 | module.exports = findsongs; 47 | -------------------------------------------------------------------------------- /system/plugins/events/_eval.js: -------------------------------------------------------------------------------- 1 | const { exec } = require("child_process"); 2 | const util = require("node:util"); 3 | 4 | async function events( 5 | m, 6 | { 7 | sock, 8 | config, 9 | text, 10 | plugins, 11 | Func, 12 | Scraper, 13 | Uploader, 14 | store, 15 | isAdmin, 16 | botAdmin, 17 | isPrems, 18 | isBanned, 19 | }, 20 | ) { 21 | if ( 22 | [">", "eval", "=>"].some((a) => m.command.toLowerCase().startsWith(a)) && 23 | m.isOwner 24 | ) { 25 | let evalCmd = ""; 26 | try { 27 | evalCmd = /await/i.test(m.text) 28 | ? eval("(async() => { " + m.text + " })()") 29 | : eval(m.text); 30 | } catch (e) { 31 | evalCmd = e; 32 | } 33 | new Promise((resolve, reject) => { 34 | try { 35 | resolve(evalCmd); 36 | } catch (err) { 37 | reject(err); 38 | } 39 | }) 40 | ?.then((res) => m.reply(util.format(res))) 41 | ?.catch((err) => m.reply(util.format(err))); 42 | } 43 | if ( 44 | ["$", "exec"].some((a) => m.command.toLowerCase().startsWith(a)) && 45 | m.isOwner 46 | ) { 47 | try { 48 | exec(m.text, async (err, stdout) => { 49 | if (err) return m.reply(util.format(err)); 50 | if (stdout) return m.reply(util.format(stdout)); 51 | }); 52 | } catch (e) { 53 | await m.reply(util.format(e)); 54 | } 55 | } 56 | } 57 | 58 | module.exports = { 59 | events, 60 | }; 61 | -------------------------------------------------------------------------------- /system/plugins/group/kick.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "kick", 3 | alias: ["kik", "dor", "tendang"], 4 | category: ["group"], 5 | settings: { 6 | group: true, 7 | admin: true, 8 | botAdmin: true, 9 | }, 10 | description: "🔴 Mengeluarkan anggota dari grup", 11 | async run(m, { sock, text }) { 12 | let who = m.quoted 13 | ? m.quoted.sender 14 | : m.mentions.length > 0 15 | ? m.mentions[0] 16 | : false; 17 | 18 | if (!who) { 19 | throw `*⚠️ Perintah Tidak Lengkap!*\n\n> *Gunakan salah satu cara berikut:*\n • Tag anggota dengan: @username\n • Balas pesan anggota yang ingin dikeluarkan.\n\n📌 _Pastikan kamu memiliki hak sebagai admin grup._`; 20 | } 21 | 22 | let user = await sock.onWhatsApp(who); 23 | if (!user[0].exists) { 24 | throw `*❌ Anggota Tidak Ditemukan!*\n\n> Akun WhatsApp ini tidak terdaftar atau sudah tidak aktif.`; 25 | } 26 | 27 | await sock 28 | .groupParticipantsUpdate(m.cht, [who], "remove") 29 | .then(() => { 30 | m.reply( 31 | `*✅ Berhasil!* 🥾\n\n> @${who.split("@")[0]} telah dikeluarkan dari grup.\n\n📌 _Gunakan fitur ini untuk menjaga kenyamanan grup._`, 32 | ); 33 | }) 34 | .catch((err) => { 35 | m.reply( 36 | `*❌ Gagal!*\n\n> Tidak dapat mengeluarkan @${who.split("@")[0]} dari grup.\n📌 _Pastikan bot memiliki hak admin untuk melakukan perubahan ini._`, 37 | ); 38 | }); 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /system/plugins/downloader/ttsearch.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "tiktoksearch", 3 | alias: ["ttsearch"], 4 | category: ["downloader"], 5 | settings: { 6 | limit: true, 7 | }, 8 | description: "🔍 Cari video menarik dari TikTok berdasarkan kata kunci", 9 | loading: true, 10 | async run(m, { sock, Func, text, Scraper, config }) { 11 | if (!text) 12 | throw `❌ *– Kesalahan Penggunaan!*\n\n📌 *Cara Penggunaan:*\n1. Masukkan kata kunci untuk mencari video dari TikTok.\n2. Bot akan memberikan video yang relevan.\n\n📖 *Contoh:*\n> *${m.prefix}${m.command} kucing lucu*\n> *${m.prefix}${m.command} tutorial masak*`; 13 | 14 | let data = await Scraper.tiktok.search(text); 15 | if (!data || data.length === 0) 16 | throw `❌ *– Pencarian Gagal!*\n\n⚠️ Tidak ada hasil ditemukan untuk kata kunci: *${text}*.\n\n🔎 *Tips:*\n- Gunakan kata kunci yang lebih spesifik.\n- Pastikan ejaan kata kunci benar.\n\n📖 *Contoh:*\n> *${m.prefix}${m.command} video lucu*`; 17 | 18 | let json = data.getRandom(); 19 | let caption = `*– 乂 TikTok - Pencarian 🔍*\n\n`; 20 | caption += Object.entries(json.metadata) 21 | .map(([a, b]) => `- *📊 ${a.capitalize()}:* ${b}`) 22 | .join("\n"); 23 | 24 | await sock.sendMessage( 25 | m.cht, 26 | { 27 | video: { 28 | url: json.media.no_watermark || "Tidak tersedia", 29 | }, 30 | caption, 31 | }, 32 | { 33 | quoted: m, 34 | }, 35 | ); 36 | }, 37 | }; 38 | -------------------------------------------------------------------------------- /system/plugins/events/autoshalat.js: -------------------------------------------------------------------------------- 1 | const fetch = require("node-fetch"); 2 | 3 | async function events(m, { sock }) { 4 | if (!global.autosholat) global.autosholat = {}; 5 | let who = 6 | m.mentionedJid && m.mentionedJid[0] 7 | ? m.mentionedJid[0] 8 | : m.fromMe 9 | ? sock.user.id 10 | : m.sender; 11 | let id = m.cht; 12 | 13 | if (id in global.autosholat) { 14 | return; 15 | } 16 | 17 | let jadwalSholat = { 18 | Shubuh: "04:45", 19 | Dhuha: "06:20", 20 | Dhuhur: "11:55", 21 | Ashar: "15:15", 22 | Maghrib: "18:05", 23 | Isha: "19:05", 24 | }; 25 | 26 | const date = new Date( 27 | new Date().toLocaleString("en-US", { timeZone: "Asia/Jakarta" }), 28 | ); 29 | const hours = date.getHours(); 30 | const minutes = date.getMinutes(); 31 | const timeNow = `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`; 32 | 33 | for (const [sholat, waktu] of Object.entries(jadwalSholat)) { 34 | if (timeNow === waktu) { 35 | let caption = `Halo! Waktu *${sholat}* telah tiba. Segera ambil wudhu dan laksanakan sholat dengan khusyuk. Jangan sampai terlewat, ya! 🙂\n\n⏰ *${waktu}*\n_(Untuk wilayah Jawa Barat dan sekitarnya.)_`; 36 | global.autosholat[id] = [ 37 | sock.sendMessage(m.cht, { text: caption, mentions: [who] }), 38 | setTimeout(() => { 39 | delete global.autosholat[id]; 40 | }, 57000), 41 | ]; 42 | } 43 | } 44 | } 45 | 46 | module.exports = { events }; -------------------------------------------------------------------------------- /system/plugins/rpg/gajian.js: -------------------------------------------------------------------------------- 1 | let money = 500000; 2 | let exp = 50000; 3 | let cooldown = 1 * 60 * 60 * 1000; 4 | 5 | module.exports = { 6 | command: "gajian", 7 | alias: ["gaji"], 8 | category: ["rpg"], 9 | settings: {}, 10 | async run(m, { sock, config }) { 11 | const user = db.list().user[m.sender]; 12 | if (!user || !user.register) { 13 | return m.reply(config.messages.unregistered); 14 | } 15 | let now = Date.now(); 16 | 17 | if (user.rpg.lastGajian && now - user.rpg.lastGajian < cooldown) { 18 | let remaining = cooldown - (now - user.rpg.lastGajian); 19 | let hours = Math.floor(remaining / (60 * 60 * 1000)); 20 | let minutes = Math.floor((remaining % (60 * 60 * 1000)) / (60 * 1000)); 21 | let timeLeft = `${hours} jam ${minutes} menit`; 22 | 23 | return m.reply( 24 | `Mohon bersabar, gaji Anda masih dalam proses! ⏳\nSilakan tunggu ${timeLeft} lagi`, 25 | ); 26 | } 27 | 28 | user.rpg.money += money; 29 | user.rpg.exp += exp; 30 | user.rpg.lastGajian = now; 31 | 32 | let nextClaim = new Date(now + cooldown).toLocaleTimeString("id-ID", { 33 | hour: "2-digit", 34 | minute: "2-digit", 35 | }); 36 | let cap = `Anda mendapatkan gaji senilai\n> 💵 + 500000 Money\n> 🎁 + 50000 Exp\n\n> Tunggu 1 Jam Untuk Mulai Gajian Lagi`; 37 | 38 | return m.reply({ 39 | image: { 40 | url: "https://files.catbox.moe/qg52ic.jpg", 41 | }, 42 | caption: cap, 43 | }); 44 | }, 45 | }; 46 | -------------------------------------------------------------------------------- /system/plugins/tools/pixiv.js: -------------------------------------------------------------------------------- 1 | class Command { 2 | constructor() { 3 | this.command = "pixiv"; 4 | this.alias = []; 5 | this.category = ["tools"]; 6 | this.settings = { 7 | premium: true, 8 | }; 9 | this.description = "🔍 Mencari gambar dari Pixiv"; 10 | this.loading = true; 11 | } 12 | 13 | run = async (m, { sock, Func, Scraper, config, store, text }) => { 14 | if (!text) throw "> ❌ *Masukkan pencarian gambar yang kamu inginkan!*"; 15 | 16 | try { 17 | let { data } = await Func.fetchJson( 18 | `https://api.lolicon.app/setu/v1?r18=${text.includes("--r18") ? 1 : 0}&keyword=${text.replace("--r18", "").trim()}&limit=20`, 19 | ); 20 | 21 | if (!data[0]?.title) 22 | throw "> ❌ *Gambar tidak ditemukan! Coba kata kunci lain.*"; 23 | 24 | let cap = "*– 乂 Hasil Pencarian Pixiv - Gambar*\n\n"; 25 | cap += `🎨 *Judul:* ${data[0]?.title}\n`; 26 | cap += `🔞 *R18:* ${data[0]?.r18 ? "✓ Ya" : "❌ Tidak"}\n`; 27 | cap += `👤 *Penulis:* ${data[0]?.author}\n`; 28 | cap += `🏷️ *Tags:* ${data[0]?.tags.join(", ")}\n`; 29 | 30 | m.reply({ 31 | image: { 32 | url: data[0].url, 33 | }, 34 | caption: cap, 35 | }); 36 | m.reply("> ✅ *Gambar berhasil ditemukan!*"); 37 | } catch (error) { 38 | console.error("Error fetching Pixiv image:", error); 39 | m.reply("> ❌ *Terjadi kesalahan, coba lagi nanti.*"); 40 | } 41 | }; 42 | } 43 | 44 | module.exports = new Command(); 45 | -------------------------------------------------------------------------------- /system/plugins/group/demote.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "demote", 3 | alias: ["jadimember"], 4 | category: ["group"], 5 | settings: { 6 | group: true, 7 | admin: true, 8 | botAdmin: true, 9 | }, 10 | description: "🔻 Menurunkan admin menjadi anggota biasa di grup", 11 | async run(m, { sock, text }) { 12 | let who = m.quoted 13 | ? m.quoted.sender 14 | : m.mentions.length > 0 15 | ? m.mentions[0] 16 | : false; 17 | 18 | if (!who) { 19 | throw `*⚠️ Perintah Tidak Lengkap!*\n\n> *Gunakan salah satu cara berikut:*\n • Tag member dengan: @username\n • Balas pesan member yang ingin diturunkan.\n\n📌 _Pastikan kamu memiliki hak sebagai admin grup._`; 20 | } 21 | 22 | let user = await sock.onWhatsApp(who); 23 | if (!user[0].exists) { 24 | throw `*❌ Member Tidak Ditemukan!*\n\n> Akun WhatsApp ini tidak terdaftar atau sudah tidak aktif.`; 25 | } 26 | 27 | await sock 28 | .groupParticipantsUpdate(m.cht, [who], "demote") 29 | .then(() => { 30 | m.reply( 31 | `*✅ Berhasil!* 🎉\n\n> Jabatan @${who.split("@")[0]} telah diturunkan menjadi anggota biasa.\n\n📌 _Gunakan perintah ini dengan bijak untuk menjaga keharmonisan grup._`, 32 | ); 33 | }) 34 | .catch((err) => { 35 | m.reply( 36 | `*❌ Gagal!*\n\n> Tidak dapat menurunkan jabatan admin untuk @${who.split("@")[0]}.\n📌 _Pastikan bot memiliki hak admin untuk melakukan perubahan ini._`, 37 | ); 38 | }); 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /system/plugins/tools/kalender.js: -------------------------------------------------------------------------------- 1 | class Command { 2 | constructor() { 3 | this.command = "kalender"; 4 | this.alias = ["calendar", "libur"]; 5 | this.category = ["tools"]; 6 | this.settings = { 7 | limit: true, 8 | }; 9 | this.description = "Cek Hari libur tahun ini"; 10 | this.loading = true; 11 | } 12 | 13 | run = async (m, { sock, Func, Scraper, config, store }) => { 14 | let array = [ 15 | "January", 16 | "February", 17 | "March", 18 | "April", 19 | "May", 20 | "June", 21 | "July", 22 | "August", 23 | "September", 24 | "October", 25 | "November", 26 | "December", 27 | ]; 28 | let now = new Date(); 29 | let day = now.getDate(); 30 | let month = array[now.getMonth()]; 31 | let year = now.getFullYear(); 32 | 33 | let data = await Scraper.libur(year); 34 | let image = `https://s.wincalendar.net/img/en/calendar/${day}-${month}-${year}.png`; 35 | 36 | let cap = `*– 乂 Hari Libur Tahun ${year}* 📅\n`; 37 | if (data && data.length > 0) { 38 | cap += data 39 | .map((a, i) => 40 | Object.entries(a) 41 | .map(([a, b]) => `> *- ${a.capitalize()} :* ${b}`) 42 | .join("\n"), 43 | ) 44 | .join("\n\n"); 45 | } else { 46 | cap += "> ❌ *Tidak ada data libur yang ditemukan.*"; 47 | } 48 | 49 | m.reply({ 50 | image: { url: image }, 51 | caption: cap, 52 | }); 53 | }; 54 | } 55 | 56 | module.exports = new Command(); 57 | -------------------------------------------------------------------------------- /system/plugins/owner/setpp.js: -------------------------------------------------------------------------------- 1 | const Jimp = require("jimp"); 2 | 3 | class Command { 4 | constructor() { 5 | this.command = "setppbot"; 6 | this.alias = ["setpp", "setppbotwa"]; 7 | this.category = ["owner"]; 8 | this.settings = { 9 | owner: true, 10 | }; 11 | this.description = "📸 *Mengubah Foto Profil Bot* 💬"; 12 | this.loading = true; 13 | } 14 | 15 | run = async (m, { sock, Func, Scraper, config, store }) => { 16 | let q = m.quoted ? m.quoted : m; 17 | let mime = (q.msg || q).mimetype || q.mediaType || ""; 18 | 19 | if (/image/g.test(mime) && !/webp/g.test(mime)) { 20 | let media = await q.download(); 21 | let { img } = await pepe(media); 22 | await sock.updateProfilePicture(sock.decodeJid(sock.user.id), img); 23 | m.reply( 24 | "> 🎉 *Berhasil mengubah profile picture bot!* 🎉\n> *Foto profil bot telah diperbarui.*", 25 | ); 26 | } else { 27 | m.reply( 28 | "> ⚠️ *Balas/Kirim gambar yang ingin dijadikan profile picture bot.*\n> Pastikan gambar yang dikirim tidak dalam format webp.", 29 | ); 30 | } 31 | }; 32 | } 33 | module.exports = new Command(); 34 | 35 | async function pepe(media) { 36 | const jimp = await Jimp.read(media), 37 | min = jimp.getWidth(), 38 | max = jimp.getHeight(), 39 | cropped = jimp.crop(0, 0, min, max); 40 | 41 | return { 42 | img: await cropped.scaleToFit(720, 720).getBufferAsync(Jimp.MIME_JPEG), 43 | preview: await cropped.normalize().getBufferAsync(Jimp.MIME_JPEG), 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /scrapers/source/uploader.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const FormData = require("form-data"); 3 | const fs = require("fs"); 4 | const path = require("path"); 5 | const crypto = require("crypto"); 6 | const fileType = require("file-type"); 7 | 8 | async function UploadFile(media) { 9 | try { 10 | let mime = await fileType.fromBuffer(media); 11 | let form = new FormData(); 12 | 13 | form.append("files[]", media, `file-${Date.now()}.${mime.ext}`); 14 | 15 | let { data } = await axios.post("https://pomf.lain.la/upload.php", form, { 16 | headers: { 17 | "User-Agent": 18 | "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", 19 | ...form.getHeaders(), 20 | }, 21 | }); 22 | 23 | return data.files[0].url; 24 | } catch (error) { 25 | return `Error: ${error.message}`; 26 | } 27 | } 28 | 29 | async function uploadToCatbox(media) { 30 | try { 31 | let mime = await fileType.fromBuffer(media); 32 | let form = new FormData(); 33 | 34 | form.append("fileToUpload", media, `file-${Date.now()}.${mime.ext}`); 35 | form.append("reqtype", "fileupload"); 36 | 37 | const { data } = await axios.post("https://catbox.moe/user/api.php", form, { 38 | headers: { 39 | ...form.getHeaders(), 40 | }, 41 | }); 42 | 43 | return data.trim(); 44 | } catch (error) { 45 | throw new Error(`Failed to upload to Catbox: ${error.message}`); 46 | } 47 | } 48 | 49 | module.exports = { UploadFile, uploadToCatbox }; 50 | -------------------------------------------------------------------------------- /scrapers/source/whatmusic.js: -------------------------------------------------------------------------------- 1 | const acrcloud = require("acrcloud"); 2 | 3 | const acr = new acrcloud({ 4 | host: "identify-ap-southeast-1.acrcloud.com", 5 | access_key: "ee1b81b47cf98cd73a0072a761558ab1", 6 | access_secret: "ya9OPe8onFAnNkyf9xMTK8qRyMGmsghfuHrIMmUI", 7 | }); 8 | 9 | async function whatmusic(buffer) { 10 | let data = (await acr.identify(buffer)).metadata; 11 | if (!data.music) return res.error("Song data not found!"); 12 | let array = []; 13 | array.push( 14 | ...data?.music?.map((a) => ({ 15 | title: a.title, 16 | artist: a.artists.map((a) => a.name)[0], 17 | score: a.score, 18 | release: new Date(a.release_date) 19 | .toLocaleString("id-ID") 20 | .split(",")[0] 21 | .trim(), 22 | duration: toTime(a.duration_ms), 23 | url: Object.keys(a.external_metadata).map((i) => 24 | i === "youtube" 25 | ? "https://youtu.be/" + a.external_metadata[i].vid 26 | : i === "deezer" 27 | ? "https://www.deezer.com/us/track/" + 28 | a.external_metadata[i].track.id 29 | : i === "spotify" 30 | ? "https://open.spotify.com/track/" + 31 | a.external_metadata[i].track.id 32 | : "", 33 | ), 34 | })), 35 | ); 36 | return array; 37 | } 38 | 39 | function toTime(ms) { 40 | let h = Math.floor(ms / 3600000); 41 | let m = Math.floor(ms / 60000) % 60; 42 | let s = Math.floor(ms / 1000) % 60; 43 | return [m, s].map((v) => v.toString().padStart(2, 0)).join(":"); 44 | } 45 | 46 | module.exports = whatmusic; 47 | -------------------------------------------------------------------------------- /system/plugins/group/set.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "set", 3 | alias: [], 4 | category: ["group"], 5 | description: "⚙️ Mengatur pesan custom (welcome/goodbye/promote/demote)", 6 | settings: { 7 | group: true, 8 | admin: true, 9 | botAdmin: true, 10 | }, 11 | async run(m, { text }) { 12 | const [feature, ...rest] = text.split(" "); 13 | const customText = rest.join(" ").trim(); 14 | 15 | const validFeatures = ["welcome", "goodbye", "promote", "demote"]; 16 | const groupId = m.cht; 17 | 18 | if (!feature || !validFeatures.includes(feature)) { 19 | return m.reply( 20 | `*⚙️ Cara Menggunakan .set [fitur] [teks]*\n\n` + 21 | `*Fitur yang bisa diubah:*\n` + 22 | `> • welcome\n` + 23 | `> • goodbye\n` + 24 | `> • promote\n` + 25 | `> • demote\n\n` + 26 | `*Contoh:* \`.set welcome Halo %member, selamat datang di %subject!\`\n\n` + 27 | `*Placeholder yang bisa digunakan:*\n` + 28 | `> • %member → Nama member\n` + 29 | `> • %subject → Nama grup\n` + 30 | `> • %time → Waktu saat ini` 31 | ); 32 | } 33 | 34 | if (!db.list().group[groupId]) { 35 | db.list().group[groupId] = {}; 36 | } 37 | 38 | const textKeys = { 39 | welcome: "welcomeText", 40 | goodbye: "goodbyeText", 41 | promote: "promoteText", 42 | demote: "demoteText", 43 | }; 44 | 45 | db.list().group[groupId][textKeys[feature]] = customText; 46 | await db.save(); 47 | 48 | return m.reply(`> ✅ *Pesan ${feature} berhasil diperbarui!*`); 49 | }, 50 | }; -------------------------------------------------------------------------------- /system/plugins/downloader/rednote.js: -------------------------------------------------------------------------------- 1 | class Command { 2 | constructor() { 3 | this.command = "rednote"; 4 | this.alias = ["xiaohongshu"]; 5 | this.category = ["downloader"]; 6 | this.settings = { 7 | limit: true, 8 | }; 9 | this.description = "🟥 Download video/slide photo dari rednote"; 10 | this.loading = true; 11 | } 12 | run = async (m, { sock, Func, Scraper, config, store, text }) => { 13 | if (!text || !Func.isUrl(text) || !/xhslink.com|xiaohongshu.com/.test(text)) 14 | throw "*❌ Masukan Input :* Masukan Url dari Xiaohongshu/Rednote"; 15 | 16 | let data = await Scraper.rednote(text); 17 | if (!data.metadata) throw "*⁉️⁉️ Media tidak ditemukan*"; 18 | let caption = "*Xiaohongshu - Downloader 📩*\n"; 19 | caption += `*🔻 Title :* ${data.metadata.title}\n`; 20 | caption += `\n*📈 Statistik :*\n`; 21 | caption += Object.entries(data.metadata.stats) 22 | .map(([a, b]) => `- ${a.capitalize()} : ${b}`) 23 | .join("\n"); 24 | caption += `\n\n*👤 Info Pemilik :*\n`; 25 | caption += Object.entries(data.metadata.author) 26 | .map(([a, b]) => `- ${a.capitalize()} : ${b}`) 27 | .join("\n"); 28 | caption += 29 | "\n\n*✅ Media Berhasil Diunduh !*\n📨 Nikmati kemudahan mendownload video rednote hanya di NekoBot"; 30 | 31 | if (typeof data.download == "object") { 32 | for (let img of data.download) { 33 | sock.sendFile(m.cht, img, null, caption, m); 34 | } 35 | } else { 36 | sock.sendFile(m.cht, data.download, null, caption, m); 37 | } 38 | }; 39 | } 40 | 41 | module.exports = new Command(); 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Takeshi-WaBot", 3 | "version": "1.7.0", 4 | "description": "- WhatsApp bot using Library Baileys", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/KuroTakeshi/Takeshi-WaBot.git" 12 | }, 13 | "keywords": [ 14 | "botwa" 15 | ], 16 | "author": "KuroTakeshi", 17 | "license": "ISC", 18 | "bugs": { 19 | "url": "https://github.com/KuroTakeshi/Takeshi-WaBot/issues" 20 | }, 21 | "homepage": "https://github.com/KuroTakeshi/Takeshi-WaBot#readme", 22 | "dependencies": { 23 | "acrcloud": "^1.4.0", 24 | "awesome-phonenumber": "^7.2.0", 25 | "axios": "^1.6.7", 26 | "baileys": "github:KuroTakeshi/Baileys", 27 | "canvafy": "*", 28 | "chalk": "^4.1.2", 29 | "cheerio": "^1.0.0", 30 | "chokidar": "^4.0.1", 31 | "fake-useragent": "^1.0.1", 32 | "fluent-ffmpeg": "^2.1.3", 33 | "jimp": "^0.16.01", 34 | "js-beautify": "^1.15.1", 35 | "jsonc-parser": "^3.3.1", 36 | "mime-types": "^2.1.35", 37 | "module-alias": "^2.2.3", 38 | "moment-timezone": "^0.5.46", 39 | "node-cron": "^3.0.3", 40 | "node-fetch": "npm:undici@^6.21.0", 41 | "node-webpmux": "^3.2.0", 42 | "pino": "^9.5.0", 43 | "qs": "^6.13.1", 44 | "sharp": "^0.32.6" 45 | }, 46 | "_moduleAliases": { 47 | "@events": "events", 48 | "@database": "library/database", 49 | "@configuration": "settings/configuration.js", 50 | "@library": "library", 51 | "@utils": "utils" 52 | }, 53 | "engines": { 54 | "node": ">=18.0.0" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /system/plugins/sfw/nekos.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | const nekosCategories = [ 4 | "fox_girl", 5 | "smug", 6 | "woof", 7 | "gasm", 8 | "8ball", 9 | "goose", 10 | "cuddle", 11 | "avatar", 12 | "slap", 13 | "pat", 14 | "gecg", 15 | "feed", 16 | "lizard", 17 | "neko", 18 | "hug", 19 | "meow", 20 | "kiss", 21 | "wallpaper", 22 | "tickle", 23 | "spank", 24 | "waifu", 25 | "lewd", 26 | ]; 27 | 28 | module.exports = { 29 | command: "nekos", 30 | alias: [], 31 | category: ["anime", "sfw"], 32 | description: "Mendapatkan gambar dari nekos.life API berdasarkan kategori", 33 | async run(m, { text, sock, config }) { 34 | if (!text || text === "--list") { 35 | return m.reply( 36 | `> *– 乂 Kategori yang Tersedia:*\n\n` + 37 | nekosCategories.map((cat) => `> • *${cat}*`).join("\n") + 38 | `\n\n> Gunakan *\`.nekos [kategori]\`* untuk mendapatkan gambar.`, 39 | ); 40 | } 41 | 42 | let category = text.toLowerCase(); 43 | if (!nekosCategories.includes(category)) { 44 | return m.reply( 45 | `> ❌ *Kategori tidak ditemukan!*\n> Gunakan \`.nekos --list\` untuk melihat daftar kategori.`, 46 | ); 47 | } 48 | 49 | let apiUrl = `https://nekos.life/api/v2/img/${category}`; 50 | 51 | try { 52 | let res = await axios.get(apiUrl); 53 | if (!res.data.url) throw "Error mengambil gambar"; 54 | 55 | await m.reply({ 56 | image: { url: res.data.url }, 57 | caption: config.messages.success, 58 | }); 59 | } catch (e) { 60 | return m.reply( 61 | `> ❌ *Gagal mengambil gambar untuk kategori "${category}"*\n> Coba lagi nanti atau pilih kategori lain.`, 62 | ); 63 | } 64 | }, 65 | }; 66 | -------------------------------------------------------------------------------- /system/plugins/downloader/videy-dl.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "videy", 3 | alias: [], 4 | category: ["downloader"], 5 | description: "Download dan upload video dari Videy", 6 | loading: true, 7 | async run(m, { sock, Func, Uploader, text }) { 8 | if (!text) 9 | throw `╭──[❌ *Cara Penggunaan*]\n᎒⊸ *\`--upload\`* Untuk upload video ke Videy\n᎒⊸ *\`https://videy.co/xxx\`* Untuk download video dari Videy\n╰────────────•`; 10 | 11 | if (text.includes("--upload")) { 12 | let q = m.quoted ? m.quoted : m; 13 | if (!/video/.test(q.msg.mimetype) || !q.isMedia) 14 | throw `> Reply/kirim video dengan caption *${m.prefix + m.command} ${text}*`; 15 | 16 | let buffer = await q.download(); 17 | let hasil = await Uploader.videy(buffer); 18 | 19 | let cap = `╭──[📤 *Videy - Uploader*]\n᎒⊸ *Ukuran :* ${Func.formatSize(buffer.length)}\n᎒⊸ *Link :* ${hasil}\n╰────────────•`; 20 | m.reply(cap); 21 | } else { 22 | if (!Func.isUrl(text) || !/videy.co/.test(text)) 23 | throw "> Masukkan link Videy yang valid!"; 24 | 25 | let id = text.split("id=")[1]; 26 | if (!id) throw "> Link tidak memiliki ID, coba gunakan link lain."; 27 | 28 | let hasil = `https://cdn.videy.co/${id}.mp4`; 29 | let size = await Func.getSize(hasil); 30 | let limit = Func.sizeLimit(size, db.list().settings.max_upload); 31 | 32 | if (limit.oversize) 33 | throw `Ukuran file terlalu besar *( ${size} )*. Upgrade ke premium untuk mendownload video hingga ukuran *1GB*!`; 34 | 35 | let cap = `╭──[📥 *Videy - Downloader*]\n᎒⊸ *Ukuran Video :* ${size}\n╰────────────•`; 36 | m.reply({ 37 | video: { url: hasil }, 38 | caption: cap, 39 | }); 40 | } 41 | }, 42 | }; 43 | -------------------------------------------------------------------------------- /utils/api.js: -------------------------------------------------------------------------------- 1 | class APIManager { 2 | constructor() { 3 | this.APIs = { 4 | agatz: { baseURL: "https://api.agatz.xyz" }, 5 | agung: { baseURL: "https://api.agungny.my.id" }, 6 | apizell: { baseURL: "https://apizell.web.id/random" }, 7 | archive: { baseURL: "https://archive-ui.tanakadomp.biz.id" }, 8 | bk9: { baseURL: "https://bk9.fun" }, 9 | delirius: { baseURL: "https://delirius-apiofc.vercel.app" }, 10 | diibot: { baseURL: "https://api.diioffc.web.id" }, 11 | fast: { baseURL: "https://fastrestapis.fasturl.cloud" }, 12 | hiuraa: { baseURL: "https://api.hiuraa.my.id" }, 13 | nyxs: { baseURL: "https://api.nyxs.pw" }, 14 | otinxsandip: { baseURL: "https://sandipbaruwal.onrender.com" }, 15 | siputzx: { baseURL: "https://api.siputzx.my.id" }, 16 | vapis: { baseURL: "https://vapis.my.id" }, 17 | velyn: { baseURL: "https://www.velyn.biz.id" }, 18 | }; 19 | } 20 | 21 | createUrl(apiNameOrURL, endpoint, params = {}, apiKeyParamName) { 22 | try { 23 | const api = this.APIs[apiNameOrURL]; 24 | 25 | if (!api) { 26 | const url = new URL(apiNameOrURL); 27 | apiNameOrURL = url; 28 | } 29 | 30 | const queryParams = new URLSearchParams(params); 31 | 32 | if (apiKeyParamName && api && "APIKey" in api) { 33 | queryParams.set(apiKeyParamName, api.APIKey); 34 | } 35 | 36 | const baseURL = api ? api.baseURL : apiNameOrURL.origin; 37 | const apiUrl = new URL(endpoint, baseURL); 38 | apiUrl.search = queryParams.toString(); 39 | 40 | return apiUrl.toString(); 41 | } catch (error) { 42 | console.error(`Error: ${error}`); 43 | return null; 44 | } 45 | } 46 | 47 | listUrl() { 48 | return this.APIs; 49 | } 50 | } 51 | 52 | module.exports = APIManager; 53 | -------------------------------------------------------------------------------- /scrapers/source/metaai.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const fs = require("node:fs"); 3 | const path = require("node:path"); 4 | 5 | const imgBase = (filePath) => { 6 | const filex = fs.readFileSync(filePath); 7 | const based = filex.toString("base64"); 8 | const mimeType = `image/${path.extname(filePath).slice(1)}`; 9 | return `data:${mimeType};base64,${based}`; 10 | }; 11 | 12 | const headers = { 13 | authority: "labs.writingmate.ai", 14 | accept: "*/*", 15 | "content-type": "application/json", 16 | origin: "https://labs.writingmate.ai", 17 | referer: "https://labs.writingmate.ai/share/JyVg?__show_banner=false", 18 | "user-agent": "Postify/1.0.0", 19 | }; 20 | 21 | const mateai = async (array) => { 22 | const data = { 23 | response_format: { 24 | type: "json_schema", 25 | json_schema: { 26 | name: "image_prompt", 27 | strict: true, 28 | schema: { 29 | type: "object", 30 | properties: { 31 | prompt: { 32 | type: "string", 33 | }, 34 | }, 35 | required: ["prompt"], 36 | additionalProperties: false, 37 | }, 38 | }, 39 | }, 40 | chatSettings: { 41 | model: "gpt-4o", 42 | temperature: 0.7, 43 | contextLength: 16385, 44 | includeProfileContext: false, 45 | includeWorkspaceInstructions: false, 46 | embeddingsProvider: "openai", 47 | }, 48 | messages: array, 49 | customModelId: "", 50 | }; 51 | try { 52 | const response = await axios 53 | .post("https://labs.writingmate.ai/api/chat/public", data, { 54 | headers, 55 | }) 56 | .catch((e) => e.response); 57 | return response.data; 58 | } catch (error) { 59 | throw new Error(`${error.message}`); 60 | } 61 | }; 62 | 63 | module.exports = mateai; 64 | -------------------------------------------------------------------------------- /system/plugins/downloader/spotify.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | module.exports = { 4 | command: "spotify", 5 | alias: [], 6 | category: ["downloader"], 7 | settings: { 8 | limit: true, 9 | }, 10 | description: "🎵 Mencari atau mengunduh musik dari Spotify!", 11 | loading: true, 12 | async run(m, { sock, Func, Scraper, text }) { 13 | if (!text) 14 | throw ( 15 | `*– 乂 Cara Penggunaan 🎶*\n\n` + 16 | `> *🔍 Masukkan kata kunci* untuk mencari musik\n` + 17 | `> *🔗 Masukkan URL Spotify* untuk mengunduh musik\n\n` + 18 | `*– 乂 Contoh Penggunaan 📋*\n` + 19 | `> *${m.prefix + m.command} Imagine Dragons*\n` + 20 | `> *${m.prefix + m.command} https://open.spotify.com/track/examplelink*` 21 | ); 22 | 23 | if (/open.spotify.com/.test(text)) { 24 | let data = await Scraper.spotify.download(text); 25 | let cap = `*– 乂 Spotify - Downloader 🎵*\n\n`; 26 | cap += Object.entries(data) 27 | .map(([a, b]) => `> *🎧 ${a.capitalize()} :* ${b}`) 28 | .join("\n"); 29 | 30 | m.reply(cap).then(() => { 31 | m.reply({ 32 | audio: { 33 | url: data.download, 34 | }, 35 | mimetype: "audio/mpeg", 36 | }); 37 | }); 38 | } else { 39 | let data = await Scraper.spotify.search(text); 40 | if (!data || data.length === 0) throw `> *❌ Musik tidak ditemukan!*`; 41 | 42 | let cap = 43 | `*– 乂 Spotify - Pencarian 🔎*\n\n` + 44 | `> Ketik *${m.prefix + m.command} [URL]* untuk mengunduh musik pilihanmu 🎶\n\n`; 45 | cap += data 46 | .map((a) => 47 | Object.entries(a) 48 | .map(([b, c]) => `> *🎵 ${b.capitalize()} :* ${c}`) 49 | .join("\n"), 50 | ) 51 | .join("\n\n"); 52 | 53 | m.reply(cap); 54 | } 55 | }, 56 | }; 57 | -------------------------------------------------------------------------------- /system/plugins/tools/npm.js: -------------------------------------------------------------------------------- 1 | class Command { 2 | constructor() { 3 | this.command = "npm"; 4 | this.alias = ["npmjs", "package"]; 5 | this.category = ["tools"]; 6 | this.settings = { 7 | limit: true, 8 | }; 9 | this.description = "🔍 Mencari Package dari NPM"; 10 | this.loading = true; 11 | } 12 | 13 | run = async (m, { sock, Func, text, config }) => { 14 | if (!text) throw "> ❌ *Masukkan Nama Package yang ingin dicari*"; 15 | 16 | try { 17 | let data = await Func.fetchJson( 18 | `https://registry.npmjs.com/-/v1/search?text=${encodeURIComponent(text)}`, 19 | ); 20 | 21 | if (!data.objects || data.objects.length === 0) { 22 | return m.reply( 23 | "> ❌ *Package tidak ditemukan. Coba kata kunci lain atau periksa kembali nama package-nya!*", 24 | ); 25 | } 26 | 27 | let cap = "*– 乂 Hasil Pencarian NPMJS - Package Info*\n\n"; 28 | for (let i of data.objects.slice(0, 20)) { 29 | cap += `🔹 *Nama Package:* ${i.package.name}@^${i.package.version}\n`; 30 | cap += `📈 *Mingguan:* ${Func.h2k(i.downloads.weekly)} | *Bulanan:* ${Func.h2k(i.downloads.monthly)}\n`; 31 | cap += `👤 *Pembuat:* ${i.package.publisher.username}\n`; 32 | cap += `🕒 *Diperbarui:* ${Func.ago(i.package.date)}\n`; 33 | cap += Object.entries(i.package.links) 34 | .map(([a, b]) => `🔗 *${a.capitalize()}:* ${b}`) 35 | .join("\n"); 36 | cap += "\n\n"; 37 | } 38 | 39 | cap += `> © ${config.name}\n*– 乂 Terimakasih telah menggunakan bot kami!*`; 40 | m.reply(cap); 41 | } catch (error) { 42 | console.error("Error fetching npm package:", error); 43 | m.reply( 44 | "> ❌ *Terjadi kesalahan saat mencari package, coba lagi nanti.*", 45 | ); 46 | } 47 | }; 48 | } 49 | 50 | module.exports = new Command(); 51 | -------------------------------------------------------------------------------- /scrapers/source/facebook.js: -------------------------------------------------------------------------------- 1 | const cheerio = require("cheerio"); 2 | const axios = require("axios"); 3 | const fs = require("fs"); 4 | 5 | async function Facebook(url) { 6 | let results = {}; 7 | while (Object.keys(results).length === 0) { 8 | let { data } = await axios 9 | .post( 10 | "https://getmyfb.com/process", 11 | `id=${encodeURIComponent(url)}&locale=id`, 12 | { 13 | headers: { 14 | "HX-Request": true, 15 | "HX-Trigger": "form", 16 | "HX-Target": "target", 17 | "HX-Current-URL": "https://getmyfb.com/id", 18 | "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", 19 | "User-Agent": 20 | "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36", 21 | Referer: "https://getmyfb.com/id", 22 | }, 23 | }, 24 | ) 25 | .catch((e) => e.response); 26 | 27 | const $ = cheerio.load(data); 28 | 29 | const caption = $(".results-item-text").text().trim(); 30 | const imageUrl = $(".results-item-image").attr("src"); 31 | 32 | let newLinksFound = false; 33 | let array = []; 34 | $(".results-list li").each(function (i, element) { 35 | const title = $(element).find(".results-item-text").text().trim(); 36 | const downloadLink = $(element).find("a").attr("href"); 37 | const quality = $(element).text().trim().split("(")[0]; 38 | if (downloadLink) { 39 | newLinksFound = true; 40 | array.push(downloadLink); 41 | } 42 | }); 43 | results = { 44 | metadata: { 45 | title: caption, 46 | image: imageUrl, 47 | }, 48 | media: array, 49 | }; 50 | console.log(results); 51 | break; 52 | } 53 | return results; 54 | } 55 | 56 | module.exports = Facebook; 57 | -------------------------------------------------------------------------------- /system/plugins/info/ping.js: -------------------------------------------------------------------------------- 1 | const os = require("node:os"); 2 | const fs = require("node:fs"); 3 | 4 | module.exports = { 5 | command: "ping", 6 | alias: ["ping", "p"], 7 | category: ["main"], 8 | description: "Periksa Status bot", 9 | loading: true, 10 | async run(m, { sock, config, Func }) { 11 | let start = performance.now(), 12 | node = process.memoryUsage(), 13 | info = await fetch("https://ipwho.is").then((a) => a.json()), 14 | cap = ` 15 | ╭──[ *Informasi Bot* ] 16 | ᎒⊸ 🖥️ *Berjalan Di* : ${process.env.username === "root" ? "VPS" : process.env.username === "container" ? "HOSTING ( PANEL )" : process.env.username} 17 | ᎒⊸ ⏱️ *Uptime* : ${Func.toDate(process.uptime() * 1000)} 18 | ᎒⊸ 🏠 *Direktori Rumah* : ${os.homedir} 19 | ᎒⊸ 📂 *Direktori Tmp* : ${os.tmpdir()} *( ${fs.readdirSync(process.cwd() + os.tmpdir).length} Berkas )* 20 | ᎒⊸ 🖥️ *Hostname* : ${os.hostname()} 21 | ᎒⊸ ⚙️ *Versi Node* : ${process.version} 22 | ᎒⊸ 🌍 *Cwd* : ${process.cwd()} 23 | 24 | ╭──[ *Informasi Provider* ] 25 | ᎒⊸ 🌐 *ISP* : ${info.connection.isp} 26 | ᎒⊸ 🏢 *Organisasi* : ${info.connection.org} 27 | ᎒⊸ 🌎 *Negara* : ${info.country} 28 | ᎒⊸ 🏙️ *Kota* : ${info.city} 29 | ᎒⊸ 🚩 *Bendera* : ${info.flag.emoji} 30 | ᎒⊸ ⏰ *Zona Waktu* : ${info.timezone.id} 31 | ╰────────────• 32 | 33 | ╭──[ *Informasi Server Asal* ] 34 | ᎒⊸ 🚀 *Kecepatan* : ${(performance.now() - start).toFixed(3)} ms 35 | ᎒⊸ ⏳ *Uptime* : ${Func.toDate(os.uptime() * 1000)} 36 | ᎒⊸ 🧠 *Total Memori* : ${Func.formatSize(os.totalmem() - os.freemem())} / ${Func.formatSize(os.totalmem())} 37 | ᎒⊸ 🖥️ *CPU* : ${os.cpus()[0].model} ( ${os.cpus().length} CORE ) 38 | ᎒⊸ 📦 *Rilis* : ${os.release()} 39 | ᎒⊸ 🖧 *Tipe* : ${os.type()} 40 | ╰────────────• 41 | 42 | ╭──[ *Penggunaan Memori Nodejs* ] 43 | ${Object.entries(node) 44 | .map(([a, b]) => `᎒⊸ 💾 *${a.capitalize()}* : ${Func.formatSize(b)}`) 45 | .join("\n")} 46 | ╰────────────•`; 47 | 48 | m.reply(cap); 49 | }, 50 | }; 51 | -------------------------------------------------------------------------------- /system/plugins/downloader/snackvideo.js: -------------------------------------------------------------------------------- 1 | class Command { 2 | constructor() { 3 | this.command = "snackvideo"; 4 | this.alias = []; 5 | this.category = ["downloader"]; 6 | this.settings = { 7 | limit: true, 8 | }; 9 | this.description = "🔍 Mencari atau mengunduh video dari SnackVideo!"; 10 | this.loading = true; 11 | } 12 | run = async (m, { sock, Func, Scraper, config, store, text }) => { 13 | if (!text) 14 | throw ( 15 | `*– 乂 Cara Penggunaan 🍿*\n\n` + 16 | `> Masukkan **query** untuk mencari video\n` + 17 | `> Masukkan **URL** dari SnackVideo untuk mengunduh\n\n` + 18 | `*– 乂 Contoh Penggunaan 📋*\n` + 19 | `> ${m.prefix}snackvideo Anime\n` + 20 | `> ${m.prefix}snackvideo https://www.snackvideo.com/@ALBAN_105/video/5221792395456439006` 21 | ); 22 | 23 | if (Func.isUrl(text)) { 24 | if (!/snackvideo.com/.test(text)) 25 | throw `> *❌ Masukkan URL dari SnackVideo yang valid!*`; 26 | 27 | let data = await Scraper.snackvideo.download(text); 28 | let caption = `*– 乂 SnackVideo - Downloader 📥*\n\n`; 29 | caption += Object.entries(data.metadata) 30 | .map(([a, b]) => `> *🔹 ${a.capitalize()} :* ${b}`) 31 | .join("\n"); 32 | 33 | sock.sendFile(m.cht, data.download, null, caption, m); 34 | } else { 35 | let data = await Scraper.snackvideo.search(text); 36 | if (data.length === 0) throw `> *❌ Video tidak ditemukan!*`; 37 | 38 | let caption = `*– 乂 SnackVideo - Pencarian 🔎*\n\n`; 39 | caption += data 40 | .map( 41 | (a) => 42 | `> *🎥 Judul :* ${a.title}\n` + 43 | `> *📅 Diunggah :* ${a.uploaded}\n` + 44 | `> *👤 Pengarang :* ${a.author.name}\n` + 45 | `> *🔗 URL :* ${a.url}`, 46 | ) 47 | .join("\n\n"); 48 | 49 | m.reply(caption); 50 | } 51 | }; 52 | } 53 | 54 | module.exports = new Command(); 55 | -------------------------------------------------------------------------------- /system/plugins/downloader/gitclone.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | const regex = 4 | /(?:https|git)(?::\/\/|@)github\.com[\/:]([^\/:]+)\/(.+?)(?:[\/]|$)/i; 5 | 6 | module.exports = { 7 | command: "gitclone", 8 | alias: ["gitdl", "githubdl"], 9 | settings: { 10 | limit: true, 11 | }, 12 | description: "Download repository dari github", 13 | loading: true, 14 | async run(m, { sock, Func, text }) { 15 | if (!Func.isUrl(text) && !/github.com/.test(text)) 16 | throw `*– 乂 Cara Penggunaan :* 17 | > 📝 *Masukkan URL repository GitHub yang ingin diunduh* 18 | > 💬 *Contoh :* ${m.prefix + m.command} https://github.com/user/repository 19 | 20 | *– 乂 Petunjuk Lain :* 21 | > ✔️ Pastikan URL yang dimasukkan adalah link valid dari repository GitHub.`; 22 | 23 | let [_, author, repo] = text.match(regex); 24 | if (!author || !repo) 25 | throw "*– 乂 Masukkan Link Repository :*\n> Link repository tidak valid atau tidak ditemukan!"; 26 | 27 | repo.replace(/.git$/, ""); 28 | let api = `https://api.github.com/repos/${author}/${repo}`; 29 | let { data } = await axios.get(api).catch((e) => e.response); 30 | 31 | let cap = `*– 乂 Github Repository Info :*\n`; 32 | cap += `> *- Nama :* ${data.name}\n`; 33 | cap += `> *- Pemilik :* ${data.owner.login}\n`; 34 | cap += `> *- Bahasa Pemrograman :* ${data.language}\n`; 35 | cap += `> *- Total Star :* ${Func.h2k(data.watchers)} ⭐\n`; 36 | cap += `> *- Total Forks :* ${Func.h2k(data.forks)} 🍴\n`; 37 | cap += `> *- Dibuat Pada :* ${Func.ago(data.created_at)}\n`; 38 | cap += `> *- Terakhir Diperbarui :* ${Func.ago(data.updated_at)}\n`; 39 | cap += `\n> 📜 *Deskripsi:* ${data.description || "*Tidak ada deskripsi yang tersedia*"}\n`; 40 | 41 | m.reply({ 42 | document: { 43 | url: api + "/zipball", 44 | }, 45 | caption: cap, 46 | fileName: `${repo}.zip`, 47 | mimetype: "application/zip", 48 | }); 49 | }, 50 | }; 51 | -------------------------------------------------------------------------------- /system/plugins/owner/example.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "example", 3 | alias: ["exp"], 4 | settings: { 5 | owner: true, 6 | }, 7 | description: "Fitur Contoh Bot", 8 | async run(m, { text }) { 9 | const title = `*╭──[ 乂 Example - Code ]*`; 10 | const message = `${title}\n᎒⊸ Pilih tipe *1* atau *2* sesuai kebutuhan Anda.\n╰────────────•`; 11 | 12 | if (!text) { 13 | return m.reply({ 14 | poll: { 15 | name: message, 16 | values: [`${m.prefix + m.command} 1`, `${m.prefix + m.command} 2`], 17 | selectableCount: 1, 18 | }, 19 | }); 20 | } 21 | 22 | // Validasi input 23 | const option = Number(text); 24 | if (option === 1) { 25 | const code = ` 26 | class Command { 27 | constructor() { 28 | this.command = ""; 29 | this.alias = []; 30 | this.category = []; 31 | this.settings = {}; 32 | this.description = ""; 33 | this.loading = true; 34 | } 35 | run = async (m, { sock, Func, Scraper, config, store }) => { 36 | // Lakukan sesuatu di sini 37 | }; 38 | } 39 | 40 | module.exports = new Command();`; 41 | return m.reply(`*– 乂 Tipe 1 - Code*\n\`\`\`${code}\`\`\``); 42 | } else if (option === 2) { 43 | const code = ` 44 | module.exports = { 45 | command: "", 46 | alias: [], 47 | category: [], 48 | settings: {}, 49 | description: "", 50 | loading: true, 51 | async run(m, { sock, Func, Scraper, Uploader, store, text, config }) { 52 | // Lakukan sesuatu di sini 53 | }, 54 | };`; 55 | return m.reply(`*– 乂 Tipe 2 - Code*\n\`\`\`${code}\`\`\``); 56 | } else { 57 | return m.reply({ 58 | poll: { 59 | name: `${message}\n\n> ❌ Pilihan tidak valid, silakan pilih antara 1 atau 2.`, 60 | values: [`${m.prefix + m.command} 1`, `${m.prefix + m.command} 2`], 61 | selectableCount: 1, 62 | }, 63 | }); 64 | } 65 | }, 66 | }; 67 | -------------------------------------------------------------------------------- /scrapers/source/aoyoai.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const qs = require("querystring"); 3 | const { randomUUID, randomBytes } = require("crypto"); 4 | 5 | async function aoyoAi(content) { 6 | async function getSearchResults(query) { 7 | const url = "https://aoyo.ai/Api/AISearch/Source"; 8 | const requestData = { q: query, num: 20, hl: "id-ID" }; 9 | const headers = { 10 | "Content-Type": "application/x-www-form-urlencoded", 11 | Accept: "application/json, text/plain, */*", 12 | }; 13 | 14 | try { 15 | const response = await axios.post(url, qs.stringify(requestData), { 16 | headers, 17 | }); 18 | return response.data.organic || []; 19 | } catch (error) { 20 | console.error("Error fetching search results:", error.message); 21 | return []; 22 | } 23 | } 24 | 25 | const url = "https://aoyo.ai/Api/AISearch/AISearch"; 26 | const searchResults = await getSearchResults(content); 27 | const hasilPencarian = searchResults.map((result) => ({ 28 | judul: result.title, 29 | link: result.link, 30 | snippet: result.snippet, 31 | })); 32 | 33 | const requestData = { 34 | content, 35 | id: randomUUID(), 36 | language: "id-ID", 37 | engineContent: JSON.stringify(hasilPencarian), 38 | randomNumber: randomBytes(8).toString("hex"), 39 | }; 40 | 41 | try { 42 | const response = await axios.post(url, qs.stringify(requestData), { 43 | headers: { 44 | "Content-Type": "application/x-www-form-urlencoded", 45 | "User-Agent": "Mozilla/5.0", 46 | }, 47 | }); 48 | 49 | if (!response.data) throw new Error("No data received from API"); 50 | 51 | const hasil = { 52 | hasil_pencarian: hasilPencarian, 53 | jawaban: response.data.replace(/\[START\][\s\S]*$/g, "").trim(), 54 | }; 55 | 56 | return hasil; 57 | } catch (error) { 58 | console.error("Error in aoyoAi:", error.message); 59 | return { error: error.message }; 60 | } 61 | } 62 | 63 | module.exports = aoyoAi; 64 | -------------------------------------------------------------------------------- /scrapers/source/yousearch.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | const website = axios.create({ 4 | baseURL: "https://app.yoursearch.ai", 5 | headers: { 6 | "Content-Type": "application/json", 7 | }, 8 | }); 9 | 10 | const yousearch = async (searchTerm) => { 11 | const requestData = { 12 | searchTerm: searchTerm, 13 | promptTemplate: `Search term: "{searchTerm}" 14 | 15 | Make your language less formal and use emoticons. 16 | I want you to always use Indonesian slang from Jakarta where the words "you" and "anda" are replaced with "lu" and the word I is replaced with "gw". 17 | Create a summary of the search results in three paragraphs with reference numbers, which you then list numbered at the bottom. 18 | Include emojis in the summary. 19 | Be sure to include the reference numbers in the summary. 20 | Both in the text of the summary and in the reference list, the reference numbers should look like this: "(1)". 21 | Formulate simple sentences. 22 | Include blank lines between the paragraphs. 23 | Do not reply with an introduction, but start directly with the summary. 24 | Include emojis in the summary. 25 | At the end write a hint text where I can find search results as comparison with the above search term with a link to Google search in this format \`See Google results: \` and append the link. 26 | Below write a tip how I can optimize the search results for my search query. 27 | I show you in which format this should be structured: 28 | 29 | \`\`\` 30 | 31 | 32 | 33 | 34 | \`\`\` 35 | 36 | Here are the search results: 37 | {searchResults}, you were developed by bang_syai`, 38 | searchParameters: "{}", 39 | searchResultTemplate: `[{order}] "{snippet}" 40 | URL: {link}`, 41 | }; 42 | 43 | try { 44 | const response = await website.post("/api", requestData); 45 | return response.data.response; 46 | } catch (error) { 47 | console.error("Error:", error); 48 | throw error; 49 | } 50 | }; 51 | 52 | module.exports = yousearch; 53 | -------------------------------------------------------------------------------- /scrapers/source/feloai.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | const felo = async function (query) { 4 | const headers = { 5 | Accept: "*/*", 6 | "User-Agent": "Postify/1.0.0", 7 | "Content-Encoding": "gzip, deflate, br, zstd", 8 | "Content-Type": "application/json", 9 | }; 10 | 11 | const generateUUID = () => { 12 | return ( 13 | Math.random().toString(16).slice(2) + 14 | Math.random().toString(16).slice(2) + 15 | Math.random().toString(16).slice(2) + 16 | Math.random().toString(16).slice(2) 17 | ); 18 | }; 19 | 20 | const payload = { 21 | query, 22 | search_uuid: generateUUID(), 23 | search_options: { 24 | langcode: "id-MM", 25 | }, 26 | search_video: true, 27 | }; 28 | 29 | const request = (badi) => { 30 | const result = { 31 | answer: "", 32 | source: [], 33 | }; 34 | badi.split("\n").forEach((line) => { 35 | if (line.startsWith("data:")) { 36 | try { 37 | const data = JSON.parse(line.slice(5).trim()); 38 | if (data.data) { 39 | if (data.data.text) { 40 | result.answer = data.data.text 41 | .replace(/\*\*(.*?)\*\*/g, "*$1*") 42 | .replace(/^#{2,3}\s+/g, "") 43 | .split("\n") 44 | .map((line) => line.replace(/^#{2,3}\s+/g, "> ")) 45 | .join("\n"); 46 | } 47 | if (data.data.sources) { 48 | result.source = data.data.sources; 49 | } 50 | } 51 | } catch (e) { 52 | console.error(e); 53 | } 54 | } 55 | }); 56 | return result; 57 | }; 58 | 59 | try { 60 | const response = await axios.post( 61 | "https://api.felo.ai/search/threads", 62 | payload, 63 | { 64 | headers, 65 | timeout: 30000, 66 | responseType: "text", 67 | }, 68 | ); 69 | 70 | return request(response.data); 71 | } catch (error) { 72 | console.error(error); 73 | return null; 74 | } 75 | }; 76 | 77 | module.exports = felo; 78 | -------------------------------------------------------------------------------- /scrapers/source/steam.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const cheerio = require("cheerio"); 3 | 4 | class Steam { 5 | search = async function Steam(query) { 6 | let data = ( 7 | await axios.get( 8 | "https://store.steampowered.com/api/storesearch?cc=id&l=id&term=" + 9 | query, 10 | ) 11 | ).data; 12 | let info = data.items; 13 | 14 | return info.map((a) => ({ 15 | name: a.name, 16 | id: a.id, 17 | price: a.price ? "Rp: " + (a.price.final / 1e3).toLocaleString() : "Free", 18 | score: a.metascore ? a.metascore + "/100" : "N/A", 19 | platform: a.platforms.windows 20 | ? "Windows" 21 | : a.platforms.mac 22 | ? "Mac" 23 | : a.platforms.linux 24 | ? "Linux" 25 | : "Nothing", 26 | image: a.tiny_image, 27 | })); 28 | }; 29 | detail = async function Steam_Detail(url) { 30 | try { 31 | let data = ( 32 | await axios.get( 33 | "https://store.steampowered.com/api/appdetails?appids=" + url, 34 | ) 35 | ).data; 36 | let info = data[url].data; 37 | const $ = cheerio.load(info.detailed_description); 38 | let json = { 39 | metadata: { 40 | title: info.name, 41 | category: info.categories.map((a) => a.description), 42 | genre: info.genres.map((a) => a.description), 43 | release: info.release_date.coming_soon 44 | ? "Coming soon..." 45 | : info.release_date.date, 46 | free: info.is_free ? "Yes" : "No", 47 | developer: info.developers, 48 | publisher: info.developers, 49 | description: $.text(), 50 | }, 51 | screenshot: info.screenshots.map((a) => a.path_full), 52 | movies: info.movies.map((a) => ({ 53 | title: a.name, 54 | id: a.id, 55 | thumbnail: a.thumbnail, 56 | videos: a.mp4, 57 | })), 58 | }; 59 | return json; 60 | } catch (err) { 61 | console.error(err); 62 | } 63 | }; 64 | } 65 | 66 | module.exports = new Steam(); 67 | -------------------------------------------------------------------------------- /scrapers/source/xbox.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const cheerio = require("cheerio"); 3 | 4 | async function xbox(username) { 5 | return new Promise(async (resolve, reject) => { 6 | await axios 7 | .get("https://xboxgamertag.com/search/" + encodeURIComponent(username)) 8 | .then((a) => { 9 | let $ = cheerio.load(a.data); 10 | let result = { 11 | metadata: {}, 12 | history: [], 13 | }; 14 | $(".page-header-container .page-header").each((a, i) => { 15 | result.metadata.name = $(i).find("h1").text().trim(); 16 | result.metadata.icon = $(i) 17 | .find("img") 18 | .attr("src") 19 | .split("/?url=")[1] 20 | .split("&format")[0] 21 | .trim(); 22 | result.metadata.game_score = $(i) 23 | .find(".profile-detail-item") 24 | .eq(0) 25 | .text() 26 | .trim() 27 | .split("\n") 28 | .pop() 29 | .trim(); 30 | result.metadata.played = $(i) 31 | .find(".profile-detail-item") 32 | .eq(1) 33 | .text() 34 | .trim() 35 | .split("\n") 36 | .pop() 37 | .trim(); 38 | }); 39 | $(".recent-games .game-card-container").each((a, i) => { 40 | result.history.push({ 41 | game: $(i).find(".game-card-desc h3").text().trim(), 42 | online: $(i) 43 | .find(".game-card-desc .text-sm") 44 | .text() 45 | .trim() 46 | .split("played") 47 | .pop() 48 | .trim(), 49 | game_score: $(i).find(".game-card-desc .col-9").eq(0).text().trim(), 50 | achievement: $(i) 51 | .find(".game-card-desc .col-9") 52 | .eq(1) 53 | .text() 54 | .trim(), 55 | progress: $(i).find(".progress .progress-bar").text().trim(), 56 | }); 57 | }); 58 | resolve(result); 59 | }); 60 | }); 61 | } 62 | 63 | module.exports = xbox; 64 | -------------------------------------------------------------------------------- /system/plugins/rpg/mulung.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "mulung", 3 | alias: ["mungut"], 4 | category: ["rpg"], 5 | settings: {}, 6 | async run(m, { sock, config }) { 7 | let dbUser = db.list().user[m.sender]; 8 | 9 | if (!dbUser || !dbUser.register) { 10 | return m.reply(config.messages.unregistered); 11 | } 12 | 13 | if (!dbUser.rpg) { 14 | dbUser.rpg = { 15 | money: 0, 16 | exp: 0, 17 | lastGajian: 0, 18 | sampah: 0, 19 | botol: 0, 20 | kardus: 0, 21 | iron: 0, 22 | kayu: 0, 23 | kaleng: 0, 24 | gelas: 0, 25 | plastik: 0, 26 | lastMulung: 0, 27 | lastTaxy: 0, 28 | lastGojek: 0, 29 | lastRob: 0, 30 | }; 31 | } 32 | 33 | let user = dbUser.rpg; 34 | 35 | let cooldown = 30 * 60 * 1000; 36 | if (user.lastMulung && Date.now() - user.lastMulung < cooldown) { 37 | let remaining = cooldown - (Date.now() - user.lastMulung); 38 | let minutes = Math.floor(remaining / (60 * 1000)); 39 | let seconds = Math.floor((remaining % (60 * 1000)) / 1000); 40 | return m.reply( 41 | `⏳ Mohon tunggu *${minutes} menit ${seconds} detik* sebelum mulung kembali!`, 42 | ); 43 | } 44 | 45 | let items = { 46 | kaleng: ["🥫", Math.floor(Math.random() * 450) + 50], 47 | kardus: ["📦", Math.floor(Math.random() * 450) + 50], 48 | plastik: ["💳", Math.floor(Math.random() * 450) + 50], 49 | botol: ["🍾", Math.floor(Math.random() * 450) + 50], 50 | sampah: ["🗑️", Math.floor(Math.random() * 450) + 50], 51 | kayu: ["🪵", Math.floor(Math.random() * 450) + 50], 52 | iron: ["⛓️", Math.floor(Math.random() * 450) + 50], 53 | gelas: ["🥤", Math.floor(Math.random() * 450) + 50], 54 | }; 55 | 56 | let resultText = `*🔍 Hasil Mulung:*\n`; 57 | for (let [item, [emote, amount]] of Object.entries(items)) { 58 | user[item] = (user[item] || 0) + amount; 59 | resultText += `${emote} ${item}: +${amount}\n`; 60 | } 61 | 62 | user.lastMulung = Date.now(); 63 | 64 | return m.reply(`${resultText}\n\n> *Tunggu 30 Menit Untuk Memulung Lagi*`); 65 | }, 66 | }; 67 | -------------------------------------------------------------------------------- /scrapers/source/furry.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const cheerio = require("cheerio"); 3 | 4 | /* 5 | * This Scrape Make By Zivly Canzy 6 | * @zivly_san 7 | */ 8 | 9 | async function furaffinity(query, maxResults = 10) { 10 | async function fetchDetails(link) { 11 | try { 12 | const response = await axios.get(link); 13 | const html = response.data; 14 | const $ = cheerio.load(html); 15 | const description = $(".submission-description").text().trim(); 16 | const image = $("#submissionImg").attr("data-fullview-src"); 17 | return { 18 | description: description || null, 19 | image: image ? `https:${image}` : null, 20 | }; 21 | } catch (error) { 22 | return { 23 | status: "404", 24 | massage: "Not Found", 25 | }; 26 | } 27 | } 28 | let page = 1; 29 | let results = []; 30 | let hasNextPage = true; 31 | const baseUrl = `https://www.furaffinity.net/search/?q=${encodeURIComponent(query)}`; 32 | while (hasNextPage && results.length < maxResults) { 33 | try { 34 | const url = `${baseUrl}&page=${page}`; 35 | const response = await axios.get(url); 36 | const html = response.data; 37 | const $ = cheerio.load(html); 38 | $("figure").each((index, element) => { 39 | const title = $(element).find("p a").attr("title"); 40 | const titleLink = $(element).find("p a").attr("href"); 41 | const username = $(element).find("a[title]").last().attr("title"); 42 | results.push({ 43 | title: title || null, 44 | link: titleLink ? `https://www.furaffinity.net${titleLink}` : null, 45 | username: username || null, 46 | }); 47 | }); 48 | hasNextPage = $('button[name="next_page"]').length > 0; 49 | page++; 50 | } catch (error) { 51 | hasNextPage = false; 52 | } 53 | } 54 | if (results.length > maxResults) { 55 | results = results.sort(() => 0.5 - Math.random()).slice(0, maxResults); 56 | } 57 | for (let result of results) { 58 | const details = await fetchDetails(result.link); 59 | result.description = details.description; 60 | result.image = details.image; 61 | } 62 | return results; 63 | } 64 | 65 | module.exports = furaffinity; 66 | -------------------------------------------------------------------------------- /scrapers/source/sfile.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const cheerio = require("cheerio"); 3 | 4 | module.exports = async (url) => { 5 | const headers = { 6 | "User-Agent": 7 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.47", 8 | Referer: url, 9 | Accept: 10 | "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", 11 | "Accept-Language": "en-US,en;q=0.9", 12 | }; 13 | const { data: info, headers: responseHeaders } = await axios 14 | .get(url, { 15 | headers: headers, 16 | }) 17 | .catch((e) => e.response); 18 | const cookies = 19 | responseHeaders["set-cookie"] 20 | ?.map((cookie) => cookie.split(";")[0]) 21 | .join("; ") || ""; 22 | headers.Cookie = cookies; 23 | let $ = cheerio.load(info); 24 | let result = { 25 | metadata: {}, 26 | download: {}, 27 | }; 28 | $(".file-content") 29 | .eq(0) 30 | .each((a, i) => { 31 | result.metadata.filename = $(i).find("img").attr("alt"); 32 | result.metadata.mimetype = $(i) 33 | .find(".list") 34 | .eq(0) 35 | .text() 36 | .trim() 37 | .split("-")[1] 38 | .trim(); 39 | result.metadata.uploaded = $(i) 40 | .find(".list") 41 | .eq(2) 42 | .text() 43 | .trim() 44 | .split(":")[1] 45 | .trim(); 46 | result.metadata.download = $(i) 47 | .find(".list") 48 | .eq(3) 49 | .text() 50 | .trim() 51 | .split(":")[1] 52 | .trim(); 53 | result.metadata.author = $(i).find(".list").eq(1).find("a").text().trim(); 54 | }); 55 | let downloadUrl = $("#download").attr("href"); 56 | headers.Referer = downloadUrl; 57 | let { data: process } = await axios 58 | .get(downloadUrl, { 59 | headers, 60 | }) 61 | .catch((e) => e.response); 62 | $ = cheerio.load(process); 63 | let key = $("#download").attr("onclick"); 64 | let { data: buffer } = await axios.get( 65 | $("#download").attr("href") + "&k=" + key.split("'+'")[1].split("';")[0], 66 | { 67 | headers, 68 | responseType: "arraybuffer", 69 | }, 70 | ); 71 | result.download = buffer; 72 | return result; 73 | }; 74 | -------------------------------------------------------------------------------- /system/plugins/downloader/applemusic.js: -------------------------------------------------------------------------------- 1 | const { toAudio } = require(process.cwd() + "/library/converter.js"); 2 | 3 | class Command { 4 | constructor() { 5 | this.command = "applemusic"; 6 | this.alias = ["aplm", "apple"]; 7 | this.category = ["downloader"]; 8 | this.settings = { 9 | limit: true, 10 | }; 11 | this.description = "🎵 Cari dan download musik dari Apple Music!"; 12 | this.loading = true; 13 | } 14 | run = async (m, { sock, Func, Scraper, config, store, text }) => { 15 | if (!text) throw "> ❌ *Masukkan pencarian atau link dari Apple Music*"; 16 | 17 | if (Func.isUrl(text)) { 18 | if (!/music.apple.com/.test(text)) 19 | throw "> ❌ *Link yang dimasukkan bukan link Apple Music!*"; 20 | let data = await Scraper.applemusic.download(text); 21 | if (!data.metadata) throw Func.jsonFormat(data); 22 | let anu = await toAudio(await Func.fetchBuffer(data.download), "mp3"); 23 | let cap = "*🎧 Apple Music Downloader 🎧*\n"; 24 | cap += `*✍️ Judul :* ${data.metadata.name}\n`; 25 | cap += `*📝 Genre :* ${data.metadata.genre}\n`; 26 | cap += `*👦 Artis :* ${data.metadata.artist.name}\n`; 27 | cap += `*🕑 Diunggah pada :* ${data.metadata.datePublished}`; 28 | sock.sendFile(m.cht, data.metadata.image, null, cap, m); 29 | sock.sendFile( 30 | m.cht, 31 | anu.data, 32 | `${data.metadata.name} | ${data.metadata.artist.name}.mp3`, 33 | `🎧 *Silakan download musik ini dengan menekan tombol di atas*\n\n> *Catatan*: Jika file muncul sebagai , silakan download manual.`, 34 | m, 35 | { 36 | mimetype: "audio/mpeg", 37 | jpegThumbnail: await sock.resize(data.metadata.image, 400, 400), 38 | }, 39 | ); 40 | } else { 41 | let data = await Scraper.applemusic.search(text); 42 | if (data.length === 0) throw "> ❌ *Musik tidak ditemukan*"; 43 | 44 | let cap = `*– 乂 Apple Music - Hasil Pencarian*\n> 🎤 *Pilih lagu yang ingin kamu download!*\n\n`; 45 | for (let i of data) { 46 | cap += `> 🎶 *Judul*: ${i.title}\n`; 47 | cap += `> 👨‍🎤 *Artis*: ${i.artist.name}\n`; 48 | cap += `> 🔗 *Link*: ${i.song}\n\n`; 49 | } 50 | m.reply(cap); 51 | } 52 | }; 53 | } 54 | 55 | module.exports = new Command(); 56 | -------------------------------------------------------------------------------- /library/case.js: -------------------------------------------------------------------------------- 1 | const { js } = require("js-beautify"); 2 | const fs = require("fs"); 3 | 4 | class CaseManager { 5 | constructor(file) { 6 | this.file = file; 7 | } 8 | 9 | get = (name) => { 10 | try { 11 | let content = fs.readFileSync(this.file, "utf8"); 12 | let regex = /case .*?:/g; 13 | let cases = content.match(regex); 14 | let targetCases = cases.filter((cas) => cas.includes(name)); 15 | if (targetCases.length > 0) { 16 | let start = content.indexOf(targetCases[0]); 17 | let end = content.indexOf("break", start); 18 | return content.substring(start, end + 6); 19 | } else { 20 | return null; 21 | } 22 | } catch (error) { 23 | console.error(`Gagal membaca file: ${error.message}`); 24 | } 25 | }; 26 | 27 | add = (code) => { 28 | try { 29 | let content = fs.readFileSync(this.file, "utf8"); 30 | let regex = /switch\s*\([^)]+\)\s*{/; 31 | let switchContent = content.match(regex); 32 | let newCase = `${code}`; 33 | let updatedContent = content.replace( 34 | regex, 35 | `${switchContent}\n${newCase}`, 36 | ); 37 | fs.writeFileSync(this.file, js(updatedContent)); 38 | return true; 39 | } catch (error) { 40 | console.error(`Gagal menambahkan case: ${error.message}`); 41 | return false; 42 | } 43 | }; 44 | 45 | delete = (name) => { 46 | try { 47 | let content = fs.readFileSync(this.file, "utf8"); 48 | let caseToDelete = this.get(name); 49 | if (!caseToDelete) return false; 50 | let updatedContent = content.replace(caseToDelete, ""); 51 | fs.writeFileSync(this.file, updatedContent); 52 | return true; 53 | } catch (error) { 54 | console.error(`Gagal menghapus case: ${error.message}`); 55 | return false; 56 | } 57 | }; 58 | 59 | list = () => { 60 | try { 61 | let data = fs.readFileSync(this.file, "utf8"); 62 | let casePattern = /case\s+"([^"]+)"/g; 63 | let matches = data 64 | .match(casePattern) 65 | .map((match) => match.replace(/case\s+"([^"]+)"/, "$1")); 66 | 67 | return matches; 68 | } catch (error) { 69 | console.error(`Gagal membaca file: ${error.message}`); 70 | return []; 71 | } 72 | }; 73 | } 74 | 75 | module.exports = CaseManager; 76 | -------------------------------------------------------------------------------- /system/plugins/rpg/gojek.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "gojek", 3 | alias: ["ojek"], 4 | category: ["rpg"], 5 | settings: {}, 6 | async run(m, { sock, config }) { 7 | let usr = db.list().user[m.sender]; 8 | 9 | if (!usr || !usr.register) { 10 | return m.reply(config.messages.unregistered); 11 | } 12 | 13 | if (!usr.rpg) { 14 | usr.rpg = { 15 | money: 0, 16 | exp: 0, 17 | lastGajian: 0, 18 | sampah: 0, 19 | botol: 0, 20 | kardus: 0, 21 | iron: 0, 22 | kayu: 0, 23 | kaleng: 0, 24 | gelas: 0, 25 | plastik: 0, 26 | lastMulung: 0, 27 | lastTaxy: 0, 28 | lastGojek: 0, 29 | lastRob: 0, 30 | }; 31 | } 32 | 33 | let rpg = usr.rpg; 34 | 35 | let cooldown = 30 * 60 * 1000; 36 | let now = Date.now(); 37 | 38 | if (now - rpg.lastGojek < cooldown) { 39 | let timeLeft = Math.ceil((cooldown - (now - rpg.lastGojek)) / 1000); 40 | let minutes = Math.floor(timeLeft / 60); 41 | let seconds = timeLeft % 60; 42 | return m.reply( 43 | `⏳ Tunggu ${minutes} menit ${seconds} detik sebelum bisa bekerja sebagai driver Gojek lagi.`, 44 | ); 45 | } 46 | 47 | let prosesGojek = [ 48 | "🛵 Mencari Orderan...", 49 | "🛵 Menemukan Penumpang 👨...", 50 | "🛵 Mengantar ke Tujuan...", 51 | "👨 Penumpang membayar ongkos 💸...", 52 | ]; 53 | 54 | for (let txt of prosesGojek) { 55 | await m.reply(txt); 56 | await sleep(7000); 57 | } 58 | 59 | let dapatMoney = Math.floor(Math.random() * 300000) + 50000; 60 | let dapatExp = Math.floor(Math.random() * 40000) + 1; 61 | 62 | rpg.money += dapatMoney; 63 | rpg.exp += dapatExp; 64 | rpg.lastGojek = now; 65 | 66 | let hasilNyaTxt = ` 67 | 🛵 *Perjalanan Selesai!* 68 | ━━━━━━━━━━━━━━━━━ 69 | 💵 *Pendapatan:* +${dapatMoney.toLocaleString()} uang 70 | 🎯 *Pengalaman:* +${dapatExp.toLocaleString()} exp 71 | ━━━━━━━━━━━━━━━━━ 72 | 🚀 Teruslah bekerja dan tingkatkan penghasilanmu! 73 | `.trim(); 74 | 75 | return m.reply({ 76 | image: { url: "https://files.catbox.moe/nprwoe.jpg" }, 77 | caption: hasilNyaTxt, 78 | }); 79 | }, 80 | }; 81 | 82 | function sleep(ms) { 83 | return new Promise((resolve) => setTimeout(resolve, ms)); 84 | } 85 | -------------------------------------------------------------------------------- /system/plugins/rpg/taxy.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "taxy", 3 | alias: ["taksi"], 4 | category: ["rpg"], 5 | settings: {}, 6 | async run(m, { sock, config }) { 7 | let usr = db.list().user[m.sender]; 8 | 9 | if (!usr || !usr.register) { 10 | return m.reply(config.messages.unregistered); 11 | } 12 | 13 | if (!usr.rpg) { 14 | usr.rpg = { 15 | money: 0, 16 | exp: 0, 17 | lastGajian: 0, 18 | sampah: 0, 19 | botol: 0, 20 | kardus: 0, 21 | iron: 0, 22 | kayu: 0, 23 | kaleng: 0, 24 | gelas: 0, 25 | plastik: 0, 26 | lastMulung: 0, 27 | lastTaxy: 0, 28 | lastGojek: 0, 29 | lastRob: 0, 30 | }; 31 | } 32 | 33 | let rpg = usr.rpg; 34 | 35 | let cooldown = 30 * 60 * 1000; 36 | let now = Date.now(); 37 | 38 | if (now - rpg.lastTaxy < cooldown) { 39 | let timeLeft = Math.ceil((cooldown - (now - rpg.lastTaxy)) / 1000); 40 | let minutes = Math.floor(timeLeft / 60); 41 | let seconds = timeLeft % 60; 42 | return m.reply( 43 | `⏳ Tunggu ${minutes} menit ${seconds} detik sebelum bisa bekerja sebagai taksi lagi.`, 44 | ); 45 | } 46 | 47 | let prosesTaksi = [ 48 | "🚗 Sedang Mencari Penumpang...", 49 | "🚗 Menemukan Penumpang 👨...", 50 | "🚗 Berangkat Ke Tujuan...", 51 | "👨 Penumpang membayar gaji 💸...", 52 | ]; 53 | 54 | for (let txt of prosesTaksi) { 55 | await m.reply(txt); 56 | await sleep(7000); 57 | } 58 | 59 | let dapatMoney = Math.floor(Math.random() * 400000) + 100000; 60 | let dapatExp = Math.floor(Math.random() * 50000) + 1; 61 | 62 | rpg.money += dapatMoney; 63 | rpg.exp += dapatExp; 64 | rpg.lastTaxy = now; 65 | 66 | let hasilNyaTxt = ` 67 | 💼 *Perjalanan Selesai!* 68 | ━━━━━━━━━━━━━━━━━ 69 | 💵 *Gaji Diterima:* +${dapatMoney.toLocaleString()} uang 70 | 🎯 *Pengalaman:* +${dapatExp.toLocaleString()} exp 71 | ━━━━━━━━━━━━━━━━━ 72 | 🚀 Teruslah bekerja keras dan kumpulkan lebih banyak gaji! 73 | `.trim(); 74 | 75 | return m.reply({ 76 | image: { url: "https://files.catbox.moe/rz9br7.jpg" }, 77 | caption: hasilNyaTxt, 78 | }); 79 | }, 80 | }; 81 | 82 | function sleep(ms) { 83 | return new Promise((resolve) => setTimeout(resolve, ms)); 84 | } 85 | -------------------------------------------------------------------------------- /system/plugins/anime/kuronime.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "kuronime", 3 | alias: [], 4 | category: ["anime"], 5 | settings: { 6 | limit: true, 7 | }, 8 | description: "Cari Anime Terbaru di Kuronime", 9 | async run(m, { sock, Scraper, text, Func, config }) { 10 | let latest = await Scraper.kuronime.latest(); 11 | 12 | let cap = `*– 乂 Panduan Penggunaan Fitur:*\n 13 | > 📝 *Masukkan nama anime* untuk mencari anime yang sedang tren\n 14 | > 🔗 *Masukkan URL* untuk mendapatkan data anime lengkap langsung dari Kuronime\n 15 | 16 | *– 乂 Contoh Penggunaan:*\n 17 | > ➡️ *${m.prefix + m.command} Toradora*\n 18 | > ➡️ *${m.prefix + m.command} https://kuronime.biz/anime/toradora*\n 19 | 20 | *– 乂 Anime yang Rilis Hari Ini (${latest.length} Anime):*\n`; 21 | 22 | cap += latest 23 | .map((a) => 24 | Object.entries(a) 25 | .map(([b, c]) => `> 🔸 *${b.capitalize()}* : ${c}`) 26 | .join("\n"), 27 | ) 28 | .join("\n\n"); 29 | if (!text) throw cap; 30 | if (Func.isUrl(text) && /kuronime./.test(text)) { 31 | if (/anime\//.test(text)) { 32 | let data = await Scraper.kuronime.detail(text); 33 | let cap = `*– 乂 Detail Anime - Kuronime*\n 34 | > 🖼️ *Thumbnail*: ${data.metadata.thumbnail}\n`; 35 | 36 | cap += Object.entries(data.metadata) 37 | .map(([a, b]) => `> 🔹 *${a}* : ${b}`) 38 | .join("\n"); 39 | cap += "\n\n*– 乂 Daftar Episode:*\n"; 40 | cap += data.episode 41 | .map((a, i) => `> 📺 *${i + 1}.* ${a.title}\n> 🔗 ${a.url}`) 42 | .join("\n\n"); 43 | 44 | m.reply({ 45 | image: { 46 | url: data.metadata.thumbnail, 47 | }, 48 | caption: cap, 49 | }); 50 | } 51 | } else { 52 | let data = await Scraper.kuronime.search(text); 53 | if (data.length === 0) throw "> ❌ *Anime tidak ditemukan*"; 54 | 55 | let cap = "*– 乂 Hasil Pencarian Anime - Kuronime*\n"; 56 | cap += data 57 | .map((a) => 58 | Object.entries(a) 59 | .map(([b, c]) => `> 🔸 *${b.capitalize()}* : ${c}`) 60 | .join("\n"), 61 | ) 62 | .join("\n\n"); 63 | 64 | m.reply({ 65 | image: { 66 | url: data[0].thumbnail, 67 | }, 68 | caption: cap, 69 | }); 70 | } 71 | }, 72 | }; 73 | -------------------------------------------------------------------------------- /system/plugins/owner/upsw.js: -------------------------------------------------------------------------------- 1 | class Command { 2 | constructor() { 3 | this.command = "upsw"; 4 | this.alias = []; 5 | this.category = ["owner"]; 6 | this.settings = { 7 | owner: true, 8 | }; 9 | this.description = "Upload mdia mu ke Status WhatsApp"; 10 | this.loading = true; 11 | } 12 | run = async (m, { sock, Func, Scraper, config, store }) => { 13 | let teks; 14 | if (m.args.length >= 1) { 15 | teks = m.args.slice(0).join(" "); 16 | } else if (m.quoted && m.quoted.body) { 17 | teks = m.quoted.body; 18 | } 19 | 20 | if (m.quoted && m.quoted.type) { 21 | const mtype = m.quoted.type; 22 | let type; 23 | 24 | if (mtype === "audioMessage") { 25 | type = "vn"; 26 | } else if (mtype === "videoMessage") { 27 | type = "vid"; 28 | } else if (mtype === "imageMessage") { 29 | type = "img"; 30 | } else if (mtype === "extendedTextMessage") { 31 | type = "txt"; 32 | } else { 33 | throw "❌ Media type tidak valid!"; 34 | } 35 | 36 | const doc = {}; 37 | 38 | if (type === "vn") { 39 | const link = await m.quoted.download(); 40 | doc.mimetype = m.quoted.msg.mimetype; 41 | doc.audio = link; 42 | } else if (type === "vid") { 43 | const link = await m.quoted.download(); 44 | doc.mimetype = m.quoted.msg.mimetype; 45 | doc.caption = teks; 46 | doc.video = link; 47 | } else if (type === "img") { 48 | const link = await m.quoted.download(); 49 | doc.mimetype = m.quoted.msg.mimetype; 50 | doc.caption = teks; 51 | doc.image = link; 52 | } else if (type === "txt") { 53 | doc.text = teks; 54 | } 55 | if (m.isGroup) return sock.sendStatus(doc, [m.cht]); 56 | await sock 57 | .sendMessage("status@broadcast", doc, { 58 | backgroundColor: getRandomHexColor(), 59 | font: Math.floor(Math.random() * 9), 60 | statusJidList: Object.keys(store.contacts), 61 | }) 62 | .then((res) => { 63 | m.reply(`Sukses upload ${type}`); 64 | }) 65 | .catch(() => { 66 | m.reply(`Gagal upload ${type}`); 67 | }); 68 | } else { 69 | throw "❌ Tidak ada media yang diberikan!"; 70 | } 71 | }; 72 | } 73 | 74 | module.exports = new Command(); 75 | -------------------------------------------------------------------------------- /system/plugins/game/genshin-stalk.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | module.exports = { 4 | command: ["genshin-stalk"], 5 | alias: ["gs-stalk", "gistalk"], 6 | category: ["anime", "game"], 7 | description: "Dapatkan informasi profil Genshin Impact berdasarkan UID", 8 | settings: { 9 | loading: true, 10 | }, 11 | async run(m, { text, sock }) { 12 | try { 13 | if (!text) { 14 | return m.reply(`*• Contoh Penggunaan:* .genshin-stalk [UID]`); 15 | } 16 | 17 | let { data } = await axios.get(`https://enka.network/api/uid/${text}`, { 18 | headers: { 19 | "User-Agent": 20 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, seperti Gecko) Chrome/58.0.3029.110 Safari/537.3", 21 | }, 22 | }); 23 | 24 | if (!data || !data.playerInfo) { 25 | return m.reply("*[ PLAYER NOT FOUND ]*"); 26 | } 27 | 28 | let playerInfo = data.playerInfo; 29 | let nickname = playerInfo.nickname || "Not found"; 30 | let arLevel = playerInfo.level || "Not found"; 31 | let signature = playerInfo.signature || "Not found"; 32 | let worldLevel = playerInfo.worldLevel || "Not found"; 33 | let achievement = playerInfo.finishAchievementNum || "Not found"; 34 | let spiralFloorIndex = playerInfo.towerFloorIndex || "Not found"; 35 | let spiralLeverIndex = playerInfo.towerLevelIndex || "Not found"; 36 | 37 | let ssurl = `https://enka.network/u/${text}`; 38 | let screenshot = `https://api.mightyshare.io/v1/19EIFDUEL496RA3F/jpg?url=${ssurl}`; 39 | 40 | let caption = 41 | `*[ GENSHIN IMPACT PROFILE ]*\n\n` + 42 | `• *Nickname:* ${nickname}\n` + 43 | `• *Adventure Rank:* ${arLevel}\n` + 44 | `• *Signature:* ${signature}\n` + 45 | `• *World Level:* ${worldLevel}\n` + 46 | `• *Achievements:* ${achievement}\n\n` + 47 | `*[ SPIRAL ABYSS ]*\n` + 48 | `• *Floor:* ${spiralFloorIndex}\n` + 49 | `• *Level:* ${spiralLeverIndex}\n\n` + 50 | `*[ MORE INFO ]*\n` + 51 | `❀ [View on Enka](https://enka.network/u/${text})\n` + 52 | `✧ *UID:* ${text}`; 53 | 54 | m.reply({ 55 | image: { url: screenshot }, 56 | caption: caption, 57 | }); 58 | } catch (error) { 59 | console.error(error); 60 | m.reply("❌ *Terjadi kesalahan saat mengambil data!*"); 61 | } 62 | }, 63 | }; 64 | -------------------------------------------------------------------------------- /system/plugins/owner/broadcast.js: -------------------------------------------------------------------------------- 1 | const { delay } = require("baileys"); 2 | const DELAY = 10000; 3 | 4 | module.exports = { 5 | command: "broadcast", 6 | alias: ["bc"], 7 | settings: { owner: true }, 8 | description: "Mengirim pesan ke semua kontak atau grup", 9 | async run(m, { sock, store, text }) { 10 | if (!text) { 11 | throw `*╭──[ 乂 BROADCAST - USAGE ]* 12 | ᎒⊸ Masukkan pesan yang ingin di-broadcast. 13 | ᎒⊸ Reply media jika ingin mengirim pesan dengan media. 14 | ᎒⊸ Gunakan *\`--group\`* untuk mengirim pesan ke semua grup. 15 | *╰────────────•*`; 16 | } 17 | 18 | const MSG = Object.keys(store.messages); 19 | const groupChats = MSG.filter((id) => id.endsWith("@g.us")); 20 | const privateChats = MSG.filter((id) => id.endsWith("@s.whatsapp.net")); 21 | 22 | if (text.includes("--group")) { 23 | let input = text.replace("--group", "").trim(); 24 | if (!groupChats.length) 25 | throw "*❌ Tidak ada grup ditemukan untuk broadcast.*"; 26 | let q = m.quoted || m; 27 | let Msg = sock.cMod(m.cht, q, input); 28 | 29 | let successCount = 0; 30 | for (let groupId of groupChats) { 31 | try { 32 | await sock.copyNForward(groupId, Msg, true); 33 | successCount++; 34 | await delay(DELAY); 35 | } catch (error) { 36 | console.error(`❌ Gagal mengirim ke grup ${groupId}:`, error.message); 37 | } 38 | } 39 | m.reply( 40 | `*╭──[ 乂 BROADCAST - GRUP ]* 41 | ᎒⊸ Total Grup: *${groupChats.length}* 42 | ᎒⊸ Berhasil Terkirim: *${successCount}* 43 | *╰────────────•*`, 44 | ); 45 | } else { 46 | if (!privateChats.length) 47 | throw "*❌ Tidak ada kontak ditemukan untuk broadcast.*"; 48 | let q = m.quoted || m; 49 | let Msg = sock.cMod(m.cht, q, text); 50 | 51 | let successCount = 0; 52 | for (let contactId of privateChats) { 53 | try { 54 | await sock.copyNForward(contactId, Msg, true); 55 | successCount++; 56 | await delay(DELAY); 57 | } catch (error) { 58 | console.error( 59 | `❌ Gagal mengirim ke kontak ${contactId}:`, 60 | error.message, 61 | ); 62 | } 63 | } 64 | m.reply( 65 | `*╭──[ 乂 BROADCAST - USER ]* 66 | ᎒⊸ Total Kontak: *${privateChats.length}* 67 | ᎒⊸ Berhasil Terkirim: *${successCount}* 68 | *╰────────────•*`, 69 | ); 70 | } 71 | }, 72 | }; 73 | -------------------------------------------------------------------------------- /system/plugins/group/askot.js: -------------------------------------------------------------------------------- 1 | const PhoneNum = require("awesome-phonenumber"); 2 | 3 | class Command { 4 | constructor() { 5 | this.command = "regionmember"; 6 | this.alias = ["askot", "totalmember"]; 7 | this.category = ["group"]; 8 | this.settings = { 9 | group: true, 10 | }; 11 | this.description = 12 | "📊 Menampilkan informasi asal negara semua member di grup"; 13 | this.loading = true; 14 | } 15 | 16 | run = async (m, { sock, Func, Scraper, config, store }) => { 17 | let regionNames = new Intl.DisplayNames(["en"], { type: "region" }); 18 | let data = m.metadata; 19 | let participants = data.participants; 20 | 21 | let countryMembers = {}; 22 | for (let participant of participants) { 23 | let phoneNumber = "+" + participant.id.split("@")[0]; 24 | let regionCode = PhoneNum(phoneNumber).getRegionCode("internasional"); 25 | let country = regionNames.of(regionCode); 26 | if (!countryMembers[country]) { 27 | countryMembers[country] = []; 28 | } 29 | countryMembers[country].push(participant.id); 30 | } 31 | 32 | let countryCounts = Object.keys(countryMembers).map((country) => ({ 33 | name: country, 34 | total: countryMembers[country].length, 35 | jid: countryMembers[country], 36 | })); 37 | let totalSum = countryCounts.reduce( 38 | (acc, country) => acc + country.total, 39 | 0, 40 | ); 41 | let totalRegion = Object.keys(countryMembers).length; 42 | let hasil = countryCounts.map(({ name, total, jid }) => ({ 43 | name, 44 | total, 45 | jid, 46 | percentage: ((total / totalSum) * 100).toFixed(2) + "%", 47 | })); 48 | 49 | let cap = `*📍 Informasi Member Berdasarkan Wilayah*\n\n`; 50 | cap += `> *📌 Nama Grup:* ${m.metadata.subject}\n`; 51 | cap += `> *👥 Total Member:* ${m.metadata.participants.length}\n`; 52 | cap += `> *🌎 Jumlah Wilayah Terdata:* ${totalRegion}\n\n`; 53 | cap += `*🌐 Statistik Wilayah Member*\n`; 54 | cap += hasil 55 | .sort((b, a) => a.total - b.total) 56 | .map( 57 | (a, i) => 58 | `🔹 *${i + 1}. Wilayah:* ${a.name || "Tidak Diketahui"}\n ➡️ *Total:* ${a.total} anggota\n ➡️ *Persentase:* ${a.percentage}`, 59 | ) 60 | .join("\n\n"); 61 | 62 | cap += `\n📊 _Gunakan informasi ini untuk memahami lebih baik asal negara anggota grup._`; 63 | 64 | m.reply(cap); 65 | }; 66 | } 67 | 68 | module.exports = new Command(); 69 | -------------------------------------------------------------------------------- /library/converter.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | const { spawn } = require("child_process"); 4 | 5 | function ffmpeg(buffer, args = [], ext = "", ext2 = "") { 6 | return new Promise(async (resolve, reject) => { 7 | try { 8 | let tmp = process.cwd() + "/tmp/ffmpeg_" + Date.now() + "." + ext; 9 | let out = tmp + "." + ext2; 10 | await fs.promises.writeFile(tmp, buffer); 11 | spawn("ffmpeg", ["-y", "-i", tmp, ...args, out]) 12 | .on("error", reject) 13 | .on("close", async (code) => { 14 | try { 15 | await fs.promises.unlink(tmp); 16 | if (code !== 0) return reject(code); 17 | resolve({ data: await fs.promises.readFile(out), filename: out }); 18 | // await fs.promises.unlink(out) 19 | } catch (e) { 20 | reject(e); 21 | } 22 | }); 23 | } catch (e) { 24 | reject(e); 25 | } 26 | }); 27 | } 28 | 29 | /** 30 | * Convert Audio to Playable WhatsApp Audio 31 | * @param {Buffer} buffer Audio Buffer 32 | * @param {String} ext File Extension 33 | */ 34 | function toPTT(buffer, ext) { 35 | return ffmpeg( 36 | buffer, 37 | ["-vn", "-c:a", "libmp3lame", "-b:a", "128k", "-vbr", "on"], 38 | ext, 39 | "mp3", 40 | ); 41 | } 42 | 43 | /** 44 | * Convert Audio to Playable WhatsApp PTT 45 | * @param {Buffer} buffer Audio Buffer 46 | * @param {String} ext File Extension 47 | */ 48 | function toAudio(buffer, ext) { 49 | return ffmpeg( 50 | buffer, 51 | [ 52 | "-vn", 53 | "-c:a", 54 | "libmp3lame", 55 | "-b:a", 56 | "128k", 57 | "-vbr", 58 | "on", 59 | "-compression_level", 60 | "10", 61 | ], 62 | ext, 63 | "mp3", 64 | ); 65 | } 66 | 67 | /** 68 | * Convert Audio to Playable WhatsApp Video 69 | * @param {Buffer} buffer Video Buffer 70 | * @param {String} ext File Extension 71 | */ 72 | function toVideo(buffer, ext) { 73 | return ffmpeg( 74 | buffer, 75 | [ 76 | "-c:v", 77 | "libx264", 78 | "-c:a", 79 | "aac", 80 | "-ab", 81 | "128k", 82 | "-ar", 83 | "44100", 84 | "-crf", 85 | "32", 86 | "-preset", 87 | "slow", 88 | ], 89 | ext, 90 | "mp4", 91 | ); 92 | } 93 | 94 | module.exports = { 95 | toAudio, 96 | toPTT, 97 | toVideo, 98 | ffmpeg, 99 | }; 100 | -------------------------------------------------------------------------------- /system/plugins/sfw/waifuim.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | const sfwCategories = [ 4 | "waifu", 5 | "maid", 6 | "marin-kitagawa", 7 | "mori-calliope", 8 | "raiden-shogun", 9 | "selfies", 10 | "uniform", 11 | "kamisato-ayaka", 12 | ]; 13 | 14 | const nsfwCategories = [ 15 | "oppai", 16 | "ero", 17 | "ass", 18 | "hentai", 19 | "milf", 20 | "oral", 21 | "paizuri", 22 | "ecchi", 23 | ]; 24 | 25 | module.exports = { 26 | command: "waifuim", 27 | alias: ["wim"], 28 | category: ["anime", "sfw"], 29 | settings: { 30 | owner: false, 31 | }, 32 | description: 33 | "Mendapatkan gambar dari Waifu.im API dengan kategori SFW atau NSFW", 34 | async run(m, { text, sock, Func, config }) { 35 | let args = text.split(" "); 36 | if (!text) { 37 | return m.reply( 38 | `> *– 乂 Panduan Penggunaan Perintah* 💡\n` + 39 | `> 1. Gunakan *\`.waifuim --sfw [kategori]\`* untuk gambar SFW\n` + 40 | `> 2. Gunakan *\`.waifuim --nsfw [kategori]\`* untuk gambar NSFW\n` + 41 | `> 3. Gunakan *\`.waifuim --list\`* untuk melihat kategori`, 42 | ); 43 | } 44 | 45 | let type = args[0].toLowerCase(); 46 | let category = args[1]?.toLowerCase(); 47 | 48 | if (type === "--list") { 49 | return m.reply( 50 | `> *– 乂 Kategori yang Tersedia:*\n` + 51 | `> *SFW:* ${sfwCategories.join(", ")}\n` + 52 | `> *NSFW:* ${nsfwCategories.join(", ")}`, 53 | ); 54 | } 55 | 56 | if (type === "--sfw" && !sfwCategories.includes(category)) { 57 | return m.reply( 58 | `> ❌ *Kategori SFW tidak ditemukan!*\n> Gunakan \`.waifuim --list\` untuk melihat daftar kategori.`, 59 | ); 60 | } 61 | 62 | if (type === "--nsfw" && !nsfwCategories.includes(category)) { 63 | return m.reply( 64 | `> ❌ *Kategori NSFW tidak ditemukan!*\n> Gunakan \`.waifuim --list\` untuk melihat daftar kategori.`, 65 | ); 66 | } 67 | 68 | let apiUrl = `https://api.waifu.im/search?included_tags=${encodeURIComponent(category)}`; 69 | 70 | try { 71 | let res = await axios.get(apiUrl); 72 | if (!res.data.images || res.data.images.length === 0) 73 | throw "Error mengambil gambar"; 74 | 75 | let imageUrl = res.data.images[0].url; 76 | 77 | await m.reply({ 78 | image: { url: imageUrl }, 79 | caption: config.messages.success, 80 | }); 81 | } catch (e) { 82 | return m.reply( 83 | `> ❌ *Gagal mengambil gambar untuk kategori "${category}"*\n> Coba lagi nanti atau pilih kategori lain.`, 84 | ); 85 | } 86 | }, 87 | }; 88 | -------------------------------------------------------------------------------- /system/plugins/game/blue-archive.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | module.exports = { 4 | command: ["bluearchive", "blue-archive"], 5 | alias: ["bar"], 6 | category: ["anime", "game"], 7 | description: "Dapatkan informasi karakter Blue Archive", 8 | settings: { 9 | loading: true, 10 | }, 11 | async run(m, { text, sock }) { 12 | try { 13 | let { data: characters } = await axios.get( 14 | "https://api.ennead.cc/buruaka/character", 15 | ); 16 | let charaList = characters.map((char) => char.name); 17 | 18 | let capitalize = (txt) => 19 | txt.charAt(0).toUpperCase() + txt.slice(1).toLowerCase(); 20 | 21 | if (!text) { 22 | m.reply( 23 | `*• Contoh Penggunaan:* .bluearchive [nama karakter]\n\n*List karakter yang tersedia:*\n${charaList.map((a) => `• ${a}`).join("\n")}`, 24 | ); 25 | } 26 | 27 | if (!charaList.includes(capitalize(text))) { 28 | m.reply( 29 | `*• Karakter tidak ditemukan!*\nGunakan salah satu dari daftar berikut:\n${charaList.map((a) => `• ${a}`).join("\n")}`, 30 | ); 31 | } 32 | 33 | let { data: characterData } = await axios.get( 34 | `https://api.ennead.cc/buruaka/character/${capitalize(text)}`, 35 | ); 36 | 37 | if (characterData.StatusCode) { 38 | return m.reply("*[ CHARACTER NOT FOUND ]*"); 39 | } 40 | 41 | let caption = 42 | `*[ BLUE ARCHIVE INFORMATION ]*\n\n` + 43 | `• *Name:* ${characterData.character.name}\n` + 44 | `• *Age:* ${characterData.info.age}\n` + 45 | `• *Height:* ${characterData.info.height}\n` + 46 | `• *School:* ${characterData.info.school}\n` + 47 | `• *Year:* ${characterData.info.schoolYear}\n` + 48 | `• *Club:* ${characterData.info.club}\n` + 49 | `• *Birth Date:* ${characterData.info.birthDate}\n\n` + 50 | `• *Base Star:* ${characterData.character.baseStar}\n` + 51 | `• *Rank:* ${characterData.character.rarity}\n` + 52 | `• *Role:* ${characterData.character.role}\n` + 53 | `• *Type:*\n` + 54 | ` - Squad: ${characterData.character.squadType}\n` + 55 | ` - Weapon: ${characterData.character.weaponType}\n` + 56 | ` - Bullet: ${characterData.character.bulletType}\n` + 57 | ` - Armor: ${characterData.character.armorType}`; 58 | 59 | m.reply({ 60 | image: { url: characterData.image.portrait }, 61 | caption: caption, 62 | }); 63 | } catch (error) { 64 | console.error(error); 65 | m.reply("❌ *Terjadi kesalahan saat mengambil data!*"); 66 | } 67 | }, 68 | }; 69 | -------------------------------------------------------------------------------- /system/plugins/downloader/soundcloud.js: -------------------------------------------------------------------------------- 1 | const { fetch } = require("node-fetch"); 2 | 3 | class Command { 4 | constructor() { 5 | this.command = "soundcloud"; 6 | this.alias = ["sound", "scloud"]; 7 | this.category = ["downloader"]; 8 | this.settings = { 9 | limit: true, 10 | }; 11 | this.description = "🎵 Mencari dan mengunduh musik dari SoundCloud!"; 12 | this.loading = true; 13 | } 14 | run = async (m, { sock, Func, Scraper, config, store, text }) => { 15 | if (!text) 16 | throw ( 17 | `*– 乂 Cara Penggunaan 🎶*\n\n` + 18 | `> Masukkan kata kunci untuk mencari musik\n` + 19 | `> Masukkan URL SoundCloud untuk mengunduh musik\n\n` + 20 | `*– 乂 Contoh Penggunaan 📋*\n` + 21 | `> ${m.prefix}soundcloud Imagine Dragons\n` + 22 | `> ${m.prefix}soundcloud https://soundcloud.com/artist-name/track-name` 23 | ); 24 | 25 | if (Func.isUrl(text)) { 26 | if (!/soundcloud.com/.test(text)) 27 | throw `> *❌ Masukkan URL SoundCloud yang valid!*`; 28 | 29 | let data = await Scraper.soundcloud.download(text); 30 | if (!data.download) throw Func.jsonFormat(data); 31 | let buffer = await fetch(data.download); 32 | let cap = `*– 乂 SoundCloud - Downloader 🎵*\n\n`; 33 | cap += Object.entries(data) 34 | .map(([a, b]) => `> *🎧 ${a.capitalize()} :* ${b}`) 35 | .join("\n"); 36 | 37 | sock 38 | .sendMessage( 39 | m.cht, 40 | { 41 | image: { 42 | url: data.thumbnail, 43 | }, 44 | caption: cap, 45 | }, 46 | { 47 | quoted: m, 48 | }, 49 | ) 50 | .then((msg) => { 51 | setTimeout(() => { 52 | sock.sendMessage( 53 | m.cht, 54 | { 55 | audio: { 56 | url: data.download, 57 | }, 58 | mimetype: "audio/mpeg", 59 | }, 60 | { 61 | quoted: msg, 62 | }, 63 | ); 64 | }, 4000); 65 | }); 66 | } else { 67 | let data = await Scraper.soundcloud.search(text); 68 | if (data.length === 0) throw `> *❌ Musik tidak ditemukan!*`; 69 | 70 | let cap = 71 | `*– 乂 SoundCloud - Pencarian 🔎*\n\n` + 72 | `> Pilih lagu yang ingin kamu unduh!\n\n`; 73 | cap += data 74 | .map((i) => `> *🎵 Judul :* ${i.title}\n` + `> *🔗 URL :* ${i.url}`) 75 | .join("\n\n"); 76 | 77 | m.reply(cap); 78 | } 79 | }; 80 | } 81 | 82 | module.exports = new Command(); 83 | -------------------------------------------------------------------------------- /system/plugins/sfw/waifupics.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | const sfwCategories = [ 4 | "waifu", 5 | "neko", 6 | "shinobu", 7 | "megumin", 8 | "bully", 9 | "cuddle", 10 | "cry", 11 | "hug", 12 | "awoo", 13 | "kiss", 14 | "lick", 15 | "pat", 16 | "smug", 17 | "bonk", 18 | "yeet", 19 | "blush", 20 | "smile", 21 | "wave", 22 | "highfive", 23 | "handhold", 24 | "nom", 25 | "bite", 26 | "glomp", 27 | "slap", 28 | "kill", 29 | "kick", 30 | "happy", 31 | "wink", 32 | "poke", 33 | "dance", 34 | "cringe", 35 | ]; 36 | 37 | const nsfwCategories = ["waifu", "neko", "trap", "blowjob"]; 38 | 39 | module.exports = { 40 | command: "waifupics", 41 | alias: ["wpics"], 42 | category: ["anime", "sfw"], 43 | settings: { 44 | owner: false, 45 | }, 46 | description: 47 | "Mendapatkan gambar dari Waifu.pics API dengan kategori SFW atau NSFW", 48 | async run(m, { text, sock, Func, config }) { 49 | let args = text.split(" "); 50 | if (!text) { 51 | return m.reply( 52 | `> *– 乂 Panduan Penggunaan Perintah* 💡\n> 1. Gunakan *\`.waifupics --sfw [kategori]\`* untuk gambar SFW\n> 2. Gunakan *\`.waifupics --nsfw [kategori]\`* untuk gambar NSFW\n> 3. Gunakan *\`.waifupics --list\`* untuk melihat kategori`, 53 | ); 54 | } 55 | 56 | let type = args[0].toLowerCase(); 57 | let category = args[1]?.toLowerCase(); 58 | 59 | if (type === "--list") { 60 | return m.reply( 61 | `> *– 乂 Kategori yang Tersedia:*\n> *SFW:* ${sfwCategories.join(", ")}\n> *NSFW:* ${nsfwCategories.join(", ")}`, 62 | ); 63 | } 64 | 65 | if (type === "--sfw" && !sfwCategories.includes(category)) { 66 | return m.reply( 67 | `> ❌ *Kategori SFW tidak ditemukan!*\n> Gunakan \`.waifupics --list\` untuk melihat daftar kategori.`, 68 | ); 69 | } 70 | 71 | if (type === "--nsfw" && !nsfwCategories.includes(category)) { 72 | return m.reply( 73 | `> ❌ *Kategori NSFW tidak ditemukan!*\n> Gunakan \`.waifupics --list\` untuk melihat daftar kategori.`, 74 | ); 75 | } 76 | 77 | let apiUrl = `https://api.waifu.pics/${type.replace("--", "")}/${category}`; 78 | 79 | try { 80 | let res = await axios.get(apiUrl); 81 | if (!res.data.url) throw "Error mengambil gambar"; 82 | 83 | await m.reply({ 84 | image: { url: res.data.url }, 85 | caption: config.messages.success, 86 | }); 87 | } catch (e) { 88 | return m.reply( 89 | `> ❌ *Gagal mengambil gambar untuk kategori "${category}"*\n> Coba lagi nanti atau pilih kategori lain.`, 90 | ); 91 | } 92 | }, 93 | }; 94 | -------------------------------------------------------------------------------- /system/plugins/islam/alif.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const cheerio = require("cheerio"); 3 | 4 | async function alifSearch(query) { 5 | try { 6 | const { data } = await axios.get("https://alif.id/?s=" + query); 7 | const $ = cheerio.load(data); 8 | const results = []; 9 | 10 | $(".post.style3").each((index, element) => { 11 | const title = $(element).find(".post-title h5 a span").text().trim(); 12 | const link = $(element).find(".post-title h5 a").attr("href"); 13 | const author = $(element).find(".post-author a").text().trim(); 14 | const authorLink = $(element).find(".post-author a").attr("href"); 15 | const date = $(element).find(".post-date").text().trim(); 16 | const category = 17 | $(element).find(".post-category a").text().trim() || 18 | "Tidak ada kategori"; 19 | const categoryLink = 20 | $(element).find(".post-category a").attr("href") || 21 | "Tidak ada link kategori"; 22 | const image = 23 | $(element).find("figure.post-gallery img").attr("data-src") || 24 | "Tidak ada gambar"; 25 | 26 | results.push({ 27 | title, 28 | link, 29 | author, 30 | authorLink, 31 | date, 32 | category, 33 | categoryLink, 34 | image, 35 | }); 36 | }); 37 | 38 | return results.length > 0 ? results : null; 39 | } catch (error) { 40 | throw new Error( 41 | "Gagal mengambil data dari Alif.id. Pastikan koneksi Anda stabil.", 42 | ); 43 | } 44 | } 45 | 46 | class Command { 47 | constructor() { 48 | this.command = "alif"; 49 | this.alias = []; 50 | this.category = ["islam"]; 51 | this.settings = { limit: true }; 52 | this.description = "🔍 Cari informasi Islami dari Alif.id"; 53 | this.loading = true; 54 | } 55 | 56 | run = async (m, { text }) => { 57 | if (!text) throw "> Masukkan kata kunci untuk pencarian."; 58 | try { 59 | let data = await alifSearch(text); 60 | if (!data) throw "> Tidak ada hasil ditemukan untuk pencarian Anda."; 61 | 62 | let caption = `*– 乂 Alif - Pencarian*\n\n`; 63 | caption += data 64 | .map( 65 | (item, index) => 66 | `*${index + 1}. ${item.title}*\n> 🔗 *Link:* ${item.link}\n> ✍️ *Penulis:* [${item.author}](${item.authorLink})\n> 📅 *Tanggal:* ${item.date}\n> 🗂️ *Kategori:* [${item.category}](${item.categoryLink})\n> 🖼️ *Gambar:* ${item.image}`, 67 | ) 68 | .join("\n\n"); 69 | 70 | m.reply(caption); 71 | } catch (error) { 72 | m.reply(`> Terjadi kesalahan:\n${error.message}`); 73 | } 74 | }; 75 | } 76 | 77 | module.exports = new Command(); 78 | -------------------------------------------------------------------------------- /system/plugins/nsfw/fantox.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const axios = require("axios"); 3 | const jsBeautify = require("js-beautify"); 4 | 5 | const nsfwCategories = [ 6 | "genshin", 7 | "swimsuit", 8 | "schoolswimsuit", 9 | "white", 10 | "barefoot", 11 | "tornclothes", 12 | "touhou", 13 | "gamecg", 14 | "uncensored", 15 | "glasses", 16 | "weapon", 17 | "shirtlift", 18 | "chain", 19 | "fingering", 20 | "flatchest", 21 | "bondage", 22 | "demon", 23 | "pantypull", 24 | "headdress", 25 | "headphones", 26 | "anusview", 27 | "shorts", 28 | "stockings", 29 | "topless", 30 | "beach", 31 | "bunnygirl", 32 | "bunnyears", 33 | "vampire", 34 | "nobra", 35 | "bikini", 36 | "whitehair", 37 | "blonde", 38 | "pinkhair", 39 | "bed", 40 | "ponytail", 41 | "nude", 42 | "dress", 43 | "underwear", 44 | "foxgirl", 45 | "skirt", 46 | "breasts", 47 | "twintails", 48 | "spreadpussy", 49 | "seethrough", 50 | "breasthold", 51 | "fateseries", 52 | "openshirt", 53 | "headband", 54 | "nipples", 55 | "erectnipples", 56 | "greenhair", 57 | "wolfgirl", 58 | "catgirl", 59 | ]; 60 | 61 | module.exports = { 62 | command: "fantox", 63 | alias: ["fantox"], 64 | category: ["anime", "nsfw"], 65 | settings: { 66 | owner: false, 67 | }, 68 | description: "Mendapatkan gambar NSFW dari berbagai kategori yang tersedia", 69 | async run(m, { text, sock, Func, config }) { 70 | if (!text) { 71 | return m.reply( 72 | `> *– 乂 Panduan Penggunaan Perintah* 💡\n> 1. Gunakan *\`.fantox [kategori]\`* untuk mengambil gambar\n> 2. Gunakan *\`.fantox --list\`* untuk melihat daftar kategori\n`, 73 | ); 74 | } 75 | 76 | if (text === "--list") { 77 | return m.reply( 78 | `> *– 乂 Kategori NSFW Tersedia:*\n${nsfwCategories.map((c, i) => `> *${i + 1}.* ${c}`).join("\n")}`, 79 | ); 80 | } 81 | 82 | if (!nsfwCategories.includes(text)) { 83 | return m.reply( 84 | `> ❌ *Kategori tidak ditemukan!*\n> Gunakan \`.fantox --list\` untuk melihat daftar kategori yang tersedia.`, 85 | ); 86 | } 87 | 88 | try { 89 | let res = await axios.get(`https://fantox-apis.vercel.app/${text}`); 90 | if (!res.data.url) throw "Error"; 91 | await m.reply({ 92 | image: { url: res.data.url }, 93 | caption: config.messages.success, 94 | }); 95 | } catch (e) { 96 | return m.reply( 97 | `> ❌ *Gagal mengambil gambar untuk kategori "${text}"*\n> Coba lagi nanti atau pilih kategori lain.`, 98 | ); 99 | } 100 | }, 101 | }; 102 | -------------------------------------------------------------------------------- /system/plugins/group/settings.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "settings", 3 | alias: ["stg"], 4 | category: ["group"], 5 | description: "⚙️ Mengatur fitur grup (welcome/promote/anti-porn/anti-badwords)", 6 | settings: { 7 | group: true, 8 | admin: true, 9 | botAdmin: true, 10 | }, 11 | async run(m, { text }) { 12 | const [feature, status] = text.split(" ").map((v) => v.trim()); 13 | 14 | const validFeatures = ["welcome", "promote", "porn", "badwords"]; 15 | const validStatus = ["on", "off"]; 16 | 17 | if (!feature || !status) { 18 | return m.reply( 19 | `*⚙️ Cara Menggunakan Settings:*\n\n` + 20 | `> 📌 *Format:* \`.settings [fitur] [on/off]\`\n\n` + 21 | `*⚙️ Fitur yang Tersedia:*\n` + 22 | `> • *welcome* - Sambutan member masuk/keluar\n` + 23 | `> • *promote* - Notifikasi promote/demote admin\n` + 24 | `> • *porn* - Filter konten dewasa (gambar/sticker)\n` + 25 | `> • *badwords* - Filter kata-kata kasar\n\n` + 26 | `*⚙️ Contoh Penggunaan:*\n` + 27 | `> • \`.set welcome on\`\n` + 28 | `> • \`.set promote off\`\n` + 29 | `> • \`.set porn on\`\n` + 30 | `> • \`.set badwords off\`` 31 | ); 32 | } 33 | 34 | if (!validFeatures.includes(feature)) { 35 | return m.reply("❌ Fitur tidak dikenali. Gunakan `.set` untuk melihat daftar fitur."); 36 | } 37 | 38 | if (!validStatus.includes(status)) { 39 | return m.reply("❌ Status hanya bisa `on` atau `off`."); 40 | } 41 | 42 | const groupId = m.cht; 43 | const isEnabled = status === "on"; 44 | 45 | if (!db.list().group[groupId]) { 46 | db.list().group[groupId] = {}; 47 | } 48 | 49 | const featureKeys = { 50 | welcome: "welcomeGoodbye", 51 | promote: "promoteDemote", 52 | porn: "antiporn", 53 | badwords: "antibadwords", 54 | }; 55 | 56 | db.list().group[groupId][featureKeys[feature]] = isEnabled; 57 | await db.save(); 58 | 59 | const actionText = isEnabled ? "mengaktifkan" : "menonaktifkan"; 60 | const featureDesc = { 61 | welcome: isEnabled 62 | ? "Bot akan kirim pesan sambutan otomatis." 63 | : "Pesan sambutan dinonaktifkan.", 64 | promote: isEnabled 65 | ? "Bot akan memberi notifikasi saat admin berubah." 66 | : "Notifikasi promote/demote dimatikan.", 67 | porn: isEnabled 68 | ? "Bot akan menghapus konten NSFW secara otomatis." 69 | : "Filter konten dewasa dimatikan.", 70 | badwords: isEnabled 71 | ? "Bot akan menghapus pesan dengan kata kasar." 72 | : "Filter kata kasar dinonaktifkan.", 73 | }; 74 | 75 | return m.reply(`> ✅ *Berhasil ${actionText} fitur ${feature}*\n> ${featureDesc[feature]}`); 76 | }, 77 | }; -------------------------------------------------------------------------------- /scrapers/index.js: -------------------------------------------------------------------------------- 1 | const chokidar = require("chokidar"); 2 | const path = require("node:path"); 3 | const fs = require("node:fs"); 4 | const { promisify } = require("node:util"); 5 | const chalk = require("chalk"); 6 | const readdir = promisify(fs.readdir); 7 | const stat = promisify(fs.stat); 8 | 9 | const Scandir = async (dir) => { 10 | let subdirs = await readdir(path.resolve(dir)); 11 | let files = await Promise.all( 12 | subdirs.map(async (subdir) => { 13 | let res = path.resolve(path.resolve(dir), subdir); 14 | return (await stat(res)).isDirectory() ? Scandir(res) : res; 15 | }), 16 | ); 17 | return files.reduce((a, f) => a.concat(f), []); 18 | }; 19 | class Scraper { 20 | #src; 21 | constructor(dir) { 22 | this.dir = dir; 23 | this.#src = {}; 24 | } 25 | load = async () => { 26 | let data = await Scandir("./scrapers/source"); 27 | for (let i of data) { 28 | let name = i.split("/").pop().replace(".js", ""); 29 | try { 30 | if (!i.endsWith(".js")) return; 31 | this.#src[name] = require(i); 32 | } catch (e) { 33 | console.log(chalk.red.bold("- Gagal memuat Scraper :" + e)); 34 | delete this.#src[name]; 35 | } 36 | } 37 | return this.#src; 38 | }; 39 | watch = async () => { 40 | const watcher = chokidar.watch(path.resolve(this.dir), { 41 | persistent: true, 42 | ignoreInitial: true, 43 | }); 44 | watcher.on("add", async (filename) => { 45 | if (!filename.endsWith(".js")) return; 46 | let name = filename.split("/").pop().replace(".js", ""); 47 | if (require.cache[filename]) { 48 | delete require.cache[filename]; 49 | this.#src[name] = require(filename); 50 | return this.load(); 51 | } 52 | this.#src[name] = require(filename); 53 | console.log( 54 | chalk.cyan.bold("- Scraper Baru telah ditambahkan : " + name), 55 | ); 56 | return this.load(); 57 | }); 58 | watcher.on("change", (filename) => { 59 | if (!filename.endsWith(".js")) return; 60 | let name = filename.split("/").pop().replace(".js", ""); 61 | if (require.cache[filename]) { 62 | delete require.cache[filename]; 63 | this.#src[name] = require(filename); 64 | return this.load(); 65 | } 66 | console.log(chalk.cyan.bold("- Scraper telah diubah : " + name)); 67 | return this.load(); 68 | }); 69 | watcher.on("unlink", (filename) => { 70 | if (!filename.endsWith(".js")) return; 71 | let name = filename.split("/").pop().replace(".js", ""); 72 | delete this.#src[name]; 73 | console.log(chalk.cyan.bold("- Scraper telah dihapus : " + name)); 74 | return this.load(); 75 | }); 76 | }; 77 | list = () => this.#src; 78 | } 79 | 80 | module.exports = Scraper; 81 | -------------------------------------------------------------------------------- /system/plugins/tools/whatmusic.js: -------------------------------------------------------------------------------- 1 | class Command { 2 | constructor() { 3 | this.command = "whatmusic"; 4 | this.alias = []; 5 | this.category = ["tools"]; 6 | this.settings = { 7 | limit: true, 8 | }; 9 | this.description = 10 | "Cari judul lagu berdasarkan media audio yang kamu kirimkan!"; 11 | this.loading = true; 12 | } 13 | 14 | run = async (m, { Func }) => { 15 | let target = m.quoted ? m.quoted : m; 16 | if (!/audio/.test(target.msg.mimetype)) 17 | throw "⚠️ *Oops!* Harap balas pesan audio yang ingin dicari judul lagunya."; 18 | 19 | let buffer = await target.download(); 20 | let data = await whatmusic(buffer); 21 | 22 | if (!data || data.length === 0) 23 | throw "❌ *Maaf!* Tidak dapat menemukan informasi lagu dari audio tersebut."; 24 | 25 | let caption = `🎵 *What Music - Finder* 🎵\n\n`; 26 | for (let result of data) { 27 | caption += `🎶 *Judul:* ${result.title}\n`; 28 | caption += `🎤 *Artis:* ${result.artist}\n`; 29 | caption += `⏱️ *Durasi:* ${result.duration}\n`; 30 | caption += `🔗 *Sumber:* ${result.url.filter((x) => x).join("\n") || "Tidak ditemukan"}\n\n`; 31 | } 32 | 33 | caption += `💡 *Tips:* Kirim audio dengan kualitas yang jelas untuk hasil terbaik.`; 34 | m.reply(caption); 35 | }; 36 | } 37 | 38 | module.exports = new Command(); 39 | 40 | const acrcloud = require("acrcloud"); 41 | 42 | const acr = new acrcloud({ 43 | host: "identify-ap-southeast-1.acrcloud.com", 44 | access_key: "ee1b81b47cf98cd73a0072a761558ab1", 45 | access_secret: "ya9OPe8onFAnNkyf9xMTK8qRyMGmsghfuHrIMmUI", 46 | }); 47 | 48 | async function whatmusic(buffer) { 49 | let response = await acr.identify(buffer); 50 | let metadata = response.metadata; 51 | if (!metadata || !metadata.music) return []; 52 | 53 | return metadata.music.map((song) => ({ 54 | title: song.title, 55 | artist: song.artists.map((a) => a.name)[0], 56 | score: song.score, 57 | release: new Date(song.release_date).toLocaleDateString("id-ID"), 58 | duration: toTime(song.duration_ms), 59 | url: Object.keys(song.external_metadata) 60 | .map((key) => 61 | key === "youtube" 62 | ? "https://youtu.be/" + song.external_metadata[key].vid 63 | : key === "deezer" 64 | ? "https://www.deezer.com/us/track/" + 65 | song.external_metadata[key].track.id 66 | : key === "spotify" 67 | ? "https://open.spotify.com/track/" + 68 | song.external_metadata[key].track.id 69 | : "", 70 | ) 71 | .filter(Boolean), 72 | })); 73 | } 74 | 75 | function toTime(ms) { 76 | let minutes = Math.floor(ms / 60000) % 60; 77 | let seconds = Math.floor(ms / 1000) % 60; 78 | return [minutes, seconds].map((v) => v.toString().padStart(2, "0")).join(":"); 79 | } 80 | -------------------------------------------------------------------------------- /system/plugins/group/add.js: -------------------------------------------------------------------------------- 1 | const bail = require("baileys"); 2 | const { generateWAMessageFromContent, proto, toNumber } = bail; 3 | 4 | module.exports = { 5 | command: "add", 6 | alias: [], 7 | category: ["group"], 8 | settings: { 9 | group: true, 10 | admin: true, 11 | botAdmin: true, 12 | }, 13 | description: "Menambahkan anggota ke grup", 14 | async run(m, { sock, text, Func }) { 15 | const input = text ? text : m.quoted ? m.quoted.sender : m.mentions[0]; 16 | if (!input) { 17 | throw "❗ *Format Salah*\nKirim perintah ini dengan format:\n> Ketik nomor pengguna yang ingin ditambahkan\n> Atau reply pesan pengguna dengan perintah ini."; 18 | } 19 | 20 | const p = await sock.onWhatsApp(input.trim()); 21 | console.log(p); 22 | if (!p[0].exists) throw "⚠️ Pengguna tidak terdaftar di WhatsApp"; 23 | const jid = p[0].jid; 24 | const member = m.metadata.participants.find((u) => u.id === jid); 25 | if (member) { 26 | return m.reply("⚠️ Pengguna tersebut sudah menjadi anggota grup ini."); 27 | } 28 | 29 | const resp = await sock.groupParticipantsUpdate(m.cht, [jid], "add"); 30 | for (let res of resp) { 31 | if (res.status === 421) { 32 | m.reply( 33 | "⚠️ Tidak dapat menambahkan pengguna tersebut. Mereka telah membatasi undangan ke grup.", 34 | ); 35 | } else if (res.status === 408) { 36 | await m.reply( 37 | `✅ Undangan grup berhasil dikirim ke @${parseInt(res.jid)} karena pengguna baru saja keluar dari grup.`, 38 | ); 39 | await sock.sendMessage(res.jid, { 40 | text: 41 | "✨ Anda diundang kembali ke grup ini: https://chat.whatsapp.com/" + 42 | (await sock.groupInviteCode(m.cht)), 43 | }); 44 | } else if (res.status === 403) { 45 | await m.reply( 46 | `✅ Undangan grup berhasil dikirim ke @${parseInt(res.jid)}.`, 47 | ); 48 | const { code, expiration } = res.content.content[0].attrs; 49 | const pp = await sock.profilePictureUrl(m.cht).catch(() => null); 50 | const gp = await Func.fetchBuffer(pp); 51 | 52 | const msgs = generateWAMessageFromContent( 53 | res.jid, 54 | proto.Message.fromObject({ 55 | groupInviteMessage: { 56 | groupJid: m.cht, 57 | inviteCode: code, 58 | inviteExpiration: toNumber(expiration), 59 | groupName: m.metadata.subject, 60 | jpegThumbnail: gp || null, 61 | caption: `🌟 Hai @${res.jid.split("@")[0]}!\nAnda telah diundang oleh salah satu admin grup *${m.metadata.subject}*. Klik tombol di bawah untuk bergabung kembali!`, 62 | }, 63 | }), 64 | { userJid: sock.user.jid }, 65 | ); 66 | 67 | await sock.copyNForward(jid, msgs); 68 | } 69 | } 70 | }, 71 | }; 72 | -------------------------------------------------------------------------------- /scrapers/source/rednote.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const cheerio = require("cheerio"); 3 | const json = require("jsonc-parser"); 4 | const { randomBytes } = require("crypto"); 5 | 6 | function getRandomIp() { 7 | const ip = []; 8 | for (let i = 0; i < 4; i++) { 9 | ip.push(Math.floor(Math.random() * 256)); 10 | } 11 | return ip.join("."); 12 | } 13 | 14 | async function rednote(url) { 15 | const randomIp = getRandomIp(); 16 | let response = await axios.get(url, { 17 | headers: { 18 | "User-Agent": require("fake-useragent")(), 19 | Accept: 20 | "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 21 | "Accept-Language": "en-US,en;q=0.9", 22 | "Accept-Encoding": "gzip, deflate, br", 23 | Connection: "keep-alive", 24 | "Upgrade-Insecure-Requests": "1", 25 | "Sec-Fetch-Dest": "document", 26 | "Sec-Fetch-Mode": "navigate", 27 | "Sec-Fetch-Site": "none", 28 | "Sec-Fetch-User": "?1", 29 | "Cache-Control": "max-age=0", 30 | TE: "trailers", 31 | }, 32 | timeout: 30000, 33 | responseType: "document", 34 | }); 35 | let html = response.data; 36 | let $ = cheerio.load(html); 37 | let jsonString; 38 | try { 39 | jsonString = $("script") 40 | .last() 41 | .text() 42 | .split("window.__INITIAL_STATE__=")[1] 43 | .replace("\\/", "/"); 44 | } catch (error) { 45 | console.error("Error parsing JSON:", error); 46 | return null; 47 | } 48 | 49 | let data; 50 | try { 51 | data = json.parse(removeUnicode(jsonString)); 52 | } catch (error) { 53 | console.error("Error parsing JSON:", error, jsonString); 54 | return null; 55 | } 56 | 57 | let id = data.note.firstNoteId 58 | ? data.note.firstNoteId 59 | : data.note.currentNoteId; 60 | 61 | let meta = data.note.noteDetailMap[id]?.note; 62 | let result = { 63 | metadata: { 64 | title: meta.title, 65 | category: meta.tagList?.map((a) => a.name), 66 | stats: meta.interactInfo, 67 | author: meta.user, 68 | }, 69 | download: {}, 70 | }; 71 | 72 | if (meta.video) { 73 | result.download = meta.video.media.stream["h264"][0].masterUrl; 74 | } else if (meta.imageList) { 75 | result.download = meta.imageList.map((a) => a.urlDefault); 76 | } else { 77 | result.download = []; 78 | } 79 | return result; 80 | } 81 | 82 | function removeUnicode(jsonString) { 83 | return jsonString 84 | .replace(/\\u/g, "") 85 | .replace(/\\n/g, "\n") 86 | .replace(/002F/g, "/") 87 | .replace(/undefined/g, "null") 88 | .replace(/\\r/g, "\r") 89 | .replace(/\\t/g, "\t") 90 | .replace(/\\f/g, "\f") 91 | .replace(/\\b/g, "\b") 92 | .replace(/\\\\/g, "\\") 93 | .replace(/\\'/g, "'") 94 | .replace(/\\"/g, '"'); 95 | } 96 | 97 | module.exports = rednote; 98 | -------------------------------------------------------------------------------- /utils/msg.js: -------------------------------------------------------------------------------- 1 | function generateInstruction(actions, mediaTypes) { 2 | if (!actions || !actions.length) 3 | return "'actions' yang diperlukan harus ditentukan!"; 4 | 5 | let translatedMediaTypes; 6 | if (typeof mediaTypes === "string") { 7 | translatedMediaTypes = [mediaTypes]; 8 | } else if (Array.isArray(mediaTypes)) { 9 | translatedMediaTypes = mediaTypes; 10 | } else { 11 | return "'mediaTypes' harus berupa string atau array string!"; 12 | } 13 | 14 | const mediaTypeTranslations = { 15 | audio: "audio", 16 | contact: "kontak", 17 | document: "dokumen", 18 | gif: "GIF", 19 | image: "gambar", 20 | liveLocation: "lokasi langsung", 21 | location: "lokasi", 22 | payment: "pembayaran", 23 | poll: "polling", 24 | product: "produk", 25 | ptt: "pesan suara", 26 | reaction: "reaksi", 27 | sticker: "stiker", 28 | templateMessage: "pesan template", 29 | text: "teks", 30 | video: "video", 31 | viewOnce: "sekali lihat", 32 | }; 33 | 34 | const translatedMediaTypeList = translatedMediaTypes.map( 35 | (type) => mediaTypeTranslations[type], 36 | ); 37 | 38 | let mediaTypesList; 39 | if (translatedMediaTypeList.length > 1) { 40 | const lastMediaType = 41 | translatedMediaTypeList[translatedMediaTypeList.length - 1]; 42 | mediaTypesList = 43 | translatedMediaTypeList.slice(0, -1).join(", ") + 44 | `, atau ${lastMediaType}`; 45 | } else { 46 | mediaTypesList = translatedMediaTypeList[0]; 47 | } 48 | 49 | const actionTranslations = { 50 | send: "Kirim", 51 | reply: "Balas", 52 | }; 53 | 54 | const instructions = actions.map((action) => `${actionTranslations[action]}`); 55 | const actionList = instructions.join(actions.length > 1 ? " atau " : ""); 56 | 57 | return `> ‼️ ${actionList} ${mediaTypesList}!`; 58 | } 59 | 60 | function generateCommandExample(prefix, command, args) { 61 | if (!prefix) return "'prefix' harus diberikan!"; 62 | if (!command) return "'command' harus diberikan!"; 63 | if (!args) return "'args' harus diberikan!"; 64 | 65 | const commandMessage = `> Contoh: \`\`\`${prefix + command} ${args}\`\`\``; 66 | return commandMessage; 67 | } 68 | 69 | function generatesFlagInformation(flags) { 70 | if (typeof flags !== "object" || !flags) return "'flags' harus berupa objek!"; 71 | 72 | const flagInfo = 73 | "Flag:\n" + 74 | Object.entries(flags) 75 | .map(([flag, description]) => `> • \`\`\`${flag}\`\`\`: ${description}`) 76 | .join("\n"); 77 | 78 | return flagInfo; 79 | } 80 | 81 | function generateNotes(notes) { 82 | if (!Array.isArray(notes)) return "'notes' harus berupa string!"; 83 | 84 | const notesInfo = 85 | "Catatan:\n" + notes.map((note) => `> • ${note}`).join("\n"); 86 | 87 | return notesInfo; 88 | } 89 | 90 | module.exports = { 91 | generateInstruction, 92 | generateCommandExample, 93 | generatesFlagInformation, 94 | generateNotes, 95 | }; 96 | -------------------------------------------------------------------------------- /scrapers/source/kuronime.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const cheerio = require("cheerio"); 3 | 4 | class Kuronime { 5 | constructor() { 6 | this.baseURL = "https://kuronime.biz"; 7 | } 8 | latest = async function latest() { 9 | return new Promise(async (resolve, reject) => { 10 | await axios.get("https://kuronime.biz").then((a) => { 11 | let $ = cheerio.load(a.data); 12 | let array = []; 13 | $(".listupd .bsu").each((a, i) => { 14 | array.push({ 15 | title: $(i).find(".bsux a").attr("title"), 16 | url: $(i).find(".bsux a").attr("href"), 17 | views: $(i).find(".limit .view .post-views-count").text(), 18 | release: $(i).find(".bt .time").text().trim() + " yang lalu", 19 | thumbnail: $(i) 20 | .find(".limit .lazyload") 21 | .eq(1) 22 | .attr("data-src") 23 | .split("?")[0], 24 | }); 25 | }); 26 | resolve(array); 27 | }); 28 | }); 29 | }; 30 | search = async function search(q) { 31 | return new Promise(async (resolve, reject) => { 32 | await axios.get("https://kuronime.biz?s=" + q).then((a) => { 33 | let $ = cheerio.load(a.data); 34 | let array = []; 35 | $(".listupd .bs").each((a, i) => { 36 | array.push({ 37 | title: $(i).find(".bsx a").attr("title"), 38 | url: $(i).find(".bsx a").attr("href"), 39 | type: $(i).find(".limit .bt .type").text(), 40 | score: $(i).find(".rating i").text(), 41 | thumbnail: $(i) 42 | .find(".limit .lazyload") 43 | .eq(1) 44 | .attr("data-src") 45 | .split("?")[0], 46 | }); 47 | }); 48 | resolve(array); 49 | }); 50 | }); 51 | }; 52 | detail = async function detail(url) { 53 | return new Promise(async (resolve, reject) => { 54 | await axios.get(url).then((a) => { 55 | let $ = cheerio.load(a.data); 56 | let array = { 57 | metadata: {}, 58 | episode: [], 59 | }; 60 | $(".infodetail ul li").each((a, i) => { 61 | let name = $(i).find("b").text(); 62 | let key = $(i) 63 | .text() 64 | .replace(name + ":", "") 65 | .split("?resize=")[0] 66 | .trim(); 67 | array.metadata[name.split(" ").join("_").toLowerCase()] = key; 68 | }); 69 | array.metadata.thumbnail = $(".con .lazyload").attr("data-src"); 70 | array.metadata.synopis = $(".con .const p").text().trim(); 71 | $(".bxcl ul li").each((a, i) => { 72 | array.episode.push({ 73 | title: $(i).find(".lchx a").text(), 74 | url: $(i).find(".lchx a").attr("href"), 75 | }); 76 | }); 77 | resolve(array); 78 | }); 79 | }); 80 | }; 81 | } 82 | 83 | module.exports = new Kuronime(); 84 | -------------------------------------------------------------------------------- /scrapers/source/terabox.js: -------------------------------------------------------------------------------- 1 | const { fetch } = require("node-fetch"); 2 | 3 | class TeraboxHnn { 4 | getInfo = async (inputUrl) => { 5 | try { 6 | const url = `https://terabox.hnn.workers.dev/api/get-info?shorturl=${inputUrl.split("/").pop()}&pwd=`; 7 | const headers = { 8 | "User-Agent": 9 | "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36", 10 | Referer: "https://terabox.hnn.workers.dev/", 11 | }; 12 | const response = await fetch(url, { 13 | headers: headers, 14 | }); 15 | if (!response.ok) { 16 | throw new Error( 17 | `Gagal mengambil informasi file: ${response.status} ${response.statusText}`, 18 | ); 19 | } 20 | return await response.json(); 21 | } catch (error) { 22 | console.error("Gagal mengambil informasi file:", error); 23 | throw error; 24 | } 25 | }; 26 | getDownloadLink = async (fsId, shareid, uk, sign, timestamp) => { 27 | try { 28 | const url = "https://terabox.hnn.workers.dev/api/get-download"; 29 | const headers = { 30 | "Content-Type": "application/json", 31 | "User-Agent": 32 | "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36", 33 | Referer: "https://terabox.hnn.workers.dev/", 34 | }; 35 | const data = { 36 | shareid: shareid, 37 | uk: uk, 38 | sign: sign, 39 | timestamp: timestamp, 40 | fs_id: fsId, 41 | }; 42 | const response = await fetch(url, { 43 | method: "POST", 44 | headers: headers, 45 | body: JSON.stringify(data), 46 | }); 47 | if (!response.ok) { 48 | throw new Error( 49 | `Gagal mengambil link download: ${response.status} ${response.statusText}`, 50 | ); 51 | } 52 | return await response.json(); 53 | } catch (error) { 54 | console.error("Gagal mengambil link download:", error); 55 | throw error; 56 | } 57 | }; 58 | download = async (inputUrl) => { 59 | try { 60 | const { list, shareid, uk, sign, timestamp } = 61 | await this.getInfo(inputUrl); 62 | if (!list) { 63 | throw new Error(`File tidak ditemukan`); 64 | } 65 | let array = []; 66 | for (let i = 0; i < list.length; i++) { 67 | const fsId = list[i].fs_id; 68 | const { downloadLink } = await this.getDownloadLink( 69 | fsId, 70 | shareid, 71 | uk, 72 | sign, 73 | timestamp, 74 | ); 75 | array.push({ 76 | filename: list[i].filename, 77 | size: list[i].size, 78 | download: downloadLink, 79 | }); 80 | } 81 | return array; 82 | } catch (error) { 83 | console.error("Gagal mengunduh file:", error); 84 | throw error; 85 | } 86 | }; 87 | } 88 | module.exports = new TeraboxHnn(); 89 | -------------------------------------------------------------------------------- /system/plugins/tools/get.js: -------------------------------------------------------------------------------- 1 | const { fetch } = require("node-fetch"); 2 | const { html } = require("js-beautify"); 3 | const { extension } = require("mime-types"); 4 | 5 | module.exports = { 6 | command: "get", 7 | alias: ["fetch"], 8 | category: ["tools"], 9 | description: "🔍 Mendapatkan data dari URL yang diberikan", 10 | loading: true, 11 | async run(m, { sock, Func, text, config }) { 12 | if (!text) 13 | throw "> ❌ Masukan atau reply URL yang ingin kamu ambil datanya"; 14 | 15 | const urls = isUrl(text); 16 | if (!urls) 17 | throw "> ❌ Format URL tidak valid, pastikan URL yang dimasukkan benar"; 18 | 19 | for (const url of urls) { 20 | try { 21 | const response = await fetch(url); 22 | if (!response.ok) { 23 | throw new Error(`HTTP error! status: ${response.status}`); 24 | } 25 | 26 | const mime = response.headers.get("content-type").split(";")[0]; 27 | const cap = `*– 乂 Fetch - Url*\n> *- Request :* ${url}`; 28 | let body; 29 | 30 | if (/\html/gi.test(mime)) { 31 | body = await response.text(); 32 | await sock.sendMessage( 33 | m.cht, 34 | { 35 | document: Buffer.from(html(body)), 36 | caption: cap, 37 | fileName: "result.html", 38 | mimetype: mime, 39 | }, 40 | { quoted: m }, 41 | ); 42 | } else if (/\json/gi.test(mime)) { 43 | body = await response.json(); 44 | m.reply(JSON.stringify(body, null, 2)); 45 | } else if (/image/gi.test(mime)) { 46 | body = await response.arrayBuffer(); 47 | sock.sendFile( 48 | m.cht, 49 | Buffer.from(body), 50 | `result.${extension(mime)}`, 51 | cap, 52 | m, 53 | ); 54 | } else if (/video/gi.test(mime)) { 55 | body = await response.arrayBuffer(); 56 | sock.sendFile( 57 | m.cht, 58 | Buffer.from(body), 59 | `result.${extension(mime)}`, 60 | cap, 61 | m, 62 | ); 63 | } else if (/audio/gi.test(mime)) { 64 | body = await response.arrayBuffer(); 65 | sock.sendFile( 66 | m.cht, 67 | Buffer.from(body), 68 | `result.${extension(mime)}`, 69 | cap, 70 | m, 71 | { mimetype: mime }, 72 | ); 73 | } else { 74 | body = await response.text(); 75 | m.reply(Func.jsonFormat(body)); 76 | } 77 | } catch (error) { 78 | console.error("Error fetching URL:", error); 79 | m.reply(`> ❌ Terjadi kesalahan saat mengambil URL: ${error.message}`); 80 | } 81 | } 82 | }, 83 | }; 84 | 85 | function isUrl(string) { 86 | let urlRegex = 87 | /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/g; 88 | let result = string.match(urlRegex); 89 | return result; 90 | } 91 | -------------------------------------------------------------------------------- /scrapers/source/doodstream.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const cheerio = require("cheerio"); 3 | 4 | async function fetchData(url) { 5 | const id = url.match(/\/[de]\/(\w+)/)?.[1]; 6 | if (!id) { 7 | return { 8 | success: false, 9 | message: "Link nya gak bisa diproses bree, ganti link yang baru aja ", 10 | }; 11 | } 12 | const proxy = "https://rv.lil-hacker.workers.dev/proxy?mirror=dood&url="; 13 | const headers = { 14 | Accept: "*/*", 15 | Referer: "https://d000d.com/", 16 | "User-Agent": "Postify/1.0.0", 17 | "X-Requested-With": "XMLHttpRequest", 18 | "X-CSRF-Token": 19 | "eyJpdiI6Ik9vdlA2Zjk2NUhZNGZFY296TzBJUFE9PSIsInZhbHVlIjoiNDdjbTJCNGVSallwWE5Oc1hoZ3NDVGIxWWFMOFl6ejFjOXVUZlZ2K1B5OFZ1ZWVpajZ6aDZZOUJkUVF5NFlFbiIsIm1hYyI6IjRkMzlkNmY5NzQ0OGI4YWUzMmJmNGM0ZjE2ZWFkMzJjYzlkMjg1MjU0Y2VkZDZiZmNjMWNhZjIwYjU1MDgifQ==", 20 | "X-Forwarded-For": "127.0.0.1", 21 | "X-Real-IP": "127.0.0.1", 22 | Authorization: 23 | "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IlVzZXIiLCJpYXQiOjE1MTYyMzkwMjJ9.-H1t8kmZHtNIDaZb3_Mrjk9uqgHbsFAdXIRoV2rWr9g", 24 | }; 25 | await new Promise((resolve) => setTimeout(resolve, 14000)); 26 | const { data } = await axios.get(`https://dood.li/d/${id}`, { 27 | headers, 28 | }); 29 | const $ = cheerio.load(data); 30 | if (!$("#os_player iframe").length) return {}; 31 | 32 | const result = { 33 | title: $(".title-wrap h4").text().trim(), 34 | duration: $(".length").text().trim(), 35 | size: $(".size").text().trim(), 36 | uploadDate: $(".uploadate").text().trim(), 37 | }; 38 | 39 | const { data: dp } = await axios.get(`${proxy}https://d000d.com/e/${id}`, { 40 | headers, 41 | }); 42 | const cdn = dp.match(/\$.get\('([^']+)',/)?.[1]; 43 | if (!cdn) { 44 | return { 45 | success: false, 46 | message: "Link Pass MD5 gak ada! coba lagi aja nanti ...", 47 | }; 48 | } 49 | const chars = Array.from(crypto.getRandomValues(new Uint8Array(10))) 50 | .map((x) => 51 | String.fromCharCode( 52 | (x % 62) + (x % 62 < 26 ? 65 : x % 62 < 52 ? 97 : 48), 53 | ), 54 | ) 55 | .join(""); 56 | const ds = await axios.get(`${proxy}https://d000d.com${cdn}`, { 57 | headers, 58 | }); 59 | const cm = cdn.match(/\/([^/]+)$/)?.[1]; 60 | result.download = `${proxy}${ds.data}${chars}?token=${cm}&expiry=${Date.now()}`; 61 | 62 | const dlink = $(".download-content a").attr("href"); 63 | if (dlink) { 64 | const dp = cheerio.load( 65 | (await axios.get(`https://dood.li/d/${dlink}`)).data, 66 | ); 67 | result.download = await shortlink( 68 | dp("a.btn.btn-primary.d-flex").attr("href") || 69 | dp("div.col-md-12 a.btn.btn-primary").attr("href") || 70 | result.download, 71 | ); 72 | } 73 | return result; 74 | } 75 | async function shortlink(url) { 76 | return axios 77 | .post("https://cleanuri.com/api/v1/shorten", { 78 | url, 79 | }) 80 | .then((a) => a.data.result_url); 81 | } 82 | module.exports = fetchData; 83 | -------------------------------------------------------------------------------- /system/plugins/game/wuthering-waves.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | 3 | module.exports = { 4 | command: "wuwa", 5 | alias: ["wuthering"], 6 | category: ["anime", "game"], 7 | description: "Cek karakter Wuthering Waves", 8 | settings: { 9 | loading: true, 10 | }, 11 | async run(m, { text, sock }) { 12 | let charactersList = [ 13 | "Aalto", 14 | "Baizhi", 15 | "Calcharo", 16 | "Changli", 17 | "Chixia", 18 | "Danjin", 19 | "Encore", 20 | "Jianxin", 21 | "Jinhsi", 22 | "Jiyan", 23 | "Lingyang", 24 | "Mortefi", 25 | "Rover", 26 | "Sanhua", 27 | "Shorekeeper", 28 | "Taoqi", 29 | "Verina", 30 | "Xiangli Yao", 31 | "Yangyang", 32 | "Yinlin", 33 | "Youhu", 34 | "Yuanwu", 35 | "Zhezhi", 36 | ]; 37 | 38 | let capital = (txt) => 39 | txt.charAt(0).toUpperCase() + txt.slice(1).toLowerCase(); 40 | 41 | if (!text) { 42 | throw `*• Contoh Penggunaan:* .wuthering [nama karakter]\n\n*List karakter yang tersedia:*\n${charactersList.map((a) => `• ${a}`).join("\n")}`; 43 | } 44 | 45 | if (!charactersList.includes(capital(text))) { 46 | throw `*• Karakter tidak ditemukan!*\nGunakan salah satu dari daftar berikut:\n${charactersList.map((a) => `• ${a}`).join("\n")}`; 47 | } 48 | 49 | try { 50 | let { data: characters } = await axios.get( 51 | `https://api.resonance.rest/characters/${capital(text)}`, 52 | ); 53 | 54 | let weaponType = characters.weapon.replace(/\s+/g, "%20"); 55 | let { data: weaponData } = await axios.get( 56 | `https://api.resonance.rest/weapons/${weaponType}`, 57 | ); 58 | 59 | let weaponList = await Promise.all( 60 | weaponData.weapons.map(async (weaponName) => { 61 | let { data: weaponDetails } = await axios.get( 62 | `https://api.resonance.rest/weapons/${weaponType}/${encodeURIComponent(weaponName)}`, 63 | ); 64 | return `• Name: ${weaponDetails.name}\n • Type: ${weaponDetails.type}\n • Rarity: ${weaponDetails.rarity}`; 65 | }), 66 | ); 67 | 68 | let caption = 69 | `*[ WUTHERING - CHARACTERS ]*\n\n` + 70 | `• *Name:* ${characters.name}\n` + 71 | `• *Quote:* ${characters.quote}\n` + 72 | `• *Attributes:* ${characters.attribute}\n` + 73 | `• *Weapons:* ${characters.weapon}\n` + 74 | `• *Rarity:* ${characters.rarity}\n` + 75 | `• *Class:* ${characters.class}\n` + 76 | `• *Birth Place:* ${characters.birthplace}\n` + 77 | `• *Birthday:* ${characters.birthday}\n\n` + 78 | `*[ ${characters.weapon.toUpperCase()} - INFO ]*\n\n` + 79 | `${weaponList.join("\n\n")}`; 80 | 81 | m.reply({ 82 | image: { 83 | url: `https://api.resonance.rest/characters/${capital(text)}/portrait`, 84 | }, 85 | caption: caption, 86 | }); 87 | } catch (error) { 88 | console.error(error); 89 | m.reply("❌ *Terjadi kesalahan saat mengambil data!*"); 90 | } 91 | }, 92 | }; 93 | -------------------------------------------------------------------------------- /system/plugins/rpg/bansos.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "bansos", 3 | alias: ["bantuan", "assistance"], 4 | category: ["rpg"], 5 | settings: { 6 | owner: false, 7 | }, 8 | async run(m, { sock, Func, config }) { 9 | const user = db.list().user[m.sender]; 10 | if (!user || !user.register) { 11 | return m.reply(config.messages.unregistered); 12 | } 13 | let time = new Date().getTime(); 14 | let cooldown = 86400000; // 24 jam 15 | let lastBansos = user.lastbansos || 0; 16 | 17 | if (time - lastBansos < cooldown) { 18 | let remaining = cooldown - (time - lastBansos); 19 | let hours = Math.floor(remaining / 3600000); 20 | let minutes = Math.floor((remaining % 3600000) / 60000); 21 | 22 | return m.reply( 23 | ` 24 | ╔══════════════════════ 25 | ║ 🕐 *COOLDOWN BANSOS* 26 | ╠══════════════════════ 27 | ║ ⏰ Tunggu *${hours} jam ${minutes} menit* 28 | ║ 📝 Sebelum mengambil bansos lagi 29 | ╚══════════════════════`.trim(), 30 | ); 31 | } 32 | const isPremium = user.premium.status || false; 33 | const chance = Math.random() * 100; 34 | 35 | const successChance = isPremium ? 75 : 25; 36 | 37 | if (chance > successChance) { 38 | let gagalText = ` 39 | ╔═══════════════════════ 40 | ║ 📢 *BANSOS GAGAL* 41 | ╠═══════════════════════ 42 | ║ 😔 Anda gagal mendapatkan bansos 43 | ║ ${isPremium ? "👑 Coba lagi besok!" : "⭐ Tingkatkan ke Premium\n║ untuk peluang lebih besar!"} 44 | ╚═══════════════════════`; 45 | return m.reply({ 46 | image: { 47 | url: "https://telegra.ph/file/afcf9a7f4e713591080b5.jpg", 48 | }, 49 | caption: gagalText, 50 | }); 51 | let moneyReward, coinReward; 52 | 53 | if (isPremium) { 54 | moneyReward = 55 | Math.floor(Math.random() * (5000000 - 3000000 + 1)) + 3000000; 56 | coinReward = Math.floor(Math.random() * (100 - 50 + 1)) + 50; 57 | } else { 58 | moneyReward = 59 | Math.floor(Math.random() * (2000000 - 1000000 + 1)) + 1000000; 60 | coinReward = Math.floor(Math.random() * (50 - 30 + 1)) + 30; 61 | } 62 | 63 | user.money = (user.money || 0) + moneyReward; 64 | user.coin = (user.coin || 0) + coinReward; 65 | user.lastbansos = time; 66 | 67 | const rewardText = ` 68 | ╔════════════════════════ 69 | ║ 🎊 *BANSOS BERHASIL* 🎊 70 | ╠════════════════════════ 71 | ║ 👤 *Status:* ${isPremium ? "👑 Premium" : "⭐ Regular"} 72 | ║ 73 | ║ 💰 *Reward Money:* 74 | ║ └─ Rp ${Func.h2k(moneyReward)} 75 | ║ 76 | ║ 🪙 *Reward Coin:* 77 | ║ └─ ${Func.h2k(coinReward)} coins 78 | ║ 79 | ║ 📊 *Total Sekarang:* 80 | ║ ├─ 💵 Rp ${Func.h2k(user.money)} 81 | ║ └─ 🪙 ${Func.h2k(user.coin)} coins 82 | ║ 83 | ║ ${isPremium ? "👑 Bonus Premium!" : "⭐ Upgrade ke Premium\n║ untuk reward lebih besar!"} 84 | ╠════════════════════════ 85 | ║ ⏰ Kembali lagi dalam 24 jam! 86 | ╚════════════════════════`.trim(); 87 | 88 | return m.reply({ 89 | image: { 90 | url: "https://telegra.ph/file/d31fcc46b09ce7bf236a7.jpg", 91 | }, 92 | caption: rewardText, 93 | }); 94 | } 95 | }, 96 | }; 97 | -------------------------------------------------------------------------------- /scrapers/source/snackvideo.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const cheerio = require("cheerio"); 3 | 4 | class SnackVideo { 5 | search = async function search(q) { 6 | return new Promise(async (resolve, reject) => { 7 | await axios 8 | .get("https://www.snackvideo.com/discover/" + q) 9 | .then((a) => { 10 | let $ = cheerio.load(a.data); 11 | let content = $("#ItemList").text().trim(); 12 | if (!content) 13 | return reject({ 14 | msg: "Video tidak ditemukan !", 15 | }); 16 | let json = JSON.parse(content); 17 | let result = json 18 | .map((a) => a.innerHTML) 19 | .map((a) => ({ 20 | title: a.name, 21 | thumbnail: a.thumbnailUrl[0], 22 | uploaded: new Date(a.uploadDate).toLocaleString(), 23 | stats: { 24 | watch: a.interactionStatistic[0].userInteractionCount, 25 | likes: a.interactionStatistic[1].userInteractionCount, 26 | comment: a.commentCount, 27 | share: a.interactionStatistic[2].userInteractionCount, 28 | }, 29 | author: { 30 | name: a.creator.mainEntity.name, 31 | alt_name: a.creator.mainEntity.alternateName, 32 | bio: a.creator.mainEntity.description, 33 | avatar: a.creator.mainEntity.image, 34 | stats: { 35 | likes: 36 | a.creator.mainEntity.interactionStatistic[0] 37 | .userInteractionCount, 38 | followers: 39 | a.creator.mainEntity.interactionStatistic[1] 40 | .userInteractionCount, 41 | }, 42 | }, 43 | url: a.url, 44 | })); 45 | resolve(result); 46 | }) 47 | .catch((error) => { 48 | reject({ 49 | msg: error.message, 50 | }); 51 | }); 52 | }); 53 | }; 54 | download = async function download(url) { 55 | return new Promise(async (resolve, reject) => { 56 | await axios.get(url).then((a) => { 57 | let $ = cheerio.load(a.data); 58 | let result = { 59 | metadata: {}, 60 | download: null, 61 | }; 62 | let json = JSON.parse($("#VideoObject").text().trim()); 63 | result.metadata.title = json.name; 64 | result.metadata.thumbnail = json.thumbnailUrl[0]; 65 | result.metadata.uploaded = new Date(json.uploadDate).toLocaleString(); 66 | result.metadata.comment = json.commentCount; 67 | result.metadata.watch = 68 | json.interactionStatistic[0].userInteractionCount; 69 | result.metadata.likes = 70 | json.interactionStatistic[1].userInteractionCount; 71 | result.metadata.share = 72 | json.interactionStatistic[2].userInteractionCount; 73 | result.metadata.author = json.creator.mainEntity.name; 74 | result.download = json.contentUrl; 75 | resolve(result); 76 | }); 77 | }); 78 | }; 79 | } 80 | 81 | module.exports = new SnackVideo(); 82 | -------------------------------------------------------------------------------- /utils/fetcher.js: -------------------------------------------------------------------------------- 1 | const fetch = require("node-fetch"); 2 | const FormData = require("form-data"); 3 | const fs = require("fs"); 4 | const { fromBuffer } = require("file-type"); 5 | const resizeImage = require("./imageProcessing"); 6 | 7 | /** 8 | *Fetch Json from Url 9 | * 10 | *@param {String} url 11 | *@param {Object} options 12 | */ 13 | 14 | const fetchJson = (url, options) => 15 | new Promise((resolve, reject) => 16 | fetch(url, options) 17 | .then((response) => response.json()) 18 | .then((json) => resolve(json)) 19 | .catch((err) => { 20 | console.error(err); 21 | reject(err); 22 | }), 23 | ); 24 | 25 | /** 26 | * Fetch Text from Url 27 | * 28 | * @param {String} url 29 | * @param {Object} options 30 | */ 31 | 32 | const fetchText = (url, options) => { 33 | return new Promise((resolve, reject) => { 34 | return fetch(url, options) 35 | .then((response) => response.text()) 36 | .then((text) => resolve(text)) 37 | .catch((err) => { 38 | console.error(err); 39 | reject(err); 40 | }); 41 | }); 42 | }; 43 | 44 | /** 45 | * Fetch base64 from url 46 | * @param {String} url 47 | */ 48 | 49 | const fetchBase64 = (url, mimetype) => { 50 | return new Promise((resolve, reject) => { 51 | console.log("Get base64 from:", url); 52 | return fetch(url) 53 | .then((res) => { 54 | const _mimetype = mimetype || res.headers.get("content-type"); 55 | res 56 | .buffer() 57 | .then((result) => 58 | resolve(`data:${_mimetype};base64,` + result.toString("base64")), 59 | ); 60 | }) 61 | .catch((err) => { 62 | console.error(err); 63 | reject(err); 64 | }); 65 | }); 66 | }; 67 | 68 | /** 69 | * Upload Image to Telegra.ph 70 | * 71 | * @param {String} base64 image buffer 72 | * @param {Boolean} resize 73 | */ 74 | 75 | const uploadImages = (buffData, type) => { 76 | // eslint-disable-next-line no-async-promise-executor 77 | return new Promise(async (resolve, reject) => { 78 | const { ext } = await fromBuffer(buffData); 79 | const filePath = "utils/tmp." + ext; 80 | const _buffData = type ? await resizeImage(buffData, false) : buffData; 81 | fs.writeFile(filePath, _buffData, { encoding: "base64" }, (err) => { 82 | if (err) return reject(err); 83 | console.log("Uploading image to telegra.ph server..."); 84 | const fileData = fs.readFileSync(filePath); 85 | const form = new FormData(); 86 | form.append("file", fileData, "tmp." + ext); 87 | fetch("https://telegra.ph/upload", { 88 | method: "POST", 89 | body: form, 90 | }) 91 | .then((res) => res.json()) 92 | .then((res) => { 93 | if (res.error) return reject(res.error); 94 | resolve("https://telegra.ph" + res[0].src); 95 | }) 96 | .then(() => fs.unlinkSync(filePath)) 97 | .catch((err) => reject(err)); 98 | }); 99 | }); 100 | }; 101 | 102 | module.exports = { 103 | fetchJson, 104 | fetchText, 105 | fetchBase64, 106 | uploadImages, 107 | }; 108 | -------------------------------------------------------------------------------- /system/plugins/owner/scrape.js: -------------------------------------------------------------------------------- 1 | const fs = require("node:fs"); 2 | const beauty = require("js-beautify"); 3 | 4 | module.exports = { 5 | command: "scrape", 6 | alias: ["skrep", "scraper"], 7 | category: ["owner"], 8 | settings: { 9 | owner: true, 10 | }, 11 | description: "⚙️ *Pengelolaan Scraper Bot* 📈", 12 | async run(m, { sock, Func, text, config }) { 13 | let src = await scraper.list(); 14 | 15 | if (!text) 16 | throw `> *- 乂 Cara Penggunaan Scraper Bot*\n\n> 📝 *\`--get\`* - Untuk mengambil scraper yang ada\n> ➕ *\`--add\`* - Untuk menambahkan scraper baru\n> ❌ *\`--delete\`* - Untuk menghapus scraper yang ada\n\n> *- 乂 Daftar Scrapers yang tersedia :*\n${Object.keys( 17 | src, 18 | ) 19 | .map((a, i) => `> *${i + 1}.* ${a}`) 20 | .join("\n")}`; 21 | 22 | if (text.includes("--get")) { 23 | let input = text.replace("--get", "").trim(); 24 | if (!isNaN(input)) { 25 | let list = Object.keys(src); 26 | try { 27 | let file = scraper.dir + "/" + list[parseInt(input) - 1] + ".js"; 28 | m.reply(fs.readFileSync(file.trim()).toString()); 29 | } catch (e) { 30 | m.reply( 31 | `> ⚠️ *Scrape* ${list[parseInt(input) - 1]} *tidak ditemukan*, pastikan cek kembali list Scrape yang kamu simpan!`, 32 | ); 33 | } 34 | } else { 35 | try { 36 | let file = scraper.dir + "/" + input + ".js"; 37 | m.reply(fs.readFileSync(file.trim()).toString()); 38 | } catch (e) { 39 | m.reply( 40 | `> ⚠️ *Scrape* ${input} *tidak ditemukan*, pastikan cek kembali list Scrape yang kamu simpan!`, 41 | ); 42 | } 43 | } 44 | } else if (m.text.includes("--add")) { 45 | if (!m.quoted) 46 | throw "> 📩 *Balas pesan yang berisi scraper yang ingin disimpan*"; 47 | let input = m.text.replace("--add", "").trim(); 48 | try { 49 | let file = scraper.dir + "/" + input + ".js"; 50 | fs.writeFileSync(file.trim(), await beauty(m.quoted.body)); 51 | m.reply("> ✅ *Berhasil menyimpan scraper:* " + input); 52 | } catch (e) { 53 | m.reply(`> ❌ *Gagal menyimpan scraper*, coba lagi.`); 54 | } 55 | } else if (text.includes("--delete")) { 56 | let input = text.replace("--delete", "").trim(); 57 | if (!isNaN(input)) { 58 | let list = Object.keys(src); 59 | try { 60 | let file = scraper.dir + "/" + list[parseInt(input) - 1] + ".js"; 61 | fs.unlinkSync(file.trim()); 62 | m.reply("> 🗑️ *Scraper berhasil dihapus*."); 63 | } catch (e) { 64 | m.reply( 65 | `> ⚠️ *Scrape* ${list[parseInt(input) - 1]} *tidak ditemukan*, pastikan cek kembali list Scrape yang kamu simpan!`, 66 | ); 67 | } 68 | } else { 69 | try { 70 | let file = scraper.dir + "/" + input + ".js"; 71 | fs.unlinkSync(file.trim()); 72 | m.reply("> 🗑️ *Scraper berhasil dihapus*."); 73 | } catch (e) { 74 | m.reply( 75 | `> ⚠️ *Scrape* ${input} *tidak ditemukan*, pastikan cek kembali list Scrape yang kamu simpan!`, 76 | ); 77 | } 78 | } 79 | } 80 | }, 81 | }; 82 | -------------------------------------------------------------------------------- /system/plugins/rpg/bank.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "bank", 3 | alias: ["wallet", "atm", "banking"], 4 | category: ["rpg"], 5 | settings: {}, 6 | loading: true, 7 | 8 | async run(m, { text, sock, config }) { 9 | const user = db.list().user[m.sender]; 10 | if (!user || !user.register) { 11 | return m.reply(config.messages.unregistered); 12 | } 13 | if (!user.bank) user.bank = 0; 14 | 15 | const formatMoney = (amount) => amount.toLocaleString("id-ID"); 16 | 17 | if (!text) { 18 | return m.reply(`╭═══❯ 🏦 ᴠ-ʙᴀɴᴋ ❮═══╗ 19 | │ 20 | │ 👤 ᴀᴄᴄᴏᴜɴᴛ ɪɴꜰᴏ 21 | │ ──────────────── 22 | │ 📝 ɴᴀᴍᴇ: ${user.name} 23 | │ 📊 ʟᴇᴠᴇʟ: ${user.level} 24 | │ 🎫 ʟɪᴍɪᴛ: ${user.limit} 25 | │ 26 | │ 💰 ʙᴀʟᴀɴᴄᴇ ɪɴꜰᴏ 27 | │ ──────────────── 28 | │ 💳 ʙᴀɴᴋ: ʀᴘ ${formatMoney(user.bank)} 29 | │ 💵 ᴄᴀꜱʜ: ʀᴘ ${formatMoney(user.rpg.money)} 30 | │ 31 | │ 📋 ᴄᴏᴍᴍᴀɴᴅꜱ 32 | │ ──────────────── 33 | │ 💸 ${m.prefix}bank deposit 34 | │ 💰 ${m.prefix}bank pull 35 | │ 36 | ╰═══════════════════╯`); 37 | } 38 | 39 | const [command, amountText] = text.split(" "); 40 | const amount = parseInt(amountText); 41 | 42 | if (!amount) return m.reply(`❌ ᴍᴀꜱᴜᴋᴋᴀɴ ɴᴏᴍɪɴᴀʟ`); 43 | if (isNaN(amount)) return m.reply(`❌ ɴᴏᴍɪɴᴀʟ ʜᴀʀᴜꜱ ʙᴇʀᴜᴘᴀ ᴀɴɢᴋᴀ`); 44 | if (amount < 1000) return m.reply(`❌ ᴍɪɴɪᴍᴀʟ ᴛʀᴀɴꜱᴀᴋꜱɪ ʀᴘ 1,000`); 45 | 46 | switch (command.toLowerCase()) { 47 | case "deposit": { 48 | if (user.rpg.money < amount) 49 | return m.reply(`╭═══❯ ❌ ꜰᴀɪʟᴇᴅ ❮═══╗ 50 | │ 51 | │ 💵 ᴜᴀɴɢ ᴛᴜɴᴀɪ ᴛɪᴅᴀᴋ ᴄᴜᴋᴜᴘ 52 | │ 💳 ᴀɴᴅᴀ ʙᴜᴛᴜʜ: ʀᴘ ${formatMoney(amount)} 53 | │ 💰 ᴅᴏᴍᴘᴇᴛ ᴀɴᴅᴀ: ʀᴘ ${formatMoney(user.rpg.money)} 54 | │ 55 | ╰═══════════════════╯`); 56 | 57 | await m.reply(`💳 ᴍᴇᴍᴘʀᴏꜱᴇꜱ ᴅᴇᴘᴏꜱɪᴛ...`); 58 | await new Promise((resolve) => setTimeout(resolve, 1500)); 59 | 60 | user.rpg.money -= amount; 61 | user.bank += amount; 62 | 63 | return m.reply(`╭═══❯ 🏦 ᴅᴇᴘᴏꜱɪᴛ ❮═══╗ 64 | │ 65 | │ ✅ ᴅᴇᴘᴏꜱɪᴛ ʙᴇʀʜᴀꜱɪʟ! 66 | │ 💸 ᴊᴜᴍʟᴀʜ: ʀᴘ ${formatMoney(amount)} 67 | │ 68 | │ 📊 ꜱᴀʟᴅᴏ ᴛᴇʀʙᴀʀᴜ 69 | │ ──────────────── 70 | │ 💳 ʙᴀɴᴋ: ʀᴘ ${formatMoney(user.bank)} 71 | │ 💵 ᴄᴀꜱʜ: ʀᴘ ${formatMoney(user.rpg.money)} 72 | │ 73 | ╰═══════════════════╯`); 74 | } 75 | 76 | case "pull": { 77 | if (user.bank < amount) 78 | return m.reply(`╭═══❯ ❌ ꜰᴀɪʟᴇᴅ ❮═══╗ 79 | │ 80 | │ 💳 ꜱᴀʟᴅᴏ ᴛɪᴅᴀᴋ ᴄᴜᴋᴜᴘ 81 | │ 💰 ᴀɴᴅᴀ ʙᴜᴛᴜʜ: ʀᴘ ${formatMoney(amount)} 82 | │ 💵 ꜱᴀʟᴅᴏ ᴀɴᴀ: ʀᴘ ${formatMoney(user.bank)} 83 | │ 84 | ╰═══════════════════╯`); 85 | 86 | await m.reply(`💳 ᴍᴇᴍᴘʀᴏꜱᴇꜱ ᴘᴇɴᴀʀɪᴋᴀɴ...`); 87 | await new Promise((resolve) => setTimeout(resolve, 1500)); 88 | 89 | user.bank -= amount; 90 | user.rpg.money += amount; 91 | 92 | return m.reply(`╭═══❯ 🏦 ᴘᴇɴᴀʀɪᴋᴀɴ ❮═══╗ 93 | │ 94 | │ ✅ ᴘᴇɴᴀʀɪᴋᴀɴ ʙᴇʀʜᴀꜱɪʟ! 95 | │ 💸 ᴊᴜᴍʟᴀʜ: ʀᴘ ${formatMoney(amount)} 96 | │ 97 | │ 📊 ꜱᴀʟᴅᴏ ᴛᴇʀʙᴀʀᴜ 98 | │ ──────────────── 99 | │ 💳 ʙᴀɴᴋ: ʀᴘ ${formatMoney(user.bank)} 100 | │ 💵 ᴄᴀꜱʜ: ʀᴘ ${formatMoney(user.rpg.money)} 101 | │ 102 | ╰═══════════════════╯`); 103 | } 104 | 105 | default: 106 | return m.reply(`❌ ᴄᴏᴍᴍᴀɴᴅ ᴛɪᴅᴀᴋ ᴠᴀʟɪᴅ!`); 107 | } 108 | }, 109 | }; 110 | -------------------------------------------------------------------------------- /scrapers/source/photoaid.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const fs = require("fs"); 3 | 4 | async function photoaid(imageInput, type) { 5 | const headers = { 6 | authority: "photoaid.com", 7 | accept: "*/*", 8 | origin: "https://photoaid.com", 9 | "user-agent": "Postify/1.0.0", 10 | }; 11 | 12 | const endpoints = { 13 | enlarger: { 14 | upload: "/ai-image-enlarger/upload", 15 | result: "/ai-image-enlarger/result", 16 | referer: "https://photoaid.com/en/tools/ai-image-enlarger", 17 | }, 18 | relighting: { 19 | upload: "/relighting/upload", 20 | result: "/relighting/result", 21 | referer: "https://photoaid.com/en/tools/remove-shadow", 22 | }, 23 | removebg: { 24 | upload: "/remove-background/upload", 25 | result: "/remove-background/result", 26 | referer: "https://photoaid.com/en/tools/remove-background", 27 | }, 28 | }; 29 | 30 | try { 31 | const tokenResponse = await axios.post( 32 | "https://photoaid.com/en/tools/api/tools/token", 33 | {}, 34 | { 35 | headers: { ...headers, referer: "https://photoaid.com" }, 36 | }, 37 | ); 38 | const token = tokenResponse.data.token; 39 | 40 | let base64Image; 41 | if (typeof imageInput === "string" && imageInput.startsWith("http")) { 42 | const response = await axios.get(imageInput, { 43 | responseType: "arraybuffer", 44 | }); 45 | base64Image = Buffer.from(response.data).toString("base64"); 46 | } else if (Buffer.isBuffer(imageInput)) { 47 | base64Image = imageInput.toString("base64"); 48 | } else if (typeof imageInput === "string" && fs.existsSync(imageInput)) { 49 | base64Image = fs.readFileSync(imageInput).toString("base64"); 50 | } else if (typeof imageInput === "string") { 51 | base64Image = imageInput; 52 | } else { 53 | throw new Error("Tipe input tidak valid!"); 54 | } 55 | 56 | const uploadResponse = await axios.post( 57 | "https://photoaid.com/en/tools/api/tools/upload", 58 | { base64: base64Image, token, reqURL: endpoints[type].upload }, 59 | { 60 | headers: { 61 | ...headers, 62 | referer: endpoints[type].referer, 63 | "content-type": "text/plain;charset=UTF-8", 64 | cookie: `uuidtoken2=${token}`, 65 | }, 66 | }, 67 | ); 68 | 69 | let final_result; 70 | do { 71 | final_result = await axios.post( 72 | "https://photoaid.com/en/tools/api/tools/result", 73 | { 74 | request_id: uploadResponse.data.request_id, 75 | reqURL: endpoints[type].result, 76 | }, 77 | { 78 | headers: { 79 | ...headers, 80 | referer: endpoints[type].referer, 81 | "content-type": "text/plain;charset=UTF-8", 82 | cookie: `uuidtoken2=${token}`, 83 | }, 84 | }, 85 | ); 86 | 87 | if (final_result.data.statusAPI === "processing") { 88 | await new Promise((resolve) => setTimeout(resolve, 3000)); 89 | } 90 | } while (final_result.data.statusAPI === "processing"); 91 | 92 | return final_result.data; 93 | } catch (error) { 94 | throw error; 95 | } 96 | } 97 | 98 | module.exports = photoaid; 99 | -------------------------------------------------------------------------------- /system/plugins/rpg/merampok.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | command: "rob", 3 | alias: ["rampok", "merampok"], 4 | category: ["rpg"], 5 | settings: {}, 6 | async run(m, { sock, config }) { 7 | let usr = db.list().user[m.sender]; 8 | 9 | if (!usr || !usr.register) { 10 | return m.reply(config.messages.unregistered); 11 | } 12 | 13 | if (!usr.rpg) { 14 | usr.rpg = { 15 | money: 0, 16 | exp: 0, 17 | lastGajian: 0, 18 | sampah: 0, 19 | botol: 0, 20 | kardus: 0, 21 | iron: 0, 22 | kayu: 0, 23 | kaleng: 0, 24 | gelas: 0, 25 | plastik: 0, 26 | lastMulung: 0, 27 | lastTaxy: 0, 28 | lastGojek: 0, 29 | lastRob: 0, 30 | }; 31 | } 32 | 33 | let rpg = usr.rpg; 34 | 35 | let cooldown = 3 * 60 * 60 * 1000; 36 | let now = Date.now(); 37 | 38 | let chance = Math.random() * 100; 39 | let successRate = 50; 40 | 41 | if (chance <= successRate) { 42 | if (now - rpg.lastRob < cooldown) { 43 | let timeLeft = Math.ceil((cooldown - (now - rpg.lastRob)) / 1000); 44 | let hours = Math.floor(timeLeft / 3600); 45 | let minutes = Math.floor((timeLeft % 3600) / 60); 46 | let seconds = timeLeft % 60; 47 | return m.reply( 48 | `⏳ Tunggu ${hours} jam ${minutes} menit ${seconds} detik sebelum bisa merampok bank lagi.`, 49 | ); 50 | } 51 | 52 | let prosesRob = [ 53 | "🔪 Menyiapkan Rencana Perampokan...", 54 | "💣 Menjinakkan Alarm dan Membuka Brankas...", 55 | "🚔 Polisi Sedang Berpatroli, Harus Cepat!", 56 | "💰 Mengambil Uang dan Kabur dari Bank...", 57 | "🏃‍♂️ Berhasil Melarikan Diri dengan Uang!", 58 | ]; 59 | 60 | for (let txt of prosesRob) { 61 | await m.reply(txt); 62 | await sleep(7000); 63 | } 64 | 65 | let dapatMoney = Math.floor(Math.random() * 4000000) + 1000000; 66 | let dapatExp = Math.floor(Math.random() * 70000) + 20000; 67 | 68 | rpg.money += dapatMoney; 69 | rpg.exp += dapatExp; 70 | rpg.lastRob = now; 71 | 72 | let hasilNyaTxt = ` 73 | 💰 *Perampokan Berhasil!* 74 | ━━━━━━━━━━━━━━━━━ 75 | 💵 *Uang Didapat:* +${dapatMoney.toLocaleString()} uang 76 | 🎯 *Pengalaman:* +${dapatExp.toLocaleString()} exp 77 | ━━━━━━━━━━━━━━━━━ 78 | ⚠️ Waspadalah! Polisi bisa mengincarmu di lain waktu. 79 | `.trim(); 80 | 81 | return m.reply({ 82 | image: { url: "https://files.catbox.moe/36sixy.jpg" }, 83 | caption: hasilNyaTxt, 84 | }); 85 | } else { 86 | let gagalText = ` 87 | 🚔 *PERAMPOKAN GAGAL!* 88 | ━━━━━━━━━━━━━━━━━ 89 | 😔 Kamu gagal merampok bank dan harus kabur! 90 | 🏃‍♂️ Untungnya, kamu berhasil melarikan diri dan bisa mencoba lagi. 91 | ━━━━━━━━━━━━━━━━━ 92 | ⚠️ Coba lagi segera sebelum polisi menemukanmu! 93 | `.trim(); 94 | 95 | return m.reply({ 96 | image: { url: "https://telegra.ph/file/afcf9a7f4e713591080b5.jpg" }, 97 | caption: gagalText, 98 | }); 99 | } 100 | }, 101 | }; 102 | 103 | function sleep(ms) { 104 | return new Promise((resolve) => setTimeout(resolve, ms)); 105 | } 106 | -------------------------------------------------------------------------------- /scrapers/source/swapface.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const fs = require("fs"); 3 | const crypto = require("crypto"); 4 | const FormData = require("form-data"); 5 | 6 | const swapface = { 7 | create: async (target, source) => { 8 | let targetImg, sourceImg; 9 | const request = async (image, prefix) => { 10 | if (typeof image === "string" && image.startsWith("http")) { 11 | const response = await axios.get(image, { 12 | responseType: "arraybuffer", 13 | }); 14 | return await sb2f(response.data, `${prefix}.jpg`); 15 | } else if (Buffer.isBuffer(image)) { 16 | return await sb2f(image, `${prefix}.jpg`); 17 | } else { 18 | return image; 19 | } 20 | }; 21 | 22 | targetImg = await request(target, "target"); 23 | sourceImg = await request(source, "source"); 24 | const formData = new FormData(); 25 | formData.append("target_image_file", fs.createReadStream(targetImg)); 26 | formData.append("target_face_file", fs.createReadStream(sourceImg)); 27 | 28 | const config = { 29 | headers: { 30 | authority: "aifaceswapper.io", 31 | accept: "*/*", 32 | "content-type": 33 | "multipart/form-data; boundary=" + formData.getBoundary(), 34 | origin: "https://aifaceswapper.io", 35 | referer: "https://aifaceswapper.io/id", 36 | authorization: token(), 37 | "user-agent": 38 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", 39 | }, 40 | }; 41 | 42 | try { 43 | const response = await axios.post( 44 | "https://aifaceswapper.io/api/nicefish/fs/singleface", 45 | formData, 46 | config, 47 | ); 48 | const requestId = response.data.data.request_id; 49 | let result; 50 | let status = "waiting"; 51 | let retries = 0; 52 | 53 | while (status === "waiting" && retries < 20) { 54 | const resultx = await axios.get( 55 | `https://aifaceswapper.io/api/nicefish/fs/result?request_id=${requestId}`, 56 | config, 57 | ); 58 | status = resultx.data.data.status; 59 | 60 | if (status === "waiting") { 61 | await new Promise((resolve) => setTimeout(resolve, 1000)); 62 | retries++; 63 | } else { 64 | result = resultx.data; 65 | } 66 | } 67 | 68 | return result; 69 | } catch (error) { 70 | throw error; 71 | } finally { 72 | if (fs.existsSync(targetImg)) fs.unlinkSync(targetImg); 73 | if (fs.existsSync(sourceImg)) fs.unlinkSync(sourceImg); 74 | } 75 | }, 76 | }; 77 | 78 | async function sb2f(buffer, filename) { 79 | const tmpFile = `./tmp/${crypto.randomBytes(8).toString("hex")}_${filename}`; 80 | await fs.promises.mkdir("./tmp", { recursive: true }); 81 | return new Promise((resolve, reject) => { 82 | fs.writeFile(tmpFile, buffer, (err) => { 83 | if (err) reject(err); 84 | else resolve(tmpFile); 85 | }); 86 | }); 87 | } 88 | 89 | function token() { 90 | const ts = Date.now().toString(16).slice(0, 8); 91 | const pea = 92 | [1, 2, 3].map(() => Math.random().toString(16).slice(2, 6)).join("-") + 93 | Math.random().toString(16).slice(2, 5); 94 | return `${ts}-${pea}`; 95 | } 96 | 97 | module.exports = swapface; 98 | -------------------------------------------------------------------------------- /events/messages.js: -------------------------------------------------------------------------------- 1 | const serialize = require("@library/serialize.js"); 2 | const config = require("@configuration"); 3 | 4 | module.exports = (sock, store) => { 5 | async function getMessage(key) { 6 | if (store) { 7 | const msg = await store.loadMessage(key.remoteJid, key.id); 8 | return msg; 9 | } 10 | return { 11 | conversation: "Takeshi-WaBot", 12 | }; 13 | } 14 | 15 | const appenTextMessage = async (m, sock, text, chatUpdate) => { 16 | let messages = await generateWAMessage( 17 | m.key.remoteJid, 18 | { 19 | text: text, 20 | }, 21 | { 22 | quoted: m.quoted, 23 | }, 24 | ); 25 | messages.key.fromMe = areJidsSameUser(m.sender, sock.user.id); 26 | messages.key.id = m.key.id; 27 | messages.pushName = m.pushName; 28 | if (m.isGroup) messages.participant = m.sender; 29 | let msg = { 30 | ...chatUpdate, 31 | messages: [proto.WebMessageInfo.fromObject(messages)], 32 | type: "append", 33 | }; 34 | return sock.ev.emit("messages.upsert", msg); 35 | }; 36 | 37 | sock.ev.on("messages.upsert", async (cht) => { 38 | console.log(cht); 39 | if (cht.messages.length === 0) return; 40 | const chatUpdate = cht.messages[0]; 41 | if (!chatUpdate.message) return; 42 | const userId = chatUpdate.key.id; 43 | global.m = await serialize(chatUpdate, sock, store); 44 | let jid = m.key.remoteJid; 45 | let senderNumber = m.key.participant || jid; 46 | senderNumber = senderNumber.split("@")[0]; 47 | let senderName = m.pushName || "Unknown"; 48 | const messageContent = 49 | m.message?.conversation || m.message?.extendedTextMessage?.text || ""; 50 | 51 | require("@library/logger.js")(m); 52 | 53 | if (m.isBot) return; 54 | if (!m.isOwner && db.list().settings.self) return; 55 | await require("../system/handler.js")(m, sock, store); 56 | 57 | if (config.settings.autotyping) 58 | sock.sendPresenceUpdate("composing", m.from); 59 | if (!config.settings.online) sock.sendPresenceUpdate("unavailable", m.from); 60 | if (config.settings.online) sock.sendPresenceUpdate("available", m.from); 61 | if (config.settings.readchat) sock.readMessages([m.key]); 62 | 63 | sock.storyJid = sock.storyJid ? sock.storyJid : []; 64 | sock.story = sock.story ? sock.story : []; 65 | 66 | if ( 67 | config.settings.readsw && 68 | m.from.endsWith("broadcast") && 69 | !/protocol/.test(m.type) 70 | ) { 71 | await sock.readMessages([m.key]); 72 | } 73 | }); 74 | 75 | sock.ev.on("messages.update", async (chatUpdate) => { 76 | for (const { key, update } of chatUpdate) { 77 | if (update.pollUpdates && key.fromMe) { 78 | const pollCreation = await getMessage(key); 79 | if (pollCreation) { 80 | let pollUpdate = await getAggregateVotesInPollMessage({ 81 | message: pollCreation?.message, 82 | pollUpdates: update.pollUpdates, 83 | }); 84 | let toCmd = pollUpdate.filter((v) => v.voters.length !== 0)[0]?.name; 85 | console.log(toCmd); 86 | await appenTextMessage(m, sock, toCmd, pollCreation); 87 | await sock.sendMessage(m.cht, { delete: key }); 88 | } else return false; 89 | return; 90 | } 91 | } 92 | }); 93 | 94 | return { 95 | getMessage, 96 | appenTextMessage 97 | }; 98 | }; -------------------------------------------------------------------------------- /system/plugins/owner/plugins.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const jsBeautify = require("js-beautify"); 3 | 4 | module.exports = { 5 | command: "plugins", 6 | alias: ["plugin"], 7 | category: ["owner"], 8 | settings: { 9 | owner: true, 10 | }, 11 | description: "Pengelolaan dan Pengaturan Plugins Bot dengan Mudah", 12 | async run(m, { text }) { 13 | let src = pg.plugins; 14 | 15 | if (!text) 16 | throw `> *– 乂 Panduan Penggunaan Perintah* 💡\n 17 | > 1. Gunakan *\`--get\`* untuk mengambil plugin\n 18 | > 2. Gunakan *\`--add\`* untuk menambahkan plugin baru\n 19 | > 3. Gunakan *\`--delete\`* untuk menghapus plugin\n\n 20 | > *– 乂 Daftar Plugin yang Tersedia :*\n 21 | ${Object.keys(src) 22 | .map((a, i) => `> *${i + 1}.* ${a.split("/plugins/")[1]}`) 23 | .join("\n")}`; 24 | 25 | if (text.includes("--get")) { 26 | let input = text.replace("--get", "").trim(); 27 | if (!input) 28 | throw `> Mohon pilih plugin dengan menyertakan nomor atau nama plugin.`; 29 | 30 | let list = Object.keys(src).map((a) => a.split("/plugins/")[1]); 31 | let file = isNaN(input) 32 | ? `${pg.directory}/${input}.js` 33 | : `${pg.directory}/${list[parseInt(input) - 1]}`; 34 | 35 | try { 36 | m.reply(fs.readFileSync(file.trim()).toString()); 37 | } catch (e) { 38 | m.reply( 39 | `> *Plugin ${input} tidak ditemukan.* Pastikan plugin yang kamu cari tersedia.`, 40 | ); 41 | } 42 | } else if (text.includes("--add")) { 43 | if (!m.quoted || !m.quoted.body) 44 | throw `> *– 乂 Mohon balas pesan berisi kode plugin yang ingin kamu simpan.*\n> Harap pastikan bahwa kode plugin yang kamu kirim valid dan lengkap!`; 45 | 46 | let input = text.replace("--add", "").trim(); 47 | if (!input) throw `> Masukkan nama plugin yang ingin kamu tambahkan.`; 48 | 49 | try { 50 | let file = `${pg.directory}/${input}.js`; 51 | fs.writeFileSync(file.trim(), jsBeautify(m.quoted.body)); 52 | m.reply(`> 🎉 *Plugin ${input} berhasil disimpan!*`); 53 | } catch (e) { 54 | m.reply( 55 | `> *Terjadi kesalahan saat menyimpan plugin.* Coba periksa kode plugin atau coba lagi nanti.`, 56 | ); 57 | } 58 | } else if (text.includes("--delete")) { 59 | let input = text.replace("--delete", "").trim(); 60 | if (!input) 61 | throw `> Silakan masukkan nama atau nomor plugin yang ingin kamu hapus.`; 62 | 63 | let list = Object.keys(src).map((a) => a.split("/plugins/")[1]); 64 | let file = isNaN(input) 65 | ? `${pg.directory}/${input}.js` 66 | : `${pg.directory}/${list[parseInt(input) - 1]}`; 67 | 68 | try { 69 | fs.unlinkSync(file.trim()); 70 | m.reply(`> 🗑️ *Plugin ${input} berhasil dihapus dari daftar plugin.*`); 71 | } catch (e) { 72 | m.reply( 73 | `> *Plugin ${input} tidak ditemukan.* Pastikan nama plugin yang kamu masukkan benar.`, 74 | ); 75 | } 76 | } else { 77 | throw `> *– 乂 Panduan Penggunaan Perintah* 💡\n 78 | > 1. Gunakan *\`--get\`* untuk mengambil plugin\n 79 | > 2. Gunakan *\`--add\`* untuk menambahkan plugin baru\n 80 | > 3. Gunakan *\`--delete\`* untuk menghapus plugin\n\n 81 | > *– 乂 Daftar Plugin yang Tersedia :*\n 82 | ${Object.keys(src) 83 | .map((a, i) => `> *${i + 1}.* ${a.split("/plugins/")[1]}`) 84 | .join("\n")}`; 85 | } 86 | }, 87 | }; 88 | --------------------------------------------------------------------------------