Download main.js from RamaZyx/StableBOT: direct link, hf CLI and curl.
- Browser
- Download file 13.2 kB
-
https://huggingface.co/RamaZyx/StableBOT/resolve/main/main.js
- Command line
-
hf download hf://RamaZyx/StableBOT/main.js
-
curl -L -o main.js https://huggingface.co/RamaZyx/StableBOT/resolve/main/main.js
13.2 kB
| import './config.js' | |
| import path, { join } from 'path' | |
| import { platform } from 'process' | |
| import chalk from 'chalk' | |
| import { fileURLToPath, pathToFileURL } from 'url' | |
| import logg from 'pino' | |
| import { createRequire } from 'module' | |
| global.__filename = function filename(pathURL = import.meta.url, rmPrefix = platform !== 'win32') { return rmPrefix ? /file:\/\/\//.test(pathURL) ? fileURLToPath(pathURL) : pathURL : pathToFileURL(pathURL).toString() }; global.__dirname = function dirname(pathURL) { return path.dirname(global.__filename(pathURL, true)) }; global.__require = function require(dir = import.meta.url) { return createRequire(dir) } | |
| import * as ws from 'ws' | |
| import { | |
| readdirSync, | |
| statSync, | |
| unlinkSync, | |
| existsSync, | |
| readFileSync, | |
| watch | |
| } from 'fs' | |
| import yargs from 'yargs' | |
| import { spawn } from 'child_process' | |
| import lodash from 'lodash' | |
| import { pino | |
| } from "pino" | |
| import readline from "readline" | |
| import syntaxerror from 'syntax-error' | |
| import { tmpdir } from 'os' | |
| import { format } from 'util' | |
| import { | |
| makeWASocket, | |
| protoType, | |
| serialize | |
| } from './lib/simple.js'; | |
| import { Low } from 'lowdb'; | |
| import { JSONFile } from "lowdb" | |
| /* import { | |
| mongoDB, | |
| mongoDBV2 | |
| } from './lib/mongoDB.js' */ | |
| import storeSys from './lib/store2.js' | |
| const store = storeSys.makeInMemoryStore() | |
| const { | |
| useMultiFileAuthState, | |
| // useSingleFileAuthState, | |
| DisconnectReason | |
| } = await import('@adiwajshing/baileys') | |
| const { CONNECTING } = ws | |
| const { chain } = lodash | |
| const PORT = process.env.PORT || process.env.SERVER_PORT || 3000 | |
| protoType() | |
| serialize() | |
| global.API = (name, path = '/', query = {}, apikeyqueryname) => (name in global.APIs ? global.APIs[name] : name) + path + (query || apikeyqueryname ? '?' + new URLSearchParams(Object.entries({ ...query, ...(apikeyqueryname ? { [apikeyqueryname]: global.APIKeys[name in global.APIs ? global.APIs[name] : name] } : {}) })) : '') | |
| // global.Fn = function functionCallBack(fn, ...args) { return fn.call(global.conn, ...args) } | |
| global.timestamp = { | |
| start: new Date | |
| } | |
| const __dirname = global.__dirname(import.meta.url) | |
| global.opts = new Object(yargs(process.argv.slice(2)).exitProcess(false).parse()) | |
| global.prefix = new RegExp('^[' + (opts['prefix'] || `/.`) + ']') | |
| global.db = new Low(/https?:\/\//.test(opts['db'] || '') ? new cloudDBAdapter(opts['db']) : new JSONFile(`${opts._[0] ? opts._[0] + '_' : ''}database.json`)) | |
| global.DATABASE = global.db // Backwards Compatibility | |
| global.loadDatabase = async function loadDatabase() { | |
| if (global.db.READ) return new Promise((resolve) => setInterval(async function () { | |
| if (!global.db.READ) { | |
| clearInterval(this) | |
| resolve(global.db.data == null ? await global.loadDatabase() : global.db.data) | |
| } | |
| }, 1 * 1000)) | |
| if (global.db.data !== null) return | |
| global.db.READ = true | |
| await global.db.read().catch(console.error) | |
| global.db.READ = null | |
| global.db.data = { | |
| users: {}, | |
| chats: {}, | |
| stats: {}, | |
| msgs: {}, | |
| sticker: {}, | |
| settings: {}, | |
| ...(global.db.data || {}) | |
| } | |
| global.db.chain = chain(global.db.data) | |
| } | |
| loadDatabase() | |
| global.authFolder = storeSys.fixFileName(`${opts._[0] || ''}sessions`) | |
| let { state, saveCreds } = await useMultiFileAuthState(path.resolve('./sessions')) | |
| const question = (text) => { | |
| const rl = readline.createInterface({ | |
| input: process.stdin, | |
| output: process.stdout | |
| }); | |
| return new Promise((resolve) => { | |
| rl.question(text, resolve) | |
| }) | |
| }; | |
| const connectionOptions = { | |
| printQRInTerminal: true, | |
| auth: state, | |
| defaultQueryTimeoutMs: undefined, | |
| downloadHistory: false, | |
| version: [2, 2318, 11], | |
| getMessage: async (key) => (store.loadMessage(key.remoteJid, key.id) || store.loadMessage(key.id) || {}).message, | |
| // get message diatas untuk mengatasi pesan gagal dikirim, "menunggu pesan", dapat dicoba lagi | |
| patchMessageBeforeSending: (message) => { | |
| const requiresPatch = !!( | |
| message.buttonsMessage | |
| || message.templateMessage | |
| || message.listMessage | |
| ); | |
| if (requiresPatch) { | |
| message = { | |
| viewOnceMessage: { | |
| message: { | |
| messageContextInfo: { | |
| deviceListMetadataVersion: 2, | |
| deviceListMetadata: {}, | |
| }, | |
| ...message, | |
| }, | |
| }, | |
| }; | |
| } | |
| return message; | |
| }, | |
| defaultQueryTimeoutMs: undefined, // for this issues https://github.com/adiwajshing/Baileys/issues/276 | |
| } | |
| global.conn = makeWASocket(connectionOptions) | |
| conn.isInit = false | |
| /*const usePairingCode = true | |
| const connectionOptions = { | |
| logger: pino({ level: "silent" }), | |
| printQRInTerminal: !usePairingCode, | |
| auth: state, | |
| browser: ['Chrome (Linux)', '', ''] | |
| } | |
| if(usePairingCode && !conn.authState.creds.registered) { | |
| const phoneNumber = "62838726142300" | |
| const code = await conn.requestPairingCode(phoneNumber.trim()) | |
| console.log(`Pairing code: ${code}`) | |
| }*/ | |
| if (!opts['test']) { | |
| (await import('./server.js')).default(PORT) | |
| setInterval(async () => { | |
| if (global.db.data) await global.db.write().catch(console.error) | |
| // if (opts['autocleartmp']) try { | |
| clearTmp() | |
| // } catch (e) { console.error(e) } | |
| }, 60 * 1000) | |
| } | |
| function clearTmp() { | |
| const tmp = [tmpdir(), join(__dirname, './tmp')] | |
| const filename = [] | |
| tmp.forEach(dirname => readdirSync(dirname).forEach(file => filename.push(join(dirname, file)))) | |
| return filename.map(file => { | |
| const stats = statSync(file) | |
| if (stats.isFile() && (Date.now() - stats.mtimeMs >= 1000 * 60 * 3)) return unlinkSync(file) // 3 minutes | |
| return false | |
| }) | |
| } | |
| async function connectionUpdate(update) { | |
| const { connection, lastDisconnect, isNewLogin } = update | |
| if (isNewLogin) conn.isInit = true | |
| const code = lastDisconnect?.error?.output?.statusCode || lastDisconnect?.error?.output?.payload?.statusCode | |
| if (code && code !== DisconnectReason.loggedOut && conn?.ws.readyState !== ws.default.CONNECTING) { | |
| console.log(await global.reloadHandler(true).catch(console.error)) | |
| global.timestamp.connect = new Date | |
| } | |
| // console.log(JSON.stringify(update, null, 4)) | |
| if (global.db.data == null) loadDatabase() | |
| if (connection === "open") { | |
| const { | |
| jid, | |
| name | |
| } = conn.user; | |
| const currentTime = new Date(); | |
| const pingStart = new Date(); | |
| const infoMsg = ` | |
| *Bot Info:* | |
| ✓ Name: ${name || 'Cherly-MD'} | |
| ✓ Tag: @${jid.split('@')[0]} | |
| ✓ Speed ping: ${pingStart - new Date()}ms | |
| ✓ Date: ${currentTime.toDateString()} | |
| ✓ Hours: ${currentTime.toLocaleTimeString()} | |
| ✓ Day: ${currentTime.toLocaleDateString('en-US', { weekday: 'long' })} | |
| ✓ Description: *lapor owner jika ada bug*. | |
| `; | |
| /*conn.sendMessage(nomorown + "@s.whatsapp.net", { | |
| text: infoMsg, | |
| mentions: [nomorown + "@s.whatsapp.net", jid] | |
| }, { | |
| quoted: null | |
| })*/ | |
| chalk.yellow('R E A D Y'); | |
| } | |
| if (connection == 'close') { | |
| console.log(chalk.yellow(`🚩ㅤConnection closed, please delete the folder sessions and rescan the QR code`)); | |
| } | |
| } | |
| process.on('uncaughtException', console.error) | |
| // let strQuot = /(["'])(?:(?=(\\?))\2.)*?\1/ | |
| let isInit = true; | |
| let handler = await import('./handler.js'); | |
| global.reloadHandler = async function(restatConn) { | |
| try { | |
| const Handler = await import(`./handler.js?update=${Date.now()}`).catch(console.error); | |
| if (Object.keys(Handler || {}).length) handler = Handler; | |
| } catch (error) { | |
| console.error; | |
| } | |
| if (restatConn) { | |
| const oldChats = global.conn.chats; | |
| try { | |
| global.conn.ws.close(); | |
| } catch {} | |
| conn.ev.removeAllListeners(); | |
| global.conn = makeWASocket(connectionOptions, { | |
| chats: oldChats | |
| }); | |
| isInit = true; | |
| } | |
| if (!isInit) { | |
| conn.ev.off('messages.upsert', conn.handler) | |
| conn.ev.off('group-participants.update', conn.participantsUpdate) | |
| conn.ev.off('message.delete', conn.onDelete) | |
| conn.ev.off('connection.update', conn.connectionUpdate) | |
| conn.ev.off('creds.update', conn.credsUpdate) | |
| } | |
| conn.welcome = 'Hai, @user!\nWelcome to @subject\n\n@desc' | |
| conn.bye = 'Sayonara @user!' | |
| conn.spromote = '@user Menjadi Admin!' | |
| conn.sdemote = '@user Bukan Admin Lagi' | |
| conn.handler = handler.handler.bind(global.conn) | |
| conn.participantsUpdate = handler.participantsUpdate.bind(global.conn) | |
| conn.onDelete = handler.deleteUpdate.bind(global.conn) | |
| conn.connectionUpdate = connectionUpdate.bind(global.conn) | |
| conn.credsUpdate = saveCreds.bind(global.conn) | |
| const currentDateTime = new Date(); | |
| const messageDateTime = new Date(conn.ev); | |
| if (currentDateTime >= messageDateTime) { | |
| const chats = Object.entries(conn.chats).filter(([jid, chat]) => !jid.endsWith('@g.us') && chat.isChats).map((v) => v[0]); | |
| } else { | |
| const chats = Object.entries(conn.chats).filter(([jid, chat]) => !jid.endsWith('@g.us') && chat.isChats).map((v) => v[0]); | |
| } | |
| conn.ev.on('messages.upsert', conn.handler) | |
| conn.ev.on('group-participants.update', conn.participantsUpdate) | |
| conn.ev.on('message.delete', conn.onDelete) | |
| conn.ev.on('connection.update', conn.connectionUpdate) | |
| conn.ev.on('creds.update', conn.credsUpdate) | |
| isInit = false | |
| return true | |
| } | |
| const pluginFolder = global.__dirname(join(__dirname, './plugins/index')); | |
| const pluginFilter = (filename) => /\.js$/.test(filename); | |
| global.plugins = {}; | |
| async function filesInit() { | |
| for (const filename of readdirSync(pluginFolder).filter(pluginFilter)) { | |
| try { | |
| const file = global.__filename(join(pluginFolder, filename)); | |
| const module = await import(file); | |
| global.plugins[filename] = module.default || module; | |
| } catch (e) { | |
| conn.logger.error(e); | |
| delete global.plugins[filename]; | |
| } | |
| } | |
| } | |
| filesInit().then((_) => Object.keys(global.plugins)).catch(console.error); | |
| global.reload = async (_ev, filename) => { | |
| if (pluginFilter(filename)) { | |
| const dir = global.__filename(join(pluginFolder, filename), true); | |
| if (filename in global.plugins) { | |
| if (existsSync(dir)) conn.logger.info(` Updated Plugin - '${filename}'`); | |
| else { | |
| conn.logger.warn(`Deleted Plugin - '${filename}'`); | |
| return delete global.plugins[filename]; | |
| } | |
| } else conn.logger.info(`New Plugin - '${filename}'`); | |
| const err = syntaxerror(readFileSync(dir), filename, { | |
| sourceType: 'module', | |
| allowAwaitOutsideFunction: true, | |
| }); | |
| if (err) conn.logger.error(`syntax error while loading '${filename}'\n${format(err)}`); | |
| else { | |
| try { | |
| const module = (await import(`${global.__filename(dir)}?update=${Date.now()}`)); | |
| global.plugins[filename] = module.default || module; | |
| } catch (e) { | |
| conn.logger.error(`error require plugin '${filename}\n${format(e)}'`); | |
| } finally { | |
| global.plugins = Object.fromEntries(Object.entries(global.plugins).sort(([a], [b]) => a.localeCompare(b))); | |
| } | |
| } | |
| } | |
| }; | |
| Object.freeze(global.reload); | |
| watch(pluginFolder, global.reload); | |
| await global.reloadHandler(); | |
| /* QuickTest */ | |
| async function _quickTest() { | |
| const test = await Promise.all([ | |
| spawn('ffmpeg'), | |
| spawn('ffprobe'), | |
| spawn('ffmpeg', ['-hide_banner', '-loglevel', 'error', '-filter_complex', 'color', '-frames:v', '1', '-f', 'webp', '-']), | |
| spawn('convert'), | |
| spawn('magick'), | |
| spawn('gm'), | |
| spawn('find', ['--version']), | |
| ].map((p) => { | |
| return Promise.race([ | |
| new Promise((resolve) => { | |
| p.on('close', (code) => { | |
| resolve(code !== 127); | |
| }); | |
| }), | |
| new Promise((resolve) => { | |
| p.on('error', (_) => resolve(false)); | |
| }) | |
| ]); | |
| })); | |
| const [ffmpeg, ffprobe, ffmpegWebp, convert, magick, gm, find] = test; | |
| const s = global.support = { | |
| ffmpeg, | |
| ffprobe, | |
| ffmpegWebp, | |
| convert, | |
| magick, | |
| gm, | |
| find | |
| }; | |
| Object.freeze(global.support); | |
| } | |
| setInterval(async () => { | |
| if (!conn || !conn.user) return; | |
| await clearTmp(); | |
| console.log(chalk.cyanBright( | |
| ` H A P P Y T O U S E ` | |
| )); | |
| }, 60 * 60 * 1000); | |
| function clockString(ms) { | |
| const d = isNaN(ms) ? '--' : Math.floor(ms / 86400000); | |
| const h = isNaN(ms) ? '--' : Math.floor(ms / 3600000) % 24; | |
| const m = isNaN(ms) ? '--' : Math.floor(ms / 60000) % 60; | |
| const s = isNaN(ms) ? '--' : Math.floor(ms / 1000) % 60; | |
| return [d, ' Day ', h, ' hours ', m, ' Minutes ', s, ' Second '].map((v) => v.toString().padStart(2, '0')).join(''); | |
| } | |
| _quickTest().catch(console.error); |