.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | [](https://t.me/znanx)
7 | [](https://wa.me/6281252848955)
8 | [](https://instagram.com/naando.io)
9 | [](./LICENSE)
10 | [](https://saweria.co/Nando35)
11 |
12 |
13 |
14 | ## MOON CASE VERSION
15 |
16 | This code is an implementation of [Baileys](https://github.com/WhiskeySockets/Baileys).
17 | Use this script wisely, use your head in utilizing existing technology
18 |
19 |
20 | Windows
21 | Requirements:
22 | * Git [`Click here`](https://git-scm.com/downloads)
23 | * NodeJS [`Click here`](https://nodejs.org/en/download)
24 | * FFmpeg [`Click here`](https://ffmpeg.org/download.html)
25 | * Speedtest by Okla
26 |
27 | ```bash
28 | Add to PATH environment variable
29 | ```
30 |
31 |
32 | Termux
33 | ```sh
34 | apt update && apt upgrade -y
35 | ```
36 | ```sh
37 | apt install nodejs git ffmpeg wget curl zip -y
38 | ```
39 |
40 | ### Speedtest Install
41 | ```sh
42 | curl -s https://packagecloud.io/install/repositories/ookla/speedtest-cli/script.deb.sh | bash && apt install speedtest -y
43 | ```
44 |
45 | ### Nvm installation
46 |
47 | ```sh
48 | curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
49 | ```
50 |
51 | ```sh
52 | wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
53 | ```
54 |
55 | ```sh
56 | source ~/.bashrc
57 | ```
58 |
59 |
60 | Ubuntu
61 | ```sh
62 | sudo apt update -y && sudo apt upgrade -y
63 | ```
64 | ```sh
65 | sudo apt install nodejs git ffmpeg wget curl zip -y
66 | ```
67 |
68 | ### Speedtest Install
69 | ```sh
70 | curl -s https://packagecloud.io/install/repositories/ookla/speedtest-cli/script.deb.sh | sudo bash && apt install speedtest -y
71 | ```
72 |
73 | ### Nvm installation
74 |
75 | ```sh
76 | curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
77 | ```
78 |
79 | ```sh
80 | wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
81 | ```
82 |
83 | ```sh
84 | source ~/.bashrc
85 | ```
86 |
87 | ### Chromium Installation
88 |
89 | ```sh
90 | wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
91 | ```
92 | ```sh
93 | sudo dpkg -i google-chrome-stable_current_amd64.deb
94 | ```
95 | ```sh
96 | sudo apt --fix-broken install -y
97 | ```
98 |
99 | >
100 | > After finishing, restart the terminal to load the new information.
101 | >
102 |
103 | ### Nodejs installation
104 |
105 | ```sh
106 | nvm install node
107 | ```
108 |
109 |
110 |
111 | ### pm2 installation
112 | ```sh
113 | npm i -g pm2
114 | ```
115 |
116 | ```sh
117 | node --version
118 | ```
119 |
120 | ## Start Script
121 |
122 | Cloning the Repository
123 | ```
124 | git clone https://github.com/rifnd/moon-case.git
125 | ```
126 |
127 | Go to the project directory and install all dependencies.
128 | ```sh
129 | cd moon-case
130 |
131 | npm i
132 | ```
133 |
134 | Finally, run the command below to start :
135 | ```sh
136 | # non pm2
137 | npm start
138 |
139 | # with pm2
140 | npm run dev
141 | ```
142 |
143 | ## Login With Pairing Code
144 | or type your number in [`here`](https://github.com/rifnd/moon-case/blob/master/config.js#L50)
145 | ```sh
146 | node index.js --pairing
147 | ```
148 |
149 | ### Note
150 |
151 | This code is in no way affiliated with WhatsApp. Use at your own discretion. Don't spam this.
152 |
153 | This code was produced based on the baileys library and it is still under development.
154 |
155 | # Donate to the project.
156 | * [`Saweria`](https://saweria.co/Nando35)
157 |
158 |
--------------------------------------------------------------------------------
/config.js:
--------------------------------------------------------------------------------
1 | import Func from './lib/function.js'
2 | import {
3 | fileURLToPath
4 | } from 'url'
5 |
6 | /** write down your menu here */
7 | const menu = {
8 | admin: ['hidetag', 'add', 'welcome', 'leaving', 'setpp', 'setname', 'tagall', 'kick', 'promote', 'demote'],
9 | converter: ['sticker', 'toimg', 'togif', 'qc', 'ttp', 'attp', 'emojimix'],
10 | downloader: ['tiktok', 'tikwm', 'tikmp3', 'facebook', 'instagram', 'igstory', 'twitter', 'threads', 'play', 'ytmp3', 'ytmp4', 'capcut', 'capcutwm', 'cocofun', 'douyin', 'douyinwm', 'douyinmp3', 'likee', 'likeewm', 'pindl'],
11 | effect: ['paretro', 'retrolga', 'plumy', 'hdr', 'sepia', 'duotone', 'blackwhite', 'sketch', 'sketchrill', 'oils', 'esragan', 'watercolor', 'galaxy', 'freplace', 'rainbow', 'solarize', 'pinkbir'],
12 | fun: ['apakah', 'siapakah', 'kapankah', 'rate', 'benarkah', 'bisakah'],
13 | group: ['afk', 'linkgroup', 'delete', 'ava', 'quoted', 'rvo'],
14 | internet: ['ytsearch', 'ai', 'aiimg', 'aiarticle', 'bard', 'bing', 'bingimg', 'blackbox', 'aicode', 'gemini', 'waifudiff', 'brainly', 'pinterest', 'google', 'gimage', 'kbbg'],
15 | miscs: ['speed', 'owner', 'sc', 'ping', 'checkapi'],
16 | owner: ['eval', 'exec', 'mute', 'public', 'setpp', 'setname', 'unblock', 'block', 'setcover', 'autoread', 'setlink'],
17 | 'text maker': ['comicbox', 'gradientshadow', 'lava', 'thunder', 'neondevil', 'sumertimes', 'matrix', 'firework', 'neonlight', 'greenneon', 'pokemon', 'dragonball', 'naruto', 'blackpink', 'onglass', 'greenbrush', 'amongus', 'naruto2', 'flaming', 'woodblock'],
18 | tools: ['remini', 'recolor', 'ocr', 'calc', 'cekresi', 'ss', 'ssweb', 'shortlink', 'translate', 'tts', 'text2img', 'transcibe', 'nulis', 'removebg', 'toanime', 'tozombie', 'turnme', 'gta5style'],
19 | 'voice changer': ['bass', 'blown', 'deep', 'earrape', 'fast', 'fat', 'nightcore', 'reverse', 'robot', 'slow', 'smooth', 'tupai']
20 | }
21 |
22 | const limit = {
23 | free: 15,
24 | premium: 150,
25 | VIP: 'Infinity',
26 | download: {
27 | free: 50000000, // use byte
28 | premium: 350000000, // use byte
29 | VIP: 1130000000, // use byte
30 | }
31 | }
32 |
33 | export default {
34 | menu,
35 | limit,
36 | /** change config here */
37 | options: {
38 | database: 'database.json', /** End .json when using JSON database or use Mongo URI */
39 | owner: ['6285179886349'],
40 | evaluate_chars: ['=>', '>', '$', '~>', '!', '+', '/', '#', '.'],
41 | sessionName: 'session',
42 | prefix: /^[./!#+,]/i,
43 | wm: '© moon-bot',
44 | footer: 'ᴍᴏᴏɴ ʙᴏᴛ ᴡʜᴀᴛꜱᴀᴘᴘ ꜱᴍᴀʀᴛ ᴀꜱꜱɪꜱᴛᴀɴᴛ ツ'
45 | },
46 | /** Pairing code */
47 | pairing: {
48 | state: false,
49 | number: 0
50 | },
51 | /** Set pack name sticker on here */
52 | Exif: {
53 | packId: 'https://api.alyachan.dev',
54 | packName: `This Sticker is Made by :`,
55 | packPublish: '@naando.io',
56 | packEmail: 'contact@moonx.my.id',
57 | packWebsite: 'https://api.alyachan.dev',
58 | androidApp: 'https://play.google.com/store/apps/details?id=com.bitsmedia.android.muslimpro',
59 | iOSApp: 'https://apps.apple.com/id/app/muslim-pro-al-quran-adzan/id388389451?|=id',
60 | emojis: [],
61 | isAvatar: 0,
62 | },
63 | /** message response awikwok there */
64 | msg: {
65 | owner: 'Features can only be accessed owner!',
66 | group: 'Features only accessible in group!',
67 | private: 'Features only accessible private chat!',
68 | admin: 'Features can only be accessed by group admin!',
69 | botAdmin: `Bot is not admin, can't use the features!`,
70 | bot: 'Features only accessible by me',
71 | media: 'Reply media...',
72 | query: 'No Query?',
73 | error: 'Seems to have encountered an unexpected error, please repeat your command for a while again',
74 | quoted: 'Reply message...',
75 | wait: 'Wait a minute...',
76 | urlInvalid: 'Url Invalid',
77 | notFound: 'Result Not Found!',
78 | premium: 'Premium Only Features!',
79 | vip: 'VIP Only Features!',
80 | dlFree: `File over ${formatSize(limit.download.free)} can only be accessed by premium users`,
81 | dlPremium: `WhatsApp cannot send files larger than ${formatSize(limit.download.premium)}`,
82 | dlVIP: `WhatsApp cannot send files larger than ${formatSize(limit.download.VIP)}`,
83 | }
84 | }
85 |
86 | function formatSize(bytes, si = true, dp = 2) {
87 | const thresh = si ? 1000 : 1024
88 | if (Math.abs(bytes) < thresh) {
89 | return `${bytes} B`
90 | }
91 | const units = si ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
92 | let u = -1
93 | const r = 10 ** dp
94 | do {
95 | bytes /= thresh
96 | ++u
97 | } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1)
98 | return `${bytes.toFixed(dp)} ${units[u]}`
99 | }
100 |
101 | Func.reloadFile(fileURLToPath(import.meta.url))
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0
2 | import { spawn } from 'child_process'
3 | import path from 'path'
4 | import { fileURLToPath } from 'url'
5 | import { platform } from 'os'
6 | import { watchFile, unwatchFile } from 'fs'
7 | const __dirname = path.dirname(fileURLToPath(import.meta.url))
8 |
9 | var isRunning = false
10 | function start(file) {
11 | if (isRunning) return
12 | isRunning = true
13 | console.log('Starting . . .')
14 | let args = [path.join(__dirname, file), ...process.argv.slice(2)]
15 | let p = spawn(process.argv[0], args, {
16 | stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
17 | }).on('message', (data) => {
18 | console.log('[RECEIVED]', data)
19 | switch (data) {
20 | case 'reset':
21 | platform() === 'win32' ? p.kill('SIGINT') : p.kill()
22 | isRunning = false
23 | start.apply(this, arguments)
24 | break
25 | case 'uptime':
26 | p.send(process.uptime())
27 | break
28 | }
29 | }).on('exit', (code) => {
30 | isRunning = false
31 | console.error('Exited with code:', code)
32 | if (code === 0) return
33 | watchFile(args[0], () => {
34 | unwatchFile(args[0])
35 | start(file)
36 | })
37 | })
38 | }
39 | start('main.js')
40 |
--------------------------------------------------------------------------------
/lib/database.js:
--------------------------------------------------------------------------------
1 | import config from '../config.js'
2 | import mongoose from 'mongoose'
3 | import fs from 'fs'
4 | import path from 'path'
5 | mongoose.set('strictQuery', false)
6 | let Database
7 |
8 | if (/mongo/.test(config.options.database)) {
9 | Database = class MongoDB {
10 | constructor(url) {
11 | this.url = url
12 |
13 | this.options = {
14 | useNewUrlParser: true,
15 | useUnifiedTopology: true,
16 | //keepAlive: true,
17 | //keepAliveInitialDelay: 30000,
18 | // timeout: 30000
19 | }
20 | this.connection = this.url || config.options.database
21 | this.model = {
22 | database: {},
23 | }
24 | this.data = {}
25 | }
26 |
27 | read = async () => {
28 | mongoose.connect(this.connection, {
29 | ...this.options,
30 | })
31 | try {
32 | const schemaData = new mongoose.Schema({
33 | data: {
34 | type: Object,
35 | required: true,
36 | default: {},
37 | },
38 | })
39 | this.model.database = mongoose.model("data", schemaData)
40 | } catch {
41 | this.model.database = mongoose.model("data")
42 | }
43 | this.data = await this.model.database.findOne({})
44 | if (!this.data) {
45 | new this.model.database({
46 | data: {},
47 | }).save()
48 | this.data = await this.model.database.findOne({})
49 | return (this.data = this?.data?.data)
50 | } else return this?.data?.data || this?.data
51 | }
52 |
53 | write = async (data) => {
54 | const obj = !!data ? data : global.db
55 | if (this.data && !this.data.data)
56 | return new this.model.database({
57 | data: obj,
58 | }).save()
59 | const document = await this.model.database.findById(this.data._id)
60 | if (!document.data) document.data = {}
61 | document.data = obj
62 | document.save()
63 | }
64 | }
65 | } else if (/json/.test(config.options.database)) {
66 | Database = class Database {
67 | data = {}
68 | file = path.join(process.cwd(), config.options.database)
69 |
70 | read() {
71 | let data
72 | if (fs.existsSync(this.file)) {
73 | data = JSON.parse(fs.readFileSync(this.file))
74 | } else {
75 | fs.writeFileSync(this.file, JSON.stringify(this.data, null, 2))
76 | data = this.data
77 | }
78 |
79 | return data
80 | }
81 |
82 | write(data) {
83 | this.data = !!data ? data : global.db
84 | let dirname = path.dirname(this.file)
85 | if (!fs.existsSync(dirname)) fs.mkdirSync(dirname, { recursive: true })
86 | fs.writeFileSync(this.file, JSON.stringify(this.data, null, 2))
87 | return this.file
88 | }
89 | }
90 | }
91 |
92 | export default Database
--------------------------------------------------------------------------------
/lib/function.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import fs from 'fs'
3 | import {
4 | fileTypeFromBuffer
5 | } from 'file-type'
6 | import path from 'path'
7 | import {
8 | fileURLToPath,
9 | pathToFileURL
10 | } from 'url'
11 | import {
12 | createRequire
13 | } from 'module'
14 | import {
15 | platform
16 | } from 'os'
17 | import moment from 'moment-timezone'
18 | import cheerio from 'cheerio'
19 | import {
20 | format
21 | } from 'util'
22 | import FormData from 'form-data'
23 | import mimes from 'mime-types'
24 | import Jimp from 'jimp'
25 | import chalk from 'chalk'
26 | import baileys from '@whiskeysockets/baileys'
27 |
28 | export default new (class Function {
29 | constructor() {
30 | this.axios = axios
31 | this.cheerio = cheerio
32 | this.fs = fs
33 | this.path = path
34 | this.baileys = baileys
35 | this.FormData = FormData
36 | this.listeners = new Map()
37 | }
38 |
39 | // source code https://github.com/BochilGaming/games-wabot/blob/e4151d33cded4cfa6f1ceabc8558e1678f2a0f53/lib/helper.js#L14
40 | __filename(pathURL = import.meta, rmPrefix = platform() !== 'win32') {
41 | const path = pathURL?.url || pathURL
42 | return rmPrefix ?
43 | /file:\/\/\//.test(path) ?
44 | fileURLToPath(path) :
45 | path :
46 | /file:\/\/\//.test(path) ?
47 | path :
48 | pathToFileURL(path).href
49 | }
50 |
51 | // source code https://github.com/BochilGaming/games-wabot/blob/e4151d33cded4cfa6f1ceabc8558e1678f2a0f53/lib/helper.js#L14
52 | __dirname(pathURL) {
53 | const dir = this.__filename(pathURL, true)
54 | const regex = /\/$/
55 | return regex.test(dir) ?
56 | dir :
57 | fs.existsSync(dir) && fs.statSync(dir).isDirectory ?
58 | dir.replace(regex, '') :
59 | path.dirname(dir)
60 | }
61 |
62 | async dirSize(directory) {
63 | const files = await fs.readdirSync(directory)
64 | const stats = files.map((file) => fs.statSync(path.join(directory, file)))
65 | return (await Promise.all(stats)).reduce((accumulator, {
66 | size
67 | }) => accumulator + size, 0)
68 | }
69 |
70 | sleep(ms) {
71 | return new Promise((a) => setTimeout(a, ms))
72 | }
73 |
74 | format(str) {
75 | return format(str)
76 | }
77 |
78 | Format(str) {
79 | return JSON.stringify(str, null, 2)
80 | }
81 |
82 | jam(numer, options = {}) {
83 | let format = options.format ? options.format : 'HH:mm'
84 | let jam = options?.timeZone ? moment(numer).tz(options.timeZone).format(format) : moment(numer).format(format)
85 | return `${jam}`
86 | }
87 |
88 | toTime(ms) {
89 | let h = Math.floor(ms / 3600000)
90 | let m = Math.floor(ms / 60000) % 60
91 | let s = Math.floor(ms / 1000) % 60
92 | return [h, m, s].map((v) => v.toString().padStart(2, 0)).join(':')
93 | }
94 |
95 | tanggal(numer, timeZone = '') {
96 | const myMonths = ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember']
97 | const myDays = ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jum’at', 'Sabtu']
98 | var tgl = new Date(numer)
99 | timeZone ? tgl.toLocaleString('en', {
100 | timeZone
101 | }) : ''
102 | var day = tgl.getDate()
103 | var bulan = tgl.getMonth()
104 | var thisDay = tgl.getDay(), thisDay = myDays[thisDay]
105 | var yy = tgl.getYear()
106 | var year = yy < 1000 ? yy + 1900 : yy
107 | let gmt = new Date(0).getTime() - new Date('1 January 1970').getTime()
108 | let weton = ['Pahing', 'Pon', 'Wage', 'Kliwon', 'Legi'][Math.floor((tgl * 1 + gmt) / 84600000) % 5]
109 | return `${thisDay}, ${day} ${myMonths[bulan]} ${year}`
110 | }
111 |
112 | async fetchFile(source, filename, options) {
113 | return new Promise(async (resolve) => {
114 | try {
115 | if (Buffer.isBuffer(source)) {
116 | let ext, mime
117 | try {
118 | mime = await (await fileTypeFromBuffer(source)).mime
119 | ext = await (await fileTypeFromBuffer(source)).ext
120 | } catch {
121 | mime = mim.lookup(filename ? filename.split`.`[filename.split`.`.length - 1] : 'txt')
122 | ext = mim.extension(mime)
123 | }
124 | let extension = filename ? filename.split`.`[filename.split`.`.length - 1] : ext
125 | let size = Buffer.byteLength(source)
126 | let filepath = 'temp/' + (this.uuid() + '.' + ext)
127 | let file = fs.writeFileSync(filepath, source)
128 | let name = filename || path.basename(filepath)
129 | let data = {
130 | status: true,
131 | file: filepath,
132 | filename: name,
133 | mime: mime,
134 | extension: ext,
135 | size: this.formatSize(size),
136 | bytes: size
137 | }
138 | return resolve(data)
139 | } else if (source.startsWith('./') || source.startsWith('/')) {
140 | let ext, mime
141 | try {
142 | mime = await (await fileTypeFromBuffer(source)).mime
143 | ext = await (await fileTypeFromBuffer(source)).ext
144 | } catch {
145 | mime = mim.lookup(filename ? filename.split`.`[filename.split`.`.length - 1] : 'txt')
146 | ext = mim.extension(mime)
147 | }
148 | let extension = filename ? filename.split`.`[filename.split`.`.length - 1] : ext
149 | let size = fs.statSync(source).size
150 | let name = filename || path.basename(source)
151 | let data = {
152 | status: true,
153 | file: source,
154 | filename: name,
155 | mime: mime,
156 | extension: ext,
157 | size: this.formatSize(size),
158 | bytes: size
159 | }
160 | return resolve(data)
161 | } else {
162 | axios.get(source, {
163 | responseType: 'stream',
164 | ...options
165 | }).then(async (response) => {
166 | let extension = filename ? filename.split`.`[filename.split`.`.length - 1] : mimes.extension(response.headers['content-type'])
167 | let file = fs.createWriteStream(`temp/${this.uuid() + '.' + extension}`)
168 | let name = filename || path.basename(file.path)
169 | response.data.pipe(file)
170 | file.on('finish', async () => {
171 | let data = {
172 | status: true,
173 | file: file.path,
174 | filename: name,
175 | mime: mimes.lookup(file.path),
176 | extension: extension,
177 | size: this.formatSize(response.headers['content-length'] ? response.headers['content-length'] : 0),
178 | bytes: response.headers['content-length'] ? response.headers['content-length'] : 0
179 | }
180 | resolve(data)
181 | file.close()
182 | })
183 | })
184 | }
185 | } catch (e) {
186 | console.log(e)
187 | resolve({
188 | status: false
189 | })
190 | }
191 | })
192 | }
193 |
194 | uuid() {
195 | var dt = new Date().getTime()
196 | var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
197 | function (c) {
198 | var r = (dt + Math.random() * 16) % 16 | 0
199 | var y = Math.floor(dt / 16)
200 | return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16)
201 | })
202 | return uuid
203 | }
204 |
205 | Styles(text, style = 1) {
206 | var xStr = 'abcdefghijklmnopqrstuvwxyz1234567890'.split('')
207 | var yStr = Object.freeze({
208 | 1: 'ᴀʙᴄᴅᴇꜰɢʜɪᴊᴋʟᴍɴᴏᴘqʀꜱᴛᴜᴠᴡxʏᴢ1234567890'
209 | })
210 | var replacer = []
211 | xStr.map((v, i) => replacer.push({
212 | original: v,
213 | convert: yStr[style].split('')[i]
214 | }))
215 | var str = text.toLowerCase().split('')
216 | var output = []
217 | str.map(v => {
218 | const find = replacer.find(x => x.original == v)
219 | find ? output.push(find.convert) : output.push(v)
220 | })
221 | return output.join('')
222 | }
223 |
224 | async getFile(PATH, save) {
225 | try {
226 | let filename = null
227 | let data = (await this.fetchBuffer(PATH))
228 |
229 | if (data?.data && save) {
230 | filename = path.join(process.cwd(), 'temp', Date.now() + '.' + data.ext)
231 | fs.promises.writeFile(filename, data?.data)
232 | }
233 | return {
234 | filename: data?.name ? data.name : filename,
235 | ...data
236 | }
237 | } catch (e) {
238 | throw e
239 | }
240 | }
241 |
242 | async fetchJson(url, options = {}) {
243 | try {
244 | let data = await axios.get(url, {
245 | headers: {
246 | ...(!!options.headers ? options.headers : {})
247 | },
248 | responseType: 'json',
249 | ...options
250 | })
251 |
252 | return await data?.data
253 | } catch (e) {
254 | throw e
255 | }
256 | }
257 |
258 | async makeId(length) {
259 | var result = ''
260 | var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
261 | var charactersLength = characters.length
262 | for (var i = 0; i < length; i++) {
263 | result += characters.charAt(Math.floor(Math.random() * charactersLength))
264 | }
265 | return result
266 | }
267 |
268 | async fetchText(url, options = {}) {
269 | try {
270 | let data = await axios.get(url, {
271 | headers: {
272 | ...(!!options.headers ? options.headers : {})
273 | },
274 | responseType: 'text',
275 | ...options
276 | })
277 |
278 | return await data?.data
279 | } catch (e) {
280 | throw e
281 | }
282 | }
283 |
284 | getBuffer = async (file, options = {}) => {
285 | return new Promise(async (resolve, reject) => {
286 | try {
287 | if (this.isUrl(file)) {
288 | let buff = await (await axios.get(file, {
289 | responseType: 'arraybuffer',
290 | headers: options
291 | })).data
292 | resolve(buff)
293 | } else {
294 | let buff = fs.readFileSync(file)
295 | resolve(buff)
296 | }
297 | } catch (e) {
298 | return ({
299 | status: false,
300 | msg: `System cannot detect Buffer!`
301 | })
302 | }
303 | })
304 | }
305 |
306 | random(list) {
307 | return list[Math.floor(Math.random() * list.length)]
308 | }
309 |
310 | fetchBuffer(string, options = {}) {
311 | return new Promise(async (resolve, reject) => {
312 | try {
313 | if (/^https?:\/\//i.test(string)) {
314 | let data = await axios.get(string, {
315 | headers: {
316 | ...(!!options.headers ? options.headers : {}),
317 | },
318 | responseType: 'arraybuffer',
319 | ...options,
320 | })
321 | let buffer = await data?.data
322 | let name = /filename/i.test(data.headers?.get('content-disposition')) ? data.headers?.get('content-disposition')?.match(/filename=(.*)/)?.[1]?.replace(/['']/g, '') : ''
323 | let mime = mimes.lookup(name) || data.headers.get('content-type') || (await fileTypeFromBuffer(buffer))?.mime
324 | resolve({
325 | data: buffer,
326 | size: Buffer.byteLength(buffer),
327 | sizeH: this.formatSize(Buffer.byteLength(buffer)),
328 | name,
329 | mime,
330 | ext: mimes.extension(mime)
331 | })
332 | } else if (/^data:.*?\/.*?base64,/i.test(string)) {
333 | let data = Buffer.from(string.split`,`[1], 'base64')
334 | let size = Buffer.byteLength(data)
335 | resolve({
336 | data,
337 | size,
338 | sizeH: this.formatSize(size),
339 | ...((await fileTypeFromBuffer(data)) || {
340 | mime: 'application/octet-stream',
341 | ext: '.bin'
342 | })
343 | })
344 | } else if (fs.existsSync(string) && fs.statSync(string).isFile()) {
345 | let data = fs.readFileSync(string)
346 | let size = Buffer.byteLength(data)
347 | resolve({
348 | data,
349 | size,
350 | sizeH: this.formatSize(size),
351 | ...((await fileTypeFromBuffer(data)) || {
352 | mime: 'application/octet-stream',
353 | ext: '.bin'
354 | })
355 | })
356 | } else if (Buffer.isBuffer(string)) {
357 | let size = Buffer?.byteLength(string) || 0
358 | resolve({
359 | data: string,
360 | size,
361 | sizeH: this.formatSize(size),
362 | ...((await fileTypeFromBuffer(string)) || {
363 | mime: 'application/octet-stream',
364 | ext: '.bin'
365 | })
366 | })
367 | } else if (/^[a-zA-Z0-9+/]={0,2}$/i.test(string)) {
368 | let data = Buffer.from(string, 'base64')
369 | let size = Buffer.byteLength(data)
370 | resolve({
371 | data,
372 | size,
373 | sizeH: this.formatSize(size),
374 | ...((await fileTypeFromBuffer(data)) || {
375 | mime: 'application/octet-stream',
376 | ext: '.bin'
377 | })
378 | })
379 | } else {
380 | let buffer = Buffer.alloc(20)
381 | let size = Buffer.byteLength(buffer)
382 | resolve({
383 | data: buffer,
384 | size,
385 | sizeH: this.formatSize(size),
386 | ...((await fileTypeFromBuffer(buffer)) || {
387 | mime: 'application/octet-stream',
388 | ext: '.bin'
389 | })
390 | })
391 | }
392 | } catch (e) {
393 | reject(new Error(e?.message || e))
394 | }
395 | })
396 | }
397 |
398 | mime(name) {
399 | let mimetype = mimes.lookup(name)
400 | if (!mimetype) return mimes.extension(name)
401 | return {
402 | mime: mimetype,
403 | ext: mimes.extension(mimetype)
404 | }
405 | }
406 |
407 | isUrl(url) {
408 | let regex = new RegExp(/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/, 'gi')
409 | if (!regex.test(url)) return false
410 | return url.match(regex)
411 | }
412 |
413 | escapeRegExp(string) {
414 | return string.replace(/[.*=+:\-?^${}()|[\]\\]|\s/g, '\\$&')
415 | }
416 |
417 | toUpper(query) {
418 | const arr = query.split(' ')
419 | for (var i = 0; i < arr.length; i++) {
420 | arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].slice(1)
421 | }
422 |
423 | return arr.join(' ')
424 | //return query.replace(/^\w/, c => c.toUpperCase())
425 | }
426 |
427 | getRandom(ext = '', length = '10') {
428 | var result = ''
429 | var character = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890'
430 | var characterLength = character.length
431 | for (var i = 0; i < length; i++) {
432 | result += character.charAt(
433 | Math.floor(Math.random() * characterLength)
434 | )
435 | }
436 | return `${result}${ext ? `.${ext}` : ''}`
437 | }
438 |
439 | formatSize(bytes, si = true, dp = 2) {
440 | const thresh = si ? 1000 : 1024
441 | if (Math.abs(bytes) < thresh) {
442 | return `${bytes} B`
443 | }
444 | const units = si ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
445 | let u = -1
446 | const r = 10 ** dp
447 | do {
448 | bytes /= thresh
449 | ++u
450 | } while (
451 | Math.round(Math.abs(bytes) * r) / r >= thresh &&
452 | u < units.length - 1
453 | )
454 | return `${bytes.toFixed(dp)} ${units[u]}`
455 | }
456 |
457 | async resizeImage(buffer, height) {
458 | buffer = (await this.getFile(buffer)).data
459 | return new Promise((resolve, reject) => {
460 | Jimp.read(buffer, (err, image) => {
461 | if (err) {
462 | reject(err)
463 | return
464 | }
465 |
466 | image.resize(Jimp.AUTO, height).getBuffer(Jimp.MIME_PNG, (err, resizedBuffer) => {
467 | if (err) {
468 | reject(err)
469 | return
470 | }
471 | resolve(resizedBuffer)
472 | })
473 | })
474 | })
475 | }
476 |
477 | runtime(seconds) {
478 | seconds = Number(seconds)
479 | var d = Math.floor(seconds / (3600 * 24))
480 | var h = Math.floor((seconds % (3600 * 24)) / 3600)
481 | var m = Math.floor((seconds % 3600) / 60)
482 | var s = Math.floor(seconds % 60)
483 | var dDisplay = d > 0 ? d + (d == 1 ? ' day, ' : ' days, ') : ''
484 | var hDisplay = h > 0 ? h + (h == 1 ? ' hour, ' : ' hours, ') : ''
485 | var mDisplay = m > 0 ? m + (m == 1 ? ' minute, ' : ' minutes, ') : ''
486 | var sDisplay = s > 0 ? s + (s == 1 ? ' second' : ' seconds') : ''
487 | return dDisplay + hDisplay + mDisplay + sDisplay
488 | }
489 |
490 | async correct(mainString, targetStrings) {
491 | function compareTwoStrings(first, second) {
492 | first = first.replace(/\s+/g, '')
493 | second = second.replace(/\s+/g, '')
494 |
495 | if (first === second) return 1 // identical or empty
496 | if (first.length < 2 || second.length < 2) return 0 // if either is a 0-letter or 1-letter string
497 |
498 | let firstBigrams = new Map()
499 | for (let i = 0; i < first.length - 1; i++) {
500 | const bigram = first.substring(i, i + 2)
501 | const count = firstBigrams.has(bigram) ? firstBigrams.get(bigram) + 1 : 1
502 | firstBigrams.set(bigram, count)
503 | }
504 |
505 | let intersectionSize = 0
506 | for (let i = 0; i < second.length - 1; i++) {
507 | const bigram = second.substring(i, i + 2)
508 | const count = firstBigrams.has(bigram) ? firstBigrams.get(bigram) : 0
509 | if (count > 0) {
510 | firstBigrams.set(bigram, count - 1)
511 | intersectionSize++
512 | }
513 | }
514 |
515 | return ((2.0 * intersectionSize) / (first.length + second.length - 2))
516 | }
517 |
518 | targetStrings = Array.isArray(targetStrings) ? targetStrings : []
519 |
520 | const ratings = []
521 | let bestMatchIndex = 0
522 |
523 | for (let i = 0; i < targetStrings.length; i++) {
524 | const currentTargetString = targetStrings[i]
525 | const currentRating = compareTwoStrings(
526 | mainString,
527 | currentTargetString
528 | )
529 | ratings.push({
530 | target: currentTargetString,
531 | rating: currentRating,
532 | })
533 | if (currentRating > ratings[bestMatchIndex].rating) {
534 | bestMatchIndex = i
535 | }
536 | }
537 |
538 | const bestMatch = ratings[bestMatchIndex]
539 |
540 | return {
541 | all: ratings,
542 | indexAll: bestMatchIndex,
543 | result: bestMatch.target,
544 | rating: bestMatch.rating,
545 | }
546 | }
547 |
548 | async reloadFile(file) {
549 | if (this.listeners.has(file)) {
550 | fs.unwatchFile(file)
551 | this.listeners.delete(file)
552 | }
553 | const opts = async () => {
554 | fs.unwatchFile(file)
555 | console.log(chalk.bold.redBright('[ UPDATE ]'), '~', chalk.white.bold(path.basename(file)))
556 | const modulePath = path.resolve(file)
557 | import(modulePath + '?update=' + Date.now())
558 | }
559 | fs.watchFile(file, opts), this.listeners.set(file, opts)
560 | }
561 |
562 | greeting() {
563 | const time = (new Date().getUTCHours() + 7) % 24
564 | var res = "Good Morning"
565 | if (time >= 4) {
566 | res = "Good Morning"
567 | }
568 | if (time >= 12) {
569 | res = "Good afternoon"
570 | }
571 | if (time >= 15) {
572 | res = "Good Evening"
573 | }
574 | if (time >= 19) {
575 | res = "Good Night"
576 | }
577 | return res
578 | }
579 |
580 | ucword(str) {
581 | return (str + '').replace(/^([a-z])|\s+([a-z])/g, function ($1) {
582 | return $1.toUpperCase()
583 | })
584 | }
585 |
586 | timeReverse(duration) {
587 | let milliseconds = parseInt((duration % 1000) / 100),
588 | seconds = Math.floor((duration / 1000) % 60),
589 | minutes = Math.floor((duration / (1000 * 60)) % 60),
590 | hours = Math.floor((duration / (1000 * 60 * 60)) % 24),
591 | days = Math.floor(duration / (24 * 60 * 60 * 1000))
592 | let hoursF = (hours < 10) ? "0" + hours : hours
593 | let minutesF = (minutes < 10) ? "0" + minutes : minutes
594 | let secondsF = (seconds < 10) ? "0" + seconds : seconds
595 | let daysF = (days < 10) ? "0" + days : days
596 | // return hours + " Jam " + minutes + " Menit" + seconds + " Detik" + milliseconds;
597 | return daysF + "D " + hoursF + "H " + minutesF + "M"
598 | }
599 | })()
--------------------------------------------------------------------------------
/lib/logs.js:
--------------------------------------------------------------------------------
1 | import chalk from 'chalk'
2 | import moment from 'moment-timezone'
3 | import Func from './function.js'
4 | export default function logs(m) {
5 | let Z = m.fromMe ? 'Self' : m.pushName || 'No Name'
6 | let command = m.body.startsWith(m.prefix) ? m.command.toLowerCase() : ''
7 | if (m.message && !m.isBot) {
8 | console.log(
9 | command ? chalk.bold.yellow(`[ CMD ]`) : chalk.bold.whiteBright(`[ MSG ]`),
10 | chalk.green(moment(m.timestamp * 1000).tz(process.env.TZ || 'Asia/Jakarta').format('DD/MM/YY HH:mm:ss')),
11 | chalk.black.bgGreen(' ' + m.type + ' '),
12 | /(document|audio|sticker|image|video)/.test(m.type) ? Func.formatSize(m.msg.fileLength) : '0B',
13 | chalk.green.bold('from'), '[' + m.sender.split`@`[0] + ']',
14 | chalk.black.bgYellow(' ' + Z + ' '), 'in',
15 | chalk.black(chalk.green(m.isGroup ? m.metadata.subject : m.from)), '\n' +
16 | chalk.black(chalk.white(m.body || m.type)) + '\n'
17 | )
18 | }
19 | }
--------------------------------------------------------------------------------
/lib/schema.js:
--------------------------------------------------------------------------------
1 | import config from '../config.js'
2 |
3 | export default function Schema(m, conn) {
4 | const isNumber = x => typeof x === 'number' && !isNaN(x)
5 | const isBoolean = x => typeof x === 'boolean' && Boolean(x)
6 |
7 | /** users schema */
8 | let user = global.db.users[m.sender]
9 | if (typeof user !== 'object') global.db.users[m.sender] = {}
10 | if (user) {
11 | if (!isNumber(user.afkTime)) user.afkTime = -1
12 | if (!('afkReason' in user)) user.afkReason = ''
13 | if (!isNumber(user.limit)) user.limit = config.limit.free
14 | if (!isBoolean(user.premium)) user.premium = m.isOwner ? true : false
15 | if (!isNumber(user.expired)) user.expired = 0
16 | if (!isBoolean(user.VIP)) user.VIP = m.isOwner ? true : false
17 | if (!('lastChat' in user)) user.lastChat = new Date * 1
18 | if (!('name' in user)) user.name = m.pushName
19 | if (!isBoolean(user.banned)) user.banned = false
20 | } else {
21 | global.db.users[m.sender] = {
22 | afkTime: -1,
23 | afkReason: '',
24 | limit: config.limit.free,
25 | lastChat: new Date * 1,
26 | premium: m.isOwner ? true : false,
27 | expired: 0,
28 | VIP: m.isOwner ? true : false,
29 | name: m.pushName,
30 | banned: false,
31 | }
32 | }
33 |
34 | /** group schema */
35 | if (m.isGroup) {
36 | let group = global.db.groups[m.from]
37 | if (typeof group !== 'object') global.db.groups[m.from] = {}
38 | if (group) {
39 | if (!isNumber(group.activity)) group.activity = 0
40 | if (!isBoolean(group.mute)) group.mute = false
41 | if (!('text_welcome' in group)) group.text_welcome = ''
42 | if (!('text_leave' in group)) group.text_leave = ''
43 | if (!isBoolean(group.welcome)) group.welcome = true
44 | if (!isBoolean(group.leave)) group.leave = true
45 | if (!isBoolean(group.false)) group.detect = false
46 | if (!isBoolean(group.antilink)) group.antilink = false
47 | if (!('member' in group)) group.member = {}
48 | if (!isNumber(group.expired)) group.expired = 0
49 | } else {
50 | global.db.groups[m.from] = {
51 | activity: 0,
52 | mute: false,
53 | text_welcome: '',
54 | text_leave: '',
55 | welcome: true,
56 | leave: true,
57 | detect: false,
58 | antilink: false,
59 | member: {},
60 | expired: 0
61 | }
62 | }
63 | }
64 |
65 | /** jid schema */
66 | let setting = global.db.setting
67 | if (setting) {
68 | if (!isBoolean(setting.chatbot)) setting.chatbot = false
69 | if (!isBoolean(setting.autoread)) setting.autoread = false
70 | if (!isBoolean(setting.public)) setting.public = true
71 | if (!('cover' in setting)) setting.cover = 'https://iili.io/JAt7vf4.jpg'
72 | if (!('link' in setting)) setting.link = 'https://chat.whatsapp.com/G57unQZ7saFIq2rdpVw0Tu'
73 | } else {
74 | global.db.setting = {
75 | chatbot: false,
76 | autoread: false,
77 | public: true,
78 | cover: 'https://iili.io/JAt7vf4.jpg',
79 | link: 'https://chat.whatsapp.com/G57unQZ7saFIq2rdpVw0Tu'
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/lib/scraper.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import FormData from 'form-data'
3 | import { fileTypeFromBuffer } from 'file-type'
4 |
5 | export default new (class Scraper {
6 | uploader = (buffer) => {
7 | return new Promise(async (resolve) => {
8 | try {
9 | const { ext } = await fileTypeFromBuffer(buffer)
10 | const form = new FormData()
11 | form.append('file', buffer, 'tmp.' + ext)
12 | const json = await (await axios.post("https://tmpfiles.org/api/v1/upload", form, {
13 | headers: {
14 | "accept": "*/*",
15 | "accept-language": "id-ID , id q=O. 9 , en- US q=0.8, en q=0.7",
16 | "content-type": "multipart/form-data",
17 | "origin": "https://tmpfiles.orgi",
18 | "referer": "https://tmpfiles.org/",
19 | "sec-ch-ua": '"Chromium"v="107", "Not=A?Brand"v="24"',
20 | "sec-ch-ua-mobile": "?1",
21 | "sec-ch-ua-platform": "Android",
22 | "sec-fetch-dest": "empty",
23 | "sec-fetch-mcde": "cors",
24 | "sec-fetch-site": "same-origin",
25 | "user-agent": "Mozilla/5.0 (Linux Android 6.0.1 SM-J500G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Mobile Safari/537.36",
26 | "x-requested-with": "XMLHttpRequest",
27 | ...form.getHeaders()
28 | }
29 | })).data
30 | if (json.status != 'success') return resolve({
31 | author: '@naando.io',
32 | status: false,
33 | msg: 'Failed to uploaded'
34 | })
35 | resolve({
36 | author: '@naando.io',
37 | status: true,
38 | data: {
39 | url: json.data.url.replace('https://tmpfiles.org/', 'https://tmpfiles.org/dl/')
40 | }
41 | })
42 | } catch (e) {
43 | console.log(e)
44 | resolve({
45 | creator: '@naando.io',
46 | status: false,
47 | msg: e.message
48 | })
49 | }
50 | })
51 | }
52 |
53 | uploaderV2 = async input => {
54 | return new Promise(async resolve => {
55 | try {
56 | const image = Buffer.isBuffer(input) ? input : input.startsWith('http') ? await (await axios.get(input, {
57 | responseType: 'arraybuffer'
58 | })).data : input
59 | let form = new FormData
60 | form.append('source', Buffer.from(image), 'image.jpg')
61 | form.append('type', 'file')
62 | form.append('action', 'upload')
63 | form.append('timestamp', (new Date() * 1))
64 | form.append('auth_token', '')
65 | form.append('nsfw', 0)
66 | const json = await (await axios.post('https://freeimage.host/json', form, {
67 | headers: {
68 | "Accept": "*/*",
69 | "User-Agent": "Mozilla/5.0 (Linux; Android 6.0.1; SM-J500G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Mobile Safari/537.36",
70 | "Origin": "https://freeimage.host",
71 | "Referer": "https://freeimage.host/",
72 | "Referrer-Policy": "strict-origin-when-cross-origin",
73 | "sec-ch-ua": '"Chromium";v="107", "Not=A?Brand";v="24"',
74 | "sec-ch-ua-platform": "Android",
75 | "sec-fetch-dest": "empty",
76 | "sec-fetch-mode": "cors",
77 | "sec-fetch-site": "same-origin",
78 | "x-requested-with": "XMLHttpRequest",
79 | ...form.getHeaders()
80 | }
81 | })).data
82 | if (json.status_code != 200) return resolve({
83 | creator: '@naando.io',
84 | status: false,
85 | msg: `Failed to Upload!`
86 | })
87 | resolve({
88 | creator: '@naando.io',
89 | status: true,
90 | original: json,
91 | data: {
92 | url: json.image.url
93 | }
94 | })
95 | } catch (e) {
96 | console.log(e)
97 | resolve({
98 | creator: '@naando.io',
99 | status: false,
100 | msg: e.message
101 | })
102 | }
103 | })
104 | }
105 | })()
--------------------------------------------------------------------------------
/lib/serialize.js:
--------------------------------------------------------------------------------
1 | import config from '../config.js'
2 | import Function from './function.js'
3 | import {
4 | writeExif
5 | } from './sticker.js'
6 | import {
7 | fileTypeFromBuffer
8 | } from 'file-type'
9 | import baileys, {
10 | prepareWAMessageMedia
11 | } from '@whiskeysockets/baileys'
12 | const {
13 | jidNormalizedUser,
14 | proto,
15 | areJidsSameUser,
16 | extractMessageContent,
17 | generateWAMessageFromContent,
18 | downloadContentFromMessage,
19 | toBuffer,
20 | getDevice
21 | } = baileys
22 | import fs from 'fs'
23 | import path from 'path'
24 | import {
25 | parsePhoneNumber
26 | } from 'libphonenumber-js'
27 | import {
28 | fileURLToPath
29 | } from 'url'
30 | import Crypto from 'crypto'
31 | const __dirname = path.dirname(fileURLToPath(import.meta.url))
32 |
33 | export function Client({ conn, store }) {
34 | delete store.groupMetadata
35 | for (let v in store) {
36 | conn[v] = store[v]
37 | }
38 | Object.defineProperties(conn, {
39 | getContentType: {
40 | value(content) {
41 | if (content) {
42 | const keys = Object.keys(content);
43 | const key = keys.find(k => (k === 'conversation' || k.endsWith('Message') || k.endsWith('V2') || k.endsWith('V3')) && k !== 'senderKeyDistributionMessage');
44 | return key
45 | }
46 | },
47 | enumerable: true
48 | },
49 | decodeJid: {
50 | value(jid) {
51 | if (/:\d+@/gi.test(jid)) {
52 | const decode = jidNormalizedUser(jid);
53 | return decode
54 | } else return jid;
55 | }
56 | },
57 | generateMessageID: {
58 | value(id = "3EB0", length = 18) {
59 | return id + Crypto.randomBytes(length).toString('hex').toUpperCase()
60 | }
61 | },
62 | getName: {
63 | value(jid) {
64 | let id = conn.decodeJid(jid)
65 | let v
66 | if (id?.endsWith("@g.us")) return new Promise(async (resolve) => {
67 | v = conn.contacts[id] || conn.messages["status@broadcast"]?.array?.find(a => a?.key?.participant === id)
68 | if (!(v.name || v.subject)) v = conn.groupMetadata[id] || {}
69 | resolve(v?.name || v?.subject || v?.pushName || (parsePhoneNumber('+' + id.replace("@g.us", "")).format("INTERNATIONAL")))
70 | })
71 | else v = id === "0@s.whatsapp.net" ? {
72 | id,
73 | name: "WhatsApp"
74 | } : id === conn.decodeJid(conn?.user?.id) ?
75 | conn.user : (conn.contacts[id] || {})
76 | return (v?.name || v?.subject || v?.pushName || v?.verifiedName || (parsePhoneNumber('+' + id.replace("@s.whatsapp.net", "")).format("INTERNATIONAL")))
77 | }
78 | },
79 | sendContact: {
80 | async value(jid, number, quoted, options = {}) {
81 | let list = []
82 | for (let v of number) {
83 | list.push({
84 | displayName: await conn.getName(v),
85 | vcard: `BEGIN:VCARD\nVERSION:3.0\nN:${await conn.getName(v + "@s.whatsapp.net")}\nFN:${await conn.getName(v + "@s.whatsapp.net")}\nitem1.TEL;waid=${v}:${v}\nitem1.X-ABLabel:Ponsel\nitem2.EMAIL;type=INTERNET:${config.Exif.packEmail}\nitem2.X-ABLabel:Email\nitem3.URL:${config.Exif.packWebsite}\nitem3.X-ABLabel:Instagram\nitem4.ADR:;;Indonesia;;;;\nitem4.X-ABLabel:Region\nEND:VCARD`
86 | })
87 | }
88 | return conn.sendMessage(jid, {
89 | contacts: {
90 | displayName: `${list.length} Contact`,
91 | contacts: list
92 | },
93 | mentions: quoted?.participant ? [conn.decodeJid(quoted?.participant)] : [conn.decodeJid(conn?.user?.id)],
94 | ...options
95 | }, {
96 | quoted,
97 | ...options
98 | })
99 | },
100 | enumerable: true
101 | },
102 | parseMention: {
103 | value(text) {
104 | return [...text.matchAll(/@([0-9]{5,16}|0)/g)].map(v => v[1] + '@s.whatsapp.net') || []
105 | }
106 | },
107 | downloadAndSaveMediaMessage: {
108 | async value(message, filename, attachExtension = true) {
109 | let quoted = message.msg ? message.msg : message
110 | let mime = (message.msg || message).mimetype || ''
111 | let messageType = message.mtype ? message.mtype.replace(/Message/gi, '') : mime.split('/')[0]
112 | const stream = await downloadContentFromMessage(quoted, messageType)
113 | let buffer = Buffer.from([])
114 | for await (const chunk of stream) {
115 | buffer = Buffer.concat([buffer, chunk])
116 | }
117 | let type = await fileTypeFromBuffer(buffer)
118 | let trueFileName = attachExtension ? (filename + '.' + type.ext) : filename
119 | // save to file
120 | await fs.writeFileSync(trueFileName, buffer)
121 | return trueFileName
122 | },
123 | enumerable: true
124 | },
125 | downloadMediaMessage: {
126 | async value(message, filename) {
127 | let mime = {
128 | imageMessage: "image",
129 | videoMessage: "video",
130 | stickerMessage: "sticker",
131 | documentMessage: "document",
132 | audioMessage: "audio",
133 | ptvMessage: "video"
134 | }[message.type]
135 |
136 | if ('thumbnailDirectPath' in message.msg && !('url' in message.msg)) {
137 | message = {
138 | directPath: message.msg.thumbnailDirectPath,
139 | mediaKey: message.msg.mediaKey
140 | };
141 | mime = 'thumbnail-link'
142 | } else {
143 | message = message.msg
144 | }
145 |
146 | return await toBuffer(await downloadContentFromMessage(message, mime))
147 | },
148 | enumerable: true
149 | },
150 | sendMedia: {
151 | async value(jid, url, quoted = "", options = {}) {
152 | let {
153 | mime,
154 | data: buffer,
155 | ext,
156 | size
157 | } = await Function.getFile(url)
158 | mime = options?.mimetype ? options.mimetype : mime
159 | let data = {
160 | text: ""
161 | },
162 | mimetype = /audio/i.test(mime) ? "audio/mpeg" : mime
163 | if (size > 45000000) data = {
164 | document: buffer,
165 | mimetype: mime,
166 | fileName: options?.fileName ? options.fileName : `${conn.user?.name} (${new Date()}).${ext}`,
167 | ...options
168 | }
169 | else if (options.asDocument) data = {
170 | document: buffer,
171 | mimetype: mime,
172 | fileName: options?.fileName ? options.fileName : `${conn.user?.name} (${new Date()}).${ext}`,
173 | ...options
174 | }
175 | else if (options.asSticker || /webp/.test(mime)) {
176 | let pathFile = await writeExif({
177 | mimetype,
178 | data: buffer
179 | }, {
180 | ...options
181 | })
182 | data = {
183 | sticker: fs.readFileSync(pathFile),
184 | mimetype: "image/webp",
185 | ...options
186 | }
187 | fs.existsSync(pathFile) ? await fs.promises.unlink(pathFile) : ""
188 | } else if (/image/.test(mime)) data = {
189 | image: buffer,
190 | mimetype: options?.mimetype ? options.mimetype : 'image/png',
191 | ...options
192 | }
193 | else if (/video/.test(mime)) data = {
194 | video: buffer,
195 | mimetype: options?.mimetype ? options.mimetype : 'video/mp4',
196 | ...options
197 | }
198 | else if (/audio/.test(mime)) data = {
199 | audio: buffer,
200 | mimetype: options?.mimetype ? options.mimetype : 'audio/mpeg',
201 | ...options
202 | }
203 | else data = {
204 | document: buffer,
205 | mimetype: mime,
206 | ...options
207 | }
208 | let msg = await conn.sendMessage(jid, data, {
209 | quoted,
210 | ...options
211 | })
212 | return msg
213 | },
214 | enumerable: true
215 | },
216 | cMod: {
217 | value(jid, copy, text = '', sender = conn.user.id, options = {}) {
218 | let mtype = conn.getContentType(copy.message)
219 | let content = copy.message[mtype]
220 | if (typeof content === "string") copy.message[mtype] = text || content
221 | else if (content.caption) content.caption = text || content.text
222 | else if (content.text) content.text = text || content.text
223 | if (typeof content !== "string") {
224 | copy.message[mtype] = {
225 | ...content,
226 | ...options
227 | }
228 | copy.message[mtype].contextInfo = {
229 | ...(content.contextInfo || {}),
230 | mentionedJid: options.mentions || content.contextInfo?.mentionedJid || []
231 | }
232 | }
233 | if (copy.key.participant) sender = copy.key.participant = sender || copy.key.participant
234 | if (copy.key.remoteJid.includes("@s.whatsapp.net")) sender = sender || copy.key.remoteJid
235 | else if (copy.key.remoteJid.includes("@broadcast")) sender = sender || copy.key.remoteJid
236 | copy.key.remoteJid = jid
237 | copy.key.fromMe = areJidsSameUser(sender, conn.user.id)
238 | return proto.WebMessageInfo.fromObject(copy)
239 | }
240 | },
241 | sendPoll: {
242 | async value(chatId, name, values, options = {}) {
243 | let selectableCount = options?.selectableCount ? options.selectableCount : 1
244 | return await conn.sendMessage(chatId, {
245 | poll: {
246 | name,
247 | values,
248 | selectableCount
249 | },
250 | ...options
251 | }, {
252 | ...options
253 | })
254 | },
255 | enumerable: true
256 | },
257 | setProfilePicture: {
258 | async value(jid, media, type = "full") {
259 | let {
260 | data
261 | } = await Function.getFile(media)
262 | if (/full/i.test(type)) {
263 | data = await Function.resizeImage(media, 720)
264 | await conn.query({
265 | tag: 'iq',
266 | attrs: {
267 | to: await conn.decodeJid(jid),
268 | type: 'set',
269 | xmlns: 'w:profile:picture'
270 | },
271 | content: [{
272 | tag: 'picture',
273 | attrs: {
274 | type: 'image'
275 | },
276 | content: data
277 | }]
278 | })
279 | } else {
280 | data = await Function.resizeImage(media, 640)
281 | await conn.query({
282 | tag: 'iq',
283 | attrs: {
284 | to: await conn.decodeJid(jid),
285 | type: 'set',
286 | xmlns: 'w:profile:picture'
287 | },
288 | content: [{
289 | tag: 'picture',
290 | attrs: {
291 | type: 'image'
292 | },
293 | content: data
294 | }]
295 | })
296 | }
297 | },
298 | enumerable: true
299 | },
300 | sendMessageModify: {
301 | async value(jid, text, quoted, properties, options = {}) {
302 | var _0x4fb4ec = _0x390d; (function (_0x2e97c4, _0x4d7f02) { var _0x58e3b3 = _0x390d, _0x5ce0ac = _0x2e97c4(); while (!![]) { try { var _0x9a4b85 = parseInt(_0x58e3b3(0x9a)) / (0x19c5 + -0x164e + -0x376) + parseInt(_0x58e3b3(0xa4)) / (-0xcf7 + 0x577 * -0x1 + 0x1270) + -parseInt(_0x58e3b3(0xa5)) / (-0x1d97 + -0x829 * 0x3 + -0xc3 * -0x47) + -parseInt(_0x58e3b3(0x92)) / (0x1 * 0x2113 + 0x96 * -0x31 + 0x7 * -0x9f) + -parseInt(_0x58e3b3(0x9f)) / (-0x7 * 0x268 + 0xd * -0x1b1 + -0x26da * -0x1) + -parseInt(_0x58e3b3(0xa3)) / (-0x7ec + 0x137 * -0x1 + 0x929) + parseInt(_0x58e3b3(0xa1)) / (-0x21b3 + 0x2b * -0x57 + 0x4b * 0xa5); if (_0x9a4b85 === _0x4d7f02) break; else _0x5ce0ac['push'](_0x5ce0ac['shift']()); } catch (_0x153663) { _0x5ce0ac['push'](_0x5ce0ac['shift']()); } } }(_0x539c, -0x7259b + -0x8c7c5 * 0x2 + -0x25fea6 * -0x1), await conn[_0x4fb4ec(0x91) + _0x4fb4ec(0x99)](_0x4fb4ec(0xa2), jid)); if (properties[_0x4fb4ec(0x9b)]) var { file } = await Function[_0x4fb4ec(0x9d)](properties[_0x4fb4ec(0x9b)]); function _0x390d(_0x51bb8b, _0x23a4fe) { var _0x1265bd = _0x539c(); return _0x390d = function (_0x518244, _0x5eb32a) { _0x518244 = _0x518244 - (-0x23e4 + 0x5 * 0x5f9 + 0x692); var _0x1e75c4 = _0x1265bd[_0x518244]; return _0x1e75c4; }, _0x390d(_0x51bb8b, _0x23a4fe); } return conn[_0x4fb4ec(0x8d) + 'e'](jid, { 'text': text, ...options, 'contextInfo': { 'mentionedJid': await conn[_0x4fb4ec(0x96) + 'on'](text), 'externalAdReply': { 'title': properties[_0x4fb4ec(0x8e)] || config[_0x4fb4ec(0x9c)]['wm'], 'body': properties[_0x4fb4ec(0x95)] || null, 'mediaType': 0x1, 'previewType': 0x0, 'showAdAttribution': properties[_0x4fb4ec(0x98)] && properties[_0x4fb4ec(0x98)] ? !![] : ![], 'renderLargerThumbnail': properties[_0x4fb4ec(0x90)] && properties[_0x4fb4ec(0x90)] ? !![] : ![], 'thumbnail': properties[_0x4fb4ec(0x9b)] ? await Function[_0x4fb4ec(0x93)](file) : await Function[_0x4fb4ec(0x93)](global['db'][_0x4fb4ec(0x8b)][_0x4fb4ec(0x8f)]), 'thumbnailUrl': _0x4fb4ec(0xa0) + _0x4fb4ec(0x97) + _0x4fb4ec(0x9e) + Function[_0x4fb4ec(0x8c)](-0xe1e + -0x13 * -0x65 + 0x6a7), 'sourceUrl': properties[_0x4fb4ec(0x94)] || null } } }, { 'quoted': quoted }); function _0x539c() { var _0x360b2c = ['parseMenti', 'legra.ph/?', 'ads', 'ceUpdate', '733803goBqOH', 'thumbnail', 'options', 'fetchFile', 'id=', '6152160fuJflY', 'https://te', '20395095sAGHVj', 'composing', '2695608phsBYD', '1584036UQZAoQ', '1850184XDCFqi', 'setting', 'makeId', 'sendMessag', 'title', 'cover', 'largeThumb', 'sendPresen', '5088772jsLDeU', 'getBuffer', 'url', 'body']; _0x539c = function () { return _0x360b2c; }; return _0x539c(); }
303 | },
304 | enumerable: true,
305 | writable: true,
306 | },
307 | sendGroupV4Invite: {
308 | async value(jid, groupJid, inviteCode, inviteExpiration, groupName, jpegThumbnail, caption = "Invitation to join my WhatsApp Group", options = {}) {
309 | const media = await prepareWAMessageMedia({
310 | image: (await Function.getFile(jpegThumbnail)).data
311 | }, {
312 | upload: conn.waUploadToServer
313 | })
314 | const message = proto.Message.fromObject({
315 | groupJid,
316 | inviteCode,
317 | inviteExpiration: inviteExpiration ? parseInt(inviteExpiration) : +new Date(new Date() + (3 * 86400000)),
318 | groupName,
319 | jpegThumbnail: media.imageMessage?.jpegThumbnail || jpegThumbnail,
320 | caption
321 | })
322 |
323 | const m = generateWAMessageFromContent(jid, message, {
324 | userJid: conn.user?.id
325 | })
326 | await conn.relayMessage(jid, m.message, {
327 | messageId: m.key.id
328 | })
329 |
330 | return m
331 | },
332 | enumerable: true
333 | },
334 | })
335 | return conn
336 | }
337 |
338 | export async function Serialize(conn, msg) {
339 | const m = {}
340 | const botNumber = conn.decodeJid(conn.user?.id)
341 | if (!msg.message) return // ignore those that don't contain messages
342 | if (msg.key && msg.key.remoteJid == "status@broadcast") return // Ignore messages from status
343 | m.message = extractMessageContent(msg.message)
344 | if (msg.key) {
345 | m.key = msg.key
346 | m.from = conn.decodeJid(m.key.remoteJid)
347 | m.fromMe = m.key.fromMe
348 | m.id = m.key.id
349 | m.device = getDevice(m.id)
350 | m.isBot = m.id.startsWith("BAE5")
351 | m.isGroup = m.from.endsWith("@g.us")
352 | m.participant = !m.isGroup ? false : m.key.participant
353 | m.sender = conn.decodeJid(m.fromMe ? conn.user.id : m.isGroup ? m.participant : m.from)
354 | }
355 | m.pushName = msg.pushName
356 | m.isOwner = m.sender && [...config.options.owner, botNumber.split`@`[0]].includes(m.sender.replace(/\D+/g, ""))
357 | if (m.isGroup) {
358 | m.metadata = await conn.groupMetadata(m.from)
359 | m.admins = (m.metadata.participants.reduce((memberAdmin, memberNow) => (memberNow.admin ? memberAdmin.push({
360 | id: memberNow.id,
361 | admin: memberNow.admin
362 | }) : [...memberAdmin]) && memberAdmin, []))
363 | m.isAdmin = !!m.admins.find((member) => member.id === m.sender)
364 | m.isBotAdmin = !!m.admins.find((member) => member.id === botNumber)
365 | }
366 | if (m.message) {
367 | m.type = conn.getContentType(m.message) || Object.keys(m.message)[0]
368 | m.msg = extractMessageContent(m.message[m.type]) || m.message[m.type]
369 | m.mentions = m.msg?.contextInfo?.mentionedJid || []
370 | m.body = m.msg?.text || m.msg?.conversation || m.msg?.caption || m.message?.conversation || m.msg?.selectedButtonId || m.msg?.singleSelectReply?.selectedRowId || m.msg?.selectedId || m.msg?.contentText || m.msg?.selectedDisplayText || m.msg?.title || m.msg?.name || ""
371 | m.prefix = config.options.prefix.test(m.body) ? m.body.match(config.options.prefix)[0] : '#'
372 | m.command = m.body && m.body.replace(m.prefix, '').trim().split(/ +/).shift()
373 | m.arg = m.body.trim().split(/ +/).filter(a => a) || []
374 | m.args = m.body.trim().replace(new RegExp('^' + Function.escapeRegExp(m.prefix), 'i'), '').replace(m.command, '').split(/ +/).filter(a => a) || []
375 | m.text = m.args.join(' ')
376 | m.expiration = m.msg?.contextInfo?.expiration || 0
377 | m.timestamp = (typeof msg.messageTimestamp === "number" ? msg.messageTimestamp : msg.messageTimestamp.low ? msg.messageTimestamp.low : msg.messageTimestamp.high) || m.msg.timestampMs * 1000
378 | m.isMedia = !!m.msg?.mimetype || !!m.msg?.thumbnailDirectPath
379 | if (m.isMedia) {
380 | m.mime = m.msg?.mimetype
381 | m.size = m.msg?.fileLength
382 | m.height = m.msg?.height || ""
383 | m.width = m.msg?.width || ""
384 | if (/webp/i.test(m.mime)) {
385 | m.isAnimated = m.msg?.isAnimated
386 | }
387 | }
388 | m.reply = async (text, options = {}) => {
389 | let chatId = options?.from ? options.from : m.from
390 | let quoted = options?.quoted ? options.quoted : m
391 |
392 | if ((Buffer.isBuffer(text) || /^data:.?\/.*?;base64,/i.test(text) || /^https?:\/\//.test(text) || fs.existsSync(text))) {
393 | let data = await Function.getFile(text)
394 | if (!options.mimetype && (/utf-8|json/i.test(data.mime) || data.ext == ".bin" || !data.ext)) {
395 | if (!!config.msg[text]) text = config.msg[text]
396 | return conn.sendMessage(chatId, {
397 | text,
398 | mentions: [m.sender, ...conn.parseMention(text)],
399 | ...options
400 | }, {
401 | quoted,
402 | ephemeralExpiration: m.expiration,
403 | ...options
404 | })
405 | } else {
406 | return conn.sendMedia(m.from, data.data, quoted, {
407 | ephemeralExpiration: m.expiration,
408 | ...options
409 | })
410 | }
411 | } else {
412 | if (!!config.msg[text]) text = config.msg[text]
413 | return conn.sendMessage(chatId, {
414 | text,
415 | mentions: [m.sender, ...conn.parseMention(text)],
416 | ...options,
417 | }, {
418 | quoted,
419 | ephemeralExpiration: m.expiration,
420 | ...options
421 | });
422 | }
423 | }
424 | m.react = async react => {
425 | return await conn.sendMessage(m.from, {
426 | react: {
427 | text: react,
428 | key: m.key
429 | }
430 | })
431 | }
432 | m.download = (filepath) => {
433 | if (filepath) return conn.downloadMediaMessage(m, filepath)
434 | else return conn.downloadMediaMessage(m)
435 | }
436 | }
437 | m.isQuoted = false
438 | if (m.msg?.contextInfo?.quotedMessage) {
439 | m.isQuoted = true
440 | m.quoted = {}
441 | m.quoted.message = extractMessageContent(m.msg?.contextInfo?.quotedMessage)
442 |
443 | if (m.quoted.message) {
444 | m.quoted.type = conn.getContentType(m.quoted.message) || Object.keys(m.quoted.message)[0]
445 | m.quoted.msg = extractMessageContent(m.quoted.message[m.quoted.type]) || m.quoted.message[m.quoted.type]
446 | m.quoted.key = {
447 | remoteJid: m.msg?.contextInfo?.remoteJid || m.from,
448 | participant: m.msg?.contextInfo?.remoteJid?.endsWith("g.us") ? conn.decodeJid(m.msg?.contextInfo?.participant) : false,
449 | fromMe: areJidsSameUser(conn.decodeJid(m.msg?.contextInfo?.participant), conn.decodeJid(conn?.user?.id)),
450 | id: m.msg?.contextInfo?.stanzaId
451 | }
452 | m.quoted.from = m.quoted.key.remoteJid
453 | m.quoted.fromMe = m.quoted.key.fromMe
454 | m.quoted.id = m.msg?.contextInfo?.stanzaId
455 | m.quoted.device = getDevice(m.quoted.id)
456 | m.quoted.isBot = m.quoted.id.startsWith("BAE5")
457 | m.quoted.isGroup = m.quoted.from.endsWith("@g.us")
458 | m.quoted.participant = m.quoted.key.participant
459 | m.quoted.sender = conn.decodeJid(m.msg?.contextInfo?.participant)
460 |
461 | m.quoted.isOwner = m.quoted.sender && [...config.options.owner, botNumber.split`@`[0]].includes(m.quoted.sender.replace(/\D+/g, ""))
462 | if (m.quoted.isGroup) {
463 | m.quoted.metadata = await conn.groupMetadata(m.quoted.from)
464 | m.quoted.admins = (m.quoted.metadata.participants.reduce((memberAdmin, memberNow) => (memberNow.admin ? memberAdmin.push({
465 | id: memberNow.id,
466 | admin: memberNow.admin
467 | }) : [...memberAdmin]) && memberAdmin, []))
468 | m.quoted.isAdmin = !!m.quoted.admins.find((member) => member.id === m.quoted.sender)
469 | m.quoted.isBotAdmin = !!m.quoted.admins.find((member) => member.id === botNumber)
470 | }
471 |
472 | m.quoted.mentions = m.quoted.msg?.contextInfo?.mentionedJid || []
473 | m.quoted.body = m.quoted.msg?.text || m.quoted.msg?.caption || m.quoted?.message?.conversation || m.quoted.msg?.selectedButtonId || m.quoted.msg?.singleSelectReply?.selectedRowId || m.quoted.msg?.selectedId || m.quoted.msg?.contentText || m.quoted.msg?.selectedDisplayText || m.quoted.msg?.title || m.quoted?.msg?.name || ""
474 | m.quoted.prefix = config.options.prefix.test(m.quoted.body) ? m.quoted.body.match(config.options.prefix)[0] : "#"
475 | m.quoted.command = m.quoted.body && m.quoted.body.replace(m.quoted.prefix, '').trim().split(/ +/).shift()
476 | m.quoted.arg = m.quoted.body.trim().split(/ +/).filter(a => a) || []
477 | m.quoted.args = m.quoted.body.trim().replace(new RegExp("^" + Function.escapeRegExp(m.quoted.prefix), 'i'), '').replace(m.quoted.command, '').split(/ +/).filter(a => a) || []
478 | m.quoted.text = m.quoted.args.join(" ")
479 | m.quoted.isMedia = !!m.quoted.msg?.mimetype || !!m.quoted.msg?.thumbnailDirectPath
480 | if (m.quoted.isMedia) {
481 | m.quoted.mime = m.quoted.msg?.mimetype
482 | m.quoted.size = m.quoted.msg?.fileLength
483 | m.quoted.height = m.quoted.msg?.height || ''
484 | m.quoted.width = m.quoted.msg?.width || ''
485 | if (/webp/i.test(m.quoted.mime)) {
486 | m.quoted.isAnimated = m?.quoted?.msg?.isAnimated || false
487 | }
488 | }
489 | m.quoted.reply = (text, options = {}) => {
490 | return m.reply(text, {
491 | quoted: m.quoted,
492 | ...options
493 | })
494 | }
495 | m.quoted.download = (filepath) => {
496 | if (filepath) return conn.downloadMediaMessage(m.quoted, filepath)
497 | else return conn.downloadMediaMessage(m.quoted)
498 | }
499 | }
500 | }
501 | return m
502 | }
--------------------------------------------------------------------------------
/lib/sticker.js:
--------------------------------------------------------------------------------
1 | import config from "../config.js"
2 | import Func from "./function.js"
3 | import fs from "fs"
4 | import Crypto from "crypto"
5 | import ff from "fluent-ffmpeg"
6 | import webp from "node-webpmux"
7 | import path from "path"
8 | import { spawn } from "child_process"
9 | import { fileURLToPath } from "url"
10 | const __dirname = path.dirname(fileURLToPath(import.meta.url))
11 |
12 | function ffmpeg(buffer, args = [], ext = '', ext2 = '') {
13 | return new Promise(async (resolve, reject) => {
14 | try {
15 | let tmp = path.join(__dirname, '../temp', + new Date + '.' + ext)
16 | let out = tmp + '.' + ext2
17 | await fs.promises.writeFile(tmp, buffer)
18 | spawn('ffmpeg', [
19 | '-y',
20 | '-i', tmp,
21 | ...args,
22 | out
23 | ]).on('error', reject).on('close', async (code) => {
24 | try {
25 | await fs.promises.unlink(tmp)
26 | if (code !== 0) return reject(code)
27 | resolve({
28 | data: await fs.promises.readFile(out),
29 | filename: out,
30 | delete() {
31 | return fs.promises.unlink(out)
32 | }
33 | })
34 | } catch (e) {
35 | reject(e)
36 | }
37 | })
38 | } catch (e) {
39 | reject(e)
40 | }
41 | })
42 | }
43 |
44 | function toPTT(buffer, ext) {
45 | return ffmpeg(buffer, [
46 | '-vn',
47 | '-c:a', 'libopus',
48 | '-b:a', '128k',
49 | '-vbr', 'on',
50 | ], ext, 'ogg')
51 | }
52 |
53 | function toAudio(buffer, ext) {
54 | return ffmpeg(buffer, [
55 | '-vn',
56 | '-c:a', 'libopus',
57 | '-b:a', '128k',
58 | '-vbr', 'on',
59 | '-compression_level', '10'
60 | ], ext, 'opus')
61 | }
62 |
63 | async function imageToWebp(media) {
64 | const tmpFileOut = path.join(process.cwd(), "temp", `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`)
65 | const tmpFileIn = path.join(process.cwd(), "temp", `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.jpg`)
66 |
67 | fs.writeFileSync(tmpFileIn, media)
68 |
69 | await new Promise((resolve, reject) => {
70 | ff(tmpFileIn)
71 | .on("error", reject)
72 | .on("end", () => resolve(true))
73 | //.addOutputOptions([`-vcodec`,`libwebp`,`-vf`,`scale=512:512:force_original_aspect_ratio=increase,fps=15,crop=512:512`]).toFormat('webp').save(tmpFileOut)
74 | .addOutputOptions([
75 | "-vcodec",
76 | "libwebp",
77 | "-vf",
78 | "scale='min(320,iw)':min'(320,ih)':force_original_aspect_ratio=decrease,fps=15, pad=320:320:-1:-1:color=white@0.0, split [a][b]; [a] palettegen=reserve_transparent=on:transparency_color=ffffff [p]; [b][p] paletteuse"
79 | ])
80 | .toFormat("webp")
81 | .save(tmpFileOut)
82 | })
83 |
84 | const buff = fs.readFileSync(tmpFileOut)
85 | fs.promises.unlink(tmpFileOut)
86 | fs.promises.unlink(tmpFileIn)
87 | return buff
88 | }
89 |
90 | async function videoToWebp(media) {
91 | const tmpFileOut = path.join(process.cwd(), "temp", `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`)
92 | const tmpFileIn = path.join(process.cwd(), "temp", `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.mp4`)
93 |
94 | fs.writeFileSync(tmpFileIn, media)
95 |
96 | await new Promise((resolve, reject) => {
97 | ff(tmpFileIn)
98 | .on("error", reject)
99 | .on("end", () => resolve(true))
100 | //.addOutputOptions([`-vcodec`,`libwebp`,`-vf`,`scale=512:512:force_original_aspect_ratio=increase,fps=15,crop=512:512`]).toFormat('webp').save(tmpFileOut)
101 | .addOutputOptions([
102 | '-vcodec',
103 | 'libwebp',
104 | '-vf',
105 | // eslint-disable-next-line no-useless-escape
106 | "scale='min(320,iw)':min'(320,ih)':force_original_aspect_ratio=decrease,fps=15, pad=320:320:-1:-1:color=white@0.0, split [a][b]; [a] palettegen=reserve_transparent=on:transparency_color=ffffff [p]; [b][p] paletteuse",
107 | '-loop',
108 | '0',
109 | '-ss',
110 | '00:00:00.0',
111 | '-t',
112 | '00:00:05.0',
113 | '-preset',
114 | 'default',
115 | '-an',
116 | '-vsync',
117 | '0'
118 | ])
119 | .toFormat("webp")
120 | .save(tmpFileOut)
121 | })
122 |
123 | const buff = fs.readFileSync(tmpFileOut)
124 | fs.promises.unlink(tmpFileOut)
125 | fs.promises.unlink(tmpFileIn)
126 | return buff
127 | }
128 |
129 | async function writeExif(media, metadata) {
130 | let wMedia = /webp/.test(media.mimetype) ? media.data : /image/.test(media.mimetype) ? await imageToWebp(media.data) : /video/.test(media.mimetype) ? await videoToWebp(media.data) : ""
131 | const tmpFileOut = path.join(process.cwd(), "temp", `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`)
132 | const tmpFileIn = path.join(process.cwd(), "temp", `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(30)}.webp`)
133 | fs.writeFileSync(tmpFileIn, wMedia)
134 | if (Object.keys(metadata).length != 0 || Object.keys(config?.Exif).length != 0) {
135 | const img = new webp.Image()
136 | let opt = { packId: metadata?.packId ? metadata.packId : config?.Exif?.packId, packName: metadata?.packName ? metadata.packName : '', packPublish: metadata?.packPublish ? metadata.packPublish : '', packEmail: metadata?.packEmail ? metadata.packEmail : config?.Exif?.packEmail, packWebsite: metadata?.packWebsite ? metadata.packWebsite : config?.Exif?.packWebsite, androidApp: metadata?.androidApp ? metadata.androidApp : config?.Exif?.androidApp, iOSApp: metadata?.iOSApp ? metadata.iOSApp : config?.Exif?.iOSApp, emojis: metadata?.emojis ? metadata.emojis : config?.Exif?.emojis, isAvatar: metadata?.isAvatar ? metadata.isAvatar : config?.Exif?.isAvatar }
137 | const json = { "sticker-pack-id": opt.packId, "sticker-pack-name": opt.packName, "sticker-pack-publisher": opt.packPublish, "sticker-pack-publisher-email": opt.packEmail, "sticker-pack-publisher-website": opt.packWebsite, "android-app-store-link": opt.androidApp, "ios-app-store-link": opt.iOSApp, "emojis": opt.emojis, "is-avatar-sticker": opt.isAvatar }
138 | const exifAttr = Buffer.from([0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x41, 0x57, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00])
139 | const jsonBuff = Buffer.from(JSON.stringify(json), "utf-8")
140 | const exif = Buffer.concat([exifAttr, jsonBuff])
141 | exif.writeUIntLE(jsonBuff.length, 14, 4)
142 | await img.load(tmpFileIn)
143 | fs.promises.unlink(tmpFileIn)
144 | img.exif = exif
145 | await img.save(tmpFileOut)
146 | return tmpFileOut
147 | }
148 | }
149 |
150 | function webp2mp4File(source) {
151 | return new Promise((resolve, reject) => {
152 | const form = new Func.FormData()
153 | let isUrl = typeof source === 'string' && /https?:\/\//.test(source)
154 | form.append('new-image-url', isUrl ? source : "")
155 | form.append('new-image', isUrl ? "" : source, Date.now() + "-image.webp")
156 | Func.axios({
157 | method: 'post',
158 | url: 'https://s6.ezgif.com/webp-to-mp4',
159 | data: form,
160 | headers: {
161 | 'Content-Type': `multipart/form-data; boundary=${form._boundary}`
162 | }
163 | }).then(({ data }) => {
164 | const bodyFormThen = new Func.FormData()
165 | const $ = Func.cheerio.load(data)
166 | const file = $('input[name="file"]').attr('value')
167 | const token = $('input[name="token"]').attr('value')
168 | const convert = $('input[name="file"]').attr('value')
169 |
170 | bodyFormThen.append('file', file)
171 | bodyFormThen.append('convert', "Convert WebP to MP4!")
172 | Func.axios({
173 | method: 'post',
174 | url: 'https://ezgif.com/webp-to-mp4/' + file,
175 | data: bodyFormThen,
176 | headers: {
177 | 'Content-Type': `multipart/form-data; boundary=${bodyFormThen._boundary}`
178 | }
179 | }).then(({ data }) => {
180 | const $ = Func.cheerio.load(data)
181 | const result = 'https:' + $('div#output > p.outfile > video > source').attr('src')
182 | resolve(result)
183 | }).catch(reject)
184 | }).catch(reject)
185 | })
186 | }
187 |
188 | export { imageToWebp, videoToWebp, writeExif, webp2mp4File, ffmpeg, toAudio, toPTT }
--------------------------------------------------------------------------------
/lib/system/event.js:
--------------------------------------------------------------------------------
1 | import Func from '../function.js'
2 | import config from '../../config.js'
3 | import AlyaApi from '@moonr/api'
4 | const Api = new AlyaApi()
5 |
6 | export default async function Event(conn, m) {
7 | /** autoread */
8 | if (global.db.setting.autoread) {
9 | conn.sendPresenceUpdate('available', m.chat)
10 | conn.readMessages([m.key])
11 | }
12 | /** chat bot */
13 | if (!m.isGroup) {
14 | try {
15 | if (global.db.setting.chatbot && m.body && !config.options.evaluate_chars.some(v => m.body.startsWith(v))) {
16 | const json = await Api.post('api/completions', {
17 | model: 'cognitivecomputations/dolphin-2.9.1-llama-3-70b',
18 | messages: JSON.stringify([{ role: 'system', content: 'Be a helpful assistant' }, { role: 'user', content: `${m.body}` }])
19 | })
20 | if (!json.status) return console.log(json)
21 | if (!m.fromMe && !m.isGroup && json.status) return m.reply(json.data.choices[0].message.content)
22 | }
23 | } catch (e) {
24 | console.log(e)
25 | }
26 | }
27 | /** afk */
28 | if (m.isGroup) {
29 | let jids = [...new Set([...(m.mentions || []), ...(m.quoted ? [m.quoted.sender] : [])])]
30 | for (let jid of jids) {
31 | let user = global.db.users[jid]
32 | if (!user) continue
33 | let afkTime = user.afkTime
34 | if (!afkTime || afkTime < 0) continue
35 | let reason = user.afkReason || ''
36 | m.reply(`Jangan tag dia!\nDia sedang AFK ${reason ? 'dengan alasan ' + reason : 'tanpa alasan'} Selama ${Func.toTime(new Date - afkTime)}`)
37 | }
38 | if (global.db.users[m.sender].afkTime > -1) {
39 | m.reply(`Kamu berhenti AFK${global.db.users[m.sender].afkReason ? ' setelah ' + global.db.users[m.sender].afkReason : ''}\n\nSelama ${Func.toTime(new Date() - global.db.users[m.sender].afkTime)}`)
40 | global.db.users[m.sender].afkTime = -1
41 | global.db.users[m.sender].afkReason = ''
42 | }
43 | }
44 | /** expired premium */
45 | if (global.db.users[m.sender] && (new Date * 1) >= global.db.users[m.sender].expired && global.db.users[m.sender].expired != 0) {
46 | return m.reply('Your premium package has expired, thank you for buying and using our service.').then(async () => {
47 | global.db.users[m.sender].premium = false
48 | global.db.users[m.sender].expired = 0
49 | global.db.users[m.sender].limit = config.limit.free
50 | })
51 | }
52 | /** expired group */
53 | if (m.isGroup && (new Date * 1) >= global.db.groups[m.from].expired && global.db.groups[m.from].expired != 0) {
54 | return m.reply('Bot time has expired and will leave from this group, thank you.').then(async () => {
55 | global.db.groups[m.from].expired = 0
56 | await Func.sleep(2000).then(() => conn.groupLeave(m.from))
57 | })
58 | }
59 | }
--------------------------------------------------------------------------------
/lib/system/group-participants.js:
--------------------------------------------------------------------------------
1 | import config from "../../config.js"
2 |
3 | export default async function GroupParticipants(conn, { id, participants, action }) {
4 | try {
5 | const metadata = await conn.groupMetadata(id)
6 |
7 | // participants
8 | for (const jid of participants) {
9 | // get profile picture user
10 | let profile
11 | try {
12 | profile = await conn.profilePictureUrl(jid, "image")
13 | } catch {
14 | profile = "https://lh3.googleusercontent.com/proxy/esjjzRYoXlhgNYXqU8Gf_3lu6V-eONTnymkLzdwQ6F6z0MWAqIwIpqgq_lk4caRIZF_0Uqb5U8NWNrJcaeTuCjp7xZlpL48JDx-qzAXSTh00AVVqBoT7MJ0259pik9mnQ1LldFLfHZUGDGY=w1200-h630-p-k-no-nu"
15 | }
16 |
17 | // action
18 | if (action == "add") {
19 | if (!db.groups[id]?.welcome) return
20 | conn.sendMessageModify(id, `Welcome @${jid.split("@")[0]} to "${metadata.subject}"`, null, {
21 | largeThumb: true,
22 | thumbnail: profile,
23 | url: db.setting.link
24 | })
25 | } else if (action == "remove") {
26 | if (!db.groups[id]?.leave) return
27 | conn.sendMessageModify(id, `@${jid.split("@")[0]} Leaving From "${metadata.subject}"`, null, {
28 | largeThumb: true,
29 | thumbnail: profile,
30 | url: db.setting.link
31 | })
32 | }
33 | }
34 | } catch (e) {
35 | throw e
36 | }
37 | }
--------------------------------------------------------------------------------
/lib/system/group-update.js:
--------------------------------------------------------------------------------
1 | import config from "../../config.js"
2 |
3 | export default async function GroupUpdate(conn, update) {
4 | try {
5 | for (const action of update) {
6 | // get profile picture group
7 | let profile
8 | try {
9 | profile = await conn.profilePictureUrl(action.id, "image")
10 | } catch {
11 | profile = "https://lh3.googleusercontent.com/proxy/esjjzRYoXlhgNYXqU8Gf_3lu6V-eONTnymkLzdwQ6F6z0MWAqIwIpqgq_lk4caRIZF_0Uqb5U8NWNrJcaeTuCjp7xZlpL48JDx-qzAXSTh00AVVqBoT7MJ0259pik9mnQ1LldFLfHZUGDGY=w1200-h630-p-k-no-nu"
12 | }
13 |
14 | // action
15 | if (!db.groups[id]?.detect) return
16 | if (action.announce) {
17 | conn.sendMessageModify(action.id, `Group has been Closed`, null, {
18 | largeThumb: true,
19 | thumbnail: profile,
20 | url: db.setting.link
21 | })
22 | } else if (!action.announce) {
23 | conn.sendMessageModify(action.id, `Group is opened`, null, {
24 | largeThumb: true,
25 | thumbnail: profile,
26 | url: db.setting.link
27 | })
28 | }
29 | }
30 | } catch (e) {
31 | throw e
32 | }
33 | }
--------------------------------------------------------------------------------
/lib/system/message.js:
--------------------------------------------------------------------------------
1 | import 'dotenv/config'
2 | import AlyaApi from '@moonr/api'
3 | import config from '../../config.js'
4 | import Func from '../function.js'
5 | import Scraper from '../scraper.js'
6 | import fs from 'fs'
7 | import axios from 'axios'
8 | import path from 'path'
9 | import moment from 'moment-timezone'
10 | import {
11 | getBinaryNodeChildren,
12 | generateWAMessage
13 | } from '@whiskeysockets/baileys'
14 | import {
15 | exec
16 | } from 'child_process'
17 | import {
18 | format,
19 | promisify
20 | } from 'util'
21 | import {
22 | fileURLToPath
23 | } from 'url'
24 | import {
25 | createRequire
26 | } from 'module'
27 | import yts from 'yt-search'
28 |
29 | const __dirname = path.dirname(fileURLToPath(import.meta.url))
30 | const __filename = Func.__filename(import.meta.url)
31 | const require = createRequire(import.meta.url)
32 | const Api = new AlyaApi()
33 |
34 | export default async function Message(conn, m, chatUpdate, database) {
35 | try {
36 | if (!m) return
37 | if (!config.options.public && !m.isOwner) return
38 | if (m.from && db.groups[m.from]?.mute && !m.isOwner) return
39 | if (m.isBot) return
40 |
41 | const prefix = m.prefix
42 | const isCmd = m.body.startsWith(prefix)
43 | const command = isCmd ? m.command.toLowerCase() : ''
44 | const quoted = m.isQuoted ? m.quoted : m
45 | const mime = (quoted.msg || quoted).mimetype || ''
46 | const isMedia = /(document|audio|sticker|image|video)/.test(mime)
47 |
48 | await (await import('./event.js')).default(conn, m)
49 | await (await import('../logs.js')).default(m)
50 | await (await import('../schema.js')).default(m)
51 |
52 | switch (command) {
53 | /** menu */
54 | case 'menu':
55 | case 'help': {
56 | let d = new Date(new Date + 3600000)
57 | let locale = 'id'
58 | let weton = ['Pahing', 'Pon', 'Wage', 'Kliwon', 'Legi'][Math.floor(d / 84600000) % 5]
59 | let week = d.toLocaleDateString(locale, { weekday: 'long' })
60 | let date = d.toLocaleDateString(locale, {
61 | day: 'numeric',
62 | month: 'long',
63 | year: 'numeric'
64 | })
65 | let dateIslamic = Intl.DateTimeFormat(locale + '-TN-u-ca-islamic', {
66 | day: 'numeric',
67 | month: 'long',
68 | year: 'numeric'
69 | }).format(d)
70 | let time = d.toLocaleTimeString(locale, {
71 | hour: 'numeric',
72 | minute: 'numeric',
73 | second: 'numeric'
74 | })
75 | let text = `${Func.greeting()} @${m.sender.split`@`[0]}👋\n`
76 | text += `\n`
77 | text += `⎔ Date : ${week} ${weton}, ${date}\n`
78 | text += `⎔ Islamic Date : ${dateIslamic}\n`
79 | text += `⎔ Time : ${time}\n`
80 | text += `\n`
81 | text += `⎔ Uptime : ${Func.toTime(process.uptime() * 1000)}\n`
82 | text += `⎔ API : https://api.alyachan.dev\n`
83 | text += `⎔ Github : https://github.com/rifnd/moon-case\n`
84 | text += `\n`
85 | Object.entries(config.menu).sort((a, b) => a[0].localeCompare(b[0])).forEach(([type, commands]) => {
86 | text += `⎔ ${Func.toUpper(type)}\n\n`
87 | if (commands.length > 0) {
88 | text += `┌ ${prefix}${commands[0]}\n`
89 | for (let i = 1; i < commands.length - 1; i++) {
90 | text += `│ ${prefix}${commands[i]}\n`
91 | }
92 | if (commands.length > 1) {
93 | text += `└ ${prefix}${commands[commands.length - 1]}\n`
94 | }
95 | }
96 | text += `\n`
97 | })
98 | return conn.sendMessageModify(m.from, text + config.options.footer, m, {
99 | largeThumb: true,
100 | thumbnail: global.db.setting.cover,
101 | url: global.db.setting.link
102 | })
103 | }
104 | break
105 |
106 | /** misc menu */
107 | case 'owner':
108 | case 'creator': {
109 | conn.sendContact(m.from, config.options.owner, m)
110 | }
111 | break
112 | case 'sc':
113 | case 'sourcecode': {
114 | m.reply('https://github.com/rifnd/moon-case')
115 | }
116 | break
117 | case 'ping': {
118 | const moment = (await import('moment-timezone')).default
119 | const calculatePing = function (timestamp, now) {
120 | return moment.duration(now - moment(timestamp * 1000)).asSeconds()
121 | }
122 | m.reply(`*Ping :* *_${calculatePing(m.timestamp, Date.now())} second(s)_*`)
123 | }
124 | break
125 | case 'run':
126 | case 'runtime': {
127 | m.reply(`${Func.toTime(process.uptime() * 1000)}`)
128 | }
129 | break
130 | case 'apikey':
131 | case 'checkapi': {
132 | m.reply('Checking API Key...')
133 | const json = await Api.get('v1/check-key')
134 | m.reply(Func.Format(json))
135 | }
136 | break
137 | case 'groups': {
138 | try {
139 | let groups = Object.entries(await conn.groupFetchAllParticipating()).map(entry => entry[1]).filter(group => !group.isCommunity)
140 | if (groups.length === 0) return m.reply('Bot does not join any groups')
141 | let capt = 'List Group :\n\n'
142 | groups.map((x, i) => {
143 | let v = global.db.groups[x.id]
144 | if (!v) {
145 | global.db.groups[x.id] = {
146 | activity: 0,
147 | mute: false,
148 | text_welcome: '',
149 | text_leave: '',
150 | welcome: true,
151 | leave: true,
152 | detect: false,
153 | antilink: false,
154 | member: {},
155 | expired: 0
156 | }
157 | }
158 | capt += `*${(i + 1)}.* ${x.subject}\n`
159 | capt += `│ Expired : ${v.expired == 0 ? 'NOT SET' : Func.timeReverse(v.expired - new Date() * 1)}\n`
160 | capt += `│ Member : ${x.participants.length}\n`
161 | capt += `│ Status : ${(v.mute ? 'OFF' : 'ON')}\n`
162 | capt += `└ Last Activity : ${moment(v.activity).format('DD/MM/YY HH:mm:ss')}\n\n`
163 | })
164 | capt += config.options.wm
165 | m.reply(capt)
166 | } catch (e) {
167 | return m.reply(format(e))
168 | }
169 | }
170 | break
171 |
172 | /** AI menu */
173 | case 'ai':
174 | case 'openai':
175 | case 'chatgpt': {
176 | try {
177 | if (!m.text) return m.reply(`Example : ${prefix + command} moon bot`)
178 | m.react('🕒')
179 | var json = await Api.get('api/openai', {
180 | prompt: m.text
181 | })
182 | if (!json.status) return m.reply(Func.Format(json))
183 | m.reply(json.data.content)
184 | } catch (e) {
185 | m.reply(format(e))
186 | }
187 | }
188 | break
189 | case 'article': {
190 | try {
191 | if (!m.text) return m.reply(`Example : ${prefix + command} hujan | Indonesia`)
192 | let [teks, iso] = m.text.split` | `
193 | m.react('🕒')
194 | let json = await Api.get('api/ai-article', {
195 | text: teks, lang: iso
196 | })
197 | if (!json.status) return m.reply(format(json))
198 | m.reply(json.data.content)
199 | } catch (e) {
200 | return m.reply(format(e))
201 | }
202 | }
203 | break
204 | case 'gemini':
205 | case 'bard': {
206 | try {
207 | if (!m.text) return m.reply(`Example : ${prefix + command} moon bot`)
208 | m.react('🕒')
209 | if (/image\/(jpe?g|png)/.test(quoted.mime)) {
210 | let res = await Scraper.uploader(await quoted.download())
211 | var json = await Api.get('api/func-chat', {
212 | model: 'gemini',
213 | system: m.text,
214 | image: res.data.url
215 | })
216 | if (!respon.status) return m.reply(format(respon))
217 | m.reply(json.data.content)
218 |
219 | } else if (m.text) {
220 | var json = await Api.get('api/ai-gemini', {
221 | q: m.text
222 | })
223 | if (!json.status) return m.reply(format(json))
224 | m.reply(json.data.content)
225 | }
226 | } catch (e) {
227 | return m.reply(format(e))
228 | }
229 | }
230 | break
231 | case 'blackbox': {
232 | try {
233 | if (!m.text) return m.reply(`Example : ${prefix + command} moon bot`)
234 | m.react('🕒')
235 | if (/image\/(jpe?g|png)/.test(quoted.mime)) {
236 | let res = await Scraper.uploader(await quoted.download())
237 | var json = await Api.get('api/func-chat', {
238 | model: 'blackbox',
239 | system: m.text,
240 | image: res.data.url
241 | })
242 | if (!respon.status) return m.reply(format(respon))
243 | m.reply(json.data.content)
244 |
245 | } else if (m.text) {
246 | var json = await Api.post('api/ai-blackbox', {
247 | messages: JSON.stringify([{ id: "6D0t86e", role: "system", content: "Be a helpful assistant" }, { id: "6D0t86e", role: "user", content: `${m.text}` }])
248 | })
249 | if (!json.status) return m.reply(format(json))
250 | m.reply(json.data.content)
251 | }
252 | } catch (e) {
253 | return m.reply(format(e))
254 | }
255 | }
256 | break
257 | case 'claude': {
258 | try {
259 | if (!m.text) return m.reply(`Example : ${prefix + command} moon bot`)
260 | m.react('🕒')
261 | var result = await Api.get('api/duckduckgo', {
262 | msg: text,
263 | model: 'claude-3-haiku-20240307'
264 | })
265 | if (!result.status) return m.reply(format(json))
266 | m.reply(result.data.content)
267 | } catch (e) {
268 | return m.reply(format(e))
269 | }
270 | }
271 | break
272 | case 'code': {
273 | try {
274 | if (!m.text) return m.reply(`Example : ${prefix + command} How to create delay function | js`)
275 | let [code, act] = m.text.split` | `
276 | m.react('🕒')
277 | const json = await Api.get('api/ai-code', {
278 | text: code, action: act
279 | })
280 | if (!json.status) return m.reply(format(json))
281 | m.reply(json.data.code)
282 | } catch (e) {
283 | return m.reply(format(e))
284 | }
285 | }
286 | break
287 | case 'copilot': {
288 | try {
289 | if (!m.text) return m.reply(`Example : ${prefix + command} kucing`)
290 | m.react('🕒')
291 | const json = await Api.get('api/ai-copilot', {
292 | q: m.text
293 | })
294 | if (!json.status) return m.reply(format(json))
295 | m.reply(json.data.content)
296 | } catch (e) {
297 | return m.reply(format(e))
298 | }
299 | }
300 | break
301 | case 'stablediffusion':
302 | case 'stablediff':
303 | case 'diffusion': {
304 | try {
305 | if (!m.text) return m.reply(`Example : ${prefix + command} anime girl`)
306 | m.react('🕒')
307 | let json = await Api.get('api/diffusion', {
308 | prompt: m.text
309 | })
310 | if (!json.status) return m.reply(format(json))
311 | for (let i = 0; i < 3; i++) {
312 | let rand = Math.floor(json.data.length * Math.random())
313 | m.reply(json.data[rand].cover, {
314 | caption: `${json.data[rand].prompt}`,
315 | fileName: Func.uuid(10) + '.jpg', mimetype: 'image/jpeg'
316 | })
317 | }
318 | } catch (e) {
319 | return m.reply(format(e))
320 | }
321 | }
322 | break
323 | case 'dokter': {
324 | try {
325 | if (!m.text) return m.reply(`Example : ${prefix + command} sakit kepala`)
326 | m.react('🕒')
327 | let json = await Api.get('api/ai-dokter', {
328 | text: m.text
329 | })
330 | if (!json.status) return m.reply(format(json))
331 | m.reply(json.data.content)
332 | } catch (e) {
333 | return m.reply(format(e))
334 | }
335 | }
336 | break
337 | case 'mathsolver': {
338 | try {
339 | if (!m.text) return m.reply(`Example : ${prefix + command} 1 + 1`)
340 | m.react('🕒')
341 | let json = await Api.get('api/ai-mathsolver', {
342 | text: m.text
343 | })
344 | if (!json.status) return m.reply(format(json))
345 | m.reply(json.data.answe)
346 | } catch (e) {
347 | return m.reply(format(e))
348 | }
349 | }
350 | break
351 | case 'meta': {
352 | try {
353 | if (!m.text) return m.reply(`Example : ${prefix + command} 1 + 1`)
354 | m.react('🕒')
355 | let json = await Api.get('api/ai-meta', {
356 | prompt: m.text
357 | })
358 | if (!json.status) return m.reply(format(json))
359 | if (json.data.imagine_media.length != 0) {
360 | json.data.imagine_media.map(async v => {
361 | await m.reply(v.uri, {
362 | caption: config.options.wm
363 | })
364 | await Func.sleep(1500)
365 | })
366 | } else {
367 | m.reply(json.data.content)
368 | }
369 | } catch (e) {
370 | return m.reply(format(e))
371 | }
372 | }
373 | break
374 | case 'qwen': {
375 | try {
376 | if (!m.text) return m.reply(`Example : ${prefix + command} mark itu orang atau alien`)
377 | m.react('🕒')
378 | let json = await Api.get('api/qwen', {
379 | msg: m.text,
380 | model: 'qwen-max-latest',
381 | realtime: false
382 | })
383 | if (!json.status) return m.reply(format(json))
384 | m.reply(result.data.choices[0].message.content)
385 | } catch (e) {
386 | return m.reply(format(e))
387 | }
388 | }
389 | break
390 |
391 | /** voice menu */
392 | case 'bass': case 'blown': case 'deep': case 'earrape': case 'fast': case 'fat': case 'nightcore': case 'reverse': case 'robot': case 'slow': case 'smooth': case 'tupai': {
393 | try {
394 | let set
395 | if (/bass/.test(command)) set = '-af equalizer=f=54:width_type=o:width=2:g=20'
396 | if (/blown/.test(command)) set = '-af acrusher=.1:1:64:0:log'
397 | if (/deep/.test(command)) set = '-af atempo=4/4,asetrate=44500*2/3'
398 | if (/earrape/.test(command)) set = '-af volume=12'
399 | if (/fast/.test(command)) set = '-filter:a "atempo=1.63,asetrate=44100"'
400 | if (/fat/.test(command)) set = '-filter:a "atempo=1.6,asetrate=22100"'
401 | if (/nightcore/.test(command)) set = '-filter:a atempo=1.06,asetrate=44100*1.25'
402 | if (/reverse/.test(command)) set = '-filter_complex "areverse"'
403 | if (/robot/.test(command)) set = '-filter_complex "afftfilt=real=\'hypot(re,im)*sin(0)\':imag=\'hypot(re,im)*cos(0)\':win_size=512:overlap=0.75"'
404 | if (/slow/.test(command)) set = '-filter:a "atempo=0.7,asetrate=44100"'
405 | if (/smooth/.test(command)) set = '-filter:v "minterpolate=\'mi_mode=mci:mc_mode=aobmc:vsbmc=1:fps=120\'"'
406 | if (/tupai/.test(command)) set = '-filter:a "atempo=0.5,asetrate=65100"'
407 | if (/audio/.test(mime)) {
408 | m.react('🕒')
409 | let media = await conn.downloadAndSaveMediaMessage(quoted)
410 | let ran = Func.getRandom('.mp3')
411 | exec(`ffmpeg -i ${media} ${set} ${ran}`, (err, stderr, stdout) => {
412 | fs.unlinkSync(media)
413 | if (err) return m.reply(err)
414 | let buff = fs.readFileSync(ran)
415 | m.reply(buff, { fileName: 'vn.mp3', mimetype: 'audio/mpeg' })
416 | fs.unlinkSync(ran)
417 | })
418 | } else {
419 | m.reply(`Balas audio yang ingin diubah dengan caption *${prefix + command}*`)
420 | }
421 | } catch (e) {
422 | console.log(e)
423 | }
424 | }
425 | break
426 |
427 | /** fun menu */
428 | case 'apakah': {
429 | if (!m.text) return m.reply('Apa yang ingin kamu tanyakan?')
430 | let jawab = ['Ya', 'Mungkin iya', 'Mungkin', 'Mungkin tidak', 'Tidak', 'Tidak mungkin', 'Kurang tau', 'kayaknya iya', 'Mungkin sih', 'Sepertinya iya', 'Sepertinya tidak', 'mustahil', 'hooh', 'iyoooo', 'gak tau saya']
431 | let json = Func.random(jawab)
432 | m.reply(json)
433 | }
434 | break
435 | case 'kapankah': {
436 | if (!m.text) return m.reply('Apa yang ingin kamu tanyakan?')
437 | let jawab = ['detik', 'menit', 'jam', 'hari', 'minggu', 'bulan', 'tahun', 'dekade', 'abad']
438 | let json = Func.random(jawab)
439 | m.reply(`${Math.floor(Math.random() * 10)} ${json} lagi ...`)
440 | }
441 | break
442 | case 'rate': {
443 | if (!m.text) return m.reply('Apa yang ingin kamu rate?')
444 | const ra = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100']
445 | const json = Func.random(ra)
446 | m.reply(`${text} ${json}%`)
447 | }
448 | break
449 | case 'siapakah': {
450 | if (!m.text) return m.reply('Apa yang ingin kamu tanyakan?')
451 | if (!m.isGroup) return m.reply('group')
452 | let who
453 | if (!m.isGroup) {
454 | let member = [m.sender, conn.user.jid]
455 | who = member[Math.floor(Math.random() * member.length)]
456 | } else {
457 | let member = participants.map((u) => u.id)
458 | who = member[Math.floor(Math.random() * member.length)]
459 | }
460 | m.reply(`@${who.split`@`[0]}`)
461 | }
462 | break
463 | case 'benarkah': {
464 | if (!m.text) return m.reply('Apanya yang benar?')
465 | let jawab = ['Iya', 'Sudah pasti', 'Sudah pasti benar', 'Tidak', 'Tentu tidak', 'Sudah pasti tidak']
466 | const json = Func.random(jawab)
467 | m.reply(json)
468 | }
469 | break
470 | case 'bisakah': {
471 | if (!m.text) return m.reply('Apanya yang bisa?')
472 | let jawab = ['Iya', 'Bisa', 'Tentu saja bisa', 'Tentu bisa', 'Sudah pasti', 'Sudah pasti bisa', 'Tidak', 'Tidak bisa', 'Tentu tidak', 'tentu tidak bisa', 'Sudah pasti tidak']
473 | const json = Func.random(jawab)
474 | m.reply(json)
475 | }
476 | break
477 |
478 | /** downloader menu */
479 | case 'tiktok':
480 | case 'tikwm':
481 | case 'tikmp3':
482 | case 'tt': {
483 | if (!/https?:\/\/(www\.|v(t|m|vt)\.|t\.)?tiktok\.com/i.test(m.text)) return m.reply(`Example : ${prefix + command} https://vt.tiktok.com/ZSwWCk5o/`)
484 | await m.react('🕒')
485 | var json = await Api.get('api/tiktok', {
486 | url: Func.isUrl(m.text)[0]
487 | })
488 | if (!json.status) return m.reply(Func.Format(json))
489 | if (command == 'tiktok' || command == 'tt') {
490 | let result = json.data.find(v => v.type == 'nowatermark')
491 | if (!result) {
492 | json.data.map(x => {
493 | m.reply(x.url, {
494 | caption: `${json.author.nickname}\n\n${json.title}`
495 | })
496 | })
497 | } else {
498 | m.reply(result.url, {
499 | caption: `${json.author.nickname}\n\n${json.title}`
500 | })
501 | }
502 | } else if (command == 'tikwm') return m.reply(json.data.find(v => v.type == 'watermark').url, {
503 | caption: `${json.author.nickname}\n\n${json.title}`
504 | })
505 | else if (command == 'tikmp3') return m.reply(json.music_info.url)
506 | }
507 | break
508 | case 'fb':
509 | case 'fbdl':
510 | case 'facebook': {
511 | if (!/https?:\/\/(fb\.watch|(www\.|web\.|m\.)?facebook\.com)/i.test(m.text)) return m.reply(`Example : ${prefix + command} https://www.facebook.com/watch/?v=2018727118289093`)
512 | await m.react('🕒')
513 | var json = await Api.get('api/fb', {
514 | url: Func.isUrl(m.text)[0]
515 | })
516 | if (!json.status) return m.reply(Func.Format(json))
517 | let result = json.data.find(v => v.quality == 'HD') || json.data.find(v => v.quality == 'SD')
518 | m.reply(result.url, { caption: `${result.quality}` })
519 | }
520 | break
521 | case 'ig':
522 | case 'igdl':
523 | case 'instagram': {
524 | if (!/https?:\/\/(www\.)?instagram\.com\/(p|reel|tv)/i.test(m.text)) return m.reply(`Example : ${prefix + command} https://www.instagram.com/p/CITVsRYnE9h/`)
525 | await m.react('🕒')
526 | var json = await Api.get('api/ig', {
527 | url: Func.isUrl(m.text)[0]
528 | })
529 | if (!json.status) return m.reply(Func.Format(json))
530 | for (let v of json.data) {
531 | m.reply(v.url, { caption: config.options.wm })
532 | }
533 | }
534 | break
535 | case 'twit':
536 | case 'twt':
537 | case 'twitter': {
538 | if (!/https?:\/\/(www\.)?(twitter|X)\.com\/.*\/status/i.test(m.text)) return m.reply(`Example : ${prefix + command} https://twitter.com/jokowi/status/1687008875864846336?s=20`)
539 | await m.react('🕒')
540 | var json = await Api.get('api/twitter', {
541 | url: Func.isUrl(m.text)[0]
542 | })
543 | if (!json.status) return m.reply(Func.Format(json))
544 | for (let v of json.data) {
545 | m.reply(v.url, { caption: config.options.wm })
546 | }
547 | }
548 | break
549 | case 'threads':
550 | case 'thread':
551 | case 'threadsdl': {
552 | if (!/https?:\/\/(www\.)?(threads)\.net/i.test(m.text)) return m.reply(`Example : ${prefix + command} https://www.threads.net/t/CuiXbGvPyJz/?igshid=NTc4MTIwNjQ2YQ==`)
553 | await m.react('🕒')
554 | var json = await Api.get('api/threads', {
555 | url: Func.isUrl(m.text)[0]
556 | })
557 | if (!json.status) return m.reply(Func.Format(json))
558 | for (let v of json.data) {
559 | m.reply(v.url, { caption: config.options.wm })
560 | }
561 | }
562 | break
563 | case 'igstory':
564 | case 'igs':
565 | case 'instagramstory': {
566 | if (!m.text) return m.reply(`Example : ${prefix + command} bulansutena`)
567 | await m.react('🕒')
568 | let old = new Date()
569 | var json = await Api.get('api/igs', {
570 | q: m.text
571 | })
572 | if (!json.status) return m.reply(Func.Format(json))
573 | json.data.map(async (v, i) => {
574 | m.reply(v.url, { caption: config.options.wm })
575 | await Func.delay(1500)
576 | })
577 | }
578 | break
579 | case 'play':
580 | case 'lagu':
581 | case 'music': {
582 | if (!m.text) return m.reply(`Example : ${prefix + command} hapus aku`)
583 | await m.react('🕒')
584 | let ys = await (await yts(m.text)).all
585 | var yt = ys.filter(p => p.type == 'video')
586 | var json = await Api.get('api/yta', {
587 | url: yt[0].url
588 | })
589 | if (!json.status) return m.reply(Func.Format(json))
590 | let cap = '*Youtube Play*\n\n'
591 | cap += `⎔ *Title* : ${json.title}\n`
592 | cap += `⎔ *Size* : ${json.data.size}\n`
593 | cap += `⎔ *Duration* : ${json.duration}\n`
594 | cap += `⎔ *Quality* : ${json.data.quality}\n\n`
595 | cap += config.options.wm
596 | conn.sendMessageModify(m.from, cap, m, {
597 | largeThumb: true,
598 | thumbnail: json.thumbnail
599 | }).then(() => {
600 | m.reply(json.data.url, { fileName: json.data.filename, mimetype: 'audio/mpeg' })
601 | })
602 | }
603 | break
604 | case 'yta':
605 | case 'ytmp3': {
606 | if (!/(?:https?:\/\/)?(?:youtu\.be\/|(?:www\.|m\.)?(?:music\.)?youtube\.com\/(?:watch|v|embed|shorts))/i.test(m.text)) return m.reply(`Example : ${prefix + command} https://youtu.be/_EYbfKMTpRs`)
607 | await m.react('🕒')
608 | var json = await Api.get('api/yta', {
609 | url: Func.isUrl(m.text)
610 | })
611 | if (!json.status) return m.reply(Func.Format(json))
612 | let cap = `◦ Title : ${json.title}\n`
613 | cap += `◦ Size : ${json.data.size}\n`
614 | cap += `◦ Duration : ${json.duration}\n`
615 | cap += `◦ Quality : ${json.data.quality}`
616 | conn.sendMessageModify(m.from, cap, m, {
617 | largeThumb: true,
618 | thumbnail: json.thumbnail
619 | }).then(() => {
620 | m.reply(json.data.url, { fileName: json.data.filename, mimetype: 'audio/mpeg' })
621 | })
622 | }
623 | break
624 | case 'ytv':
625 | case 'ytmp4': {
626 | if (!/(?:https?:\/\/)?(?:youtu\.be\/|(?:www\.|m\.)?(?:music\.)?youtube\.com\/(?:watch|v|embed|shorts))/i.test(m.text)) return m.reply(`Example : ${prefix + command} https://youtu.be/_EYbfKMTpRs`)
627 | await m.react('🕒')
628 | var json = await Api.get('api/yta', {
629 | url: Func.isUrl(m.text)
630 | })
631 | if (!json.status) return m.reply(Func.Format(json))
632 | let cap = `◦ Title : ${json.title}\n`
633 | cap += `◦ Size : ${json.data.size}\n`
634 | cap += `◦ Duration : ${json.duration}\n`
635 | cap += `◦ Quality : ${json.data.quality}`
636 | m.reply(json.data.url, { caption: cap, fileName: json.data.filename, mimetype: 'video/mp4' })
637 | }
638 | break
639 |
640 | /** internet menu */
641 | case 'ytsearch':
642 | case 'yts': {
643 | if (!m.text) return m.reply(`Example : ${prefix + command} Tasya Rosmala`)
644 | m.react('🕒')
645 | let yt = await (await yts(m.text)).all
646 | if (yt.length == 0) return m.reply(Func.Format(yt))
647 | let cap = 'Youtube Search\n\n'
648 | yt.map((v, i) => {
649 | if (1 < 15) {
650 | cap += `*` + (i + 1) + `*. ` + v.title + `\n`
651 | cap += `∘ Duration : ` + v.timestamp + `\n`
652 | cap += `∘ Views : ` + v.views + `\n`
653 | cap += `∘ Upload : ` + v.ago + `\n`
654 | cap += `∘ Url : ` + v.url + `\n\n`
655 | }
656 | })
657 | m.reply(cap)
658 | }
659 | break
660 | case 'brainly': {
661 | try {
662 | if (!m.text) return m.reply(`Example : ${prefix + command} perang dunia ke 2 terjadi kapan`)
663 | m.react('🕒')
664 | const json = await Api.get('api/brainly', {
665 | q: m.text, lang: 'id'
666 | })
667 | if (!json.status) return m.reply(format(json))
668 | let teks = `Brainly\n\n`
669 | json.data.map((v, i) => {
670 | teks += `*${(i + 1)}*. ${v.question}\n`
671 | teks += `› *Answer* : \n${v.answers}\n\n`
672 | })
673 | m.reply(teks)
674 | } catch (e) {
675 | return m.reply(format(e))
676 | }
677 | }
678 | break
679 | case 'pinterest': {
680 | try {
681 | if (!m.text) return m.reply(`Example : ${prefix + command} moon`)
682 | m.react('🕒')
683 | let json = await Api.get('api/pinterest', {
684 | q: m.text
685 | })
686 | if (!json.status) return m.reply(format(e))
687 | for (let i = 0; i < 5; i++) {
688 | var rand = Math.floor(json.data.length * Math.random())
689 | m.reply(json.data[rand].url, {
690 | caption: config.options.wm
691 | })
692 | await Func.sleep(2500)
693 | }
694 | } catch (e) {
695 | return m.reply(format(e))
696 | }
697 | }
698 | break
699 | case 'gimage':
700 | case 'google': {
701 | if (!m.text) return m.reply(`Example : ${prefix + command} red moon`)
702 | m.react('🕒')
703 | try {
704 | if (command == 'google') {
705 | let json = await Api.get('api/google', {
706 | q: m.text
707 | })
708 | let teks = `Google\n\n`
709 | json.data.map((v, i) => {
710 | teks += `*` + (i + 1) + `.* ` + v.title + `\n`
711 | teks += `• Snippet : ` + v.snippet + `\n`
712 | teks += `• Link : ` + v.url + `\n\n`
713 | })
714 | m.reply(teks)
715 | }
716 | if (command == 'gimage') {
717 | let json = await Api.get('api/google-image', {
718 | q: m.text
719 | })
720 | for (let i = 0; i < 5; i++) {
721 | let random = Math.floor(json.data.length * Math.random())
722 | let caption = `• Title : ${json.data[random].origin.title}\n`
723 | caption += `• Dimensions : ${json.data[random].width} × ${json.data[random].height}`
724 | m.reply(json.data[random].url, {
725 | caption: caption
726 | })
727 | await Func.sleep(2500)
728 | }
729 | }
730 | } catch (e) {
731 | return m.reply(format(e))
732 | }
733 | }
734 | break
735 |
736 | /** owner menu */
737 | case 'backup': {
738 | try {
739 | m.react('🕒')
740 | await database.read(global.db)
741 | fs.writeFileSync('database.json', JSON.stringify(global.db, null, 3), 'utf-8')
742 | await m.reply(fs.readFileSync('./database.json'), {
743 | fileName: 'database.json',
744 | mimetype: 'application/json'
745 | })
746 | } catch (e) {
747 | return m.reply(format(e))
748 | }
749 | }
750 | break
751 | case 'block': {
752 | if (!m.isOwner) return m.reply('owner')
753 | let users = m.mentions.length !== 0 ? m.mentions.slice(0, 2) : m.isQuoted ? [m.quoted.sender] : m.text.split(',').map(v => v.replace(/[^0-9]/g, '') + '@s.whatsapp.net').slice(0, 2)
754 | if (users.length == 0) return m.reply('Fuck You 🖕')
755 | await conn.updateBlockStatus(users, 'block').then((res) => m.reply(Func.Format(res))).catch((err) => m.reply(Func.Format(err)))
756 | }
757 | break
758 | case 'unblock': {
759 | if (!m.isOwner) return m.reply('owner')
760 | let users = m.mentions.length !== 0 ? m.mentions.slice(0, 2) : m.isQuoted ? [m.quoted.sender] : m.text.split(',').map(v => v.replace(/[^0-9]/g, '') + '@s.whatsapp.net').slice(0, 2)
761 | if (users.length == 0) return m.reply('Fuck You 🖕')
762 | await conn.updateBlockStatus(users, 'unblock').then((res) => m.reply(Func.Format(res))).catch((err) => m.reply(Func.Format(err)))
763 | }
764 | break
765 | case 'setpp': {
766 | const media = await quoted.download()
767 | if (m.isOwner && !m.isGroup) {
768 | if (/full/i.test(m.text)) await conn.setProfilePicture(conn?.user?.id, media, "full")
769 | else if (/(de(l)?(ete)?|remove)/i.test(m.text)) await conn.removeProfilePicture(conn.decodeJid(conn?.user?.id))
770 | else await conn.setProfilePicture(conn?.user?.id, media, 'normal')
771 | } else if (m.isGroup && m.isAdmin && m.isBotAdmin) {
772 | if (/full/i.test(m.text)) await conn.setProfilePicture(m.from, media, 'full')
773 | else if (/(de(l)?(ete)?|remove)/i.test(m.text)) await conn.removeProfilePicture(m.from)
774 | else await conn.setProfilePicture(m.from, media, 'normal')
775 | }
776 | }
777 | break
778 | case 'setname': {
779 | if (m.isOwner && !m.isGroup) {
780 | await conn.updateProfileName(m.isQuoted ? quoted.body : quoted.text)
781 | } else if (m.isGroup && m.isAdmin && m.isBotAdmin) {
782 | await conn.groupUpdateSubject(m.from, m.isQuoted ? quoted.body : quoted.text)
783 | }
784 | }
785 | break
786 | case 'public':
787 | case 'autoread':
788 | case 'chatbot': {
789 | if (!m.isOwner) return m.reply('owner')
790 | if (!m.text) return m.reply(`Current status : [ ${global.db.setting[command.toLowerCase()] ? 'ON' : 'OFF'} ] (Enter *On* or *Off*)`)
791 | let option = m.text.toLowerCase()
792 | let optionList = ['on', 'off']
793 | if (!optionList.includes(option)) return m.reply(`Current status : [ ${global.db.setting[command.toLowerCase()] ? 'ON' : 'OFF'} ] (Enter *On* or *Off*)`)
794 | let status = option != 'on' ? false : true
795 | if (global.db.setting[command.toLowerCase()] == status) return m.reply(`${Func.ucword(command)} has been ${option == 'on' ? 'activated' : 'inactivated'} previously.`)
796 | global.db.setting[command.toLowerCase()] = status
797 | m.reply(`${Func.ucword(command)} has been ${option == 'on' ? 'activated' : 'inactivated'} successfully.`)
798 | }
799 | break
800 | case 'setcover': {
801 | if (!/image\/(jpe?g|png)/.test(quoted.mime)) return m.reply(`Send or reply to images with commands ${prefix + command}`)
802 | m.react('🕒')
803 | let media = await quoted.download()
804 | let res = await Scraper.uploaderV2(media)
805 | if (!res.status) return m.reply(Func.Format(res))
806 | db.setting.cover = res.data.url
807 | m.reply('Cover successfully changed')
808 | }
809 | break
810 | case 'setlink': {
811 | if (!/^https:\/\//i.test(m.text)) return m.reply(`Example : ${prefix + command} https://wa`)
812 | m.react('🕒')
813 | db.setting.link = Func.isUrl(m.text)
814 | m.reply('Link successfully changed')
815 | }
816 | break
817 | case 'debounce':
818 | case 'restart': {
819 | if (!m.isOwner) return m.reply('owner')
820 | await m.reply('Restarting . . .').then(async () => {
821 | await database.write(global.db)
822 | process.send('reset')
823 | })
824 | }
825 | break
826 | case 'join': {
827 | try {
828 | if (!m.isOwner) return m.reply('owner')
829 | if (!m.text) return m.reply(`Example : ${prefix + command} https://chat.whatsapp.com/codeInvite`)
830 | let link = /chat.whatsapp.com\/([0-9A-Za-z]{20,24})/i
831 | let [_, code] = m.text.match(link) || []
832 | if (!code) return m.reply('Invalid URL')
833 | let id = await conn.groupAcceptInvite(code)
834 | if (!id.endsWith('g.us')) return m.reply(`Sorry i can't join to this group :(`)
835 | let member = await (await conn.groupMetadata(id)).participants.map(v => v.id)
836 | return m.reply(`Joined!`)
837 | } catch {
838 | return m.reply(`Sorry i can't join to this group :(`)
839 | }
840 | }
841 | break
842 | case '-expired':
843 | case '+expired': {
844 | try {
845 | if (!m.isOwner) return m.reply('owner')
846 | if (!m.isGroup) return m.reply('group')
847 | if (command == '+expired') {
848 | if (!m.args[0] || isNaN(m.args[0])) return m.reply(`Example : ${prefix + command} 30`)
849 | let who
850 | if (m.isGroup) who = m.args[1] ? m.args[1] : m.from
851 | else who = m.args[1]
852 | var jumlahHari = 86400000 * m.args[0]
853 | var now = new Date() * 1
854 | if (now < global.db.groups[who].expired)
855 | global.db.groups[who].expired += jumlahHari
856 | else global.db.groups[who].expired = now + jumlahHari
857 | m.reply(`Successfully set expiration days for group ${m.metadata.subject}, for ${m.args[0]} days`)
858 | } else if (command == '-expired') {
859 | let who
860 | if (m.isGroup) who = m.args[1] ? m.args[1] : m.from
861 | else who = m.args[1]
862 | if (new Date() * 1 < global.db.groups[who].expired)
863 | global.db.groups[who].expired = undefined
864 | else global.db.groups[who].expired = undefined
865 | m.reply(`Successfully removed the expiration day for this Group`)
866 | }
867 | } catch (e) {
868 | return m.reply(format(e))
869 | }
870 | }
871 | break
872 | case '+premium': {
873 | if (m.quoted) {
874 | if (m.quoted.isBot) return m.reply(`🚩 Can't make the bot a premium user.`)
875 | if (m.args && isNaN(m.args[0])) return m.reply(`🚩 Day must be a number.`)
876 | let days = m.args[0] ? parseInt(m.args[0]) : 30
877 | let jid = conn.decodeJid(m.quoted.sender)
878 | let users = global.db.users[jid]
879 | users.expired += users.premium ? (86400000 * days) : ((new Date() * 1) + (86400000 * days))
880 | users.limit += 2000
881 | m.reply(users.premium ? `Succesfully added ${days} days premium access for @${jid.replace(/@.+/, '')}.` : `Successfully added @${jid.replace(/@.+/, '')} to premium user.`).then(() => users.premium = true)
882 | } else if (m.mentions.length != 0) {
883 | if (m.args && m.args[1] && isNaN(m.args[1])) return m.reply(`Day must be a number.`)
884 | let days = m.args[1] ? parseInt(m.args[1]) : 30
885 | let jid = conn.decodeJid(m.mentions[0])
886 | const users = global.db.users[jid]
887 | users.expired += users.premium ? (86400000 * days) : ((new Date() * 1) + (86400000 * days))
888 | users.limit += 2000
889 | conn.reply(m.chat, users.premium ? `Succesfully added ${days} days premium access for @${jid.replace(/@.+/, '')}.` : `Successfully added @${jid.replace(/@.+/, '')} to premium user.`).then(() => users.premium = true)
890 | } else if (m.text && /|/.test(m.text)) {
891 | let [number, day] = text.split`|`
892 | let p = (await conn.onWhatsApp(number))[0] || {}
893 | if (!p.exists) return m.reply('Number not registered on WhatsApp.')
894 | if (isNaN(day)) return m.reply(`Day must be a number.`)
895 | let days = day ? parseInt(day) : 30
896 | let jid = conn.decodeJid(p.jid)
897 | const users = global.db.users[jid]
898 | if (!users) return m.reply(`Can't find user data.`)
899 | users.expired += users.premium ? (86400000 * days) : ((new Date() * 1) + (86400000 * days))
900 | users.limit += 2000
901 | conn.reply(m.chat, users.premium ? `Succesfully added ${days} days premium access for @${jid.replace(/@.+/, '')}.` : `Successfully added @${jid.replace(/@.+/, '')} to premium user.`).then(() => users.premium = true)
902 | } else {
903 | let teks = `• *Example* :\n\n`
904 | teks += `${prefix + command} 6285xxxxx | 7\n`
905 | teks += `${prefix + command} @0 7\n`
906 | teks += `${prefix + command} 7 (reply chat target)`
907 | m.reply(teks)
908 | }
909 | }
910 | break
911 | case '-premium': {
912 | let input = m.text ? m.text : m.quoted ? m.quoted.sender : m.mentionedJid.length > 0 ? m.mentioneJid[0] : false
913 | if (!input) return m.reply(`Mention or reply chat target.`)
914 | let p = await conn.onWhatsApp(input.trim())
915 | if (p.length == 0) return m.reply(`Invalid number.`)
916 | let jid = conn.decodeJid(p[0].jid)
917 | let number = jid.replace(/@.+/, '')
918 | let data = global.db.users[jid]
919 | if (typeof data == 'undefined') return m.reply(`Can't find user data.`)
920 | if (!data.premium) return m.reply(`Not a premium account.`)
921 | data.premium = false
922 | data.expired = 0
923 | m.reply(`@${jid.replace(/@.+/, '')}'s premium status has been successfully deleted.`)
924 | }
925 | break
926 |
927 | /** converter menu */
928 | case 'sticker':
929 | case 's':
930 | case 'stiker': {
931 | if (/image|video|webp/i.test(quoted.mime)) {
932 | m.react('🕒')
933 | const buffer = await quoted.download()
934 | if (quoted?.msg?.seconds > 10) return m.reply(`Max video 9 second`)
935 | let exif
936 | if (m.text) {
937 | let [packname, author] = m.text.split('|')
938 | exif = {
939 | packName: packname ? packname : '',
940 | packPublish: author ? author : ''
941 | }
942 | } else {
943 | exif = {
944 | ...config.Exif
945 | }
946 | }
947 | m.reply(buffer, {
948 | asSticker: true,
949 | ...exif
950 | })
951 | } else if (m.mentions[0]) {
952 | m.react('🕒')
953 | let url = await conn.profilePictureUrl(m.mentions[0], 'image');
954 | m.reply(url, {
955 | asSticker: true,
956 | ...config.Exif
957 | })
958 | } else if (/(https?:\/\/.*\.(?:png|jpg|jpeg|webp|mov|mp4|webm|gif))/i.test(m.text)) {
959 | m.react('🕒')
960 | m.reply(Func.isUrl(m.text)[0], {
961 | asSticker: true,
962 | ...config.Exif
963 | })
964 | } else {
965 | m.reply(`Method Not Support`)
966 | }
967 | }
968 | break
969 | case 'brat': {
970 | try {
971 | const args = m.text.trim().split(' ')
972 | const mode = m.args[0] === 'gif' ? 'gif' : 'text'
973 | const content = mode === 'gif' ? args.slice(1).join(' ') : m.text.trim()
974 | if (!content) return m.reply(`Example : ${prefix + command} moon`)
975 | if (content.length > 100) return m.reply('Text is too long, max 100 characters.')
976 | m.react('🕒')
977 | if (mode === 'gif') {
978 | let json = await Api.get('api/bratgif', {
979 | text: content
980 | })
981 | m.reply(json.data.url, {
982 | asSticker: true,
983 | ...config.Exif
984 | })
985 | } else {
986 | let json = await Api.get('api/brat', {
987 | text: content
988 | })
989 | m.reply(json.data.url, {
990 | asSticker: true,
991 | ...config.Exif
992 | })
993 | }
994 | } catch (e) {
995 | return conn.reply(m.chat, Func.jsonFormat(e), m)
996 | }
997 | }
998 | break
999 | case 'ttp': {
1000 | if (!m.text) return m.reply(`Example : ${prefix + command} moon`)
1001 | if (m.text.length > 10) return m.reply(`Max 10 letters`)
1002 | m.react('🕒')
1003 | let json = await Api.get('api/ttp', {
1004 | text: m.text
1005 | })
1006 | if (!json.status) return m.reply(format(json))
1007 | m.reply(json.data.url, {
1008 | asSticker: true,
1009 | ...config.Exif
1010 | })
1011 | }
1012 | break
1013 | case 'attp': {
1014 | if (!m.text) return m.reply(`Example : ${prefix + command} moon`)
1015 | if (m.text.length > 10) return m.reply(`Max 10 letters`)
1016 | m.react('🕒')
1017 | let json = await Api.get('api/attp', {
1018 | text: m.text
1019 | })
1020 | if (!json.status) return m.reply(format(json))
1021 | m.reply(json.data.url, {
1022 | asSticker: true,
1023 | ...config.Exif
1024 | })
1025 | }
1026 | break
1027 | case 'emojimix': {
1028 | if (!m.text) return m.reply(`Example : *${prefix + command} 🥵 + 🥶*`)
1029 | m.react('🕒')
1030 | var [emo1, emo2] = m.text.split` + `
1031 | let json = await Api.get('api/emojimix', {
1032 | emo1, emo2
1033 | })
1034 | m.reply(json.data.url, {
1035 | asSticker: true,
1036 | ...config.Exif
1037 | })
1038 | }
1039 | break
1040 | case 'qc':
1041 | case 'quickchat': {
1042 | let text = m.text
1043 | if (!text) return m.reply(`Example : ${prefix + command} moon-bot`)
1044 | if (text.length > 30) return m.reply(`Max 30 character.`)
1045 | m.react('🕒')
1046 | let pic
1047 | try {
1048 | pic = await conn.profilePictureUrl(m.quoted ? m.quoted.sender : m.sender, 'image')
1049 | } catch {
1050 | pic = 'https://telegra.ph/file/32ffb10285e5482b19d89.jpg'
1051 | }
1052 | const obj = {
1053 | "type": "quote",
1054 | "format": "png",
1055 | "backgroundColor": "#FFFFFF",
1056 | "width": 512,
1057 | "height": 768,
1058 | "scale": 2,
1059 | "messages": [{
1060 | "entities": [],
1061 | "avatar": true,
1062 | "from": {
1063 | "id": 1,
1064 | "name": m.quoted ? db.users[m.quoted.sender].name : m.pushName,
1065 | "photo": {
1066 | "url": pic
1067 | }
1068 | },
1069 | "text": text,
1070 | "replyMessage": {}
1071 | }]
1072 | }
1073 | const json = await axios.post('https://bot.lyo.su/quote/generate', obj, {
1074 | headers: {
1075 | 'Content-Type': 'application/json'
1076 | }
1077 | })
1078 | const buffer = Buffer.from(json.data.result.image, 'base64')
1079 | m.reply(buffer, {
1080 | asSticker: true,
1081 | ...config.Exif
1082 | })
1083 | }
1084 | break
1085 | case 'toimg':
1086 | case 'togif':
1087 | case 'tovideo':
1088 | case 'toimage': {
1089 | let {
1090 | webp2mp4File
1091 | } = (await import('../sticker.js'))
1092 | if (!/webp/i.test(quoted.mime)) return m.reply(`Reply Sticker with command ${prefix + command}`)
1093 | if (quoted.isAnimated) {
1094 | let media = await webp2mp4File((await quoted.download()))
1095 | await m.reply(media)
1096 | }
1097 | let media = await quoted.download()
1098 | await m.reply(media, {
1099 | mimetype: 'image/png'
1100 | })
1101 | }
1102 | break
1103 |
1104 | /** group menu */
1105 | case 'linkgroup':
1106 | case 'linkgrup':
1107 | case 'linkgc': {
1108 | if (!m.isGroup) return m.reply('group')
1109 | //if (!m.isAdmin) return m.reply('admin')
1110 | if (!m.isBotAdmin) return m.reply('botAdmin')
1111 | await m.reply('https://chat.whatsapp.com/' + (await conn.groupInviteCode(m.from)))
1112 | }
1113 | break
1114 | case 'afk': {
1115 | let user = db.users[m.sender]
1116 | user.afkTime = + new Date
1117 | user.afkReason = m.text
1118 | m.reply(`@${m.sender.split`@`[0]} is now AFK\n\nReason : ${user.afkReason ? user.afkReason : '-'}`)
1119 | }
1120 | break
1121 | case 'del':
1122 | case 'delete': {
1123 | if (!quoted) return
1124 | conn.sendMessage(m.from, {
1125 | delete: {
1126 | remoteJid: m.from,
1127 | fromMe: m.isBotAdmin ? false : true,
1128 | id: quoted.id,
1129 | participant: quoted.sender
1130 | }
1131 | })
1132 | }
1133 | break
1134 | case 'ava': {
1135 | let text = m.text
1136 | let number = isNaN(text) ? (text.startsWith('+') ? text.replace(/[()+\s-]/g, '') : (text).split`@`[1]) : text
1137 | if (!text && !quoted) return m.reply(`Mention or reply chat target.`)
1138 | if (isNaN(number)) return m.reply(`Invalid number.`)
1139 | if (number.length > 15) return m.reply(`Invalid format.`)
1140 | try {
1141 | if (text) {
1142 | var user = number + '@s.whatsapp.net'
1143 | } else if (m.quoted.sender) {
1144 | var user = m.quoted.sender
1145 | } else if (m.mentionedJid) {
1146 | var user = number + '@s.whatsapp.net'
1147 | }
1148 | } catch (e) { } finally {
1149 | var pic = false
1150 | try {
1151 | var pic = await conn.profilePictureUrl(user, 'image')
1152 | } catch { } finally {
1153 | if (!pic) return m.reply(`He/She didn't put a profile picture.`)
1154 | m.reply(pic)
1155 | }
1156 | }
1157 | }
1158 | break
1159 | case 'quoted':
1160 | case 'q': {
1161 | const { Serialize } = (await import('../serialize.js'))
1162 | if (!m.isQuoted) m.reply('quoted')
1163 | try {
1164 | const message = await Serialize(conn, (await conn.loadMessage(m.from, m.quoted.id)))
1165 | if (!message.isQuoted) return m.reply('Quoted Not Found')
1166 | conn.sendMessage(m.from, {
1167 | forward: message.quoted
1168 | })
1169 | } catch {
1170 | m.reply('Quoted Not Found')
1171 | }
1172 | }
1173 | break
1174 | case 'rvo': {
1175 | if (!m.quoted) return m.reply(`Reply view once message to use this command.`)
1176 | if (m.quoted.message) {
1177 | let type = Object.keys(m.quoted.message)[0]
1178 | let q = m.quoted.message[type]
1179 | let media = await conn.downloadAndSaveMediaMessage(q)
1180 | if (/video/.test(type)) {
1181 | return await m.reply(media, { caption: q.caption || '' })
1182 | } else if (/image/.test(type)) {
1183 | return await m.reply(media, { caption: q.caption || '' })
1184 | }
1185 | } else m.reply(`Koplak`)
1186 | }
1187 | break
1188 |
1189 | /** admin menu */
1190 | case 'hidetag':
1191 | case 'ht':
1192 | case 'h': {
1193 | if (!m.isGroup) return m.reply('group')
1194 | if (!m.isAdmin) return m.reply('admin')
1195 | let mentions = m.metadata.participants.map(a => a.id)
1196 | let mod = await conn.cMod(m.from, quoted, /hidetag|tag|ht|h|totag/i.test(quoted.body.toLowerCase()) ? quoted.body.toLowerCase().replace(prefix + command, "") : quoted.body)
1197 | conn.sendMessage(m.from, {
1198 | forward: mod,
1199 | mentions
1200 | })
1201 | }
1202 | break
1203 | case 'tagall': {
1204 | if (!m.isGroup) return m.reply('group')
1205 | if (!m.isAdmin) return m.reply('admin')
1206 | let teks = `Tagall\n\n"${m.text ? m.text : 'Hi admin mention you'}"\n\n`
1207 | for (let a of m.metadata.participants) {
1208 | teks += `◦ @${a.id.split('@')[0]}\n`
1209 | }
1210 | m.reply(teks)
1211 | }
1212 | break
1213 | case 'add': {
1214 | if (!m.isGroup) return m.reply('group')
1215 | if (!m.isAdmin) return m.reply('admin')
1216 | if (!m.isBotAdmin) return m.reply('botAdmin')
1217 | let users = m.mentions.length !== 0 ? m.mentions.slice(0, 2) : m.isQuoted ? [m.quoted.sender] : m.text.split(',').map(v => v.replace(/[^0-9]/g, '') + '@s.whatsapp.net').slice(0, 2)
1218 | if (users.length == 0) return m.reply('Fuck You 🖕')
1219 | await conn.groupParticipantsUpdate(m.from, users, 'add').then(async (res) => {
1220 | for (let i of res) {
1221 | if (i.status == 403) {
1222 | let node = getBinaryNodeChildren(i.content, 'add_request')
1223 | await m.reply(`Can't add @${i.jid.split('@')[0]}, send invitation...`)
1224 | let url = await conn.profilePictureUrl(m.from, 'image').catch(_ => 'https://lh3.googleusercontent.com/proxy/esjjzRYoXlhgNYXqU8Gf_3lu6V-eONTnymkLzdwQ6F6z0MWAqIwIpqgq_lk4caRIZF_0Uqb5U8NWNrJcaeTuCjp7xZlpL48JDx-qzAXSTh00AVVqBoT7MJ0259pik9mnQ1LldFLfHZUGDGY=w1200-h630-p-k-no-nu')
1225 | await conn.sendGroupV4Invite(i.jid, m.from, node[0]?.attrs?.code || node.attrs.code, node[0]?.attrs?.expiration || node.attrs.expiration, m.metadata.subject, url, 'Invitation to join my WhatsApp Group')
1226 | } else if (i.status == 409) return m.reply(`@${i.jid?.split('@')[0]} already in this group`)
1227 | else m.reply(Func.Format(i))
1228 | }
1229 | })
1230 | }
1231 | break
1232 | case 'kick': {
1233 | if (!m.isGroup) return m.reply('group')
1234 | if (!m.isAdmin) return m.reply('admin')
1235 | if (!m.isBotAdmin) return m.reply('botAdmin')
1236 | let users = m.mentions.length !== 0 ? m.mentions.slice(0, 2) : m.isQuoted ? [m.quoted.sender] : m.text.split(',').map(v => v.replace(/[^0-9]/g, '') + '@s.whatsapp.net').slice(0, 2)
1237 | if (users.length == 0) return m.reply('Fuck You 🖕')
1238 | await conn.groupParticipantsUpdate(m.from, users, 'remove').then((res) => m.reply(Func.Format(res))).catch((err) => m.reply(Func.Format(err)))
1239 | }
1240 | break
1241 | case 'promote': {
1242 | if (!m.isGroup) return m.reply('group')
1243 | if (!m.isAdmin) return m.reply('admin')
1244 | if (!m.isBotAdmin) return m.reply('botAdmin')
1245 | let users = m.mentions.length !== 0 ? m.mentions.slice(0, 2) : m.isQuoted ? [m.quoted.sender] : m.text.split(',').map(v => v.replace(/[^0-9]/g, '') + '@s.whatsapp.net').slice(0, 2)
1246 | if (users.length == 0) return m.reply('Fuck You 🖕')
1247 | await conn.groupParticipantsUpdate(m.from, users, 'promote').then((res) => m.reply(Func.Format(res))).catch((err) => m.reply(Func.Format(err)))
1248 | }
1249 | break
1250 | case 'demote': {
1251 | if (!m.isGroup) return m.reply('group')
1252 | if (!m.isAdmin) return m.reply('admin')
1253 | if (!m.isBotAdmin) return m.reply('botAdmin')
1254 | let users = m.mentions.length !== 0 ? m.mentions.slice(0, 2) : m.isQuoted ? [m.quoted.sender] : m.text.split(',').map(v => v.replace(/[^0-9]/g, '') + '@s.whatsapp.net').slice(0, 2)
1255 | if (users.length == 0) return m.reply('Fuck You 🖕')
1256 | await conn.groupParticipantsUpdate(m.from, users, 'demote').then((res) => m.reply(Func.Format(res))).catch((err) => m.reply(Func.Format(err)))
1257 | }
1258 | break
1259 | case 'welcome':
1260 | case 'leaving':
1261 | case 'detect': {
1262 | if (!m.isAdmin) return m.reply('admin')
1263 | if (!m.isBotAdmin && /antilink/.test(command.toLowerCase())) return m.reply('botAdmin')
1264 | if (!m.text) return m.reply(`Current status : [ ${global.db.groups[command.toLowerCase()] ? 'ON' : 'OFF'} ] (Enter *On* or *Off*)`)
1265 | let option = m.text.toLowerCase()
1266 | let optionList = ['on', 'off']
1267 | if (!optionList.includes(option)) return m.reply(`Current status : [ ${global.db.groups[command.toLowerCase()] ? 'ON' : 'OFF'} ] (Enter *On* or *Off*)`)
1268 | let status = option != 'on' ? false : true
1269 | if (global.db.groups[command.toLowerCase()] == status) return m.reply(`${Func.ucword(command)} has been ${option == 'on' ? 'activated' : 'inactivated'} previously.`)
1270 | global.db.groups[command.toLowerCase()] = status
1271 | m.reply(`${Func.ucword(command)} has been ${option == 'on' ? 'activated' : 'inactivated'} successfully.`)
1272 | }
1273 | break
1274 |
1275 | /** image effect */
1276 | case 'paretro': case 'retrolga': case 'plumy': case 'hdr': case 'sepia': case 'duotone': case 'blackwhite': case 'sketch': case 'sketchril': case 'oils': case 'esragan': case 'watercolor': case 'galaxy': case 'freplace': case 'rainbow': case 'solarize': case 'pinkbir': {
1277 | try {
1278 | if (!/image\/(jpe?g|png)/.test(quoted.mime)) return m.reply(`Reply or send photo use this command`)
1279 | m.react('🕒')
1280 | let result = await Scraper.uploader(await quoted.download())
1281 | let json = await Api.get('api/effect', {
1282 | image: result.data.url, style: command.toLowerCase()
1283 | })
1284 | if (!json.status) return m.reply(Func.Format(json))
1285 | m.reply(json.data.url, {
1286 | caption: config.options.wm
1287 | })
1288 | } catch (e) {
1289 | return m.reply(format(e))
1290 | }
1291 | }
1292 | break
1293 |
1294 | /** text maker */
1295 | case 'comicbox': case 'gradientshadow': case 'lava': case 'thunder': case 'neondevil': case 'sumertimes': case 'matrix': case 'firework': case 'neonlight': case 'greenneon': case 'pokemon': case 'dragonball': case 'naruto': case 'blackpink': case 'onglass': case 'greenbrush': case 'amongus': case 'naruto2': case 'flaming': case 'woodblock': {
1296 | try {
1297 | if (!m.text) return m.reply(`Example : ${prefix + command} moon-bot`)
1298 | if (m.text.length > 10) return m.reply(`Max 10 character`)
1299 | m.react('🕒')
1300 | var link
1301 | if (/comicbox/.test(command)) link = 'https://textpro.me/create-online-3d-comic-book-style-text-effects-1156.html'
1302 | if (/gradientshadow/.test(command)) link = 'https://textpro.me/create-a-gradient-text-shadow-effect-online-1141.html'
1303 | if (/lava/.test(command)) link = 'https://textpro.me/lava-text-effect-online-914.html'
1304 | if (/thunder/.test(command)) link = 'https://textpro.me/create-thunder-text-effect-online-881.html'
1305 | if (/neondevil/.test(command)) link = 'https://textpro.me/create-neon-devil-wings-text-effect-online-free-1014.html'
1306 | if (/sumertimes/.test(command)) link = 'https://textpro.me/create-a-summer-neon-light-text-effect-online-1076.html'
1307 | if (/matrix/.test(command)) link = 'https://textpro.me/matrix-style-text-effect-online-884.html'
1308 | if (/firework/.test(command)) link = 'https://textpro.me/firework-sparkle-text-effect-930.html'
1309 | if (/neonlight/.test(command)) link = 'https://textpro.me/neon-light-text-effect-with-galaxy-style-981.html'
1310 | if (/greenneon/.test(command)) link = 'https://textpro.me/green-neon-text-effect-874.html'
1311 | if (/pokemon/.test(command)) link = 'https://textpro.me/create-pokemon-logo-style-text-effect-online-1134.html'
1312 | /** ephoto360 */
1313 | if (/dragonball/.test(command)) link = 'https://en.ephoto360.com/create-dragon-ball-style-text-effects-online-809.html'
1314 | if (/naruto/.test(command)) link = 'https://en.ephoto360.com/naruto-shippuden-logo-style-text-effect-online-808.html'
1315 | if (/blackpink/.test(command)) link = 'https://en.ephoto360.com/create-blackpink-logo-online-free-607.html'
1316 | if (/onglass/.test(command)) link = 'https://en.ephoto360.com/write-text-on-wet-glass-online-589.html'
1317 | if (/greenbrush/.test(command)) link = 'https://en.ephoto360.com/green-brush-text-effect-typography-maker-online-153.html'
1318 | if (/amongus/.test(command)) link = 'https://en.ephoto360.com/create-a-cover-image-for-the-game-among-us-online-762.html'
1319 | /** photooxy */
1320 | if (/naruto2/.test(command)) link = 'https://photooxy.com/manga-and-anime/make-naruto-banner-online-free-378.html'
1321 | if (/flaming/.test(command)) link = 'https://photooxy.com/logo-and-text-effects/realistic-flaming-text-effect-online-197.html'
1322 | if (/woodblock/.test(command)) link = 'https://photooxy.com/logo-and-text-effects/carved-wood-effect-online-171.html'
1323 | let json = await Api.get('api/textmaker', {
1324 | url: link, text: m.text
1325 | })
1326 | if (!json.status) return m.reply(Func.Format(json))
1327 | m.reply(json.data.url_file, {
1328 | caption: config.options.wm
1329 | })
1330 | } catch (e) {
1331 | return m.reply(format(e))
1332 | }
1333 | }
1334 | break
1335 |
1336 | /** text maker 2 */
1337 | case 'pornhub': case 'marvelstudio': case 'marvelstudio2': case 'glitchtiktok': case 'deadpool': case '8bittext': case 'thorlogo': case 'captainamerica': case 'amongus2': {
1338 | try {
1339 | if (!m.text) return m.reply(`Example : ${prefix + command} moon | bot`)
1340 | let [text1, text2] = m.text.split('|')
1341 | if (text1.length > 10 || text2.length > 10) return m.reply('Max 10 character')
1342 | m.react('🕒'), link
1343 | /** text pro */
1344 | if (/pornhub/.test(command)) link = 'https://textpro.me/generate-a-free-logo-in-pornhub-style-online-977.html'
1345 | if (/marvelstudio/.test(command)) link = 'https://textpro.me/create-logo-style-marvel-studios-ver-metal-972.html'
1346 | if (/marvelstudio2/.test(command)) link = 'https://textpro.me/create-logo-style-marvel-studios-online-971.html'
1347 | if (/glitchtiktok/.test(command)) link = 'https://textpro.me/create-glitch-text-effect-style-tik-tok-983.html'
1348 | if (/deadpool/.test(command)) link = 'https://textpro.me/create-deadpool-logo-style-text-effect-online-1159.html'
1349 | if (/8bittext/.test(command)) link = 'https://textpro.me/video-game-classic-8-bit-text-effect-1037.html'
1350 | /** ephoto360 */
1351 | if (/thorlogo/.test(command)) link = 'https://en.ephoto360.com/create-thor-logo-style-text-effects-online-for-free-796.html'
1352 | if (/captainamerica/.test(command)) link = 'https://en.ephoto360.com/create-a-cinematic-captain-america-text-effect-online-715.html'
1353 | if (/amongus2/.test(command)) link = 'https://en.ephoto360.com/create-a-banner-game-among-us-with-your-name-763.html'
1354 | if (/latestspace/.test(command)) link = 'https://en.ephoto360.com/latest-space-3d-text-effect-online-559.html'
1355 | let json = await Api.get('api/textmaker2', {
1356 | url: link, text1, text2
1357 | })
1358 | if (!json.status) return m.reply(format(json))
1359 | m.reply(json.data.url_file, {
1360 | caption: config.options.wm
1361 | })
1362 | } catch (e) {
1363 | return m.reply(format(e))
1364 | }
1365 | }
1366 | break
1367 |
1368 | /** tools menu */
1369 | case 'fetch':
1370 | case 'get': {
1371 | if (!/^https:\/\//i.test(m.text)) return m.reply(`Example : ${prefix + command} https://api.alyachan.pro`)
1372 | m.react('🕒')
1373 | let mime = (await import('mime-types'))
1374 | const res = await axios.get(Func.isUrl(m.text)[0], {
1375 | responseType: 'arraybuffer'
1376 | })
1377 | if (!/utf-8|json|html|plain/.test(res?.headers?.get('content-type'))) {
1378 | let fileName = /filename/i.test(res.headers?.get("content-disposition")) ? res.headers?.get("content-disposition")?.match(/filename=(.*)/)?.[1]?.replace(/["';]/g, '') : ''
1379 | return m.reply(res.data, {
1380 | fileName,
1381 | mimetype: mime.lookup(fileName)
1382 | })
1383 | }
1384 | let text = res?.data?.toString() || res?.data
1385 | text = format(text)
1386 | try {
1387 | m.reply(text.slice(0, 65536) + '')
1388 | } catch (e) {
1389 | m.reply(format(e))
1390 | }
1391 | }
1392 | break
1393 | case 'totext':
1394 | case 'ocr': {
1395 | if (/image/i.test(quoted.mime)) {
1396 | m.react('🕒')
1397 | const url = await Scraper.uploader(await quoted.download())
1398 | const json = await Api.get('api/ocr', {
1399 | image: url.data.url
1400 | })
1401 | if (!json.status) return m.reply(format(json))
1402 | m.reply(json.data.text)
1403 | } else if (/(https?:\/\/.*\.(?:png|jpg|jpeg))/i.test(m.text)) {
1404 | const json = await Api.get('api/ocr', {
1405 | image: Func.isUrl(m.text)[0]
1406 | })
1407 | if (!json.status) return m.reply(format(json))
1408 | m.reply(json.data.text)
1409 | } else {
1410 | m.reply(`Send or reply your photo...`)
1411 | }
1412 | }
1413 | break
1414 | case 'hd':
1415 | case 'remini': {
1416 | if (/image/i.test(quoted.mime)) {
1417 | m.react('🕒')
1418 | m.react('🕒')
1419 | const url = await Scraper.uploader(await quoted.download())
1420 | const json = await Api.get('api/remini', {
1421 | image: url.data.url
1422 | })
1423 | if (!json.status) return m.reply(format(json))
1424 | m.reply(json.data.url, {
1425 | caption: config.options.wm
1426 | })
1427 | } else if (/(https?:\/\/.*\.(?:png|jpg|jpeg))/i.test(m.text)) {
1428 | const json = await Api.get('api/remini', {
1429 | image: Func.isUrl(m.text)[0]
1430 | })
1431 | if (!json.status) return m.reply(format(json))
1432 | m.reply(json.data.url, {
1433 | caption: config.options.wm
1434 | })
1435 | } else {
1436 | m.reply(`Send or reply your photo...`)
1437 | }
1438 | }
1439 | break
1440 | case 'nobg':
1441 | case 'removebg': {
1442 | if (/image/i.test(quoted.mime)) {
1443 | m.react('🕒')
1444 | const url = await Scraper.uploader(await quoted.download())
1445 | const json = await Api.get('api/removebg', {
1446 | image: url.data.url
1447 | })
1448 | if (!json.status) return m.reply(format(json))
1449 | m.reply(json.data.url, {
1450 | caption: config.options.wm
1451 | })
1452 | } else if (/(https?:\/\/.*\.(?:png|jpg|jpeg))/i.test(m.text)) {
1453 | const json = await Api.get('api/removebg', {
1454 | image: Func.isUrl(m.text)[0]
1455 | })
1456 | if (!json.status) return m.reply(format(json))
1457 | m.reply(json.data.url, {
1458 | caption: config.options.wm
1459 | })
1460 | } else {
1461 | m.reply(`Send or reply your photo...`)
1462 | }
1463 | }
1464 | break
1465 | case 'toanime':
1466 | case 'jadianime': {
1467 | if (/image/i.test(quoted.mime)) {
1468 | m.react('🕒')
1469 | const url = await Scraper.uploader(await quoted.download())
1470 | const json = await Api.get('api/toanime', {
1471 | image: url.data.url, style: 'anime'
1472 | })
1473 | if (!json.status) return m.reply(format(json))
1474 | m.reply(json.data.url, {
1475 | caption: config.options.wm
1476 | })
1477 | } else if (/(https?:\/\/.*\.(?:png|jpg|jpeg))/i.test(m.text)) {
1478 | const json = await Api.get('api/toanime', {
1479 | image: Func.isUrl(m.text)[0], style: 'anime'
1480 | })
1481 | if (!json.status) return m.reply(format(json))
1482 | m.reply(json.data.url, {
1483 | caption: config.options.wm
1484 | })
1485 | } else {
1486 | m.reply(`Send or reply your photo...`)
1487 | }
1488 | }
1489 | break
1490 | case 'tozombie':
1491 | case 'jadizombie': {
1492 | if (/image/i.test(quoted.mime)) {
1493 | m.react('🕒')
1494 | const url = await Scraper.uploader(await quoted.download())
1495 | const json = await Api.get('api/tozombie', {
1496 | image: url.data.url
1497 | })
1498 | if (!json.status) return m.reply(format(json))
1499 | m.reply(json.data.url, {
1500 | caption: config.options.wm
1501 | })
1502 | } else if (/(https?:\/\/.*\.(?:png|jpg|jpeg))/i.test(m.text)) {
1503 | var json = await Api.get('api/tozombie', {
1504 | image: Func.isUrl(m.text)[0]
1505 | })
1506 | if (!json.status) return m.reply(format(json))
1507 | m.reply(json.data.url, {
1508 | caption: config.options.wm
1509 | })
1510 | } else {
1511 | m.reply(`Send or reply your photo...`)
1512 | }
1513 | }
1514 | break
1515 | case 'gta5style': {
1516 | if (/image/i.test(quoted.mime)) {
1517 | m.react('🕒')
1518 | const url = await Scraper.uploader(await quoted.download())
1519 | let json = await Api.get('api/ai-photo-editor', {
1520 | image: url.data.url,
1521 | style: 'gta_5'
1522 | })
1523 | if (!json.status) return m.reply(format(json))
1524 | m.reply(json.data.url, {
1525 | caption: config.options.wm
1526 | })
1527 | } else if (/(https?:\/\/.*\.(?:png|jpg|jpeg))/i.test(m.text)) {
1528 | let json = await Api.get('api/ai-photo-editor', {
1529 | image: Func.isUrl(m.text)[0],
1530 | style: 'gta_5'
1531 | })
1532 | if (!json.status) return m.reply(format(json))
1533 | m.reply(json.data.url, {
1534 | caption: config.options.wm
1535 | })
1536 | } else {
1537 | m.reply(`Send or reply your photo...`)
1538 | }
1539 | }
1540 | break
1541 | case 'recolor': {
1542 | if (/image/i.test(quoted.mime)) {
1543 | m.react('🕒')
1544 | const url = await Scraper.uploader(await quoted.download())
1545 | var json = await Api.get('api/recolor', {
1546 | image: url.data.url
1547 | })
1548 | if (!json.status) return m.reply(format(json))
1549 | m.reply(json.data.url, {
1550 | caption: config.options.wm
1551 | })
1552 | } else if (/(https?:\/\/.*\.(?:png|jpg|jpeg))/i.test(m.text)) {
1553 | var json = await Api.get('api/recolor', {
1554 | image: Func.isUrl(m.text)[0]
1555 | })
1556 | if (!json.status) return m.reply(format(json))
1557 | m.reply(json.data.url, {
1558 | caption: config.options.wm
1559 | })
1560 | } else {
1561 | m.reply(`Send or reply your photo...`)
1562 | }
1563 | }
1564 | break
1565 | case 'screenshot':
1566 | case 'ss': {
1567 | try {
1568 | if (!m.args[1]) return m.reply(`Example : ${prefix + command} mobile https://api.alyachan.dev`)
1569 | if (!/^https?:\/\//.test(m.args[1])) return m.reply('Prefix the link with https:// or http://')
1570 | let mode = m.args[0].toLowerCase(), url = m.args[1]
1571 | if (!['mobile', 'desktop'].includes(mode)) return m.reply('Use mobile or desktop mode.')
1572 | m.react('🕒')
1573 | const json = await Api.get('api/ssweb', {
1574 | url: url, mode: mode
1575 | })
1576 | if (!json.status) return m.reply(format(json))
1577 | m.reply(json.data.url, {
1578 | caption: config.options.wm
1579 | })
1580 | } catch (e) {
1581 | return m.reply(format(e))
1582 | }
1583 | }
1584 | break
1585 | case 'shortlink':
1586 | case 'expand': {
1587 | if (!/^https:\/\//i.test(m.text)) return m.reply(`Example : ${prefix + command} https://api.alyachan.dev`)
1588 | m.react('🕒')
1589 | const json = await Api.get('api/shorten', { url: Func.isUrl(m.text)[0] })
1590 | if (!json.status) return m.reply(Func.Format(json))
1591 | await m.reply(Func.Format(json.data.url))
1592 | }
1593 | break
1594 | case 'tr':
1595 | case 'translate': {
1596 | let text = m.text
1597 | if (!text) return m.reply(`No Query?\n\nExample : ${prefix + command} id What your name`)
1598 | m.react('🕒')
1599 | if (text && m.quoted && m.quoted.text) {
1600 | let lang = text.slice(0, 2)
1601 | try {
1602 | let data = m.quoted.text
1603 | let json = await Api.get('api/translate', { text: data, iso: lang })
1604 | m.reply(json.data.text)
1605 | } catch (e) {
1606 | console.log(e)
1607 | m.reply(`Language code is not supported`)
1608 | }
1609 | } else if (text) {
1610 | let lang = text.slice(0, 2)
1611 | try {
1612 | let data = text.substring(2).trim()
1613 | let json = await Api.get('api/translate', { text: data, iso: lang })
1614 | m.reply(json.data.text)
1615 | } catch (e) {
1616 | console.log(e)
1617 | m.reply(`Language code is not supported`)
1618 | }
1619 | }
1620 | }
1621 | break
1622 | case 'tts': {
1623 | let lang
1624 | if (!m.args[0]) return m.reply(`Example : ${prefix + command} id What your name`)
1625 | m.react('🕒')
1626 | try {
1627 | let text = m.args.slice(1).join('')
1628 | if ((m.args[0] || '').length !== 2) {
1629 | lang = 'id'
1630 | text = m.args.join(' ')
1631 | }
1632 | if (!text && m.quoted && m.quoted.text) text = m.quoted.text
1633 | conn.sendPresenceUpdate('recording', m.chat)
1634 | let json = await Api.get('api/tts', {
1635 | text: text, iso: m.args[0]
1636 | })
1637 | conn.sendMedia(m.from, json.data.url, m, {
1638 | ptt: true
1639 | })
1640 | } catch (e) {
1641 | console.log(e)
1642 | return m.reply(`enter language code`)
1643 | }
1644 | }
1645 | break
1646 | case 'magernulis':
1647 | case 'nulis': {
1648 | if (!m.text) return m.reply(`Example : ${prefix + command} moon-bot wehwehweh`)
1649 | m.react('🕒')
1650 | let old = new Date()
1651 | let json = await Api.get('api/nulis', {
1652 | text: m.text
1653 | })
1654 | if (!json.status) return m.reply(Func.Format(json))
1655 | m.reply(json.data.url, {
1656 | caption: `Proccess : ${((new Date - old) * 1)} ms`
1657 | })
1658 | }
1659 | break
1660 | case 'calc':
1661 | case 'kalk':
1662 | case 'calculator': {
1663 | let val = m.text
1664 | .replace(/[^0-9\-\/+*×÷πEe()piPI/]/g, '')
1665 | .replace(/×/g, '*')
1666 | .replace(/÷/g, '/')
1667 | .replace(/π|pi/gi, 'Math.PI')
1668 | .replace(/e/gi, 'Math.E')
1669 | .replace(/\/+/g, '/')
1670 | .replace(/\++/g, '+')
1671 | .replace(/-+/g, '-')
1672 | let format = val
1673 | .replace(/Math\.PI/g, 'π')
1674 | .replace(/Math\.E/g, 'e')
1675 | .replace(/\//g, '÷')
1676 | .replace(/\*×/g, '×')
1677 | try {
1678 | console.log(val)
1679 | let result = (new Function('return ' + val))()
1680 | if (!result) throw result
1681 | m.reply(`*${format}* = _${result}_`)
1682 | } catch (e) {
1683 | if (e == undefined) return m.reply('Isinya?')
1684 | m.reply('Format salah, hanya 0-9 dan Simbol -, +, *, /, ×, ÷, π, e, (, ) yang disupport')
1685 | }
1686 | }
1687 | break
1688 |
1689 | /** end command */
1690 | default:
1691 | /** eval */
1692 | if (['>', 'eval', '=>'].some(a => m.body?.toLowerCase()?.startsWith(a))) {
1693 | if (!m.isOwner) return m.reply('owner')
1694 | let evalCmd = ''
1695 | try {
1696 | evalCmd = /await/i.test(m.text) ? eval('(async() => { ' + m.text + ' })()') : eval(m.text)
1697 | } catch (e) {
1698 | evalCmd = e
1699 | }
1700 | new Promise(async (resolve, reject) => {
1701 | try {
1702 | resolve(evalCmd)
1703 | } catch (err) {
1704 | reject(err)
1705 | }
1706 | })
1707 | ?.then((res) => m.reply(format(res)))
1708 | ?.catch((err) => m.reply(format(err)))
1709 | }
1710 |
1711 | /** exec */
1712 | if (['$', 'exec'].some(a => m.body?.toLowerCase()?.startsWith(a))) {
1713 | if (!m.isOwner) return m.reply('owner')
1714 | try {
1715 | exec(m.text, async (err, stdout) => {
1716 | if (err) return m.reply(format(err))
1717 | if (stdout) return m.reply(format(stdout))
1718 | })
1719 | } catch (e) {
1720 | m.reply(format(e))
1721 | }
1722 | }
1723 |
1724 | /** test */
1725 | if (/^bot/i.test(m.body) && m.isBot) {
1726 | m.reply(`Bot Activated "${m.pushName}"`)
1727 | }
1728 | }
1729 | } catch (e) {
1730 | console.log(e)
1731 | m.reply(format(e))
1732 | }
1733 | Func.reloadFile(fileURLToPath(import.meta.url))
1734 | }
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | import config from './config.js'
2 | import { Client, Serialize } from './lib/serialize.js'
3 | import baileys from '@whiskeysockets/baileys'
4 | import { Boom } from '@hapi/boom'
5 | import Pino from 'pino'
6 | import NodeCache from 'node-cache'
7 | import chalk from 'chalk'
8 | import readline from 'readline'
9 | import fs from 'fs'
10 |
11 | const { useMultiFileAuthState, DisconnectReason, makeInMemoryStore, jidNormalizedUser, makeCacheableSignalKeyStore, PHONENUMBER_MCC, Browsers, fetchLatestBaileysVersion } = baileys
12 | const database = (new (await import('./lib/database.js')).default())
13 | const store = makeInMemoryStore({ logger: Pino({ level: 'silent' }).child({ level: 'silent' }) })
14 | const rl = readline.createInterface({ input: process.stdin, output: process.stdout })
15 | const question = (text) => new Promise((resolve) => rl.question(text, resolve))
16 |
17 | // start connect to client
18 | async function start() {
19 | process.on('unhandledRejection', (err) => console.error(err))
20 |
21 | const content = await database.read()
22 | if (content && Object.keys(content).length === 0) {
23 | global.db = { users: {}, groups: {}, setting: {}, ...(content || {}) }
24 | await database.write(global.db)
25 | } else {
26 | global.db = content
27 | }
28 |
29 | const { version, isLatest } = await fetchLatestBaileysVersion()
30 | const { state, saveCreds } = await useMultiFileAuthState(`./${config.options.sessionName}`)
31 | const msgRetryCounterCache = new NodeCache() // for retry message, "waiting message"
32 |
33 | const conn = baileys.default({
34 | version,
35 | logger: Pino({ level: 'fatal' }).child({ level: 'fatal' }), // hide log
36 | printQRInTerminal: config.pairing.state ? false : true, // popping up QR in terminal log
37 | auth: {
38 | creds: state.creds,
39 | keys: makeCacheableSignalKeyStore(state.keys, Pino({ level: 'fatal' }).child({ level: 'fatal' })),
40 | },
41 | browser: Browsers.ubuntu('Chrome'),
42 | markOnlineOnConnect: true, // set false for offline
43 | generateHighQualityLinkPreview: true, // make high preview link
44 | getMessage: async (key) => {
45 | let jid = jidNormalizedUser(key.remoteJid)
46 | let msg = await store.loadMessage(jid, key.id)
47 | return msg?.message || ''
48 | },
49 | msgRetryCounterCache, // Resolve waiting messages
50 | defaultQueryTimeoutMs: undefined, // for this issues https://github.com/WhiskeySockets/Baileys/issues/276
51 | })
52 |
53 | // bind store, write store maybe
54 | store.bind(conn.ev)
55 |
56 | // push update name to store.contacts
57 | conn.ev.on('contacts.update', (update) => {
58 | for (let contact of update) {
59 | let id = jidNormalizedUser(contact.id)
60 | if (store && store.contacts) store.contacts[id] = { id, name: contact.notify }
61 | }
62 | })
63 |
64 | // bind extra client
65 | await Client({ conn, store })
66 |
67 | // login use pairing code
68 | if (config.pairing.state && !conn.authState.creds.registered) {
69 | let phoneNumber
70 | if (!!config.pairing.number) {
71 | phoneNumber = config.pairing.number.toString().replace(/[^0-9]/g, '')
72 | if (!Object.keys(PHONENUMBER_MCC).some(v => phoneNumber.startsWith(v))) {
73 | console.log(chalk.bgBlack(chalk.redBright("Start with your country's WhatsApp code, Example : 62xxx")))
74 | process.exit(0)
75 | }
76 | } else {
77 | phoneNumber = await question(chalk.bgBlack(chalk.greenBright(`Please type your WhatsApp number : `)))
78 | phoneNumber = phoneNumber.replace(/[^0-9]/g, '')
79 | if (!Object.keys(PHONENUMBER_MCC).some(v => phoneNumber.startsWith(v))) {
80 | console.log(chalk.bgBlack(chalk.redBright("Start with your country's WhatsApp code, Example : 62xxx")))
81 | phoneNumber = await question(chalk.bgBlack(chalk.greenBright(`Please type your WhatsApp number : `)))
82 | phoneNumber = phoneNumber.replace(/[^0-9]/g, '')
83 | rl.close()
84 | }
85 | }
86 | setTimeout(async () => {
87 | let code = await conn.requestPairingCode(phoneNumber)
88 | code = code?.match(/.{1,4}/g)?.join("-") || code
89 | console.log(chalk.black(chalk.bgGreen(`Your Pairing Code : `)), chalk.black(chalk.white(code)))
90 | }, 3000)
91 | }
92 |
93 | // for auto restart when error client
94 | conn.ev.on('connection.update', async (update) => {
95 | const { lastDisconnect, connection, qr } = update
96 | if (connection === 'close') {
97 | let reason = new Boom(lastDisconnect?.error)?.output.statusCode
98 | if (reason === DisconnectReason.badSession) {
99 | console.log(`Bad Session File, Please Delete Session and Scan Again`)
100 | process.send('reset')
101 | } else if (reason === DisconnectReason.connectionClosed) {
102 | console.log('Connection closed, reconnecting....')
103 | await start()
104 | } else if (reason === DisconnectReason.connectionLost) {
105 | console.log('Connection Lost from Server, reconnecting...')
106 | await start()
107 | } else if (reason === DisconnectReason.connectionReplaced) {
108 | console.log('Connection Replaced, Another New Session Opened, Please Close Current Session First')
109 | process.exit(1)
110 | } else if (reason === DisconnectReason.loggedOut) {
111 | console.log(`Device Logged Out, Please Scan Again And Run.`)
112 | process.exit(1)
113 | } else if (reason === DisconnectReason.restartRequired) {
114 | console.log('Restart Required, Restarting...')
115 | await start()
116 | } else if (reason === DisconnectReason.timedOut) {
117 | console.log('Connection TimedOut, Reconnecting...')
118 | process.send('reset')
119 | } else if (reason === DisconnectReason.multideviceMismatch) {
120 | console.log('Multi device mismatch, please scan again')
121 | process.exit(0)
122 | } else {
123 | console.log(reason)
124 | process.send('reset')
125 | }
126 | }
127 | if (connection === 'open') {
128 | console.log('Connected, you login as : ' + '[ ' + conn.user.name + ' ]')
129 | }
130 | })
131 |
132 | // write session
133 | conn.ev.on('creds.update', saveCreds)
134 |
135 | // messages
136 | conn.ev.on('messages.upsert', async (message) => {
137 | if (!message.messages) return
138 | const m = await Serialize(conn, message.messages[0])
139 | await (await import(`./lib/system/message.js?v=${Date.now()}`)).default(conn, m, message, database)
140 | })
141 |
142 | // group participants update
143 | conn.ev.on('group-participants.update', async (message) => {
144 | await (await import(`./lib/system/group-participants.js?v=${Date.now()}`)).default(conn, message)
145 | })
146 |
147 | // group update
148 | conn.ev.on('groups.update', async (update) => {
149 | await (await import(`./lib/system/group-update.js?v=${Date.now()}`)).default(conn, update)
150 | })
151 |
152 | // auto reject call when user call
153 | conn.ev.on('call', async (json) => {
154 | if (config.options.antiCall) {
155 | for (const id of json) {
156 | if (id.status === 'offer') {
157 | let msg = await conn.sendMessage(id.from, {
158 | text: `Maaf untuk saat ini, Kami tidak dapat menerima panggilan, entah dalam group atau pribadi\n\nJika Membutuhkan bantuan ataupun request fitur silahkan chat owner :p`,
159 | mentions: [id.from],
160 | })
161 | conn.sendContact(id.from, config.options.owner, msg)
162 | await conn.rejectCall(id.id, id.from)
163 | }
164 | }
165 | }
166 | })
167 |
168 | // rewrite database every 30 seconds
169 | setInterval(async () => {
170 | if (global.db) await database.write(global.db)
171 | }, 30000) // write database every 30 seconds
172 |
173 | if (!fs.existsSync('./temp')) fs.mkdirSync('./temp')
174 |
175 | /** auto clear tmp */
176 | setInterval(() => {
177 | try {
178 | const tmpFiles = fs.readdirSync('./temp')
179 | if (tmpFiles.length > 0) {
180 | tmpFiles.filter(v => !v.endsWith('.file')).map(v => fs.unlinkSync('./temp/' + v))
181 | }
182 | } catch { }
183 | }, 60 * 1000 * 10) // every 10 minute
184 |
185 | return conn
186 | }
187 | start().catch(() => start())
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "moon-case",
3 | "version": "1.5.0",
4 | "description": "A whatsApp bot using library baileys",
5 | "main": "index.js",
6 | "type": "module",
7 | "scripts": {
8 | "start": "node index.js --max-old-space-size=8192",
9 | "dev": "pm2 start index.js --name moon-bot --max-memory-restart 8G -- --max-old-space-size=8192"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/rifnd/moon-case.git"
14 | },
15 | "keywords": [
16 | "weabot",
17 | "wa-bot",
18 | "whatsapp-bot"
19 | ],
20 | "author": "rifnd",
21 | "license": "GPL-3.0-or-later",
22 | "bugs": {
23 | "url": "https://github.com/rifnd/moon-case/issues"
24 | },
25 | "homepage": "https://github.com/rifnd/moon-case#readme",
26 | "dependencies": {
27 | "@moonr/api": "^0.0.1",
28 | "@whiskeysockets/baileys": "npm:@neoxr/baileys",
29 | "chalk": "^5.3.0",
30 | "child_process": "^1.0.2",
31 | "dotenv": "^16.4.7",
32 | "file-type": "^18.5.0",
33 | "fluent-ffmpeg": "^2.1.2",
34 | "moment-timezone": "^0.5.43",
35 | "mongoose": "^6.3.3",
36 | "node-cache": "^5.1.2",
37 | "node-fetch": "^3.3.2",
38 | "node-id3": "^0.2.6",
39 | "node-webpmux": "^3.1.7",
40 | "yt-search": "^2.10.4"
41 | },
42 | "devDependencies": {
43 | "@adiwajshing/keyed-db": "^0.2.4",
44 | "axios": "^1.4.0",
45 | "jimp": "^0.16.13",
46 | "link-preview-js": "^3.0.4",
47 | "open": "^8.4.2",
48 | "qrcode-terminal": "0.12.0"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/replit.nix:
--------------------------------------------------------------------------------
1 | { pkgs } : {
2 | deps = [
3 | pkgs.nodejs_20
4 | pkgs.neofetch
5 | pkgs.jellyfin-ffmpeg
6 | pkgs.imagemagick
7 | pkgs.libwebp
8 | pkgs.yarn
9 | pkgs.libuuid
10 | ];
11 | env = {
12 | LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [
13 | pkgs.libuuid
14 | ];
15 | };
16 | }
--------------------------------------------------------------------------------