| 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 storeSys from './lib/store2.js' |
| const store = storeSys.makeInMemoryStore() |
| const { |
| useMultiFileAuthState, |
| |
| 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.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 |
| 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, |
| |
| patchMessageBeforeSending: (message) => { |
| const requiresPatch = !!( |
| message.buttonsMessage |
| || message.templateMessage |
| || message.listMessage |
| ); |
| if (requiresPatch) { |
| message = { |
| viewOnceMessage: { |
| message: { |
| messageContextInfo: { |
| deviceListMetadataVersion: 2, |
| deviceListMetadata: {}, |
| }, |
| ...message, |
| }, |
| }, |
| }; |
| } |
|
|
| return message; |
| }, |
| defaultQueryTimeoutMs: undefined, |
| } |
| global.conn = makeWASocket(connectionOptions) |
| conn.isInit = false |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| if (!opts['test']) { |
| (await import('./server.js')).default(PORT) |
| setInterval(async () => { |
| if (global.db.data) await global.db.write().catch(console.error) |
| |
| clearTmp() |
| |
| }, 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) |
| 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 |
| } |
| |
| 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*. |
| `; |
| |
| |
| |
| |
| |
| |
| 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 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(); |
|
|
| |
| 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); |