.
675 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | ## Clone this project
20 |
21 | ```bash
22 | > git clone https://github.com/MhankBarBar/termux-wabot
23 | ```
24 |
25 | ## Install the dependencies:
26 | Before running the below command, make sure you're in the project directory that
27 | you've just cloned!!
28 |
29 | ```bash
30 | > cd termux-wabot
31 | > bash install.sh
32 | ```
33 |
34 | ### Usage
35 | ```bash
36 | > npm start
37 | ```
38 |
39 | ### Settings
40 | ```json
41 | {
42 | "prefix": ".",
43 | "ownerNumber": "62858xxxxx",
44 | "apiKey": "Your ApiKey here"
45 | }
46 | ```
47 |
48 | ## Features
49 |
50 | | Sticker Creator | Feature |
51 | | :-----------: | :--------------------------------: |
52 | | ✅ | Send Photo with Caption |
53 | | ✅ | Reply A Photo |
54 | | ✅ | Reply A Video or GIF |
55 | | ✅ | Send Video or GIF with Caption |
56 | | ✅ | Reply A Sticker ( sticker to image ) |
57 |
58 | | Other | Feature |
59 | | :------------: | :---------------------------------------------: |
60 | | ✅ | Get a random meme |
61 | | ✅ | Text to speech |
62 | | ✅ | Writing feature |
63 | | ✅ | What Anime Is This |
64 | | ✅ | Url2Img ( Screeenshot Web ) |
65 | | ✅ | Simsimi |
66 |
67 | | Group | Feature |
68 | | :-----------: | :--------------------------------: |
69 | | ✅ | Tagall/Mentionall member |
70 | | ✅ | Tagall2/Mentionall member |
71 | | ✅ | Tagall3/Mentionall member |
72 | | ✅ | Kick Member Group |
73 | | ✅ | Add Member Group |
74 | | ✅ | Get List Admins Group |
75 | | ✅ | Get Group Invite Link |
76 | | ✅ | Bot leave the group |
77 |
78 | | Owner Bot | Feature |
79 | | :-----------: | :--------------------------------: |
80 | | ✅ | Set Prefix |
81 | | ✅ | Broadcast |
82 | | ✅ | Clear All Chats |
83 |
84 | ## Special Thanks to
85 | *
86 |
87 | ## Group
88 | *
89 |
90 | ### Donate
91 | *
92 | *
93 |
94 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const {
2 | WAConnection,
3 | MessageType,
4 | Presence,
5 | Mimetype,
6 | GroupSettingChange
7 | } = require('@adiwajshing/baileys')
8 | const { color, bgcolor } = require('./lib/color')
9 | const { help } = require('./src/help')
10 | const { wait, simih, getBuffer, h2k, generateMessageID, getGroupAdmins, getRandom, banner, start, info, success, close } = require('./lib/functions')
11 | const { fetchJson, fetchText } = require('./lib/fetcher')
12 | const { recognize } = require('./lib/ocr')
13 | const fs = require('fs')
14 | const moment = require('moment-timezone')
15 | const { exec } = require('child_process')
16 | const fetch = require('node-fetch')
17 | //const tiktod = require('tiktok-scraper')
18 | const ffmpeg = require('fluent-ffmpeg')
19 | const { removeBackgroundFromImageFile } = require('remove.bg')
20 | const lolis = require('lolis.life')
21 | const loli = new lolis()
22 | const welkom = JSON.parse(fs.readFileSync('./src/welkom.json'))
23 | const nsfw = JSON.parse(fs.readFileSync('./src/nsfw.json'))
24 | const samih = JSON.parse(fs.readFileSync('./src/simi.json'))
25 | const setting = JSON.parse(fs.readFileSync('./src/settings.json'))
26 | prefix = setting.prefix
27 | blocked = []
28 |
29 | function kyun(seconds){
30 | function pad(s){
31 | return (s < 10 ? '0' : '') + s;
32 | }
33 | var hours = Math.floor(seconds / (60*60));
34 | var minutes = Math.floor(seconds % (60*60) / 60);
35 | var seconds = Math.floor(seconds % 60);
36 |
37 | //return pad(hours) + ':' + pad(minutes) + ':' + pad(seconds)
38 | return `${pad(hours)} Jam ${pad(minutes)} Menit ${pad(seconds)} Detik`
39 | }
40 |
41 | async function starts() {
42 | const client = new WAConnection()
43 | client.logger.level = 'warn'
44 | console.log(banner.string)
45 | client.on('qr', () => {
46 | console.log(color('[','white'), color('!','red'), color(']','white'), color(' Scan the qr code above'))
47 | })
48 |
49 | fs.existsSync('./BarBar.json') && client.loadAuthInfo('./BarBar.json')
50 | client.on('connecting', () => {
51 | start('2', 'Connecting...')
52 | })
53 | client.on('open', () => {
54 | success('2', 'Connected')
55 | })
56 | await client.connect({timeoutMs: 30*1000})
57 | fs.writeFileSync('./BarBar.json', JSON.stringify(client.base64EncodedAuthInfo(), null, '\t'))
58 |
59 | client.on('group-participants-update', async (anu) => {
60 | if (!welkom.includes(anu.jid)) return
61 | try {
62 | const mdata = await client.groupMetadata(anu.jid)
63 | console.log(anu)
64 | if (anu.action == 'add') {
65 | num = anu.participants[0]
66 | try {
67 | ppimg = await client.getProfilePicture(`${anu.participants[0].split('@')[0]}@c.us`)
68 | } catch {
69 | ppimg = 'https://i0.wp.com/www.gambarunik.id/wp-content/uploads/2019/06/Top-Gambar-Foto-Profil-Kosong-Lucu-Tergokil-.jpg'
70 | }
71 | teks = `Halo @${num.split('@')[0]}\nSelamat datang di group *${mdata.subject}*`
72 | let buff = await getBuffer(ppimg)
73 | client.sendMessage(mdata.id, buff, MessageType.image, {caption: teks, contextInfo: {"mentionedJid": [num]}})
74 | } else if (anu.action == 'remove') {
75 | num = anu.participants[0]
76 | try {
77 | ppimg = await client.getProfilePicture(`${num.split('@')[0]}@c.us`)
78 | } catch {
79 | ppimg = 'https://i0.wp.com/www.gambarunik.id/wp-content/uploads/2019/06/Top-Gambar-Foto-Profil-Kosong-Lucu-Tergokil-.jpg'
80 | }
81 | teks = `Sayonara @${num.split('@')[0]}👋`
82 | let buff = await getBuffer(ppimg)
83 | client.sendMessage(mdata.id, buff, MessageType.image, {caption: teks, contextInfo: {"mentionedJid": [num]}})
84 | }
85 | } catch (e) {
86 | console.log('Error : %s', color(e, 'red'))
87 | }
88 | })
89 |
90 | client.on('CB:Blocklist', json => {
91 | if (blocked.length > 2) return
92 | for (let i of json[1].blocklist) {
93 | blocked.push(i.replace('c.us','s.whatsapp.net'))
94 | }
95 | })
96 |
97 | client.on('chat-update', async (mek) => {
98 | try {
99 | if (!mek.hasNewMessage) return
100 | mek = mek.messages.all()[0]
101 | if (!mek.message) return
102 | if (mek.key && mek.key.remoteJid == 'status@broadcast') return
103 | if (mek.key.fromMe) return
104 | global.prefix
105 | global.blocked
106 | const content = JSON.stringify(mek.message)
107 | const from = mek.key.remoteJid
108 | const type = Object.keys(mek.message)[0]
109 | const apiKey = setting.apiKey // contact me on whatsapp wa.me/6285892766102
110 | const { text, extendedText, contact, location, liveLocation, image, video, sticker, document, audio, product } = MessageType
111 | const time = moment.tz('Asia/Jakarta').format('DD/MM HH:mm:ss')
112 | body = (type === 'conversation' && mek.message.conversation.startsWith(prefix)) ? mek.message.conversation : (type == 'imageMessage') && mek.message.imageMessage.caption.startsWith(prefix) ? mek.message.imageMessage.caption : (type == 'videoMessage') && mek.message.videoMessage.caption.startsWith(prefix) ? mek.message.videoMessage.caption : (type == 'extendedTextMessage') && mek.message.extendedTextMessage.text.startsWith(prefix) ? mek.message.extendedTextMessage.text : ''
113 | budy = (type === 'conversation') ? mek.message.conversation : (type === 'extendedTextMessage') ? mek.message.extendedTextMessage.text : ''
114 | const command = body.slice(1).trim().split(/ +/).shift().toLowerCase()
115 | const args = body.trim().split(/ +/).slice(1)
116 | const isCmd = body.startsWith(prefix)
117 |
118 | mess = {
119 | wait: '⌛ Sedang di Prosess ⌛',
120 | success: '✔️ Berhasil ✔️',
121 | error: {
122 | stick: '❌ Gagal, terjadi kesalahan saat mengkonversi gambar ke sticker ❌',
123 | Iv: '❌ Link tidak valid ❌'
124 | },
125 | only: {
126 | group: '❌ Perintah ini hanya bisa di gunakan dalam group! ❌',
127 | ownerG: '❌ Perintah ini hanya bisa di gunakan oleh owner group! ❌',
128 | ownerB: '❌ Perintah ini hanya bisa di gunakan oleh owner bot! ❌',
129 | admin: '❌ Perintah ini hanya bisa di gunakan oleh admin group! ❌',
130 | Badmin: '❌ Perintah ini hanya bisa di gunakan ketika bot menjadi admin! ❌'
131 | }
132 | }
133 |
134 | const botNumber = client.user.jid
135 | const ownerNumber = [`${setting.ownerNumber}@s.whatsapp.net`] // replace this with your number
136 | const isGroup = from.endsWith('@g.us')
137 | const sender = isGroup ? mek.participant : mek.key.remoteJid
138 | const groupMetadata = isGroup ? await client.groupMetadata(from) : ''
139 | const groupName = isGroup ? groupMetadata.subject : ''
140 | const groupId = isGroup ? groupMetadata.jid : ''
141 | const groupMembers = isGroup ? groupMetadata.participants : ''
142 | const groupAdmins = isGroup ? getGroupAdmins(groupMembers) : ''
143 | const isBotGroupAdmins = groupAdmins.includes(botNumber) || false
144 | const isGroupAdmins = groupAdmins.includes(sender) || false
145 | const isWelkom = isGroup ? welkom.includes(from) : false
146 | const isNsfw = isGroup ? nsfw.includes(from) : false
147 | const isSimi = isGroup ? samih.includes(from) : false
148 | const isOwner = ownerNumber.includes(sender)
149 | const isUrl = (url) => {
150 | return url.match(new RegExp(/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)/, 'gi'))
151 | }
152 | const reply = (teks) => {
153 | client.sendMessage(from, teks, text, {quoted:mek})
154 | }
155 | const sendMess = (hehe, teks) => {
156 | client.sendMessage(hehe, teks, text)
157 | }
158 | const mentions = (teks, memberr, id) => {
159 | (id == null || id == undefined || id == false) ? client.sendMessage(from, teks.trim(), extendedText, {contextInfo: {"mentionedJid": memberr}}) : client.sendMessage(from, teks.trim(), extendedText, {quoted: mek, contextInfo: {"mentionedJid": memberr}})
160 | }
161 |
162 | colors = ['red','white','black','blue','yellow','green']
163 | const isMedia = (type === 'imageMessage' || type === 'videoMessage')
164 | const isQuotedImage = type === 'extendedTextMessage' && content.includes('imageMessage')
165 | const isQuotedVideo = type === 'extendedTextMessage' && content.includes('videoMessage')
166 | const isQuotedSticker = type === 'extendedTextMessage' && content.includes('stickerMessage')
167 | if (!isGroup && isCmd) console.log('\x1b[1;31m~\x1b[1;37m>', '[\x1b[1;32mEXEC\x1b[1;37m]', time, color(command), 'from', color(sender.split('@')[0]), 'args :', color(args.length))
168 | if (!isGroup && !isCmd) console.log('\x1b[1;31m~\x1b[1;37m>', '[\x1b[1;31mRECV\x1b[1;37m]', time, color('Message'), 'from', color(sender.split('@')[0]), 'args :', color(args.length))
169 | if (isCmd && isGroup) console.log('\x1b[1;31m~\x1b[1;37m>', '[\x1b[1;32mEXEC\x1b[1;37m]', time, color(command), 'from', color(sender.split('@')[0]), 'in', color(groupName), 'args :', color(args.length))
170 | if (!isCmd && isGroup) console.log('\x1b[1;31m~\x1b[1;37m>', '[\x1b[1;31mRECV\x1b[1;37m]', time, color('Message'), 'from', color(sender.split('@')[0]), 'in', color(groupName), 'args :', color(args.length))
171 | let authorname = client.contacts[from] != undefined ? client.contacts[from].vname || client.contacts[from].notify : undefined
172 | if (authorname != undefined) { } else { authorname = groupName }
173 |
174 | function addMetadata(packname, author) {
175 | if (!packname) packname = 'WABot'; if (!author) author = 'Bot';
176 | author = author.replace(/[^a-zA-Z0-9]/g, '');
177 | let name = `${author}_${packname}`
178 | if (fs.existsSync(`./src/stickers/${name}.exif`)) return `./src/stickers/${name}.exif`
179 | const json = {
180 | "sticker-pack-name": packname,
181 | "sticker-pack-publisher": author,
182 | }
183 | const littleEndian = Buffer.from([0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x41, 0x57, 0x07, 0x00])
184 | const bytes = [0x00, 0x00, 0x16, 0x00, 0x00, 0x00]
185 |
186 | let len = JSON.stringify(json).length
187 | let last
188 |
189 | if (len > 256) {
190 | len = len - 256
191 | bytes.unshift(0x01)
192 | } else {
193 | bytes.unshift(0x00)
194 | }
195 |
196 | if (len < 16) {
197 | last = len.toString(16)
198 | last = "0" + len
199 | } else {
200 | last = len.toString(16)
201 | }
202 |
203 | const buf2 = Buffer.from(last, "hex")
204 | const buf3 = Buffer.from(bytes)
205 | const buf4 = Buffer.from(JSON.stringify(json))
206 |
207 | const buffer = Buffer.concat([littleEndian, buf2, buf3, buf4])
208 |
209 | fs.writeFile(`./src/stickers/${name}.exif`, buffer, (err) => {
210 | return `./src/stickers/${name}.exif`
211 | })
212 |
213 | }
214 | switch(command) {
215 | case 'help':
216 | case 'menu':
217 | client.sendMessage(from, help(prefix), text)
218 | break
219 | case 'info':
220 | me = client.user
221 | uptime = process.uptime()
222 | teks = `*Nama bot* : ${me.name}\n*Nomor Bot* : @${me.jid.split('@')[0]}\n*Prefix* : ${prefix}\n*Total Block Contact* : ${blocked.length}\n*The bot is active on* : ${kyun(uptime)}`
223 | buffer = await getBuffer(me.imgUrl)
224 | client.sendMessage(from, buffer, image, {caption: teks, contextInfo:{mentionedJid: [me.jid]}})
225 | break
226 | case 'blocklist':
227 | teks = 'This is list of blocked number :\n'
228 | for (let block of blocked) {
229 | teks += `~> @${block.split('@')[0]}\n`
230 | }
231 | teks += `Total : ${blocked.length}`
232 | client.sendMessage(from, teks.trim(), extendedText, {quoted: mek, contextInfo: {"mentionedJid": blocked}})
233 | break
234 | case 'ocr':
235 | if ((isMedia && !mek.message.videoMessage || isQuotedImage) && args.length == 0) {
236 | const encmedia = isQuotedImage ? JSON.parse(JSON.stringify(mek).replace('quotedM','m')).message.extendedTextMessage.contextInfo : mek
237 | const media = await client.downloadAndSaveMediaMessage(encmedia)
238 | reply(mess.wait)
239 | await recognize(media, {lang: 'eng+ind', oem: 1, psm: 3})
240 | .then(teks => {
241 | reply(teks.trim())
242 | fs.unlinkSync(media)
243 | })
244 | .catch(err => {
245 | reply(err.message)
246 | fs.unlinkSync(media)
247 | })
248 | } else {
249 | reply('Foto aja mas')
250 | }
251 | break
252 | case 'tp':
253 | if (args.length < 1) {
254 | return reply('Pilih themenya om, 1 - 162')
255 | } else if (args[0].toLowerCase() === 'list') {
256 | teks = await fetchText('https://mhankbarbar.moe/api/textpro/listtheme')
257 | teks = teks.replace(/
/g, '\n')
258 | return reply(teks)
259 | } else if (args.length < 2) {
260 | return reply('Teksnya juga dong om')
261 | }
262 | reply(mess.wait)
263 | anu = `https://mhankbarbar.moe/api/textpro?pack=${args[0]}&text=${body.slice(3+args[0].length+1)}&apiKey=${apiKey}`
264 | voss = await fetch(anu)
265 | ftype = require('file-type')
266 | vuss = await ftype.fromStream(voss.body)
267 | if (vuss !== undefined) {
268 | client.sendMessage(from, await getBuffer(anu), image, { caption: mess.success, quoted: mek })
269 | } else {
270 | reply('Terjadi kesalahan, silahkan pilih theme lain')
271 | }
272 | break
273 | case 'ep':
274 | if (args.length < 1) {
275 | return reply('Pilih themenya om, 1 - 216')
276 | } else if (args[0].toLowerCase() === 'list') {
277 | teks = await fetchText('https://mhankbarbar.moe/api/ephoto/listtheme')
278 | teks = teks.replace(/
/g, '\n')
279 | return reply(teks)
280 | } else if (args.length < 2) {
281 | return reply('Teksnya juga dong om')
282 | }
283 | reply(mess.wait)
284 | anu = `https://mhankbarbar.moe/api/ephoto?pack=${args[0]}&text=${body.slice(3+args[0].length+1)}&apiKey=${apiKey}`
285 | voss = await fetch(anu)
286 | ftype = require('file-type')
287 | vuss = await ftype.fromStream(voss.body)
288 | //console.log(vuss)
289 | if (vuss !== undefined) {
290 | client.sendMessage(from, await getBuffer(anu), image, { caption: mess.success, quoted: mek })
291 | } else {
292 | reply('Terjadi kesalahan, silahkan pilih theme lain')
293 | }
294 | break
295 | case 'tahta':
296 | if (args.length < 1) return reply('Teksnya om')
297 | anu = `https://mhankbarbar.moe/api/htahta?text=${args.join(' ')}&apiKey=${apiKey}`
298 | voss = await fetch(anu)
299 | ftype = require('file-type')
300 | vuss = await ftype.fromStream(voss.body)
301 | if (vuss !== undefined) {
302 | client.sendMessage(from, await getBuffer(anu), image, { quoted: mek, caption: mess.sucess })
303 | } else {
304 | reply('Terjadi kesalahan')
305 | }
306 | break
307 | case 'stiker':
308 | case 'sticker':
309 | if ((isMedia && !mek.message.videoMessage || isQuotedImage) && args.length == 0) {
310 | const encmedia = isQuotedImage ? JSON.parse(JSON.stringify(mek).replace('quotedM','m')).message.extendedTextMessage.contextInfo : mek
311 | const media = await client.downloadAndSaveMediaMessage(encmedia)
312 | ran = getRandom('.webp')
313 | await ffmpeg(`./${media}`)
314 | .input(media)
315 | .on('start', function (cmd) {
316 | console.log(`Started : ${cmd}`)
317 | })
318 | .on('error', function (err) {
319 | console.log(`Error : ${err}`)
320 | fs.unlinkSync(media)
321 | reply(mess.error.stick)
322 | })
323 | .on('end', function () {
324 | console.log('Finish')
325 | exec(`webpmux -set exif ${addMetadata('BOT', authorname)} ${ran} -o ${ran}`, async (error) => {
326 | if (error) return reply(mess.error.stick)
327 | client.sendMessage(from, fs.readFileSync(ran), sticker, {quoted: mek})
328 | fs.unlinkSync(media)
329 | fs.unlinkSync(ran)
330 | })
331 | /*client.sendMessage(from, fs.readFileSync(ran), sticker, {quoted: mek})
332 | fs.unlinkSync(media)
333 | fs.unlinkSync(ran)*/
334 | })
335 | .addOutputOptions([`-vcodec`,`libwebp`,`-vf`,`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`])
336 | .toFormat('webp')
337 | .save(ran)
338 | } else if ((isMedia && mek.message.videoMessage.seconds < 11 || isQuotedVideo && mek.message.extendedTextMessage.contextInfo.quotedMessage.videoMessage.seconds < 11) && args.length == 0) {
339 | const encmedia = isQuotedVideo ? JSON.parse(JSON.stringify(mek).replace('quotedM','m')).message.extendedTextMessage.contextInfo : mek
340 | const media = await client.downloadAndSaveMediaMessage(encmedia)
341 | ran = getRandom('.webp')
342 | reply(mess.wait)
343 | await ffmpeg(`./${media}`)
344 | .inputFormat(media.split('.')[1])
345 | .on('start', function (cmd) {
346 | console.log(`Started : ${cmd}`)
347 | })
348 | .on('error', function (err) {
349 | console.log(`Error : ${err}`)
350 | fs.unlinkSync(media)
351 | tipe = media.endsWith('.mp4') ? 'video' : 'gif'
352 | reply(`❌ Gagal, pada saat mengkonversi ${tipe} ke stiker`)
353 | })
354 | .on('end', function () {
355 | console.log('Finish')
356 | exec(`webpmux -set exif ${addMetadata('BOT', authorname)} ${ran} -o ${ran}`, async (error) => {
357 | if (error) return reply(mess.error.stick)
358 | client.sendMessage(from, fs.readFileSync(ran), sticker, {quoted: mek})
359 | fs.unlinkSync(media)
360 | fs.unlinkSync(ran)
361 | })
362 | /*client.sendMessage(from, fs.readFileSync(ran), sticker, {quoted: mek})
363 | fs.unlinkSync(media)
364 | fs.unlinkSync(ran)*/
365 | })
366 | .addOutputOptions([`-vcodec`,`libwebp`,`-vf`,`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`])
367 | .toFormat('webp')
368 | .save(ran)
369 | } else if ((isMedia || isQuotedImage) && args[0] == 'nobg') {
370 | const encmedia = isQuotedImage ? JSON.parse(JSON.stringify(mek).replace('quotedM','m')).message.extendedTextMessage.contextInfo : mek
371 | const media = await client.downloadAndSaveMediaMessage(encmedia)
372 | ranw = getRandom('.webp')
373 | ranp = getRandom('.png')
374 | reply(mess.wait)
375 | keyrmbg = 'Your-ApiKey'
376 | await removeBackgroundFromImageFile({path: media, apiKey: keyrmbg, size: 'auto', type: 'auto', ranp}).then(res => {
377 | fs.unlinkSync(media)
378 | let buffer = Buffer.from(res.base64img, 'base64')
379 | fs.writeFileSync(ranp, buffer, (err) => {
380 | if (err) return reply('Gagal, Terjadi kesalahan, silahkan coba beberapa saat lagi.')
381 | })
382 | exec(`ffmpeg -i ${ranp} -vcodec libwebp -filter:v fps=fps=20 -lossless 1 -loop 0 -preset default -an -vsync 0 -s 512:512 ${ranw}`, (err) => {
383 | fs.unlinkSync(ranp)
384 | if (err) return reply(mess.error.stick)
385 | exec(`webpmux -set exif ${addMetadata('BOT', authorname)} ${ranw} -o ${ranw}`, async (error) => {
386 | if (error) return reply(mess.error.stick)
387 | client.sendMessage(from, fs.readFileSync(ranw), sticker, {quoted: mek})
388 | fs.unlinkSync(ranw)
389 | })
390 | //client.sendMessage(from, fs.readFileSync(ranw), sticker, {quoted: mek})
391 | })
392 | })
393 | /*} else if ((isMedia || isQuotedImage) && colors.includes(args[0])) {
394 | const encmedia = isQuotedImage ? JSON.parse(JSON.stringify(mek).replace('quotedM','m')).message.extendedTextMessage.contextInfo : mek
395 | const media = await client.downloadAndSaveMediaMessage(encmedia)
396 | ran = getRandom('.webp')
397 | await ffmpeg(`./${media}`)
398 | .on('start', function (cmd) {
399 | console.log('Started :', cmd)
400 | })
401 | .on('error', function (err) {
402 | fs.unlinkSync(media)
403 | console.log('Error :', err)
404 | })
405 | .on('end', function () {
406 | console.log('Finish')
407 | fs.unlinkSync(media)
408 | client.sendMessage(from, fs.readFileSync(ran), sticker, {quoted: mek})
409 | fs.unlinkSync(ran)
410 | })
411 | .addOutputOptions([`-vcodec`,`libwebp`,`-vf`,`scale='min(320,iw)':min'(320,ih)':force_original_aspect_ratio=decrease,fps=15, pad=320:320:-1:-1:color=${args[0]}@0.0, split [a][b]; [a] palettegen=reserve_transparent=off; [b][p] paletteuse`])
412 | .toFormat('webp')
413 | .save(ran)*/
414 | } else {
415 | reply(`Kirim gambar dengan caption ${prefix}sticker atau tag gambar yang sudah dikirim`)
416 | }
417 | break
418 | case 'gtts':
419 | if (args.length < 1) return client.sendMessage(from, 'Kode bahasanya mana om?', text, {quoted: mek})
420 | const gtts = require('./lib/gtts')(args[0])
421 | if (args.length < 2) return client.sendMessage(from, 'Textnya mana om', text, {quoted: mek})
422 | dtt = body.slice(9)
423 | ranm = getRandom('.mp3')
424 | dtt.length > 600
425 | ? reply('Textnya kebanyakan om')
426 | : gtts.save(ranm, dtt, function() {
427 | client.sendMessage(from, fs.readFileSync(ranm), audio, {quoted: mek, mimetype: 'audio/mp4', ptt:true})
428 | fs.unlinkSync(ranm)
429 | })
430 | break
431 | case 'meme':
432 | meme = await fetchJson('https://kagchi-api.glitch.me/meme/memes', { method: 'get' })
433 | buffer = await getBuffer(`https://imgur.com/${meme.hash}.jpg`)
434 | client.sendMessage(from, buffer, image, {quoted: mek, caption: '.......'})
435 | break
436 | /*case 'memeindo':
437 | memein = await kagApi.memeindo()
438 | buffer = await getBuffer(`https://imgur.com/${memein.hash}.jpg`)
439 | client.sendMessage(from, buffer, image, {quoted: mek, caption: '.......'})
440 | break*/
441 | case 'setprefix':
442 | if (args.length < 1) return
443 | if (!isOwner) return reply(mess.only.ownerB)
444 | prefix = args[0]
445 | setting.prefix = prefix
446 | fs.writeFileSync('./src/settings.json', JSON.stringify(setting, null, '\t'))
447 | reply(`Prefix berhasil di ubah menjadi : ${prefix}`)
448 | break
449 | /*case 'loli':
450 | loli.getSFWLoli(async (err, res) => {
451 | if (err) return reply('❌ *ERROR* ❌')
452 | buffer = await getBuffer(res.url)
453 | client.sendMessage(from, buffer, image, {quoted: mek, caption: 'Ingat! Citai Lolimu'})
454 | })
455 | break
456 | case 'nsfwloli':
457 | if (!isNsfw) return reply('❌ *FALSE* ❌')
458 | loli.getNSFWLoli(async (err, res) => {
459 | if (err) return reply('❌ *ERROR* ❌')
460 | buffer = await getBuffer(res.url)
461 | client.sendMessage(from, buffer, image, {quoted: mek, caption: 'Jangan jadiin bahan buat comli om'})
462 | })
463 | break
464 | case 'hilih':
465 | if (args.length < 1) return reply('Teksnya mana um?')
466 | anu = await fetchJson(`https://mhankbarbars.herokuapp.com/api/hilih?teks=${body.slice(7)}`, {method: 'get'})
467 | reply(anu.result)
468 | break*/
469 | case 'yt2mp3':
470 | if (args.length < 1) return reply('Urlnya mana um?')
471 | if(!isUrl(args[0]) && !args[0].includes('youtu')) return reply(mess.error.Iv)
472 | anu = await fetchJson(`https://mhankbarbar.moe/api/yta?url=${args[0]}&apiKey=${apiKey}`, {method: 'get'})
473 | if (anu.error) return reply(anu.error)
474 | teks = `*Title* : ${anu.title}\n*Filesize* : ${anu.filesize}`
475 | thumb = await getBuffer(anu.thumb)
476 | client.sendMessage(from, thumb, image, {quoted: mek, caption: teks})
477 | buffer = await getBuffer(anu.result)
478 | client.sendMessage(from, buffer, audio, {mimetype: 'audio/mp4', filename: `${anu.title}.mp3`, quoted: mek})
479 | break
480 | case 'ytsearch':
481 | if (args.length < 1) return reply('Yang mau di cari apaan? titit?')
482 | anu = await fetchJson(`https://mhankbarbar.moe/api/ytsearch?q=${body.slice(10)}&apiKey=${apiKey}`, {method: 'get'})
483 | if (anu.error) return reply(anu.error)
484 | teks = '=================\n'
485 | for (let i of anu.result) {
486 | teks += `*Title* : ${i.title}\n*Id* : ${i.id}\n*Published* : ${i.publishTime}\n*Duration* : ${i.duration}\n*Views* : ${h2k(i.views)}\n=================\n`
487 | }
488 | reply(teks.trim())
489 | break
490 | case 'tiktok':
491 | if (args.length < 1) return reply('Urlnya mana um?')
492 | if (!isUrl(args[0]) && !args[0].includes('tiktok.com')) return reply(mess.error.Iv)
493 | reply(mess.wait)
494 | anu = await fetchJson(`https://mhankbarbar.moe/api/tiktok?url=${args[0]}&apiKey=${apiKey}`, {method: 'get'})
495 | if (anu.error) return reply(anu.error)
496 | buffer = await getBuffer(anu.result)
497 | client.sendMessage(from, buffer, video, {quoted: mek})
498 | break
499 | /*case 'tiktokstalk':
500 | try {
501 | if (args.length < 1) return client.sendMessage(from, 'Usernamenya mana um?', text, {quoted: mek})
502 | let { user, stats } = await tiktod.getUserProfileInfo(args[0])
503 | reply(mess.wait)
504 | teks = `*ID* : ${user.id}\n*Username* : ${user.uniqueId}\n*Nickname* : ${user.nickname}\n*Followers* : ${stats.followerCount}\n*Followings* : ${stats.followingCount}\n*Posts* : ${stats.videoCount}\n*Luv* : ${stats.heart}\n`
505 | buffer = await getBuffer(user.avatarLarger)
506 | client.sendMessage(from, buffer, image, {quoted: mek, caption: teks})
507 | } catch (e) {
508 | console.log(`Error :`, color(e,'red'))
509 | reply('Kemungkinan username tidak valid')
510 | }
511 | break*/
512 | case 'nulis':
513 | case 'tulis':
514 | if (args.length < 1) return reply('Yang mau di tulis apaan?')
515 | teks = body.slice(7)
516 | reply(mess.wait)
517 | anu = await fetchJson(`https://mhankbarbar.moe/nulis?text=${teks}&apiKey=${apiKey}`, {method: 'get'})
518 | if (anu.error) return reply(anu.error)
519 | buff = await getBuffer(anu.result)
520 | client.sendMessage(from, buff, image, {quoted: mek, caption: mess.success})
521 | break
522 | case 'url2img':
523 | tipelist = ['desktop','tablet','mobile']
524 | if (args.length < 1) return reply('Tipenya apa um?')
525 | if (!tipelist.includes(args[0])) return reply('Tipe desktop|tablet|mobile')
526 | if (args.length < 2) return reply('Urlnya mana um?')
527 | if (!isUrl(args[1])) return reply(mess.error.Iv)
528 | reply(mess.wait)
529 | anu = await fetchJson(`https://mhankbarbar.moe/api/url2image?tipe=${args[0]}&url=${args[1]}&apiKey=${apiKey}`, {method: 'get'})
530 | if (anu.error) return reply(anu.error)
531 | buff = await getBuffer(anu.result)
532 | client.sendMessage(from, buff, image, {quoted: mek})
533 | break
534 | case 'tstiker':
535 | case 'tsticker':
536 | if (args.length < 1) return reply('Textnya mana um?')
537 | ranp = getRandom('.png')
538 | rano = getRandom('.webp')
539 | teks = body.slice(9).trim()
540 | anu = await fetchJson(`https://mhankbarbar.moe/api/text2image?text=${teks}&apiKey=${apiKey}`, {method: 'get'})
541 | if (anu.error) return reply(anu.error)
542 | exec(`wget ${anu.result} -O ${ranp} && ffmpeg -i ${ranp} -vcodec libwebp -filter:v fps=fps=20 -lossless 1 -loop 0 -preset default -an -vsync 0 -s 512:512 ${rano}`, (err) => {
543 | fs.unlinkSync(ranp)
544 | if (err) return reply(mess.error.stick)
545 | exec(`webpmux -set exif ${addMetadata('BOT', authorname)} ${rano} -o ${rano}`, async (error) => {
546 | if (error) return reply(mess.error.stick)
547 | client.sendMessage(from, fs.readFileSync(rano), sticker, {quoted: mek})
548 | fs.unlinkSync(rano)
549 | })
550 | /*client.sendMessage(from, fs.readFileSync(rano), sticker, {quoted: mek})
551 | fs.unlinkSync(rano)*/
552 | })
553 | break
554 | case 'tagall':
555 | if (!isGroup) return reply(mess.only.group)
556 | if (!isGroupAdmins) return reply(mess.only.admin)
557 | members_id = []
558 | teks = (args.length > 1) ? body.slice(8).trim() : ''
559 | teks += '\n\n'
560 | for (let mem of groupMembers) {
561 | teks += `*#* @${mem.jid.split('@')[0]}\n`
562 | members_id.push(mem.jid)
563 | }
564 | mentions(teks, members_id, true)
565 | break
566 | case 'tagall2':
567 | members_id = []
568 | teks = (args.length > 1) ? body.slice(8).trim() : ''
569 | teks += '\n\n'
570 | for (let mem of groupMembers) {
571 | teks += `╠➥ @${mem.jid.split('@')[0]}\n`
572 | members_id.push(mem.jid)
573 | }
574 | reply(teks)
575 | break
576 | case 'tagall3':
577 | members_id = []
578 | teks = (args.length > 1) ? body.slice(8).trim() : ''
579 | teks += '\n\n'
580 | for (let mem of groupMembers) {
581 | teks += `╠➥ https://wa.me/${mem.jid.split('@')[0]}\n`
582 | members_id.push(mem.jid)
583 | }
584 | client.sendMessage(from, teks, text, {detectLinks: false, quoted: mek})
585 | break
586 | case 'clearall':
587 | if (!isOwner) return reply('Kamu siapa?')
588 | anu = await client.chats.all()
589 | client.setMaxListeners(25)
590 | for (let _ of anu) {
591 | client.deleteChat(_.jid)
592 | }
593 | reply('Sukses delete all chat :)')
594 | break
595 | case 'bc':
596 | if (!isOwner) return reply('Kamu siapa?')
597 | if (args.length < 1) return reply('.......')
598 | anu = await client.chats.all()
599 | if (isMedia && !mek.message.videoMessage || isQuotedImage) {
600 | const encmedia = isQuotedImage ? JSON.parse(JSON.stringify(mek).replace('quotedM','m')).message.extendedTextMessage.contextInfo : mek
601 | buff = await client.downloadMediaMessage(encmedia)
602 | for (let _ of anu) {
603 | client.sendMessage(_.jid, buff, image, {caption: `[ Ini Broadcast ]\n\n${body.slice(4)}`})
604 | }
605 | reply('Suksess broadcast')
606 | } else {
607 | for (let _ of anu) {
608 | sendMess(_.jid, `[ Ini Broadcast ]\n\n${body.slice(4)}`)
609 | }
610 | reply('Suksess broadcast')
611 | }
612 | break
613 | case 'promote':
614 | if (!isGroup) return reply(mess.only.group)
615 | if (!isGroupAdmins) return reply(mess.only.admin)
616 | if (!isBotGroupAdmins) return reply(mess.only.Badmin)
617 | if (mek.message.extendedTextMessage === undefined || mek.message.extendedTextMessage === null) return
618 | mentioned = mek.message.extendedTextMessage.contextInfo.mentionedJid
619 | if (mentioned.length > 1) {
620 | teks = 'Berhasil Promote\n'
621 | for (let _ of mentioned) {
622 | teks += `@${_.split('@')[0]}\n`
623 | }
624 | mentions(from, mentioned, true)
625 | client.groupRemove(from, mentioned)
626 | } else {
627 | mentions(`Berhasil Promote @${mentioned[0].split('@')[0]} Sebagai Admin Group!`, mentioned, true)
628 | client.groupMakeAdmin(from, mentioned)
629 | }
630 | break
631 | case 'demote':
632 | if (!isGroup) return reply(mess.only.group)
633 | if (!isGroupAdmins) return reply(mess.only.admin)
634 | if (!isBotGroupAdmins) return reply(mess.only.Badmin)
635 | if (mek.message.extendedTextMessage === undefined || mek.message.extendedTextMessage === null) return
636 | mentioned = mek.message.extendedTextMessage.contextInfo.mentionedJid
637 | if (mentioned.length > 1) {
638 | teks = 'Berhasil Demote\n'
639 | for (let _ of mentioned) {
640 | teks += `@${_.split('@')[0]}\n`
641 | }
642 | mentions(teks, mentioned, true)
643 | client.groupRemove(from, mentioned)
644 | } else {
645 | mentions(`Berhasil Demote @${mentioned[0].split('@')[0]} Menjadi Member Group!`, mentioned, true)
646 | client.groupDemoteAdmin(from, mentioned)
647 | }
648 | break
649 | case 'add':
650 | if (!isGroup) return reply(mess.only.group)
651 | if (!isGroupAdmins) return reply(mess.only.admin)
652 | if (!isBotGroupAdmins) return reply(mess.only.Badmin)
653 | if (args.length < 1) return reply('Yang mau di add jin ya?')
654 | if (args[0].startsWith('08')) return reply('Gunakan kode negara mas')
655 | try {
656 | num = `${args[0].replace(/ /g, '')}@s.whatsapp.net`
657 | client.groupAdd(from, [num])
658 | } catch (e) {
659 | console.log('Error :', e)
660 | reply('Gagal menambahkan target, mungkin karena di private')
661 | }
662 | break
663 | case 'kick':
664 | if (!isGroup) return reply(mess.only.group)
665 | if (!isGroupAdmins) return reply(mess.only.admin)
666 | if (!isBotGroupAdmins) return reply(mess.only.Badmin)
667 | if (mek.message.extendedTextMessage === undefined || mek.message.extendedTextMessage === null) return reply('Tag target yang ingin di tendang!')
668 | mentioned = mek.message.extendedTextMessage.contextInfo.mentionedJid
669 | if (mentioned.length > 1) {
670 | teks = 'Perintah di terima, mengeluarkan :\n'
671 | for (let _ of mentioned) {
672 | teks += `@${_.split('@')[0]}\n`
673 | }
674 | mentions(teks, mentioned, true)
675 | client.groupRemove(from, mentioned)
676 | } else {
677 | mentions(`Perintah di terima, mengeluarkan : @${mentioned[0].split('@')[0]}`, mentioned, true)
678 | client.groupRemove(from, mentioned)
679 | }
680 | break
681 | case 'listadmins':
682 | if (!isGroup) return reply(mess.only.group)
683 | teks = `List admin of group *${groupMetadata.subject}*\nTotal : ${groupAdmins.length}\n\n`
684 | no = 0
685 | for (let admon of groupAdmins) {
686 | no += 1
687 | teks += `[${no.toString()}] @${admon.split('@')[0]}\n`
688 | }
689 | mentions(teks, groupAdmins, true)
690 | break
691 | case 'linkgroup':
692 | if (!isGroup) return reply(mess.only.group)
693 | if (!isGroupAdmins) return reply(mess.only.admin)
694 | if (!isBotGroupAdmins) return reply(mess.only.Badmin)
695 | linkgc = await client.groupInviteCode(from)
696 | reply('https://chat.whatsapp.com/'+linkgc)
697 | break
698 | case 'leave':
699 | if (!isGroup) return reply(mess.only.group)
700 | if (isGroupAdmins || isOwner) {
701 | client.groupLeave(from)
702 | } else {
703 | reply(mess.only.admin)
704 | }
705 | break
706 | case 'toimg':
707 | if (!isQuotedSticker) return reply('❌ reply stickernya um ❌')
708 | reply(mess.wait)
709 | encmedia = JSON.parse(JSON.stringify(mek).replace('quotedM','m')).message.extendedTextMessage.contextInfo
710 | media = await client.downloadAndSaveMediaMessage(encmedia)
711 | ran = getRandom('.png')
712 | exec(`ffmpeg -i ${media} ${ran}`, (err) => {
713 | fs.unlinkSync(media)
714 | if (err) return reply('❌ Gagal, pada saat mengkonversi sticker ke gambar ❌')
715 | buffer = fs.readFileSync(ran)
716 | client.sendMessage(from, buffer, image, {quoted: mek, caption: '>//<'})
717 | fs.unlinkSync(ran)
718 | })
719 | break
720 | case 'simi':
721 | if (args.length < 1) return reply('Textnya mana um?')
722 | teks = body.slice(5)
723 | anu = await simih(teks) //fetchJson(`https://mhankbarbars.herokuapp.com/api/samisami?text=${teks}`, {method: 'get'})
724 | //if (anu.error) return reply('Simi ga tau kak')
725 | reply(anu)
726 | break
727 | case 'simih':
728 | if (!isGroup) return reply(mess.only.group)
729 | if (!isGroupAdmins) return reply(mess.only.admin)
730 | if (args.length < 1) return reply('Hmmmm')
731 | if (Number(args[0]) === 1) {
732 | if (isSimi) return reply('Mode simi sudah aktif')
733 | samih.push(from)
734 | fs.writeFileSync('./src/simi.json', JSON.stringify(samih))
735 | reply('Sukses mengaktifkan mode simi di group ini ✔️')
736 | } else if (Number(args[0]) === 0) {
737 | samih.splice(from, 1)
738 | fs.writeFileSync('./src/simi.json', JSON.stringify(samih))
739 | reply('Sukes menonaktifkan mode simi di group ini ✔️')
740 | } else {
741 | reply('1 untuk mengaktifkan, 0 untuk menonaktifkan')
742 | }
743 | break
744 | case 'welcome':
745 | if (!isGroup) return reply(mess.only.group)
746 | if (!isGroupAdmins) return reply(mess.only.admin)
747 | if (args.length < 1) return reply('Hmmmm')
748 | if (Number(args[0]) === 1) {
749 | if (isWelkom) return reply('Udah aktif um')
750 | welkom.push(from)
751 | fs.writeFileSync('./src/welkom.json', JSON.stringify(welkom))
752 | reply('Sukses mengaktifkan fitur welcome di group ini ✔️')
753 | } else if (Number(args[0]) === 0) {
754 | welkom.splice(from, 1)
755 | fs.writeFileSync('./src/welkom.json', JSON.stringify(welkom))
756 | reply('Sukses menonaktifkan fitur welcome di group ini ✔️')
757 | } else {
758 | reply('1 untuk mengaktifkan, 0 untuk menonaktifkan')
759 | }
760 | break
761 | case 'clone':
762 | if (!isGroup) return reply(mess.only.group)
763 | if (!isGroupAdmins) return reply(mess.only.admin)
764 | if (args.length < 1) return reply('Tag target yang ingin di clone')
765 | if (mek.message.extendedTextMessage === undefined || mek.message.extendedTextMessage === null) return reply('Tag cvk')
766 | mentioned = mek.message.extendedTextMessage.contextInfo.mentionedJid[0]
767 | let { jid, id, notify } = groupMembers.find(x => x.jid === mentioned)
768 | try {
769 | pp = await client.getProfilePicture(id)
770 | buffer = await getBuffer(pp)
771 | client.updateProfilePicture(botNumber, buffer)
772 | mentions(`Foto profile Berhasil di perbarui menggunakan foto profile @${id.split('@')[0]}`, [jid], true)
773 | } catch (e) {
774 | reply('Gagal om')
775 | }
776 | break
777 | case 'wait':
778 | if ((isMedia && !mek.message.videoMessage || isQuotedImage) && args.length == 0) {
779 | reply(mess.wait)
780 | const encmedia = isQuotedImage ? JSON.parse(JSON.stringify(mek).replace('quotedM','m')).message.extendedTextMessage.contextInfo : mek
781 | media = await client.downloadMediaMessage(encmedia)
782 | await wait(media).then(res => {
783 | client.sendMessage(from, res.video, video, {quoted: mek, caption: res.teks.trim()})
784 | }).catch(err => {
785 | reply(err)
786 | })
787 | } else {
788 | reply('Foto aja mas')
789 | }
790 | break
791 | default:
792 | if (isGroup && isSimi && budy != undefined) {
793 | console.log(budy)
794 | muehe = await simih(budy)
795 | console.log(muehe)
796 | reply(muehe)
797 | } else {
798 | return //console.log(color('[WARN]','red'), 'Unregistered Command from', color(sender.split('@')[0]))
799 | }
800 | }
801 | } catch (e) {
802 | console.log('Error : %s', color(e, 'red'))
803 | }
804 | })
805 | }
806 | starts()
807 |
--------------------------------------------------------------------------------
/install.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/bash
2 |
3 | apt-get update
4 | apt-get upgrade
5 | apt-get install -y nodejs libwebp ffmpeg wget tesseract
6 | wget -O ~/../usr/share/tessdata/ind.traineddata "https://github.com/tesseract-ocr/tessdata/blob/master/ind.traineddata?raw=true"
7 | npm install
8 |
9 | echo "[*] All dependencies have been installed, please run the command \"npm start\" to immediately start the script"
10 |
--------------------------------------------------------------------------------
/lib/color.js:
--------------------------------------------------------------------------------
1 | const chalk = require('chalk')
2 |
3 | const color = (text, color) => {
4 | return !color ? chalk.green(text) : chalk.keyword(color)(text)
5 | }
6 |
7 | const bgcolor = (text, bgcolor) => {
8 | return !bgcolor ? chalk.green(text) : chalk.bgKeyword(bgcolor)(text)
9 | }
10 |
11 | module.exports = {
12 | color,
13 | bgcolor
14 | }
15 |
--------------------------------------------------------------------------------
/lib/fetcher.js:
--------------------------------------------------------------------------------
1 | const fetch = require('node-fetch')
2 | const fs = require('fs')
3 |
4 | exports.getBase64 = getBase64 = async (url) => {
5 | const response = await fetch(url, { headers: { 'User-Agent': 'okhttp/4.5.0' } });
6 | if (!response.ok) throw new Error(`unexpected response ${response.statusText}`);
7 | const buffer = await response.buffer();
8 | const videoBase64 = `data:${response.headers.get('content-type')};base64,` + buffer.toString('base64');
9 | if (buffer)
10 | return videoBase64;
11 | };
12 |
13 | exports.getBuffer = getBuffer = async (url) => {
14 | const res = await fetch(url, {headers: { 'User-Agent': 'okhttp/4.5.0'}, method: 'GET' })
15 | const anu = fs.readFileSync('./src/emror.jpg')
16 | if (!res.ok) return { type: 'image/jpeg', result: anu }
17 | const buff = await res.buffer()
18 | if (buff)
19 | return { type: res.headers.get('content-type'), result: buff }
20 | }
21 |
22 | exports.fetchJson = fetchJson = (url, options) => new Promise(async (resolve, reject) => {
23 | fetch(url, options)
24 | .then(response => response.json())
25 | .then(json => {
26 | // console.log(json)
27 | resolve(json)
28 | })
29 | .catch((err) => {
30 | reject(err)
31 | })
32 | })
33 |
34 |
35 | exports.fetchText = fetchText = (url, options) => new Promise(async (resolve, reject) => {
36 | fetch(url, options)
37 | .then(response => response.text())
38 | .then(text => {
39 | // console.log(text)
40 | resolve(text)
41 | })
42 | .catch((err) => {
43 | reject(err)
44 | })
45 | })
46 |
47 | //exports.getBase64 = getBase64;
48 |
--------------------------------------------------------------------------------
/lib/functions.js:
--------------------------------------------------------------------------------
1 | const fetch = require('node-fetch')
2 | const axios = require('axios')
3 | const cfonts = require('cfonts')
4 | const spin = require('spinnies')
5 | const Crypto = require('crypto')
6 |
7 | const wait = async (media) => new Promise(async (resolve, reject) => {
8 | const attachmentData = `data:image/jpeg;base64,${media.toString('base64')}`
9 | const response = await fetch("https://trace.moe/api/search",{method: "POST",body: JSON.stringify({ image: attachmentData }),headers: { "Content-Type": "application/json" }});
10 | if (!response.ok) reject(`Gambar tidak ditemukan!`);
11 | const result = await response.json()
12 | try {
13 | const { is_adult, title, title_chinese, title_romaji, title_english, episode, season, similarity, filename, at, tokenthumb, anilist_id } = result.docs[0]
14 | let belief = () => similarity < 0.89 ? "Saya memiliki keyakinan rendah dalam hal ini : " : ""
15 | let ecch = () => is_adult ? "Iya" : "Tidak"
16 | resolve({video: await getBuffer(`https://media.trace.moe/video/${anilist_id}/${encodeURIComponent(filename)}?t=${at}&token=${tokenthumb}`), teks: `${belief()}
17 | ~> Ecchi : *${ecch()}*
18 | ~> Judul Jepang : *${title}*
19 | ~> Ejaan Judul : *${title_romaji}*
20 | ~> Judul Inggris : *${title_english}*
21 | ~> Episode : *${episode}*
22 | ~> Season : *${season}*`});
23 | } catch (e) {
24 | console.log(e)
25 | reject(`Saya tidak tau ini anime apa`)
26 | }
27 | })
28 |
29 | const simih = async (text) => {
30 | try {
31 | const sami = await fetch(`https://secureapp.simsimi.com/v1/simsimi/talkset?uid=297971048&av=6.9.3.4&lc=id&cc=ID&tz=Asia%2FJakarta&os=a&ak=quS%2FxiW%2Bb8ys5agzpljUdoPdLH8%3D&message_sentence=${text}&normalProb=8&isFilter=1&talkCnt=1&talkCntTotal=1&reqFilter=1&session=nSt8PSSmKRbcR7quUkfhXYpmDYgErtBefVbkkri9CrGSVjm4Cj2e2zBFjvdxSijp56WjyK6g2EWTj3KxKz65DL22&triggerKeywords=%5B%5D`, {method: 'GET'})
32 | const res = await sami.json()
33 | return res.simsimi_talk_set.answers[0].sentence
34 | } catch {
35 | return 'Simi ga tau kak'
36 | }
37 | }
38 |
39 | const h2k = (number) => {
40 | var SI_POSTFIXES = ["", " K", " M", " G", " T", " P", " E"]
41 | var tier = Math.log10(Math.abs(number)) / 3 | 0
42 | if(tier == 0) return number
43 | var postfix = SI_POSTFIXES[tier]
44 | var scale = Math.pow(10, tier * 3)
45 | var scaled = number / scale
46 | var formatted = scaled.toFixed(1) + ''
47 | if (/\.0$/.test(formatted))
48 | formatted = formatted.substr(0, formatted.length - 2)
49 | return formatted + postfix
50 | }
51 |
52 | const getBuffer = async (url, options) => {
53 | try {
54 | options ? options : {}
55 | const res = await axios({
56 | method: "get",
57 | url,
58 | headers: {
59 | 'DNT': 1,
60 | 'Upgrade-Insecure-Request': 1
61 | },
62 | ...options,
63 | responseType: 'arraybuffer'
64 | })
65 | return res.data
66 | } catch (e) {
67 | console.log(`Error : ${e}`)
68 | }
69 | }
70 |
71 | const randomBytes = (length) => {
72 | return Crypto.randomBytes(length)
73 | }
74 |
75 | const generateMessageID = () => {
76 | return randomBytes(10).toString('hex').toUpperCase()
77 | }
78 |
79 | const getGroupAdmins = (participants) => {
80 | admins = []
81 | for (let i of participants) {
82 | i.isAdmin ? admins.push(i.jid) : ''
83 | }
84 | return admins
85 | }
86 |
87 | const getRandom = (ext) => {
88 | return `${Math.floor(Math.random() * 10000)}${ext}`
89 | }
90 |
91 | const spinner = {
92 | "interval": 120,
93 | "frames": [
94 | "🕐",
95 | "🕑",
96 | "🕒",
97 | "🕓",
98 | "🕔",
99 | "🕕",
100 | "🕖",
101 | "🕗",
102 | "🕘",
103 | "🕙",
104 | "🕚",
105 | "🕛"
106 | ]}
107 |
108 | let globalSpinner;
109 |
110 |
111 | const getGlobalSpinner = (disableSpins = false) => {
112 | if(!globalSpinner) globalSpinner = new spin({ color: 'blue', succeedColor: 'green', spinner, disableSpins});
113 | return globalSpinner;
114 | }
115 |
116 | spins = getGlobalSpinner(false)
117 |
118 | const start = (id, text) => {
119 | spins.add(id, {text: text})
120 | }
121 | const info = (id, text) => {
122 | spins.update(id, {text: text})
123 | }
124 | const success = (id, text) => {
125 | spins.succeed(id, {text: text})
126 |
127 | }
128 |
129 | const close = (id, text) => {
130 | spins.fail(id, {text: text})
131 | }
132 |
133 | const banner = cfonts.render(('TERMUX|WHATSAPP|BOT'), {
134 | font: 'chrome',
135 | color: 'candy',
136 | align: 'center',
137 | gradient: ["red","yellow"],
138 | lineHeight: 3
139 | });
140 |
141 |
142 | module.exports = { wait, simih, getBuffer, h2k, generateMessageID, getGroupAdmins, getRandom, start, info, success, banner, close }
143 |
--------------------------------------------------------------------------------
/lib/gtts.js:
--------------------------------------------------------------------------------
1 | const request = require('request');
2 | const escapeStringRegexp = require('escape-string-regexp');
3 | const async = require('async');
4 | const fs = require('fs');
5 | const MultiStream = require('multistream');
6 | const fakeUa = require('fake-useragent');
7 |
8 | const GOOGLE_TTS_URL = 'http://translate.google.com/translate_tts';
9 | const MAX_CHARS = 100;
10 | const LANGUAGES = {
11 | 'af': 'Afrikaans',
12 | 'sq': 'Albanian',
13 | 'ar': 'Arabic',
14 | 'hy': 'Armenian',
15 | 'ca': 'Catalan',
16 | 'zh': 'Chinese',
17 | 'zh-cn': 'Chinese (Mandarin/China)',
18 | 'zh-tw': 'Chinese (Mandarin/Taiwan)',
19 | 'zh-yue': 'Chinese (Cantonese)',
20 | 'hr': 'Croatian',
21 | 'cs': 'Czech',
22 | 'da': 'Danish',
23 | 'nl': 'Dutch',
24 | 'en': 'English',
25 | 'en-au': 'English (Australia)',
26 | 'en-uk': 'English (United Kingdom)',
27 | 'en-us': 'English (United States)',
28 | 'eo': 'Esperanto',
29 | 'fi': 'Finnish',
30 | 'fr': 'French',
31 | 'de': 'German',
32 | 'el': 'Greek',
33 | 'ht': 'Haitian Creole',
34 | 'hi': 'Hindi',
35 | 'hu': 'Hungarian',
36 | 'is': 'Icelandic',
37 | 'id': 'Indonesian',
38 | 'it': 'Italian',
39 | 'ja': 'Japanese',
40 | 'ko': 'Korean',
41 | 'la': 'Latin',
42 | 'lv': 'Latvian',
43 | 'mk': 'Macedonian',
44 | 'no': 'Norwegian',
45 | 'pl': 'Polish',
46 | 'pt': 'Portuguese',
47 | 'pt-br': 'Portuguese (Brazil)',
48 | 'ro': 'Romanian',
49 | 'ru': 'Russian',
50 | 'sr': 'Serbian',
51 | 'sk': 'Slovak',
52 | 'es': 'Spanish',
53 | 'es-es': 'Spanish (Spain)',
54 | 'es-us': 'Spanish (United States)',
55 | 'sw': 'Swahili',
56 | 'sv': 'Swedish',
57 | 'ta': 'Tamil',
58 | 'th': 'Thai',
59 | 'tr': 'Turkish',
60 | 'vi': 'Vietnamese',
61 | 'cy': 'Welsh'
62 | }
63 |
64 | function Text2Speech(_lang, _debug) {
65 | var lang = _lang || 'en';
66 | var debug = _debug || false;
67 | lang = lang.toLowerCase();
68 |
69 | if (!LANGUAGES[lang])
70 | throw new Error('Language not supported: ' + lang);
71 |
72 | var getArgs = getArgsFactory(lang);
73 |
74 | return {
75 | tokenize: tokenize,
76 | createServer: (port) => createServer(getArgs, port),
77 | stream: (text) => stream(getArgs, text),
78 | save: (filepath, text, callback) => save(getArgs, filepath, text, callback)
79 | }
80 | }
81 |
82 | function save(getArgs, filepath, text, callback) {
83 | var text_parts = tokenize(text);
84 | var total = text_parts.length;
85 | async.eachSeries(text_parts, function(part, cb) {
86 | var index = text_parts.indexOf(part);
87 | var headers = getHeader();
88 | var args = getArgs(part, index, total);
89 | var fullUrl = GOOGLE_TTS_URL + args;
90 |
91 | var writeStream = fs.createWriteStream(filepath, {
92 | flags: index > 0 ? 'a' : 'w'
93 | });
94 | request({
95 | uri: fullUrl,
96 | headers: headers,
97 | method: 'GET'
98 | })
99 | .pipe(writeStream);
100 | writeStream.on('finish', cb);
101 | writeStream.on('error', cb);
102 | }, callback);
103 | }
104 |
105 | function stream(getArgs, text) {
106 | var text_parts = tokenize(text);
107 | var total = text_parts.length;
108 |
109 | return MultiStream(text_parts.map(function(part, index) {
110 | var headers = getHeader();
111 | var args = getArgs(part, index, total);
112 | var fullUrl = GOOGLE_TTS_URL + args
113 |
114 | return request({
115 | uri: fullUrl,
116 | headers: headers,
117 | method: 'GET'
118 | });
119 | }));
120 | }
121 |
122 | function getHeader() {
123 | var headers = {
124 | "User-Agent": fakeUa()
125 | };
126 | //console.log('headers', headers);
127 | return headers;
128 | }
129 |
130 | function getArgsFactory(lang){
131 | return function (text, index, total) {
132 | var textlen = text.length;
133 | var encodedText = encodeURIComponent(text);
134 | var language = lang || 'en';
135 | return `?ie=UTF-8&tl=${language}&q=${encodedText}&total=${total}&idx=${index}&client=tw-ob&textlen=${textlen}`
136 | }
137 | }
138 |
139 | function tokenize(text) {
140 | var text_parts = [];
141 | if (!text)
142 | throw new Error('No text to speak');
143 |
144 | var punc = '¡!()[]¶;|°•—«»≤≥«»‹›\n ';
145 | var punc_list = punc.split('').map(function(char) {
146 | return escapeStringRegexp(char);
147 | });
148 |
149 | var pattern = punc_list.join('|');
150 | var parts = text.split(new RegExp(pattern));
151 | parts = parts.filter(p => p.length > 0);
152 |
153 | var output = [];
154 | var i = 0;
155 | for (let p of parts) {
156 | if (!output[i]) {
157 | output[i] = '';
158 | }
159 | if (output[i].length + p.length < MAX_CHARS) {
160 | output[i] += ' ' + p;
161 | } else {
162 | i++;
163 | output[i] = p;
164 | }
165 | }
166 | output[0] = output[0].substr(1);
167 | return output;
168 | }
169 |
170 | function createServer(getArgs, port) {
171 | var http = require("http");
172 | var url = require('url');
173 |
174 | var server = http.createServer(function(req, res) {
175 | var queryData = url.parse(req.url, true).query;
176 | var argsCallback = getArgs;
177 | if (queryData && queryData.lang && LANGUAGES[queryData.lang]) {
178 | argsCallback = getArgsFactory(queryData.lang);
179 | }
180 | if (queryData && queryData.text) {
181 | res.writeHead(200, {'Content-Type': 'audio/mpeg'});
182 | stream(argsCallback, queryData.text).pipe(res);
183 | } else {
184 | console.log(req.headers);
185 | res.writeHead(200, {'Content-Type': 'application/json'});
186 | res.end(JSON.stringify({
187 | code: -1,
188 | message: `Missing text. Please try: ${req.headers.host}?text=your+text`
189 | }))
190 | }
191 | });
192 |
193 | server.listen(port);
194 | console.log("Text-to-Speech Server running on " + port);
195 | }
196 |
197 | module.exports = Text2Speech;
198 |
--------------------------------------------------------------------------------
/lib/ocr.js:
--------------------------------------------------------------------------------
1 | const exec = require("child_process").exec
2 | const log = console.debug
3 |
4 | function recognize(filename, config = {}) {
5 | const options = getOptions(config)
6 | const binary = config.binary || "tesseract"
7 |
8 | const command = [binary, `"${filename}"`, "stdout", ...options].join(" ")
9 | if (config.debug) log("command", command)
10 |
11 | return new Promise((resolve, reject) => {
12 | exec(command, (error, stdout, stderr) => {
13 | if (config.debug) log(stderr)
14 | if (error) reject(error)
15 | resolve(stdout)
16 | })
17 | })
18 | }
19 |
20 | function getOptions(config) {
21 | const ocrOptions = ["tessdata-dir", "user-words", "user-patterns", "psm", "oem", "dpi"]
22 |
23 | return Object.entries(config)
24 | .map(([key, value]) => {
25 | if (["debug", "presets", "binary"].includes(key)) return
26 | if (key === "lang") return `-l ${value}`
27 | if (ocrOptions.includes(key)) return `--${key} ${value}`
28 |
29 | return `-c ${key}=${value}`
30 | })
31 | .concat(config.presets)
32 | .filter(Boolean)
33 | }
34 |
35 | module.exports = {
36 | recognize,
37 | }
38 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "termux-wabot",
3 | "version": "0.0.2",
4 | "description": "No comment",
5 | "main": "index.js",
6 | "directories": {
7 | "lib": "lib"
8 | },
9 | "scripts": {
10 | "test": "echo \"Error: no test specified\" && exit 1",
11 | "start": "node index.js"
12 | },
13 | "keywords": [
14 | "termux",
15 | "whatsapp",
16 | "bot",
17 | "whatsapp",
18 | "bot"
19 | ],
20 | "author": "MhankBarBar",
21 | "license": "ISC",
22 | "dependencies": {
23 | "@adiwajshing/baileys": "^3.4.1",
24 | "async": "^3.2.0",
25 | "axios": "^0.21.1",
26 | "cfonts": "^2.9.0",
27 | "escape-string-regexp": "^5.0.0",
28 | "fake-useragent": "^1.0.1",
29 | "file-type": "^16.2.0",
30 | "fluent-ffmpeg": "^2.1.2",
31 | "lolis.life": "^4.0.0",
32 | "moment-timezone": "^0.5.32",
33 | "multistream": "^4.0.1",
34 | "node-fetch": "^2.6.1",
35 | "remove.bg": "^1.3.0",
36 | "request": "^2.81.0",
37 | "spinnies": "^0.5.1",
38 | "tiktok-scraper": "^1.4.7"
39 | },
40 | "devDependencies": {},
41 | "repository": {
42 | "type": "git",
43 | "url": "git+https://github.com/mhankbarbar/termux-wabot.git"
44 | },
45 | "bugs": {
46 | "url": "https://github.com/mhankbarbar/termux-wabot/issues"
47 | },
48 | "homepage": "https://github.com/mhankbarbar/termux-wabot#readme"
49 | }
50 |
--------------------------------------------------------------------------------
/src/emror.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MhankBarBar/termux-wabot/107fb35e49592555790949be488f39dd5c2a16b6/src/emror.jpg
--------------------------------------------------------------------------------
/src/emror.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MhankBarBar/termux-wabot/107fb35e49592555790949be488f39dd5c2a16b6/src/emror.mp4
--------------------------------------------------------------------------------
/src/help.js:
--------------------------------------------------------------------------------
1 | const help = (prefix) => {
2 | return `> *Sticker Commands* <
3 | command : *${prefix}sticker* or *${prefix}stiker*
4 | desc : convert image/gif/video to sticker
5 | usage : reply image/gif/video, or send image/gif/video with caption\n
6 | command : *${prefix}sticker nobg* or *${prefix}stiker nobg*
7 | desc : convert image to sticker while removing the background
8 | usage : reply image, or send image with caption\n
9 | command : *${prefix}toimg*
10 | desc : convert sticker to image
11 | usage : reply sticker\n
12 | command : *${prefix}tsticker* or *${prefix}tstiker*
13 | desc : convert text to sticker
14 | usage : *${prefix}tsticker text in here*\n
15 | > *Meme Commands* <
16 | command : *${prefix}meme*
17 | desc : random meme images [english]
18 | usage : just send the command\n
19 | > *Others Commands* <
20 | command : *${prefix}tp*
21 | desc : Text / Logo maker from textpro.me
22 | usage : *${prefix}tp [no] [text]*\nexample : *${prefix}tp 1 YourText*
23 | note : *${prefix}tp list* ( for show all theme )\n
24 | command : *${prefix}ep*
25 | desc : Text / Logo maker from ephoto360.com
26 | usage : *${prefix}ep [no] [text]*\nexample : *${prefix}ep 1 YourText*
27 | note : *${prefix}ep list* ( for show all theme )\n
28 | command : *${prefix}tahta*
29 | desc : Harta Tahta .....
30 | usage : *${prefix}tahta [text]*\nexample : *${prefix}tahta YourText*\n
31 | command : *${prefix}gtts*
32 | desc : convert text to speech/audio
33 | usage : *${prefix}gtts [cc] [text]*\nexample : *${prefix}gtts ja On2-chan*\n
34 | command : *${prefix}loli*
35 | desc : random loli images
36 | usage : just send the command\n
37 | command : *${prefix}nsfwloli*
38 | desc : random nsfw loli images
39 | usage : just send the command\n
40 | command : *${prefix}url2img*
41 | desc : take web screenshots
42 | usage : *${prefix}url2img [tipe] [url]*\n
43 | command : *${prefix}simi*
44 | desc : your message will be replied to by simi
45 | usage : *${prefix}simi yourmessage*\n
46 | command : *${prefix}ocr*
47 | desc : take the text in the picture
48 | usage : reply image, or send image with caption\n
49 | command : *${prefix}wait*
50 | desc : search anime with image [ What Anime Is This/That ]
51 | usage : reply image, or send image with caption\n
52 | command : *${prefix}setprefix*
53 | desc : replace prefix
54 | usage : *${prefix}setprefix [text|optional]*\nexample : *${prefix}setprefix ?*
55 | note : This command can only be used by the bot owner\n
56 | > *Group Comands* <
57 | command : *${prefix}add*
58 | desc : add member into group
59 | usage : *${prefix}add 62813xxxxx*\n
60 | note : can only be used when the bot becomes admin, and the one who sends the command is admin!\n
61 | command : *${prefix}kick*
62 | desc : kick members from group
63 | usage : *${prefix}kick @tagmember*\n
64 | note : can only be used when the bot becomes admin, and the one who sends the command is admin!\n
65 | command : *${prefix}promote*
66 | desc : make the group member as group admin
67 | usage : *${prefix}promote @tagmember*\n
68 | note : can only be used when the bot becomes admin, and the one who sends the command is admin!\n
69 | command : *${prefix}demote*
70 | desc : make the group admin as group member
71 | usage : *${prefix}demote @tagmember*\n
72 | note : can only be used when the bot becomes admin, and the one who sends the command is admin!\n
73 | command : *${prefix}linkgroup*
74 | desc : take the group link
75 | usage : just send the command
76 | note : can only be used when the bot becomes admin, and the one who sends the command is admin!\n
77 | command : *${prefix}leave*
78 | desc : Make bot leave the group
79 | usage : just send the command
80 | note : Can only be used by Group admins and Bot owner\n
81 | command : *${prefix}tagall*
82 | desc : tags all group members including admins too
83 | usage : just send the command
84 | note : This command can be used if you are a group admin\n
85 | command : *${prefix}simih*
86 | desc : activate simi mode in the group
87 | usage : *${prefix}simih 1* to activate simi mode and *${prefix}simih 0* to deactivate simi mode
88 | note : This command can be used if you are a group admin\n`
89 | }
90 |
91 | exports.help = help
92 |
--------------------------------------------------------------------------------
/src/nsfw.json:
--------------------------------------------------------------------------------
1 | []
2 |
--------------------------------------------------------------------------------
/src/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "prefix": ".",
3 | "ownerNumber": "6285892766102",
4 | "apiKey": "YourApiKey"
5 | }
6 |
--------------------------------------------------------------------------------
/src/simi.json:
--------------------------------------------------------------------------------
1 | []
2 |
--------------------------------------------------------------------------------
/src/stickers/.keep:
--------------------------------------------------------------------------------
1 | []
2 |
--------------------------------------------------------------------------------
/src/stickers/mekih.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MhankBarBar/termux-wabot/107fb35e49592555790949be488f39dd5c2a16b6/src/stickers/mekih.txt
--------------------------------------------------------------------------------
/src/welkom.json:
--------------------------------------------------------------------------------
1 | []
2 |
--------------------------------------------------------------------------------