├── 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 |
--------------------------------------------------------------------------------