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);