├── .github ├── CODE_OF_CONDUCT.md └── workflows │ └── greetings.yml ├── .gitignore ├── .replit ├── Dockerfile ├── LICENSE ├── Procfile ├── README.md ├── app.json ├── config.js ├── docker-compose.yml ├── handler.js ├── index.html ├── index.js ├── lib ├── cloudDBAdapter.js ├── convert.js ├── converter.js ├── database.js ├── gdrive.js ├── levelling.js ├── logs.js ├── mongoDB.js ├── print.js ├── simple.js ├── sticker.js ├── store.js ├── store2.js ├── tictactoe.d.ts ├── tictactoe.js ├── uploadFile.js ├── uploadImage.js ├── util.js ├── webp.js ├── webp2mp4.js ├── welcome.js └── y2mate.js ├── main.js ├── me.png ├── me2.jpeg ├── package.json ├── plugins ├── _afk.js ├── _antilink.js ├── _cek.js ├── _func.js ├── _memfess-Ans.js ├── _templateResponse.js ├── _ttt.js ├── afk.js ├── ai-animediff.js ├── ai-animediff2.js ├── ai-chatgpt.js ├── anonymous_chat.js ├── anonymous_chat_.js ├── cmd-del.js ├── cmd-list.js ├── cmd-lock.js ├── cmd-set.js ├── creator.js ├── downloader-danbooru.js ├── downloader-fb.js ├── downloader-gddl.js ├── downloader-git.js ├── downloader-ig.js ├── downloader-mediafire.js ├── downloader-play.js ├── downloader-sfile.js ├── downloader-tiktok.js ├── enable.js ├── game-ttt.js ├── general-menu.js ├── general-toimg.js ├── general-tomp3.js ├── general-tomp4.js ├── group-demote.js ├── group-hidetag.js ├── group-link.js ├── group-mute.js ├── group-promote.js ├── group-revoke.js ├── group-sdesc.js ├── group-set.js ├── group-setname.js ├── group-setpp.js ├── group-tagall.js ├── image-gimage.js ├── internet-freepik.js ├── misc--pinterest.js ├── misc-bonk.js ├── misc-dashboard.js ├── misc-delete.js ├── misc-emojimix.js ├── misc-listgc.js ├── misc-memfess.js ├── misc-profile.js ├── misc-react.js ├── misc-runtime.js ├── misc-speed.js ├── misc-stats.js ├── misc-total.js ├── owner-add.js ├── owner-broadcastgc.js ├── owner-df.js ├── owner-exec.js ├── owner-exec2.js ├── owner-gp.js ├── owner-join.js ├── owner-kick.js ├── owner-pinchat.js ├── owner-setbio.js ├── owner-setpp.js ├── owner-sf.js ├── sc.js ├── setpref.js ├── sticker-null.js ├── sticker-qc.js ├── sticker-wm.js ├── sticker.js ├── tools-base64.js ├── tools-blur.js ├── tools-device.js ├── tools-enc.js ├── tools-fetch.js ├── tools-getcaption.js ├── tools-google.js ├── tools-inspect.js ├── tools-lyrics.js ├── tools-mention.js ├── tools-npm.js ├── tools-obfus.js ├── tools-ocr.js ├── tools-polling.js ├── tools-ptv.js ├── tools-qr.js ├── tools-readmore.js ├── tools-rvo.js ├── tools-sauce.js ├── tools-sendquoted.js ├── tools-ssweb.js ├── tools-style.js ├── tools-tempmail.js ├── tools-tourl.js ├── tools-tovn.js ├── tools-tts.js ├── tools-ttstalk.js ├── tools-weather.js ├── tools-webcek.js ├── tools-whatmusic.js ├── weebs-loli.js ├── weebs-ppcp.js ├── weebs-waifupics.js ├── yt-yta.js ├── yt-yts.js └── yt-ytv.js ├── replit.nix ├── server.js ├── src ├── Aesthetic │ ├── Aesthetic_000.jpeg │ ├── Aesthetic_001.jpg │ ├── Aesthetic_002.jpg │ ├── Thumbs.db │ └── r ├── LICENSE ├── UwU by Lua ├── avatar_contact.png ├── font │ ├── 212BabyGirl.otf │ ├── 212LeahleeSans.ttf │ ├── 99HandWritting.ttf │ ├── ACallingFontDby7NTypes.otf │ ├── ACasualHandwrittenPenNoncommercial.ttf │ ├── ADayinSeptember.otf │ ├── ASMelanieHandwritting.ttf │ ├── Alittlesunshine.ttf │ ├── And-This-Happened.ttf │ ├── AvenirCondensedHand.ttf │ ├── Avocados.ttf │ ├── BabyDoll.ttf │ ├── BattleOfKingsRegular.ttf │ ├── BrayNotes.ttf │ ├── Convered-By-Your-Grace.ttf │ ├── Edoms-Handwritting-Normal.ttf │ ├── Futura Bold Italic font.ttf │ ├── Futura Bold font.ttf │ ├── Futura Book Italic font.ttf │ ├── Futura Book font.ttf │ ├── Futura Extra Black font.ttf │ ├── Futura Heavy Italic font.ttf │ ├── Futura Heavy font.ttf │ ├── Futura Light Italic font.ttf │ ├── Futura Light font.ttf │ ├── Futura Medium Italic font.ttf │ ├── Futura XBlk BT.ttf │ ├── Futura-CondensedLight.otf │ ├── GloriaHallelujah-Regular.ttf │ ├── HandwritingCR-2.ttf │ ├── Kempton-Demo-Handwritting.ttf │ ├── MyHandsareHoldingYou.ttf │ ├── My_handwriting.ttf │ ├── Nadeznas-Handwritting.ttf │ ├── Roboto-Black.ttf │ ├── Roboto-BlackItalic.ttf │ ├── Roboto-Bold.ttf │ ├── Roboto-BoldItalic.ttf │ ├── Roboto-Italic.ttf │ ├── Roboto-Light.ttf │ ├── Roboto-LightItalic.ttf │ ├── Roboto-Medium.ttf │ ├── Roboto-MediumItalic.ttf │ ├── Roboto-Regular.ttf │ ├── Roboto-Thin.ttf │ ├── Roboto-ThinItalic.ttf │ ├── ShadowsIntoLight-Regular.ttf │ ├── Zahraaa.ttf │ ├── angelina.ttf │ ├── futur.ttf │ ├── futura light bt.ttf │ ├── futura medium bt.ttf │ ├── futura medium condensed bt.ttf │ ├── level_c.otf │ ├── michellehandwritting.ttf │ └── texts.otf ├── level_c.otf ├── lvlup_template.jpg ├── r ├── texts.otf └── welcome.svg ├── test.js └── tmp └── cro skkk /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at slavyan@secret.fyi. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /.github/workflows/greetings.yml: -------------------------------------------------------------------------------- 1 | name: Greetings 2 | 3 | on: [pull_request, issues] 4 | 5 | jobs: 6 | greeting: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/first-interaction@v1 10 | with: 11 | repo-token: ${{ secrets.GITHUB_TOKEN }} 12 | issue-message: 'Hello! Thanks for submiting the issue, we will respond to you ASAP.' 13 | pr-message: 'Hello! Thank you for contributing to this repo, we will review your commits ASAP.' 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | tmp/* 3 | 4 | # Dependency directories 5 | .git/ 6 | node_modules/ 7 | 8 | # data-single-auth 9 | session.data.json 10 | database.json 11 | package-lock.json 12 | 13 | #data-multi-auth 14 | data.store.json 15 | sessions/ 16 | -------------------------------------------------------------------------------- /.replit: -------------------------------------------------------------------------------- 1 | run = "clear && node ." 2 | 3 | [nix] 4 | channel = "unstable" 5 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:lts-buster 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y \ 5 | ffmpeg \ 6 | imagemagick \ 7 | webp && \ 8 | apt-get upgrade -y && \ 9 | rm -rf /var/lib/apt/lists/* 10 | 11 | COPY package.json . 12 | 13 | RUN npm install && npm install qrcode-terminal 14 | 15 | COPY . . 16 | 17 | EXPOSE 5000 18 | 19 | CMD ["npm", "start"] 20 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | worker: npm start 2 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wa bot md by zoro md", 3 | "description": "Whatsapp bot. recode by lua ser ofc", 4 | "keywords": [ 5 | "whatsapp bot", 6 | "nodejs" 7 | ], 8 | "repository": "https://github.com/xxirfanx/zoromd", 9 | "buildpacks": [ 10 | { 11 | "url": "heroku/nodejs" 12 | }, 13 | { 14 | "url": "https://github.com/DuckyTeam/heroku-buildpack-imagemagick.git" 15 | }, 16 | { 17 | "url": "https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest" 18 | }, 19 | { 20 | "url": "https://github.com/clhuang/heroku-buildpack-webp-binaries.git" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | import { fileURLToPath } from 'url' 3 | import { watchFile, unwatchFile, readFileSync } from 'fs' 4 | 5 | global.owner = 6 | [ 7 | ['+91 6235 050 956', '𝖑𝖚𝖆 𝖘𝖊𝖗 𝖔𝖋𝖈', true] 8 | ] 9 | // Put your number here 10 | // [number, he creator/owner?, he developer?] 11 | 12 | global.mods = [] // Want some help? 13 | global.prems = [] // Premium user has unlimited limit 14 | 15 | // api key here okay 16 | global.xyro = 'LyrK9JMI7N' // https://api.xyroinee.xyz free limit unlimited 17 | global.apilol = 'GataDios' // https://api.lolhuman.xyz free limit unlimited by @BrunoSobrino 18 | 19 | global.APIs = { // API Prefix 20 | // name: 'https://website' 21 | nrtm: 'https://nurutomo.herokuapp.com', 22 | xteam: 'https://api.xteam.xyz' 23 | } 24 | global.APIKeys = { // APIKey Here 25 | // 'https://website': 'apikey' 26 | 'https://api.xteam.xyz': 'd90a9e986e18778b' 27 | } 28 | 29 | global.thumbnailUrl = [ 30 | 'https://telegra.ph/file/81260a8b9e8cff26d2b48.jpg', 'https://telegra.ph/file/ac4928f0824a2a0492737.jpg', 31 | 'https://telegra.ph/file/6359b013bc7e52c3b346f.jpg', 'https://telegra.ph/file/d43c89a5d2da72875ec05.jpg', 32 | 'https://telegra.ph/file/7d6c0e35f9c8f52715541.jpg', 'https://telegra.ph/file/ef4b742d47e6a9115e2ff.jpg', 33 | 'https://telegra.ph/file/55e5af5f33fbd57104187.jpg', 'https://telegra.ph/file/af236598456b95884bd15.jpg', 34 | 'https://telegra.ph/file/de92ed4a729887ffc974c.jpg', 'https://telegra.ph/file/00ce42a193b1dbbf907d4.jpg' 35 | ] 36 | 37 | // Sticker WM 38 | global.packname = `「 Cʀᴇᴀᴛᴇᴅ Bʏ 𝖑𝖚𝖆 𝖘𝖊𝖗 𝖔𝖋𝖈 」` 39 | global.author = '' 40 | global.thumb = readFileSync('./me.png') 41 | global.thumb2 = readFileSync('./me2.jpeg') 42 | global.multiplier = 69 // The higher, The harder levelup 43 | 44 | //Text here 45 | global.me = 'Cʀᴇᴀᴛᴇᴅ Bʏ 𝖑𝖚𝖆 𝖘𝖊𝖗 𝖔𝖋𝖈 - 2023' 46 | global.bott = 'zoro md' 47 | global.nomorown = '916235050956' 48 | // owner put this creator.js 49 | global.str = '-------------' 50 | global.l = '「' 51 | global.r = '」' 52 | global.wait = '```「▰▰▰▱▱▱▱▱▱▱」ʟ ᴏ ᴀ ᴅ ɪ ɴ ɢ...```' 53 | global.eror = '```404 ᴇʀʀᴏʀ```' 54 | 55 | global.rpg = { 56 | emoticon(string) { 57 | string = string.toLowerCase() 58 | let emot = { 59 | level: '🧬', 60 | limit: '🌌', 61 | health: '❤️', 62 | exp: '✉️', 63 | money: '💵', 64 | potion: '🥤', 65 | diamond: '💎', 66 | common: '📦', 67 | uncommon: '🎁', 68 | mythic: '🗳️', 69 | legendary: '🗃️', 70 | pet: '🎁', 71 | trash: '🗑', 72 | armor: '🥼', 73 | sword: '⚔️', 74 | wood: '🪵', 75 | rock: '🪨', 76 | string: '🕸️', 77 | horse: '🐎', 78 | cat: '🐈', 79 | dog: '🐕', 80 | fox: '🦊', 81 | petFood: '🍖', 82 | iron: '⛓️', 83 | gold: '👑', 84 | emerald: '💚' 85 | } 86 | let results = Object.keys(emot).map(v => [v, new RegExp(v, 'gi')]).filter(v => v[1].test(string)) 87 | if (!results.length) return '' 88 | else return emot[results[0][0]] 89 | } 90 | } 91 | 92 | let file = fileURLToPath(import.meta.url) 93 | watchFile(file, () => { 94 | unwatchFile(file) 95 | console.log(chalk.cyanBright("Update 'config.js'")) 96 | import(`${file}?update=${Date.now()}`) 97 | }) 98 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "4.0" 2 | services: 3 | worker: 4 | build: . 5 | volumes: 6 | - .:/code 7 | - logvolume01:/var/log 8 | links: 9 | - redis 10 | redis: 11 | image: redis 12 | volumes: 13 | logvolume01: {} 14 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 |

whatsapp bot by zoromd

2 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | console.log('Starting Bot...') 2 | 3 | import yargs from 'yargs'; import cfonts from 'cfonts'; import { fileURLToPath } from 'url'; import { join, dirname } from 'path'; import { createRequire } from 'module'; import { createInterface } from 'readline'; import { setupMaster, fork } from 'cluster'; import { watchFile, unwatchFile } from 'fs'; 4 | 5 | // https://stackoverflow.com/a/50052194 6 | const { say } = cfonts 7 | const rl = createInterface(process.stdin, process.stdout) 8 | const __dirname = dirname(fileURLToPath(import.meta.url)) 9 | const require = createRequire(__dirname) 10 | 11 | say('Lightweight\nWhatsApp Bot MD', { font: 'chrome', align: 'center', gradient: ['red', 'magenta'] }) 12 | say('Bot created by lua sakura', { font: 'console', align: 'center', gradient: ['red', 'magenta'] }) 13 | 14 | var isRunning = false 15 | /** 16 | * Start a js file 17 | * @param {String} file `path/to/file` 18 | */ 19 | function start(file) { 20 | if (isRunning) return 21 | isRunning = true 22 | let args = [join(__dirname, file), ...process.argv.slice(2)] 23 | say([process.argv[0], ...args].join(' '), { font: 'console', align: 'center', gradient: ['red', 'magenta'] }) 24 | setupMaster({ exec: args[0], args: args.slice(1) }) 25 | let p = fork() 26 | p.on('message', data => { 27 | console.log('[✅RECEIVED]', data) 28 | switch (data) { 29 | case 'reset': 30 | p.process.kill() 31 | isRunning = false 32 | start.apply(this, arguments) 33 | break 34 | case 'uptime': 35 | p.send(process.uptime()) 36 | break 37 | } 38 | }) 39 | p.on('exit', (_, code) => { 40 | isRunning = false 41 | console.error('Exited with code:', code) 42 | if (code !== 0) return start(file) 43 | watchFile(args[0], () => { 44 | unwatchFile(args[0]) 45 | start(file) 46 | }) 47 | }) 48 | let opts = new Object(yargs(process.argv.slice(2)).exitProcess(false).parse()) 49 | if (!opts['test']) 50 | if (!rl.listenerCount()) rl.on('line', line => { 51 | p.emit('message', line.trim()) 52 | }) 53 | // console.log(p) 54 | } 55 | 56 | start('main.js') 57 | -------------------------------------------------------------------------------- /lib/cloudDBAdapter.js: -------------------------------------------------------------------------------- 1 | import got from 'got' 2 | 3 | const stringify = obj => JSON.stringify(obj, null, 2) 4 | const parse = str => JSON.parse(str, (_, v) => { 5 | if ( 6 | v !== null && 7 | typeof v === 'object' && 8 | 'type' in v && 9 | v.type === 'Buffer' && 10 | 'data' in v && 11 | Array.isArray(v.data)) { 12 | return Buffer.from(v.data) 13 | } 14 | return v 15 | }) 16 | class CloudDBAdapter { 17 | constructor(url, { 18 | serialize = stringify, 19 | deserialize = parse, 20 | fetchOptions = {} 21 | } = {}) { 22 | this.url = url 23 | this.serialize = serialize 24 | this.deserialize = deserialize 25 | this.fetchOptions = fetchOptions 26 | } 27 | 28 | async read() { 29 | try { 30 | let res = await got(this.url, { 31 | method: 'GET', 32 | headers: { 33 | 'Accept': 'application/json;q=0.9,text/plain' 34 | }, 35 | ...this.fetchOptions 36 | }) 37 | if (res.statusCode !== 200) throw res.statusMessage 38 | return this.deserialize(res.body) 39 | } catch (e) { 40 | return null 41 | } 42 | } 43 | 44 | async write(obj) { 45 | let res = await got(this.url, { 46 | method: 'POST', 47 | headers: { 48 | 'Content-Type': 'application/json' 49 | }, 50 | ...this.fetchOptions, 51 | body: this.serialize(obj) 52 | }) 53 | if (res.statusCode !== 200) throw res.statusMessage 54 | return res.body 55 | } 56 | } 57 | 58 | export default CloudDBAdapter 59 | -------------------------------------------------------------------------------- /lib/convert.js: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs' 2 | import * as path from 'path' 3 | import ffmpeg from 'fluent-ffmpeg' 4 | import { exec } from 'child_process' 5 | import { addExif } from './sticker.js' 6 | 7 | function convert(file, ext1, ext2, options = []) { 8 | return new Promise(async (resolve, reject) => { 9 | let temp = path.join(__dirname(import.meta.url), '../tmp', Date.now() + '.' + ext1), 10 | out = temp + '.' + ext2; 11 | await fs.promises.writeFile(temp, file); 12 | ffmpeg(temp) 13 | .on('start', (cmd) => { 14 | console.log(cmd); 15 | }) 16 | .on('error', (e) => { 17 | fs.unlinkSync(temp); 18 | reject(e); 19 | }) 20 | .on('end', () => { 21 | console.log("Finish"); 22 | setTimeout(() => { 23 | fs.unlinkSync(temp); 24 | fs.unlinkSync(out); 25 | }, 2000) 26 | resolve(fs.readFileSync(out)); 27 | }) 28 | .addOutputOptions(options) 29 | .toFormat(ext2) 30 | .save(out); 31 | }); 32 | } 33 | 34 | function convert2(file, ext1, ext2, options = []) { 35 | return new Promise(async (resolve, reject) => { 36 | let temp = path.join(__dirname(import.meta.url), '../tmp', Date.now() + '.' + ext1), 37 | out = temp + '.' + ext2; 38 | await fs.promises.writeFile(temp, file); 39 | ffmpeg(temp) 40 | .on('start', (cmd) => { 41 | console.log(cmd); 42 | }) 43 | .on('error', (e) => { 44 | fs.unlinkSync(temp); 45 | reject(e); 46 | }) 47 | .on('end', () => { 48 | console.log("Finish"); 49 | setTimeout(() => { 50 | fs.unlinkSync(temp); 51 | fs.unlinkSync(out); 52 | }, 2000) 53 | resolve(fs.readFileSync(out)); 54 | }) 55 | .addOutputOptions(options) 56 | .seekInput("00:00") 57 | .setDuration("00:05") 58 | .toFormat(ext2) 59 | .save(out); 60 | }); 61 | } 62 | 63 | async function sticker(file, opts) { 64 | if (typeof opts.cmdType === "undefined") opts.cmdType = "1" 65 | const cmd = { 66 | 1: ["-fs 1M", "-vcodec", "libwebp", "-vf", `scale=512:512:flags=lanczos:force_original_aspect_ratio=decrease,format=rgba,pad=512:512:(ow-iw)/2:(oh-ih)/2:color=#00000000,setsar=1`], 67 | 2: ["-fs 1M", "-vcodec", "libwebp"] 68 | } 69 | /* 70 | if (opts.withPackInfo) { 71 | if (!opts.packInfo) throw Error("'packInfo' must be filled when using 'withPackInfo'"); 72 | let ext = opts.isImage !== undefined || false ? "jpg" : opts.isVideo !== undefined || false ? "mp4" : null; 73 | return stickerWithExif(file, ext, opts.packInfo, cmd[parseInt(opts.cmdType)]); 74 | } 75 | */ 76 | if (opts.isImage) { 77 | return convert(file, "jpg", "webp", cmd[parseInt(opts.cmdType)]); 78 | } 79 | if (opts.isVideo) { 80 | return convert2(file, "mp4", "webp", cmd[parseInt(opts.cmdType)]); 81 | } 82 | } 83 | /* 84 | function stickerWithExif(file, ext, packInfo, cmd) { 85 | return new Bluebird(async (res, rej) => { 86 | let { packname, author } = packInfo; 87 | const filename = Date.now(); 88 | const stickerBuffer = ext === "jpg" ? (await convert(file, ext, "webp", cmd)) : (await convert2(file, ext, "webp", cmd)); 89 | ex.create(packname !== undefined || '' ? packname : "Original", author !== undefined || '' ? author : "SMH-BOT", filename); 90 | await fs.promises.writeFile(`./temp/${filename}.webp`, stickerBuffer); 91 | run(`webpmux -set exif ./temp/${filename}.exif ./temp/${filename}.webp -o ./temp/${filename}.webp`, async (err) => { 92 | if (err) rej(err) && await Promise.all([ 93 | fs.unlink(`./temp/${filename}.webp`), 94 | fs.unlink(`./temp/${filename}.exif`) 95 | ]); 96 | setTimeout(() => { 97 | fs.unlinkSync(`./temp/${filename}.exif`); fs.unlinkSync(`./temp/${filename}.webp`); 98 | }, 2000); 99 | res(fs.readFileSync(`./temp/${filename}.webp`)); 100 | }) 101 | }); 102 | } 103 | */ 104 | export { 105 | sticker 106 | } 107 | -------------------------------------------------------------------------------- /lib/converter.js: -------------------------------------------------------------------------------- 1 | import { promises } from 'fs' 2 | import { join } from 'path' 3 | import { spawn } from 'child_process' 4 | 5 | function ffmpeg(buffer, args = [], ext = '', ext2 = '') { 6 | return new Promise(async (resolve, reject) => { 7 | try { 8 | let tmp = join(global.__dirname(import.meta.url), '../tmp', + new Date + '.' + ext) 9 | let out = tmp + '.' + ext2 10 | await promises.writeFile(tmp, buffer) 11 | spawn('ffmpeg', [ 12 | '-y', 13 | '-i', tmp, 14 | ...args, 15 | out 16 | ]) 17 | .on('error', reject) 18 | .on('close', async (code) => { 19 | try { 20 | await promises.unlink(tmp) 21 | if (code !== 0) return reject(code) 22 | resolve({ 23 | data: await promises.readFile(out), 24 | filename: out, 25 | delete() { 26 | return promises.unlink(out) 27 | } 28 | }) 29 | } catch (e) { 30 | reject(e) 31 | } 32 | }) 33 | } catch (e) { 34 | reject(e) 35 | } 36 | }) 37 | } 38 | 39 | /** 40 | * Convert Audio to Playable WhatsApp Audio 41 | * @param {Buffer} buffer Audio Buffer 42 | * @param {String} ext File Extension 43 | * @returns {Promise<{data: Buffer, filename: String, delete: Function}>} 44 | */ 45 | function toPTT(buffer, ext) { 46 | return ffmpeg(buffer, [ 47 | '-vn', 48 | '-c:a', 'libopus', 49 | '-b:a', '128k', 50 | '-vbr', 'on', 51 | ], ext, 'ogg') 52 | } 53 | 54 | /** 55 | * Convert Audio to Playable WhatsApp PTT 56 | * @param {Buffer} buffer Audio Buffer 57 | * @param {String} ext File Extension 58 | * @returns {Promise<{data: Buffer, filename: String, delete: Function}>} 59 | */ 60 | function toAudio(buffer, ext) { 61 | return ffmpeg(buffer, [ 62 | '-vn', 63 | '-c:a', 'libopus', 64 | '-b:a', '128k', 65 | '-vbr', 'on', 66 | '-compression_level', '10' 67 | ], ext, 'opus') 68 | } 69 | 70 | /** 71 | * Convert Audio to Playable WhatsApp Video 72 | * @param {Buffer} buffer Video Buffer 73 | * @param {String} ext File Extension 74 | * @returns {Promise<{data: Buffer, filename: String, delete: Function}>} 75 | */ 76 | function toVideo(buffer, ext) { 77 | return ffmpeg(buffer, [ 78 | '-c:v', 'libx264', 79 | '-c:a', 'aac', 80 | '-ab', '128k', 81 | '-ar', '44100', 82 | '-crf', '32', 83 | '-preset', 'slow' 84 | ], ext, 'mp4') 85 | } 86 | 87 | export { 88 | toAudio, 89 | toPTT, 90 | toVideo, 91 | ffmpeg, 92 | } 93 | -------------------------------------------------------------------------------- /lib/database.js: -------------------------------------------------------------------------------- 1 | import { resolve, dirname as _dirname } from 'path' 2 | import _fs, { existsSync, readFileSync } from 'fs' 3 | const { promises: fs } = _fs 4 | 5 | class Database { 6 | /** 7 | * Create new Database 8 | * @param {String} filepath Path to specified json database 9 | * @param {...any} args JSON.stringify arguments 10 | */ 11 | constructor(filepath, ...args) { 12 | this.file = resolve(filepath) 13 | this.logger = console 14 | 15 | this._load() 16 | 17 | this._jsonargs = args 18 | this._state = false 19 | this._queue = [] 20 | this._interval = setInterval(async () => { 21 | if (!this._state && this._queue && this._queue[0]) { 22 | this._state = true 23 | await this[this._queue.shift()]().catch(this.logger.error) 24 | this._state = false 25 | } 26 | }, 1000) 27 | 28 | } 29 | 30 | get data() { 31 | return this._data 32 | } 33 | 34 | set data(value) { 35 | this._data = value 36 | this.save() 37 | } 38 | 39 | /** 40 | * Queue Load 41 | */ 42 | load() { 43 | this._queue.push('_load') 44 | } 45 | 46 | /** 47 | * Queue Save 48 | */ 49 | save() { 50 | this._queue.push('_save') 51 | } 52 | 53 | _load() { 54 | try { 55 | return this._data = existsSync(this.file) ? JSON.parse(readFileSync(this.file)) : {} 56 | } catch (e) { 57 | this.logger.error(e) 58 | return this._data = {} 59 | } 60 | } 61 | 62 | async _save() { 63 | let dirname = _dirname(this.file) 64 | if (!existsSync(dirname)) await fs.mkdir(dirname, { recursive: true }) 65 | await fs.writeFile(this.file, JSON.stringify(this._data, ...this._jsonargs)) 66 | return this.file 67 | } 68 | } 69 | 70 | export default Database 71 | 72 | -------------------------------------------------------------------------------- /lib/gdrive.js: -------------------------------------------------------------------------------- 1 | import { join } from 'path' 2 | import { promises as fs } from 'fs' 3 | import { promisify } from 'util' 4 | import { google } from 'googleapis' 5 | 6 | 7 | // If modifying these scopes, delete token.json. 8 | const SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly'] 9 | // The file token.json stores the user's access and refresh tokens, and is 10 | // created automatically when the authorization flow completes for the first 11 | // time. 12 | const TOKEN_PATH = join(__dirname, '..', 'token.json') 13 | 14 | class GoogleAuth extends EventEmitter { 15 | constructor() { 16 | super() 17 | } 18 | 19 | async authorize(credentials) { 20 | let token 21 | const { client_secret, client_id } = credentials 22 | const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, `http://localhost:${port}`) 23 | try { 24 | token = JSON.parse(await fs.readFile(TOKEN_PATH)) 25 | } catch (e) { 26 | const authUrl = oAuth2Client.generateAuthUrl({ 27 | access_type: 'offline', 28 | scope: SCOPES 29 | }) 30 | this.emit('auth', authUrl) 31 | let code = await promisify(this.once).bind(this)('token') 32 | token = await oAuth2Client.getToken(code) 33 | await fs.writeFile(TOKEN_PATH, JSON.stringify(token)) 34 | } finally { 35 | await oAuth2Client.setCredentials(token) 36 | } 37 | } 38 | 39 | token(code) { 40 | this.emit('token', code) 41 | } 42 | } 43 | 44 | class GoogleDrive extends GoogleAuth { 45 | constructor() { 46 | super() 47 | this.path = '/drive/api' 48 | } 49 | 50 | async getFolderID(path) { 51 | 52 | } 53 | 54 | async infoFile(path) { 55 | 56 | } 57 | 58 | async folderList(path) { 59 | 60 | } 61 | 62 | async downloadFile(path) { 63 | 64 | } 65 | 66 | async uploadFile(path) { 67 | 68 | } 69 | } 70 | 71 | export { 72 | GoogleAuth, 73 | GoogleDrive, 74 | } 75 | -------------------------------------------------------------------------------- /lib/levelling.js: -------------------------------------------------------------------------------- 1 | export const growth = Math.pow(Math.PI / Math.E, 1.618) * Math.E * .75 2 | export function xpRange(level, multiplier = global.multiplier || 1) { 3 | if (level < 0) 4 | throw new TypeError('level cannot be negative value') 5 | level = Math.floor(level) 6 | let min = level === 0 ? 0 : Math.round(Math.pow(level, growth) * multiplier) + 1 7 | let max = Math.round(Math.pow(++level, growth) * multiplier) 8 | return { 9 | min, 10 | max, 11 | xp: max - min 12 | } 13 | } 14 | export function findLevel(xp, multiplier = global.multiplier || 1) { 15 | if (xp === Infinity) 16 | return Infinity 17 | if (isNaN(xp)) 18 | return NaN 19 | if (xp <= 0) 20 | return -1 21 | let level = 0 22 | do 23 | level++ 24 | while (xpRange(level, multiplier).min <= xp) 25 | return --level 26 | } 27 | export function canLevelUp(level, xp, multiplier = global.multiplier || 1) { 28 | if (level < 0) 29 | return false 30 | if (xp === Infinity) 31 | return true 32 | if (isNaN(xp)) 33 | return false 34 | if (xp <= 0) 35 | return false 36 | return level < findLevel(xp, multiplier) 37 | } 38 | -------------------------------------------------------------------------------- /lib/logs.js: -------------------------------------------------------------------------------- 1 | let stdouts = [] 2 | export default (maxLength = 200) => { 3 | let oldWrite = process.stdout.write.bind(process.stdout) 4 | module.exports.disable = () => { 5 | module.exports.isModified = false 6 | return process.stdout.write = oldWrite 7 | } 8 | process.stdout.write = (chunk, encoding, callback) => { 9 | stdouts.push(Buffer.from(chunk, encoding)) 10 | oldWrite(chunk, encoding, callback) 11 | if (stdouts.length > maxLength) stdouts.shift() 12 | } 13 | module.exports.isModified = true 14 | return module.exports 15 | } 16 | 17 | export const isModified = false 18 | export function logs() { return Buffer.concat(stdouts)} 19 | 20 | -------------------------------------------------------------------------------- /lib/mongoDB.js: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose' 2 | 3 | const { Schema, connect, model: _model } = mongoose 4 | const defaultOptions = { useNewUrlParser: true, useUnifiedTopology: true } 5 | 6 | export class mongoDB { 7 | constructor(url, options = defaultOptions) { 8 | /** 9 | * @type {string} 10 | */ 11 | this.url = url 12 | /** 13 | * @type {mongoose.ConnectOptions} 14 | */ 15 | this.options = options 16 | this.data = this._data = {} 17 | /** 18 | * @type {mongoose.Schema} 19 | */ 20 | this._schema = {} 21 | /** 22 | * @type {mongoose.Model} 23 | */ 24 | this._model = {} 25 | /** 26 | * @type {Promise} 27 | */ 28 | this.db = connect(this.url, { ...this.options }).catch(console.error) 29 | } 30 | async read() { 31 | this.conn = await this.db 32 | let schema = this._schema = new Schema({ 33 | data: { 34 | type: Object, 35 | required: true, //depends on whether the field is mandatory or not 36 | default: {} 37 | } 38 | }) 39 | try { this._model = _model('data', schema) } catch { this._model = _model('data') } 40 | this._data = await this._model.findOne({}) 41 | if (!this._data) { 42 | this.data = {} 43 | const [_, _data] = await Promise.all([ 44 | this.write(this.data), 45 | this._model.findOne({}) 46 | ]) 47 | this._data = _data 48 | } else this.data = this._data.data 49 | return this.data 50 | } 51 | 52 | write(data) { 53 | return new Promise(async (resolve, reject) => { 54 | if (!data) return reject(data) 55 | if (!this._data) return resolve((new this._model({ data })).save()) 56 | this._model.findById(this._data._id, (err, docs) => { 57 | if (err) return reject(err) 58 | if (!docs.data) docs.data = {} 59 | docs.data = data 60 | this.data = {} 61 | return docs.save(resolve) 62 | }) 63 | }) 64 | } 65 | } 66 | 67 | export const mongoDBV2 = class MongoDBV2 { 68 | constructor(url, options = defaultOptions) { 69 | /** 70 | * @type {string} 71 | */ 72 | this.url = url 73 | /** 74 | * @type {mongoose.ConnectOptions} 75 | */ 76 | this.options = options 77 | /** 78 | * @type {{ name: string, model: mongoose.Model}[]} 79 | */ 80 | this.models = [] 81 | /** 82 | * @type {{ [Key: string]: any }} 83 | */ 84 | this.data = {} 85 | this.lists 86 | /** 87 | * @type {mongoose.Model} 88 | */ 89 | this.list 90 | /** 91 | * @type {Promise} 92 | */ 93 | this.db = connect(this.url, { ...this.options }).catch(console.error) 94 | } 95 | async read() { 96 | this.conn = await this.db 97 | let schema = new Schema({ 98 | data: [{ 99 | name: String, 100 | }] 101 | }) 102 | try { this.list = _model('lists', schema) } catch (e) { this.list = _model('lists') } 103 | this.lists = await this.list.findOne({}) 104 | if (!lists?.data) { 105 | await this.list.create({ data: [] }) 106 | // await (new this.list({ data: [] })).save() 107 | this.lists = await this.list.findOne({}) 108 | } 109 | let garbage = [] 110 | for (let { name } of this.lists.data) { // get data from list 111 | /** 112 | * @type {mongoose.Model} 113 | */ 114 | let collection 115 | try { collection = _model(name, new Schema({ data: Array })) } catch (e) { 116 | console.error(e) 117 | try { collection = _model(name) } catch (e) { 118 | garbage.push(name) 119 | console.error(e) 120 | } 121 | } 122 | if (collection) { 123 | this.models.push({ name, model: collection }) 124 | let collectionsData = await collection.find({}) 125 | this.data[name] = Object.fromEntries(collectionsData.map(v => v.data)) 126 | } 127 | } 128 | try { 129 | // Delete list if not exist 130 | let del = await this.list.findById(this.lists._id) 131 | del.data = del.data.filter(v => !garbage.includes(v.name)) 132 | await del.save() 133 | } catch (e) { 134 | console.error(e) 135 | } 136 | 137 | return this.data 138 | } 139 | write(data) { 140 | return new Promise(async (resolve, reject) => { 141 | if (!this.lists || !data) return reject(data || this.lists) 142 | let collections = Object.keys(data), listDoc = [], index = 0 143 | for (let key of collections) { 144 | // Update if exist 145 | if ((index = this.models.findIndex(v => v.name === key)) !== -1) { 146 | let doc = this.models[index].model 147 | await doc.deleteMany().catch(console.error) // alwasy insert, no matter delete error 148 | await doc.insertMany(Object.entries(data[key]).map(v => ({ data: v }))) 149 | if (doc && key) listDoc.push({ name: key }) 150 | } else { // if not exist, create new model 151 | let schema = new Schema({ 152 | data: Array 153 | }) 154 | /** 155 | * @type {mongoose.Model} 156 | */ 157 | let doc 158 | try { 159 | doc = _model(key, schema) 160 | } catch (e) { 161 | console.error(e) 162 | doc = _model(key) 163 | } 164 | index = this.models.findIndex(v => v.name === key) 165 | this.models[index === -1 ? this.models.length : index] = { name: key, model: doc } 166 | await doc.insertMany(Object.entries(data[key]).map(v => ({ data: v }))) 167 | if (doc && key) listDoc.push({ name: key }) 168 | } 169 | } 170 | 171 | // save list 172 | this.list.findById(this.lists._id, function (err, doc) { 173 | if (err) return reject(err) 174 | doc.data = listDoc 175 | this.data = {} 176 | return doc.save(resolve) 177 | }) 178 | return resolve(true) 179 | }) 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /lib/tictactoe.d.ts: -------------------------------------------------------------------------------- 1 | export declare class TicTacToe { 2 | /* X PlayerName */ 3 | playerX: string; 4 | /* Y PlayerName */ 5 | playerY: string; 6 | /* X if true, Y if false */ 7 | _currentTurn: boolean; 8 | _x: number; 9 | _y: number; 10 | _turns: number; 11 | constructor(playerX: string, playerY: string); 12 | get board(): number; 13 | turn(player, index: number): boolean; 14 | turn(player, x: number, y: number): boolean; 15 | } 16 | -------------------------------------------------------------------------------- /lib/tictactoe.js: -------------------------------------------------------------------------------- 1 | class TicTacToe { 2 | constructor(playerX = 'x', playerO = 'o') { 3 | this.playerX = playerX 4 | this.playerO = playerO 5 | this._currentTurn = false 6 | this._x = 0 7 | this._o = 0 8 | this.turns = 0 9 | } 10 | 11 | get board() { 12 | return this._x | this._o 13 | } 14 | 15 | get currentTurn() { 16 | return this._currentTurn ? this.playerO : this.playerX 17 | } 18 | 19 | get enemyTurn() { 20 | return this._currentTurn ? this.playerX : this.playerO 21 | } 22 | 23 | static check(state) { 24 | for (let combo of [7, 56, 73, 84, 146, 273, 292, 448]) 25 | if ((state & combo) === combo) 26 | return !0 27 | return !1 28 | } 29 | 30 | /** 31 | * ```js 32 | * TicTacToe.toBinary(1, 2) // 0b010000000 33 | * ``` 34 | */ 35 | static toBinary(x = 0, y = 0) { 36 | if (x < 0 || x > 2 || y < 0 || y > 2) throw new Error('invalid position') 37 | return 1 << x + (3 * y) 38 | } 39 | 40 | /** 41 | * @param player `0` is `X`, `1` is `O` 42 | * 43 | * - `-3` `Game Ended` 44 | * - `-2` `Invalid` 45 | * - `-1` `Invalid Position` 46 | * - ` 0` `Position Occupied` 47 | * - ` 1` `Sucess` 48 | * @returns {-3|-2|-1|0|1} 49 | */ 50 | turn(player = 0, x = 0, y) { 51 | if (this.board === 511) return -3 52 | let pos = 0 53 | if (y == null) { 54 | if (x < 0 || x > 8) return -1 55 | pos = 1 << x 56 | } else { 57 | if (x < 0 || x > 2 || y < 0 || y > 2) return -1 58 | pos = TicTacToe.toBinary(x, y) 59 | } 60 | if (this._currentTurn ^ player) return -2 61 | if (this.board & pos) return 0 62 | this[this._currentTurn ? '_o' : '_x'] |= pos 63 | this._currentTurn = !this._currentTurn 64 | this.turns++ 65 | return 1 66 | } 67 | 68 | /** 69 | * @returns {('X'|'O'|1|2|3|4|5|6|7|8|9)[]} 70 | */ 71 | static render(boardX = 0, boardO = 0) { 72 | let x = parseInt(boardX.toString(2), 4) 73 | let y = parseInt(boardO.toString(2), 4) * 2 74 | return [...(x + y).toString(4).padStart(9, '0')].reverse().map((value, index) => value == 1 ? 'X' : value == 2 ? 'O' : ++index) 75 | } 76 | 77 | /** 78 | * @returns {('X'|'O'|1|2|3|4|5|6|7|8|9)[]} 79 | */ 80 | render() { 81 | return TicTacToe.render(this._x, this._o) 82 | } 83 | 84 | get winner() { 85 | let x = TicTacToe.check(this._x) 86 | let o = TicTacToe.check(this._o) 87 | return x ? this.playerX : o ? this.playerO : false 88 | } 89 | } 90 | 91 | new TicTacToe().turn 92 | 93 | export default TicTacToe 94 | -------------------------------------------------------------------------------- /lib/uploadFile.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch' 2 | import { FormData, Blob } from 'formdata-node' 3 | import { fileTypeFromBuffer } from 'file-type' 4 | 5 | export default async buffer => { 6 | let { ext, mime } = await fileTypeFromBuffer(buffer) 7 | let form = new FormData() 8 | let blob = new Blob([buffer.toArrayBuffer()], { type: mime }) 9 | form.append('file', blob, 'tmp.' + ext) 10 | let res = await fetch('https://ichikaa.xyz/upload', { 11 | method: 'post', 12 | body: form 13 | }) 14 | if (!res.ok) throw await res.text() 15 | let img = await res.json() 16 | return img.result.url 17 | } 18 | -------------------------------------------------------------------------------- /lib/uploadImage.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch'; 2 | import { FormData, Blob } from 'formdata-node'; 3 | import { fileTypeFromBuffer } from 'file-type' 4 | 5 | /** 6 | * Upload image to telegra.ph 7 | * Supported mimetype: 8 | * - `image/jpeg` 9 | * - `image/jpg` 10 | * - `image/png`s 11 | * @param {Buffer} buffer Image Buffer 12 | * @return {Promise} 13 | */ 14 | 15 | export default async buffer => { 16 | const { ext, mime } = await fileTypeFromBuffer(buffer) 17 | let form = new FormData() 18 | const blob = new Blob([buffer.toArrayBuffer()], { type: mime }) 19 | form.append('file', blob, 'tmp.' + ext) 20 | let res = await fetch('https://telegra.ph/upload', { 21 | method: 'POST', 22 | body: form 23 | }) 24 | let img = await res.json() 25 | if (img.error) throw img.error 26 | return 'https://telegra.ph' + img[0].src 27 | } 28 | -------------------------------------------------------------------------------- /lib/util.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch' 2 | 3 | export const shortUrl = async (url) => { 4 | return await (await fetch(`https://tinyurl.com/api-create.php?url=${url}`)).text() 5 | } 6 | -------------------------------------------------------------------------------- /lib/webp2mp4.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch'; 2 | import { FormData, Blob } from 'formdata-node'; 3 | import { JSDOM } from 'jsdom'; 4 | import https from 'https'; 5 | 6 | let agent = new https.Agent({ rejectUnauthorized: false }); 7 | 8 | /** 9 | * 10 | * @param {Buffer|String} source 11 | */ 12 | async function webp2mp4(source) { 13 | let form = new FormData() 14 | let isUrl = typeof source === 'string' && /https?:\/\//.test(source) 15 | const blob = !isUrl && new Blob([source.toArrayBuffer()]) 16 | form.append('new-image-url', isUrl ? blob : '') 17 | form.append('new-image', isUrl ? '' : blob, 'image.webp') 18 | let res = await fetch('https://s6.ezgif.com/webp-to-mp4', { 19 | method: 'POST', 20 | body: form, 21 | agent 22 | }) 23 | let html = await res.text() 24 | let { document } = new JSDOM(html).window 25 | let form2 = new FormData() 26 | let obj = {} 27 | for (let input of document.querySelectorAll('form input[name]')) { 28 | obj[input.name] = input.value 29 | form2.append(input.name, input.value) 30 | } 31 | let res2 = await fetch('https://ezgif.com/webp-to-mp4/' + obj.file, { 32 | method: 'POST', 33 | body: form2, 34 | agent 35 | }) 36 | let html2 = await res2.text() 37 | let { document: document2 } = new JSDOM(html2).window 38 | return new URL(document2.querySelector('div#output > p.outfile > video > source').src, res2.url).toString() 39 | } 40 | 41 | async function webp2png(source) { 42 | let form = new FormData() 43 | let isUrl = typeof source === 'string' && /https?:\/\//.test(source) 44 | const blob = !isUrl && new Blob([source.toArrayBuffer()]) 45 | form.append('new-image-url', isUrl ? blob : '') 46 | form.append('new-image', isUrl ? '' : blob, 'image.webp') 47 | let res = await fetch('https://s6.ezgif.com/webp-to-png', { 48 | method: 'POST', 49 | body: form, 50 | agent 51 | }) 52 | let html = await res.text() 53 | let { document } = new JSDOM(html).window 54 | let form2 = new FormData() 55 | let obj = {} 56 | for (let input of document.querySelectorAll('form input[name]')) { 57 | obj[input.name] = input.value 58 | form2.append(input.name, input.value) 59 | } 60 | let res2 = await fetch('https://ezgif.com/webp-to-png/' + obj.file, { 61 | method: 'POST', 62 | body: form2, 63 | agent 64 | }) 65 | let html2 = await res2.text() 66 | let { document: document2 } = new JSDOM(html2).window 67 | return new URL(document2.querySelector('div#output > p.outfile > img').src, res2.url).toString() 68 | } 69 | 70 | export { 71 | webp2mp4, 72 | webp2png 73 | } 74 | -------------------------------------------------------------------------------- /lib/y2mate.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch'; 2 | import { JSDOM } from 'jsdom' 3 | 4 | function post(url, formdata) { 5 | return fetch(url, { 6 | method: 'POST', 7 | headers: { 8 | accept: "*/*", 9 | 'accept-language': "en-US,en;q=0.9", 10 | 'content-type': "application/x-www-form-urlencoded; charset=UTF-8" 11 | }, 12 | body: new URLSearchParams(Object.entries(formdata)) 13 | }) 14 | } 15 | const ytIdRegex = /(?:http(?:s|):\/\/|)(?:(?:www\.|)youtube(?:\-nocookie|)\.com\/(?:shorts\/)?(?:watch\?.*(?:|\&)v=|embed\/|v\/)|youtu\.be\/)([-_0-9A-Za-z]{11})/ 16 | 17 | /** 18 | * Download YouTube Video via y2mate 19 | * @param {String} url YouTube Video URL 20 | * @param {String} quality (avaiable: `144p`, `240p`, `360p`, `480p`, `720p`, `1080p`, `1440p`, `2160p`) 21 | * @param {String} type (avaiable: `mp3`, `mp4`) 22 | * @param {String} bitrate (avaiable for video: `144`, `240`, `360`, `480`, `720`, `1080`, `1440`, `2160`) 23 | * (avaiable for audio: `128`) 24 | * @param {String} server (avaiable: `id4`, `en60`, `en61`, `en68`) 25 | */ 26 | async function yt(url, quality, type, bitrate, server = 'en68') { 27 | if (!ytIdRegex.test(url)) throw 'Invalid URL' 28 | let ytId = ytIdRegex.exec(url) 29 | url = 'https://youtu.be/' + ytId[1] 30 | let res = await post(`https://www.y2mate.com/mates/${server}/analyze/ajax`, { 31 | url, 32 | q_auto: 0, 33 | ajax: 1 34 | }) 35 | let json = await res.json() 36 | let { document } = (new JSDOM(json.result)).window 37 | let tables = document.querySelectorAll('table') 38 | let table = tables[{ mp4: 0, mp3: 1 }[type] || 0] 39 | let list 40 | switch (type) { 41 | case 'mp4': 42 | list = Object.fromEntries([...table.querySelectorAll('td > a[href="#"]')].filter(v => !/\.3gp/.test(v.innerHTML)).map(v => [v.innerHTML.match(/.*?(?=\()/)[0].trim(), v.parentElement.nextSibling.nextSibling.innerHTML])) 43 | break 44 | case 'mp3': 45 | list = { 46 | '128kbps': table.querySelector('td > a[href="#"]').parentElement.nextSibling.nextSibling.innerHTML 47 | } 48 | break 49 | default: 50 | list = {} 51 | } 52 | let filesize = list[quality] 53 | let id = /var k__id = "(.*?)"/.exec(document.body.innerHTML) || ['', ''] 54 | let thumb = document.querySelector('img').src 55 | let title = document.querySelector('b').innerHTML 56 | let res2 = await post(`https://www.y2mate.com/mates/${server}/convert`, { 57 | type: 'youtube', 58 | _id: id[1], 59 | v_id: ytId[1], 60 | ajax: '1', 61 | token: '', 62 | ftype: type, 63 | fquality: bitrate 64 | }) 65 | let json2 = await res2.json() 66 | let KB = parseFloat(filesize) * (1000 * /MB$/.test(filesize)) 67 | return { 68 | dl_link: / m 2 | handler.before = m => { 3 | let user = global.DATABASE.data.users[m.sender] 4 | if (user.afk > -1) { 5 | m.reply(` 6 | You stop AFK${user.afkReason ? ' after ' + user.afkReason : ''} 7 | During ${clockString(new Date - user.afk)} 8 | `.trim()) 9 | user.afk = -1 10 | user.afkReason = '' 11 | } 12 | let jids = [...new Set([...(m.mentionedJid || []), ...(m.quoted ? [m.quoted.sender] : [])])] 13 | for (let jid of jids) { 14 | let user = global.DATABASE.data.users[jid] 15 | if (!user) continue 16 | let afkTime = user.afk 17 | if (!afkTime || afkTime < 0) continue 18 | let reason = user.afkReason || '' 19 | m.reply(` 20 | Don't tag him! 21 | He is AFK ${reason ? ' with reason ' + reason : 'no reason'} 22 | During ${clockString(new Date - afkTime)} 23 | `.trim()) 24 | } 25 | return true 26 | } 27 | 28 | export default handler 29 | 30 | function clockString(ms) { 31 | let h = isNaN(ms) ? '--' : Math.floor(ms / 3600000) 32 | let m = isNaN(ms) ? '--' : Math.floor(ms / 60000) % 60 33 | let s = isNaN(ms) ? '--' : Math.floor(ms / 1000) % 60 34 | return [h, m, s].map(v => v.toString().padStart(2, 0) ).join(':') 35 | } 36 | -------------------------------------------------------------------------------- /plugins/_antilink.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created By LUA SER OFC 3 | * CopyRight 2024 MIT License 4 | * My Github : https://github.com/xxirfanx 5 | * My Instagram : https://instagram.com/luaserofc 6 | * My Youtube : https://youtube.com/@luaserofc 7 | */ 8 | 9 | const linkRegex = /chat.whatsapp.com\/(?:invite\/)?([0-9A-Za-z]{20,24})/i 10 | 11 | export async function before(m, {conn, isAdmin, isBotAdmin }) { 12 | if (m.isBaileys && m.fromMe) 13 | return !0 14 | if (!m.isGroup) return !1 15 | let chat = global.db.data.chats[m.chat] 16 | let bot = global.db.data.settings[this.user.jid] || {} 17 | const isGroupLink = linkRegex.exec(m.text) 18 | 19 | if (chat.antiLink && isGroupLink && !isAdmin) { 20 | if (isBotAdmin) { 21 | const linkThisGroup = `https://chat.whatsapp.com/${await this.groupInviteCode(m.chat)}` 22 | if (m.text.includes(linkThisGroup)) return !0 23 | } 24 | await conn.reply(m.chat, `*⛽ Detected Link* 25 | 26 | We do not allow links from other groups 27 | I'm sorry *@${m.sender.split('@')[0]}* you will be expelled from the group ${isBotAdmin ? '' : '\n\n Im not an admin so I cant expel you :"v'}`, null, { mentions: [m.sender] } ) 28 | if (isBotAdmin && chat.antiLink) { 29 | await conn.sendMessage(m.chat, { delete: m.key }) 30 | await conn.groupParticipantsUpdate(m.chat, [m.sender], 'remove') 31 | } else if (!chat.antiLink) return //m.reply('') 32 | } 33 | return !0 34 | } 35 | -------------------------------------------------------------------------------- /plugins/_cek.js: -------------------------------------------------------------------------------- 1 | let handler = async ( m ) => { 2 | m.reply('Hello!') 3 | } 4 | 5 | handler.command = /^(cek|tes|alive|p|a)$/i 6 | 7 | export default handler 8 | -------------------------------------------------------------------------------- /plugins/_memfess-Ans.js: -------------------------------------------------------------------------------- 1 | export async function before(m) { 2 | if (!m.chat.endsWith('@s.whatsapp.net')) return !0; 3 | this.menfess = this.menfess ? this.menfess : {} 4 | let mf = Object.values(this.menfess).find(v => v.status === false && v.penerima == m.sender) 5 | if (!mf) return !0 6 | console.log(m) 7 | if (m.text === 'Reply' && m.quoted.mtype == 'buttonsMessage') return m.reply("Please send your reply message."); 8 | let txt = `Hai @${mf.dari.split('@')[0]}, you received this reply.\n\nReply message:\n${m.text}\n`.trim(); 9 | await this.reply(mf.dari, txt, null).then(() => { 10 | m.reply('Menfess reply sent.') 11 | this.delay(1000) 12 | delete this.menfess[mf.id] 13 | return !0 14 | }) 15 | } -------------------------------------------------------------------------------- /plugins/_templateResponse.js: -------------------------------------------------------------------------------- 1 | const { 2 | proto, 3 | generateWAMessage, 4 | areJidsSameUser 5 | } = (await import('@adiwajshing/baileys')).default 6 | 7 | export async function all(m, chatUpdate) { 8 | if (m.isBaileys) return 9 | if (!m.message) return 10 | if (!(m.message.buttonsResponseMessage || m.message.templateButtonReplyMessage || m.message.listResponseMessage || m.message.interactiveResponseMessage || m.message.pollUpdateMessage || m.message.editedMessage)) return 11 | 12 | let id = (m.mtype === 'conversation') ? m.message.conversation : (m.mtype == 'imageMessage') ? m.message.imageMessage.caption : (m.mtype == 'videoMessage') ? m.message.videoMessage.caption : (m.mtype == 'extendedTextMessage') ? m.message.extendedTextMessage.text : (m.mtype == 'buttonsResponseMessage') ? m.message.buttonsResponseMessage.selectedButtonId : (m.mtype == 'listResponseMessage') ? m.message.listResponseMessage.singleSelectReply.selectedRowId : (m.mtype == 'templateButtonReplyMessage') ? m.message.templateButtonReplyMessage.selectedId : (m.mtype == 'interactiveResponseMessage') ? JSON.parse(m.msg.nativeFlowResponseMessage.paramsJson).id : (m.mtype == 'templateButtonReplyMessage') ? appenTextMessage(m.msg.selectedId, chatUpdate) : (m.mtype === 'messageContextInfo') ? (m.message.buttonsResponseMessage?.selectedButtonId || m.message.listResponseMessage?.singleSelectReply.selectedRowId || m.text) : (m.mtype === 'editedMessage') ? m.message.editedMessage.message.protocolMessage.editedMessage.conversation ? m.message.editedMessage.message.protocolMessage.editedMessage.conversation : m.message.editedMessage.message.protocolMessage.editedMessage.extendedTextMessage.text : '' 13 | 14 | try { 15 | 16 | let messages = await generateWAMessage(m.chat, { text: id, mentions: m.mentionedJid }, { 17 | userJid: this.user.id, 18 | quoted: m.quoted && m.quoted.fakeObj 19 | }) 20 | messages.key.fromMe = areJidsSameUser(m.sender, this.user.id) 21 | messages.key.id = m.key.id 22 | messages.pushName = m.name 23 | if (m.isGroup) 24 | messages.key.participant = messages.participant = m.sender 25 | let msg = { 26 | ...chatUpdate, 27 | messages: [proto.WebMessageInfo.fromObject(messages)].map(v => (v.conn = this, v)), 28 | type: 'append' 29 | } 30 | this.ev.emit('messages.upsert', msg) 31 | } catch (e) { 32 | false 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /plugins/_ttt.js: -------------------------------------------------------------------------------- 1 | import { format } from 'util' 2 | 3 | let debugMode = !1 4 | 5 | let winScore = 4999 6 | let playScore = 99 7 | 8 | export async function before(m) { 9 | let ok 10 | let isWin = !1 11 | let isTie = !1 12 | let isSurrender = !1 13 | this.game = this.game ? this.game : {} 14 | let room = Object.values(this.game).find(room => room.id && room.game && room.state && room.id.startsWith('tictactoe') && [room.game.playerX, room.game.playerO].includes(m.sender) && room.state == 'PLAYING') 15 | if (room) { 16 | // m.reply(`[DEBUG]\n${parseInt(m.text)}`) 17 | if (!/^([1-9]|(me)?nyerah|surr?ender)$/i.test(m.text)) 18 | return !0 19 | isSurrender = !/^[1-9]$/.test(m.text) 20 | if (m.sender !== room.game.currentTurn) { // nek wayahku 21 | if (!isSurrender) 22 | return !0 23 | } 24 | if (debugMode) 25 | m.reply('[DEBUG]\n' + require('util').format({ 26 | isSurrender, 27 | text: m.text 28 | })) 29 | if (!isSurrender && 1 > (ok = room.game.turn(m.sender === room.game.playerO, parseInt(m.text) - 1))) { 30 | m.reply({ 31 | '-3': 'Game has ended', 32 | '-2': 'Invalid', 33 | '-1': 'Position Invalid', 34 | 0: 'Position Invalid', 35 | }[ok]) 36 | return !0 37 | } 38 | if (m.sender === room.game.winner) 39 | isWin = true 40 | else if (room.game.board === 511) 41 | isTie = true 42 | let arr = room.game.render().map(v => { 43 | return { 44 | X: '❌', 45 | O: '⭕', 46 | 1: '1️⃣', 47 | 2: '2️⃣', 48 | 3: '3️⃣', 49 | 4: '4️⃣', 50 | 5: '5️⃣', 51 | 6: '6️⃣', 52 | 7: '7️⃣', 53 | 8: '8️⃣', 54 | 9: '9️⃣', 55 | }[v] 56 | }) 57 | if (isSurrender) { 58 | room.game._currentTurn = m.sender === room.game.playerX 59 | isWin = true 60 | } 61 | let winner = isSurrender ? room.game.currentTurn : room.game.winner 62 | let str = ` 63 | ${arr.slice(0, 3).join('')} 64 | ${arr.slice(3, 6).join('')} 65 | ${arr.slice(6).join('')} 66 | ${isWin ? `@${winner.split('@')[0]} Win! (+${winScore} XP)` : isTie ? `Game over (+${playScore} XP)` : `turn ${['❌', '⭕'][1 * room.game._currentTurn]} (@${room.game.currentTurn.split('@')[0]})`} 67 | ❌: @${room.game.playerX.split('@')[0]} 68 | ⭕: @${room.game.playerO.split('@')[0]} 69 | Type *giveup* for giveup 70 | Room ID: ${room.id} 71 | `.trim() 72 | let users = db.data.users 73 | if ((room.game._currentTurn ^ isSurrender ? room.x : room.o) !== m.chat) 74 | room[room.game._currentTurn ^ isSurrender ? 'x' : 'o'] = m.chat 75 | const btn = isTie ? ['TicTacToe', '/ttt'] : ['giveup', 'giveup'] 76 | if (room.x !== room.o) 77 | await this.reply(room.x, str, m, { 78 | mentions: this.parseMention(str) 79 | }) 80 | await this.reply(room.o, str, m, { 81 | mentions: this.parseMention(str) 82 | }) 83 | if (isTie || isWin) { 84 | users[room.game.playerX].exp += playScore 85 | users[room.game.playerO].exp += playScore 86 | if (isWin) 87 | users[winner].exp += winScore - playScore 88 | if (debugMode) 89 | m.reply('[DEBUG]\n' + format(room)) 90 | delete this.game[room.id] 91 | } 92 | } 93 | return !0 94 | } -------------------------------------------------------------------------------- /plugins/afk.js: -------------------------------------------------------------------------------- 1 | let handler = async (m, { text }) => { 2 | let user = global.DATABASE.data.users[m.sender] 3 | user.afk = + new Date 4 | user.afkReason = text 5 | m.reply(` 6 | ${conn.getName(m.sender)} is now AFK${text ? ': ' + text : ''} 7 | `) 8 | } 9 | handler.help = ['afk [reason]'] 10 | handler.tags = ['main'] 11 | handler.command = /^afk$/i 12 | 13 | export default handler -------------------------------------------------------------------------------- /plugins/ai-animediff.js: -------------------------------------------------------------------------------- 1 | import fetch from "node-fetch" 2 | 3 | let handler = async (m, { conn, text, usedPrefix, command }) => { 4 | let wm = global.me 5 | 6 | if (!text) throw `This command generates image from texts\n\n Example usage\n${ usedPrefix + command } 1girl, blush, megane, school uniform` 7 | await m.reply('*Processing image*') 8 | await conn.relayMessage(m.chat, { reactionMessage: { key: m.key, text: '⌛' }}, { messageId: m.key.id }) 9 | try { 10 | let url = `https://api.xyroinee.xyz/api/ai/animediffusion?q=${text}&apikey=${global.xyro}` 11 | await conn.sendFile(m.chat, await(await fetch(url)).buffer(), 'image.jpg', wm, m) 12 | m.react(done) 13 | } catch (e) { 14 | console.log(e) 15 | m.reply(eror) 16 | } 17 | 18 | } 19 | 20 | 21 | handler.help = ['animediff '] 22 | handler.tags = ['ai'] 23 | handler.command = /^(animediff)$/i 24 | 25 | export default handler -------------------------------------------------------------------------------- /plugins/ai-animediff2.js: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------*/ 2 | /* [❗] [❗] [❗] */ 3 | /* */ 4 | /* |- [ ⚠ ] - CODE CREDITS - [ ⚠ ] -| */ 5 | /* —◉ DEVELOPED BY LUA SER OFC: */ 6 | /* ◉ git : (https://github.com/xxirfanx) */ 7 | /* */ 8 | /* [❗] [❗] [❗] */ 9 | /* -------------------------------------------------------*/ 10 | import fetch from "node-fetch" 11 | 12 | let handler = async (m, { conn, text, usedPrefix, command }) => { 13 | let wm = global.me 14 | if (!text) throw `This command generates image from texts\n\n Example usage\n${ usedPrefix + command } 1girl, blush, megane, school uniform` 15 | await m.reply('*Processing image*') 16 | await conn.relayMessage(m.chat, { reactionMessage: { key: m.key, text: '⌛' }}, { messageId: m.key.id }) 17 | try { 18 | let ff = await fetch(`https://api.neoxr.eu/api/waifudiff?q=${text}`) 19 | let anu = await ff.json() 20 | await conn.sendFile(m.chat, anu.data.url, 'image.jpg', wm, m) 21 | m.react('🎐') 22 | } catch (e) { 23 | console.log(e) 24 | m.reply(eror) 25 | } 26 | } 27 | 28 | handler.help = ['animediff2 '] 29 | handler.tags = ['ai'] 30 | handler.command = /^(animediff2)$/i 31 | 32 | export default handler 33 | -------------------------------------------------------------------------------- /plugins/ai-chatgpt.js: -------------------------------------------------------------------------------- 1 | // made by lua ser ofc 2 | import fetch from 'node-fetch' 3 | 4 | let handler = async (m, { text, usedPrefix, command }) => { 5 | if (!text) throw `Hey is there anything I can help you with??` 6 | let order = { text: wait, mentions: [m.sender], contextInfo: { forwardingScore: 256, isForwarded: true }}; 7 | let aii = await fetch(`https://api.lolhuman.xyz/api/openai?apikey=${apilol} 8 | &text=${text}&user=user-unique-en`) 9 | let oke = await aii.json() 10 | let { key } = await conn.sendMessage(m.chat, order, { quoted: m }); 11 | await new Promise(resolve => setTimeout(resolve, 2000)); 12 | await conn.sendMessage(m.chat, { text: `${oke.result}`, edit: key }, { quoted: m }); 13 | } 14 | 15 | handler.help = ['ai', 'openai', 'gpt'] 16 | handler.tags = ['ai'] 17 | handler.command = /^(ai|openai|gpt)$/i 18 | 19 | export default handler 20 | -------------------------------------------------------------------------------- /plugins/anonymous_chat.js: -------------------------------------------------------------------------------- 1 | async function handler(m, { command }) { 2 | this.anonymous = this.anonymous ? this.anonymous : {} 3 | switch (command) { 4 | case 'next': 5 | case 'leave': { 6 | let room = Object.values(this.anonymous).find(room => room.check(m.sender)) 7 | if (!room) return this.reply(m.chat, '_You are not currently in anonymous chat_\n\ntype *.start* to find partners', m) 8 | m.reply('Ok') 9 | let other = room.other(m.sender) 10 | if (other) await this.reply(other, '_Partners leave chat_\n\ntype *.start* to find partners', m) 11 | delete this.anonymous[room.id] 12 | if (command === 'leave') break 13 | } 14 | case 'start': { 15 | if (Object.values(this.anonymous).find(room => room.check(m.sender))) return this.reply(m.chat, '_You are still in the anonymous chat, waiting for a partner_\n\ntype *.leave* to get out of', m) 16 | let room = Object.values(this.anonymous).find(room => room.state === 'WAITING' && !room.check(m.sender)) 17 | if (room) { 18 | await this.reply(room.a, '_Partner found!_', m) 19 | room.b = m.sender 20 | room.state = 'CHATTING' 21 | await this.reply(room.b, '_Partner found!_', m) 22 | } else { 23 | let id = + new Date 24 | this.anonymous[id] = { 25 | id, 26 | a: m.sender, 27 | b: '', 28 | state: 'WAITING', 29 | check: function (who = '') { 30 | return [this.a, this.b].includes(who) 31 | }, 32 | other: function (who = '') { 33 | return who === this.a ? this.b : who === this.b ? this.a : '' 34 | }, 35 | } 36 | await this.reply(m.chat, '_Waiting for partners..._\n\ntype *.leave* to get out of', m) 37 | } 38 | break 39 | } 40 | } 41 | } 42 | 43 | handler.help = ['start', 'leave', 'next'] 44 | handler.tags = ['anonymous'] 45 | handler.command = ['start', 'leave', 'next'] 46 | 47 | handler.private = true 48 | 49 | export default handler 50 | -------------------------------------------------------------------------------- /plugins/anonymous_chat_.js: -------------------------------------------------------------------------------- 1 | export async function before(m, { match }) { 2 | // if (match) return !1 3 | if (!m.chat.endsWith('@s.whatsapp.net')) 4 | return !0 5 | this.anonymous = this.anonymous ? this.anonymous : {} 6 | let room = Object.values(this.anonymous).find(room => [room.a, room.b].includes(m.sender) && room.state === 'CHATTING') 7 | if (room) { 8 | if (/^.*(next|leave|start)/.test(m.text)) 9 | return 10 | let other = [room.a, room.b].find(user => user !== m.sender) 11 | await m.copyNForward(other, true) 12 | } 13 | return !0 14 | } 15 | -------------------------------------------------------------------------------- /plugins/cmd-del.js: -------------------------------------------------------------------------------- 1 | let handler = async (m, { conn, usedPrefix, text, command }) => { 2 | let hash = text 3 | if (m.quoted && m.quoted.fileSha256) hash = m.quoted.fileSha256.toString('hex') 4 | if (!hash) throw `No hash` 5 | let sticker = global.db.data.sticker 6 | if (sticker[hash] && sticker[hash].locked) throw 'You do not have permission to remove this sticker prompt' 7 | delete sticker[hash] 8 | m.reply(`Succeed!`) 9 | } 10 | 11 | 12 | handler.help = ['cmd'].map(v => 'del' + v + ' ') 13 | handler.tags = ['database'] 14 | handler.command = ['delcmd'] 15 | handler.premium = true 16 | 17 | export default handler -------------------------------------------------------------------------------- /plugins/cmd-list.js: -------------------------------------------------------------------------------- 1 | let handler = async (m, { conn }) => { 2 | conn.reply(m.chat, ` 3 | *LIST HASH* 4 | \`\`\` 5 | ${Object.entries(global.db.data.sticker).map(([key, value], index) => `${index + 1}. ${value.locked ? `(Locked) ${key}` : key} : ${value.text}`).join('\n')} 6 | \`\`\` 7 | `.trim(), null, { 8 | mentions: Object.values(global.db.data.sticker).map(x => x.mentionedJid).reduce((a, b) => [...a, ...b], []) 9 | }) 10 | } 11 | 12 | 13 | handler.help = ['listcmd'] 14 | handler.tags = ['database'] 15 | handler.command = ['listcmd'] 16 | 17 | export default handler -------------------------------------------------------------------------------- /plugins/cmd-lock.js: -------------------------------------------------------------------------------- 1 | let handler = async (m, { conn, text, usedPrefix, command }) => { 2 | if (!m.quoted) throw 'Reply Message!' 3 | if (!m.quoted.fileSha256) throw 'SHA256 Hash Missing' 4 | let sticker = global.db.data.sticker 5 | let hash = m.quoted.fileSha256.toString('hex') 6 | if (!(hash in sticker)) throw 'Hash not found in database' 7 | sticker[hash].locked = !/^un/i.test(command) 8 | m.reply('Done!') 9 | } 10 | handler.help = ['un', ''].map(v => v + 'lockcmd') 11 | handler.tags = ['database'] 12 | handler.command = /^(un)?lockcmd$/i 13 | handler.premium = true 14 | 15 | export default handler -------------------------------------------------------------------------------- /plugins/cmd-set.js: -------------------------------------------------------------------------------- 1 | let handler = async (m, { text, usedPrefix, command }) => { 2 | global.db.data.sticker = global.db.data.sticker || {} 3 | if (!m.quoted) throw `Reply to stickers with commands *${usedPrefix + command}*` 4 | if (!m.quoted.fileSha256) throw 'SHA256 Hash Missing' 5 | if (!text) throw `Use:\n${usedPrefix + command} \n\nExample:\n${usedPrefix + command} tes` 6 | let sticker = global.db.data.sticker 7 | let hash = m.quoted.fileSha256.toString('base64') 8 | if (sticker[hash] && sticker[hash].locked) throw 'You do not have permission to change the order of this sticker' 9 | sticker[hash] = { 10 | text, 11 | mentionedJid: m.mentionedJid, 12 | creator: m.sender, 13 | at: + new Date, 14 | locked: false, 15 | } 16 | m.reply(`Succeed!`) 17 | } 18 | 19 | handler.help = handler.alias = ['cmdset'] 20 | handler.tags = ['database'] 21 | handler.command = /^((set|add)cmd|cmd(set|add))$/i 22 | 23 | handler.database = true 24 | 25 | export default handler 26 | -------------------------------------------------------------------------------- /plugins/creator.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch' 2 | let handler = async (m, { conn, usedPrefix, text, args, command }) => { 3 | let who = m.mentionedJid && m.mentionedJid[0] ? m.mentionedJid[0] : m.fromMe ? conn.user.jid : m.sender 4 | let pp = await conn.profilePictureUrl(who).catch(_ => thumbnailUrl.getRandom()) 5 | let name = await conn.getName(who) 6 | 7 | const sentMsg = await conn.sendContactArray(m.chat, [ 8 | [nomorown, `${await conn.getName(nomorown + '@s.whatsapp.net')}`, `💌 Developer Bot `, `Not Famous`, `sousakura666@gmail.com`, `🇯🇵 japan`, `📍 https://xxirfanx.github.io`, `👤 Owner zoro Bot`], 9 | [`${conn.user.jid.split('@')[0]}`, `${await conn.getName(conn.user.jid)}`, `🎈 Whatsapp Bot`, `📵 Dont Spam`, `Nothing`, `🇯🇵 japan`, `📍 https://github.com/xxirfanx/zoromd`, `Just a normal bot that sometimes has an error ☺`] 10 | ], fkontak) 11 | await conn.reply(m.chat,`Hello @${m.sender.split(`@`)[0]} Thats my owner, dont spam or i will block u`, sentMsg, { 12 | mentions: [m.sender] 13 | }) 14 | } 15 | 16 | handler.help = ['owner', 'creator'] 17 | handler.tags = ['info'] 18 | 19 | handler.command = /^(owner|creator)$/i 20 | 21 | export default handler 22 | -------------------------------------------------------------------------------- /plugins/downloader-fb.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch' 2 | import fg from 'api-dylux' 3 | 4 | 5 | const handler = async (m, { conn, args, usedPrefix, command }) => { 6 | if (!args[0]) { 7 | throw `✳️ Please send the link of a Facebook video\n\n📌 EXAMPLE :\n*${usedPrefix + command}* https://www.facebook.com/Ankursajiyaan/videos/981948876160874/?mibextid=rS40aB7S9Ucbxw6v`; 8 | } 9 | 10 | const urlRegex = /^(?:https?:\/\/)?(?:www\.)?(?:facebook\.com|fb\.watch)\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/i; 11 | if (!urlRegex.test(args[0])) { 12 | throw '⚠️ PLEASE GIVE A VALID URL.' 13 | } 14 | 15 | await conn.relayMessage(m.chat, { reactionMessage: { key: m.key, text: '⌛' }}, { messageId: m.key.id }) 16 | 17 | try { 18 | const result = await fg.fbdl(args[0]); 19 | const tex = ` 20 | ⊱ ─── {* Facebook dwd *} ─── ⊰ 21 | ↳ *VIDEO TITLE:* ${result.title} 22 | ⊱ ────── {⋆♬⋆} ────── ⊰` 23 | 24 | const response = await fetch(result.videoUrl) 25 | const arrayBuffer = await response.arrayBuffer() 26 | const videoBuffer = Buffer.from(arrayBuffer) 27 | 28 | conn.sendFile(m.chat, videoBuffer, 'fb.mp4', tex, m) 29 | } catch (error) { 30 | console.log(error) 31 | m.reply('⚠️ An error occurred while processing the request. Please try again later.') 32 | } 33 | } 34 | 35 | handler.help = ['facebook '] 36 | handler.tags = ['downloader'] 37 | handler.command = /^((facebook|fb)(downloder|dl)?)$/i 38 | 39 | export default handler 40 | -------------------------------------------------------------------------------- /plugins/downloader-gddl.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch' 2 | import { sizeFormatter } from 'human-readable' 3 | let formatSize = sizeFormatter({ 4 | std: 'JEDEC', decimalPlaces: 2, keepTrailingZeroes: false, render: (literal, symbol) => `${literal} ${symbol}B` 5 | }) 6 | 7 | let handler = async (m, { conn, args }) => { 8 | if (!args[0]) throw 'Input URL' 9 | GDriveDl(args[0]).then(async (res) => { 10 | if (!res) throw res 11 | await m.reply(JSON.stringify(res, null, 2)) 12 | conn.sendMessage(m.chat, { document: { url: res.downloadUrl }, fileName: res.fileName, mimetype: res.mimetype }, { quoted: m }) 13 | }) 14 | } 15 | 16 | handler.help = ['gdrive'] 17 | handler.tags = ['downloader'] 18 | handler.command = /^(gdrive)$/i 19 | handler.disabled = false 20 | 21 | export default handler 22 | 23 | async function GDriveDl(url) { 24 | let id 25 | if (!(url && url.match(/drive\.google/i))) throw 'Invalid URL' 26 | id = (url.match(/\/?id=(.+)/i) || url.match(/\/d\/(.*?)\//))[1] 27 | if (!id) throw 'ID Not Found' 28 | let res = await fetch(`https://drive.google.com/uc?id=${id}&authuser=0&export=download`, { 29 | method: 'post', 30 | headers: { 31 | 'accept-encoding': 'gzip, deflate, br', 32 | 'content-length': 0, 33 | 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 34 | 'origin': 'https://drive.google.com', 35 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36', 36 | 'x-client-data': 'CKG1yQEIkbbJAQiitskBCMS2yQEIqZ3KAQioo8oBGLeYygE=', 37 | 'x-drive-first-party': 'DriveWebUi', 38 | 'x-json-requested': 'true' 39 | } 40 | }) 41 | let { fileName, sizeBytes, downloadUrl } = JSON.parse((await res.text()).slice(4)) 42 | if (!downloadUrl) throw 'Link Download Limit!' 43 | let data = await fetch(downloadUrl) 44 | if (data.status !== 200) throw data.statusText 45 | return { downloadUrl, fileName, fileSize: formatSize(sizeBytes), mimetype: data.headers.get('content-type') } 46 | } -------------------------------------------------------------------------------- /plugins/downloader-git.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch' 2 | const regex = /(?:https|git)(?::\/\/|@)github\.com[\/:]([^\/:]+)\/(.+)/i 3 | 4 | let handler = async (m, {conn, text, args, usedPrefix, command }) => { 5 | if (!args[0]) throw `Example user ${usedPrefix}${command} xxirfanx/zoromd` 6 | let [usr, rep] = text.split`/` 7 | let url = `https://api.github.com/repos/${encodeURIComponent(usr)}/${encodeURIComponent(rep)}/zipball` 8 | let name = `${encodeURIComponent(rep)}.zip` 9 | m.reply(`D o w n l o a d i n g. . .`) 10 | conn.sendFile(m.chat, url, name, null, m) 11 | } 12 | 13 | handler.help = ['gitclone /'] 14 | handler.tags = ['downloader'] 15 | handler.command = /gitclone/i 16 | 17 | export default handler -------------------------------------------------------------------------------- /plugins/downloader-ig.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created By LUA SER OFC 3 | * CopyRight 2024 MIT License 4 | * My Github : https://github.com/xxirfanx 5 | * My Instagram : https://instagram.com/luaserofc 6 | * My Youtube : https://youtube.com/@luaserofc 7 | */ 8 | 9 | const ig = await import('@sasmeee/igdl'); 10 | import fetch from 'node-fetch'; 11 | 12 | var handler = async (m, { args, conn, usedPrefix, command }) => { 13 | if (!args[0]) throw `Ex:\n${usedPrefix}${command} Link put`; 14 | 15 | conn.reply(m.chat, 'Currently downloading video...', m); 16 | 17 | let res = await ig.default(args[0]); 18 | let media = await res[0].download_link; 19 | 20 | const response = await fetch(media) 21 | const arrayBuffer = await response.arrayBuffer() 22 | const videoBuffer = Buffer.from(arrayBuffer) 23 | 24 | if (!res) throw 'Can\'t download the post'; 25 | 26 | conn.sendFile(m.chat, videoBuffer, 'ig.mp4', null, m) 27 | }; 28 | 29 | handler.help = ['instagram']; 30 | handler.tags = ['downloader']; 31 | handler.command = /^(ig(dl)?|instagram(dl)?|insta)$/i; 32 | 33 | export default handler; 34 | -------------------------------------------------------------------------------- /plugins/downloader-mediafire.js: -------------------------------------------------------------------------------- 1 | import { lookup } from 'mime-types' 2 | import { mediafiredl } from '@bochilteam/scraper' 3 | 4 | let handler = async (m, { conn, args }) => { 5 | if (!args[0]) throw 'Input URL' 6 | if (!/https?:\/\/(www\.)?mediafire\.com/.test(args[0])) throw 'Invalid URL' 7 | let res = await mediafiredl(args[0]) 8 | let mimetype = await lookup(res.url) 9 | delete res.url2 10 | m.reply(Object.keys(res).map(v => `*• ${v.capitalize()}:* ${res[v]}`).join('\n') + '\n\n_Sending file..._') 11 | conn.sendMessage(m.chat, { document: { url: res.url }, fileName: res.filename, mimetype }, { quoted: m }) 12 | } 13 | handler.help = handler.alias = ['mediafire'] 14 | handler.tags = ['downloader'] 15 | handler.command = /^(mediafire)$/i 16 | 17 | export default handler 18 | -------------------------------------------------------------------------------- /plugins/downloader-play.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created By LUA SER OFC 3 | * CopyRight 2024 MIT License 4 | * My Github : https://github.com/xxirfanx 5 | * My Instagram : https://instagram.com/luaserofc 6 | * My Youtube : https://youtube.com/@luaserofc 7 | */ 8 | 9 | import yts from 'yt-search'; 10 | 11 | let handler = async (m, { conn, command, text, usedPrefix }) => { 12 | if (!text) throw ` 🦄Use example *${usedPrefix + command}* Somewhere Only We Know`; 13 | let res = await yts(text) 14 | let vid = res.videos[0] 15 | if (!vid) throw `🍊 Audio not find title song `; 16 | let { title, description, thumbnail, videoId, timestamp, views, ago, url } = vid 17 | //const url = 'https://www.youtube.com/watch?v=' + videoId 18 | m.react(`🐢`) 19 | let play = ` 20 | 📺 *Title:* ${vid.title} 21 | ⌛ *Duration:* ${vid.timestamp} 22 | 👀 *Views:* ${vid.views.toLocaleString()} 23 | 📅 *Upload:* ${vid.ago} 24 | ` 25 | await conn.sendButton2(m.chat, play, '> Zoro md', thumbnail, [ 26 | ['🎶 MP3', `${usedPrefix}vfmp3 ${url}`]], null, null, m) 27 | } 28 | 29 | handler.help = ['play'].map((v) => v + ' ') 30 | handler.tags = ['downloader'] 31 | handler.command = ['play', 'song'] 32 | handler.disabled = false 33 | 34 | export default handler 35 | -------------------------------------------------------------------------------- /plugins/downloader-sfile.js: -------------------------------------------------------------------------------- 1 | import cheerio from 'cheerio' 2 | import fetch from 'node-fetch' 3 | 4 | let handler = async (m, { conn, text }) => { 5 | if (text.match(/(https:\/\/sfile.mobi\/)/gi)) { 6 | let res = await sfileDl(text) 7 | if (!res) throw 'Error :/' 8 | await m.reply(Object.keys(res).map(v => `*• ${v.capitalize()}:* ${res[v]}`).join('\n') + '\n\n_Sending file..._') 9 | conn.sendMessage(m.chat, { document: { url: res.download }, fileName: res.filename, mimetype: res.mimetype }, { quoted: m }) 10 | } else if (text) { 11 | let [query, page] = text.split`|` 12 | let res = await sfileSearch(query, page) 13 | if (!res.length) throw `Query "${text}" not found :/` 14 | res = res.map((v) => `*Title:* ${v.title}\n*Size:* ${v.size}\n*Link:* ${v.link}`).join`\n\n` 15 | m.reply(res) 16 | } else throw 'Input Query / Sfile Url!' 17 | } 18 | handler.help = handler.alias = ['sfile'] 19 | handler.tags = ['downloader'] 20 | handler.command = /^(sfile)$/i 21 | 22 | export default handler 23 | 24 | async function sfileSearch(query, page = 1) { 25 | let res = await fetch(`https://sfile.mobi/search.php?q=${query}&page=${page}`) 26 | let $ = cheerio.load(await res.text()) 27 | let result = [] 28 | $('div.list').each(function () { 29 | let title = $(this).find('a').text() 30 | let size = $(this).text().trim().split('(')[1] 31 | let link = $(this).find('a').attr('href') 32 | if (link) result.push({ title, size: size.replace(')', ''), link }) 33 | }) 34 | return result 35 | } 36 | 37 | async function sfileDl(url) { 38 | let res = await fetch(url) 39 | let $ = cheerio.load(await res.text()) 40 | let filename = $('div.w3-row-padding').find('img').attr('alt') 41 | let mimetype = $('div.list').text().split(' - ')[1].split('\n')[0] 42 | let filesize = $('#download').text().replace(/Download File/g, '').replace(/\(|\)/g, '').trim() 43 | let download = $('#download').attr('href') + '&k=' + Math.floor(Math.random() * (15 - 10 + 1) + 10) 44 | return { filename, filesize, mimetype, download } 45 | } 46 | -------------------------------------------------------------------------------- /plugins/downloader-tiktok.js: -------------------------------------------------------------------------------- 1 | import fg from 'api-dylux' 2 | import { tiktokdl } from '@bochilteam/scraper' 3 | 4 | let handler = async (m, { conn, text, args, usedPrefix, command}) => { 5 | if (!args[0]) throw `Enter the link of the video Tiktok` 6 | if (!args[0].match(/tiktok/gi)) throw `Verify that the link is from tiktok` 7 | let old = new Date() 8 | let txt = `∘ *Fetching* : ${((new Date - old) * 1)} ms` 9 | conn.reply(m.chat, global.wait, m, { 10 | contextInfo: { externalAdReply :{ mediaUrl: null, mediaType: 1, description: null, 11 | title: '📤| downloads By Zoro md 🌸', 12 | body: me, 13 | previewType: 0, thumbnail: thumb2, jpegThumbnail: thumb, 14 | sourceUrl: 'https://github.com/xxirfanx' }}}) 15 | try { 16 | let p = await fg.tiktok(args[0]) 17 | conn.sendFile(m.chat, p.play, 'tiktok.mp4', txt, m) 18 | } catch { 19 | try { 20 | const { author: { nickname }, video, description } = await tiktokdl(args[0]) 21 | const url = video.no_watermark2 || video.no_watermark || 'https://tikcdn.net' + video.no_watermark_raw || video.no_watermark_hd 22 | if (!url) throw global.eror 23 | conn.sendFile(m.chat, url, 'fb.mp4', ``, m) 24 | } catch { 25 | m.reply('*☓ An unexpected error occurred*') 26 | }}} 27 | 28 | handler.help = ['tiktok'].map((v) => v + ' '); 29 | handler.tags = ['downloader']; 30 | handler.command = /^t(t|iktok(d(own(load(er)?)?|l))?|td(own(load(er)?)?|l))$/i; 31 | 32 | export default handler 33 | -------------------------------------------------------------------------------- /plugins/enable.js: -------------------------------------------------------------------------------- 1 | let handler = async (m, { conn, usedPrefix, command, args, isOwner, isAdmin, isROwner }) => { 2 | let isEnable = /true|enable|(turn)?on|1/i.test(command) 3 | let chat =global.DATABASE.data.chats[m.chat] 4 | let user = global.DATABASE.data.users[m.sender] 5 | let bot = global.DATABASE.data.settings[conn.user.jid] || {} 6 | let type = (args[0] || '').toLowerCase() 7 | let isAll = false, isUser = false 8 | switch (type) { 9 | case 'welcome': 10 | if (!m.isGroup) { 11 | if (!isOwner) { 12 | global.dfail('group', m, conn) 13 | throw false 14 | } 15 | } else if (!isAdmin) { 16 | global.dfail('admin', m, conn) 17 | throw false 18 | } 19 | chat.welcome = isEnable 20 | break 21 | case 'delete': 22 | if (m.isGroup) { 23 | if (!(isAdmin || isOwner)) { 24 | global.dfail('admin', m, conn) 25 | throw false 26 | } 27 | } 28 | chat.delete = isEnable 29 | break 30 | case 'antidelete': 31 | if (m.isGroup) { 32 | if (!(isAdmin || isOwner)) { 33 | global.dfail('admin', m, conn) 34 | throw false 35 | } 36 | } 37 | chat.delete = !isEnable 38 | break 39 | case 'public': 40 | isAll = true 41 | if (!isROwner) { 42 | global.dfail('rowner', m, conn) 43 | throw false 44 | } 45 | global.opts['self'] = !isEnable 46 | break 47 | case 'antilink': 48 | if (m.isGroup) { 49 | if (!(isAdmin || isOwner)) { 50 | global.dfail('admin', m, conn) 51 | throw false 52 | } 53 | } 54 | chat.antiLink = isEnable 55 | break 56 | case 'restrict': 57 | isAll = true 58 | if (!isOwner) { 59 | global.dfail('owner', m, conn) 60 | throw false 61 | } 62 | bot.restrict = isEnable 63 | break 64 | case 'nyimak': 65 | isAll = true 66 | if (!isROwner) { 67 | global.dfail('rowner', m, conn) 68 | throw false 69 | } 70 | global.opts['nyimak'] = isEnable 71 | break 72 | case 'autoread': 73 | isAll = true 74 | if (!isROwner) { 75 | global.dfail('rowner', m, conn) 76 | throw false 77 | } 78 | global.opts['autoread'] = isEnable 79 | break 80 | case 'pconly': 81 | case 'privateonly': 82 | isAll = true 83 | if (!isROwner) { 84 | global.dfail('rowner', m, conn) 85 | throw false 86 | } 87 | global.opts['pconly'] = isEnable 88 | break 89 | case 'gconly': 90 | case 'grouponly': 91 | isAll = true 92 | if (!isROwner) { 93 | global.dfail('rowner', m, conn) 94 | throw false 95 | } 96 | global.opts['gconly'] = isEnable 97 | break 98 | case 'swonly': 99 | case 'statusonly': 100 | isAll = true 101 | if (!isROwner) { 102 | global.dfail('rowner', m, conn) 103 | throw false 104 | } 105 | global.opts['swonly'] = isEnable 106 | break 107 | default: 108 | if (!/[01]/.test(command)) return m.reply(` 109 | List option: welcome | delete | public | antilink | antidelete | antitoxic | autolevelup | detect | document | whitelistmycontacts | restrict | nyimak | autoread | pconly | gconly | swonly 110 | Contoh: 111 | ${usedPrefix}enable welcome 112 | ${usedPrefix}disable welcome 113 | `.trim()) 114 | throw false 115 | } 116 | m.reply(` 117 | *${type}* succeeded in *${isEnable ? 'on' : 'dead'}right* ${isAll ? 'for these bots' : isUser ? '' : 'for this chat'} 118 | `.trim()) 119 | } 120 | handler.help = ['en', 'dis'].map(v => v + 'able