Spaces:
Build error
Build error
File size: 6,675 Bytes
6598bed cab9cad 6598bed cab9cad 96d1924 6598bed cab9cad 6598bed 96d1924 cab9cad 6598bed 96d1924 6598bed 96d1924 6598bed 96d1924 6598bed 96d1924 cab9cad 6598bed 3076e7e 6598bed e7b6c41 6598bed 3076e7e 6598bed 0094678 6598bed 0094678 6598bed 0094678 6598bed 0094678 6598bed 0094678 3076e7e 6598bed 96d1924 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | // ===============================================================
// AKIRA BOT — JID/LID unify + Session fix + Reply PV/Group logic
// ===============================================================
const {
default: makeWASocket,
useMultiFileAuthState,
fetchLatestBaileysVersion,
Browsers,
delay
} = require('@whiskeysockets/baileys');
const pino = require('pino');
const axios = require('axios');
const express = require('express');
const qrcode = require('qrcode-terminal');
const logger = pino({ level: 'info' });
const AKIRA_API_URL = 'https://akra35567-akira.hf.space/api/akira';
const PORT = process.env.PORT || 3000;
let sock;
let BOT_JID = null;
let lastProcessedTime = 0;
// ===============================================================
// 🔧 UTILITÁRIOS
// ===============================================================
function extractNumber(input = '') {
if (!input) return 'desconhecido';
const clean = input.toString();
const match = clean.match(/2449\d{8}/);
if (match) return match[0];
const local = clean.match(/9\d{8}/);
if (local) return `244${local[0]}`;
return clean.replace(/\D/g, '').slice(-12);
}
function normalizeJid(jid = '') {
if (!jid) return null;
jid = jid.toString().trim();
// remove lixo e sufixos
jid = jid.replace(/[:@].*/g, '');
if (jid.startsWith('37') || jid.startsWith('202') || jid.length < 9)
return BOT_JID || '244952786417@s.whatsapp.net';
if (!jid.startsWith('244') && /^9\d{8}$/.test(jid))
jid = '244' + jid;
return `${jid}@s.whatsapp.net`;
}
function isBotJid(jid) {
const norm = normalizeJid(jid);
return norm === normalizeJid(BOT_JID);
}
// ===============================================================
// ⚙️ CONEXÃO
// ===============================================================
async function connect() {
const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys');
const { version } = await fetchLatestBaileysVersion();
sock = makeWASocket({
version,
auth: state,
logger,
browser: Browsers.macOS('Desktop'),
markOnlineOnConnect: true,
syncFullHistory: false,
connectTimeoutMs: 60000
});
sock.ev.on('creds.update', saveCreds);
sock.ev.on('connection.update', async (update) => {
const { connection, qr } = update;
if (qr) {
qrcode.generate(qr, { small: true });
console.log('\n📱 ESCANEIE O QR PARA CONECTAR\n');
}
if (connection === 'open') {
BOT_JID = normalizeJid(sock.user.id);
console.log('✅ AKIRA BOT ONLINE!');
console.log('botJid detectado:', BOT_JID);
lastProcessedTime = Date.now();
}
if (connection === 'close') {
console.log('⚠️ Conexão perdida. Tentando reconectar...');
setTimeout(connect, 5000);
}
});
// ===============================================================
// 💬 MENSAGENS
// ===============================================================
sock.ev.on('messages.upsert', async (m) => {
const msg = m.messages[0];
if (!msg.message || msg.key.fromMe) return;
const from = msg.key.remoteJid;
const isGroup = from.endsWith('@g.us');
if (msg.messageTimestamp && msg.messageTimestamp * 1000 < lastProcessedTime - 10000) return;
// Extração inteligente do número real
let sender = msg.key.participant || msg.participant || msg.key.remoteJid;
const pn = msg.message?.participantPn || msg.message?.senderPn;
const lid = msg.key.senderLid || msg.participantLid || msg.message?.senderLid;
const possible = pn || lid || sender;
const senderNumber = extractNumber(possible);
const nome = msg.pushName || senderNumber;
const text =
msg.message.conversation ||
msg.message.extendedTextMessage?.text ||
msg.message?.imageMessage?.caption ||
msg.message?.videoMessage?.caption ||
'';
if (!text.trim()) return;
console.log(`\n[MENSAGEM] ${isGroup ? 'GRUPO' : 'PV'} | ${nome} (${senderNumber}): ${text}`);
const ativar = await shouldActivate(msg, isGroup, text);
if (!ativar) {
console.log('[IGNORADO] Não ativado para responder (não reply ou não menção).');
return;
}
await sock.sendPresenceUpdate('composing', from);
try {
const res = await axios.post(AKIRA_API_URL, {
usuario: nome,
mensagem: text,
numero: senderNumber
});
const resposta = res.data.resposta || '...';
console.log(`[RESPOSTA] ${resposta}`);
await delay(Math.min(resposta.length * 50, 4000));
await sock.sendPresenceUpdate('paused', from);
await sock.sendMessage(from, { text: resposta }, { quoted: msg });
} catch (err) {
console.error('⚠️ Erro na API:', err.message);
await sock.sendMessage(from, { text: 'Erro interno. 😴' }, { quoted: msg });
}
});
// ===============================================================
// 🧰 REGENERAÇÃO DE SESSÃO
// ===============================================================
sock.ev.on('message-decrypt-failed', async (msgKey) => {
console.log('⚠️ Tentando regenerar sessão perdida...');
try {
await sock.sendRetryRequest(msgKey.key);
} catch (e) {
console.log('❌ Falha ao regenerar sessão:', e.message);
}
});
}
// ===============================================================
// 🎯 ATIVAÇÃO (reply / menção / PV)
// ===============================================================
async function shouldActivate(msg, isGroup, text) {
const context = msg.message?.extendedTextMessage?.contextInfo;
const lowered = text.toLowerCase();
// Reply ao bot
if (context?.participant) {
const quoted = normalizeJid(context.participant);
if (isBotJid(quoted)) {
console.log(`[ATIVAÇÃO] Reply ao bot detectado (${BOT_JID})`);
return true;
}
}
// Menção direta no grupo
if (isGroup) {
const mentions = context?.mentionedJid || [];
const mentionMatch = mentions.some(
j => isBotJid(j) || j.includes(BOT_JID.split('@')[0])
);
if (lowered.includes('akira') || mentionMatch) {
console.log('[ATIVAÇÃO] Menção direta a Akira detectada.');
return true;
}
}
// PV → sempre responde
if (!isGroup) return true;
return false;
}
// ===============================================================
// 🌐 HEALTH CHECK
// ===============================================================
const app = express();
const server = app.listen(PORT, '0.0.0.0', () => {
console.log(`Health check na porta ${server.address().port}`);
});
app.get('/', (req, res) => res.send('AKIRA BOT ONLINE ✅'));
connect();
|