| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | const { |
| | default: makeWASocket, |
| | useMultiFileAuthState, |
| | fetchLatestBaileysVersion, |
| | Browsers, |
| | delay, |
| | DisconnectReason |
| | } = require('@whiskeysockets/baileys'); |
| | const pino = require('pino'); |
| | const path = require('path'); |
| | const fs = require('fs'); |
| |
|
| | |
| | |
| | |
| | |
| | function smartRequire(moduleName) { |
| | try { |
| | return require(`./${moduleName}`); |
| | } catch (e) { |
| | try { |
| | return require(`./modules/${moduleName}`); |
| | } catch (e2) { |
| | console.error(`β [BotCore] Erro ao carregar componente: ${moduleName}`); |
| | return null; |
| | } |
| | } |
| | } |
| |
|
| | |
| | const HFCorrections = smartRequire('HFCorrections'); |
| | const ConfigManager = smartRequire('ConfigManager'); |
| | const APIClient = smartRequire('APIClient'); |
| | const AudioProcessor = smartRequire('AudioProcessor'); |
| | const MediaProcessor = smartRequire('MediaProcessor'); |
| | const MessageProcessor = smartRequire('MessageProcessor'); |
| | const ModerationSystem = smartRequire('ModerationSystem'); |
| | const LevelSystem = smartRequire('LevelSystem'); |
| | const CommandHandler = smartRequire('CommandHandler'); |
| |
|
| | class BotCore { |
| | constructor() { |
| | this.config = ConfigManager ? ConfigManager.getInstance() : {}; |
| | this.logger = pino({ level: 'silent' }); |
| | this.sock = null; |
| | this.state = null; |
| | this.saveCreds = null; |
| | this.currentQR = null; |
| | this.isConnected = false; |
| | this.reconnectAttempts = 0; |
| | this.maxReconnectAttempts = 15; |
| |
|
| | |
| | this.apiClient = APIClient ? new APIClient() : null; |
| | this.moderation = ModerationSystem ? new ModerationSystem() : null; |
| | this.levels = LevelSystem ? new LevelSystem() : null; |
| | this.audioProcessor = AudioProcessor ? new AudioProcessor() : null; |
| | this.mediaProcessor = MediaProcessor ? new MediaProcessor() : null; |
| | this.commandHandler = null; |
| | } |
| |
|
| | |
| | |
| | |
| | async initialize() { |
| | console.log('π Preparando diretΓ³rios de sistema...'); |
| | const folders = ['auth_info', 'temp', '/tmp/akira_data']; |
| | folders.forEach(f => { |
| | if (!fs.existsSync(f)) fs.mkdirSync(f, { recursive: true }); |
| | }); |
| | return true; |
| | } |
| |
|
| | |
| | |
| | |
| | async connect() { |
| | try { |
| | console.log('π§ Configurando credenciais de autenticaΓ§Γ£o...'); |
| | const { state, saveCreds } = await useMultiFileAuthState(path.join(__dirname, 'auth_info')); |
| | this.state = state; |
| | this.saveCreds = saveCreds; |
| |
|
| | const { version } = await fetchLatestBaileysVersion(); |
| | console.log(`π‘ Baileys Version: ${version.join('.')}`); |
| |
|
| | |
| | |
| | |
| | this.sock = makeWASocket({ |
| | version, |
| | logger: this.logger, |
| | printQRInTerminal: true, |
| | auth: this.state, |
| | browser: Browsers.ubuntu('Chrome'), |
| | |
| | |
| | agent: HFCorrections ? HFCorrections.createHFAgent() : undefined, |
| | socketConfig: HFCorrections ? HFCorrections.createWebSocketOptions() : {}, |
| | |
| | |
| | connectTimeoutMs: 60000, |
| | defaultQueryTimeoutMs: 0, |
| | keepAliveIntervalMs: 30000, |
| | |
| | |
| | getNextIp: (host) => { |
| | const ip = HFCorrections ? HFCorrections.getWhatsAppIP() : undefined; |
| | return ip; |
| | } |
| | }); |
| |
|
| | |
| | if (CommandHandler) { |
| | this.commandHandler = new CommandHandler(this, this.sock); |
| | } |
| |
|
| | |
| |
|
| | this.sock.ev.on('creds.update', this.saveCreds); |
| |
|
| | this.sock.ev.on('connection.update', async (update) => { |
| | const { connection, lastDisconnect, qr } = update; |
| |
|
| | if (qr) { |
| | this.currentQR = qr; |
| | console.log('β¨ [QR CODE] Novo cΓ³digo disponΓvel na Web UI.'); |
| | } |
| |
|
| | if (connection === 'close') { |
| | this.isConnected = false; |
| | const statusCode = (lastDisconnect?.error)?.output?.statusCode; |
| | const shouldReconnect = statusCode !== DisconnectReason.loggedOut; |
| | |
| | console.log(`β οΈ ConexΓ£o encerrada. Motivo: ${lastDisconnect?.error?.message || 'Desconhecido'}`); |
| | |
| | if (shouldReconnect && this.reconnectAttempts < this.maxReconnectAttempts) { |
| | this.reconnectAttempts++; |
| | const backoff = Math.min(this.reconnectAttempts * 5000, 45000); |
| | console.log(`π Tentando reconexΓ£o em ${backoff/1000}s...`); |
| | setTimeout(() => this.connect(), backoff); |
| | } else if (statusCode === DisconnectReason.loggedOut) { |
| | console.error('β SessΓ£o encerrada permanentemente. Apague a pasta auth_info.'); |
| | } |
| | } |
| |
|
| | if (connection === 'open') { |
| | this.isConnected = true; |
| | this.reconnectAttempts = 0; |
| | this.currentQR = null; |
| | console.log('π AKIRA BOT CONECTADO COM SUCESSO!'); |
| | } |
| | }); |
| |
|
| | |
| | this.sock.ev.on('messages.upsert', async (chatUpdate) => { |
| | try { |
| | const m = chatUpdate.messages[0]; |
| | if (!m.message || m.key.fromMe) return; |
| |
|
| | if (MessageProcessor) { |
| | const processor = new MessageProcessor(this, this.sock); |
| | await processor.handle(m); |
| | } |
| | } catch (err) { |
| | console.error('β Erro ao processar mensagem recebida:', err.message); |
| | } |
| | }); |
| |
|
| | } catch (error) { |
| | console.error('β Falha crΓtica no BotCore:', error); |
| | throw error; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | getStatus() { |
| | return { |
| | isConnected: this.isConnected, |
| | reconnectAttempts: this.reconnectAttempts, |
| | botName: this.config.BOT_NAME || 'Akira Bot' |
| | }; |
| | } |
| |
|
| | getQRCode() { |
| | return this.currentQR; |
| | } |
| |
|
| | |
| | |
| | |
| | async sendMessage(jid, content, options = {}) { |
| | try { |
| | if (!this.isConnected || !this.sock) return false; |
| | return await this.sock.sendMessage(jid, content, options); |
| | } catch (err) { |
| | console.error(`β Falha no envio para ${jid}:`, err.message); |
| | return false; |
| | } |
| | } |
| | } |
| |
|
| | module.exports = BotCore; |