|
|
const ConfigManager = require('./ConfigManager'); |
|
|
const fs = require('fs'); |
|
|
const path = require('path'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const premiumFeatureUsage = new Map(); |
|
|
|
|
|
class CommandHandler { |
|
|
constructor(botCore) { |
|
|
this.bot = botCore; |
|
|
this.config = ConfigManager.getInstance(); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
canUsePremiumFeature(userId) { |
|
|
const now = new Date(); |
|
|
const usage = premiumFeatureUsage.get(userId) || { lastUse: 0, count: 0, resetDate: now }; |
|
|
|
|
|
|
|
|
const threeMonthsAgo = new Date(now.getTime() - (90 * 24 * 60 * 60 * 1000)); |
|
|
|
|
|
if (usage.resetDate < threeMonthsAgo) { |
|
|
usage.count = 0; |
|
|
usage.resetDate = now; |
|
|
} |
|
|
|
|
|
const canUse = usage.count === 0; |
|
|
if (canUse) { |
|
|
usage.count = 1; |
|
|
usage.lastUse = now.getTime(); |
|
|
} |
|
|
|
|
|
premiumFeatureUsage.set(userId, usage); |
|
|
return canUse; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getDivider() { |
|
|
return 'โ'.repeat(54); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getMenuHeader(emoji, title) { |
|
|
return `โ${'โ'.repeat(52)}โ |
|
|
โ ${emoji} ${title.padEnd(48)} โ |
|
|
โ${'โ'.repeat(52)}โ`; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getMenuSection(emoji, section) { |
|
|
return `\n${this.getDivider()} |
|
|
${emoji} ${section} |
|
|
${this.getDivider()}`; |
|
|
} |
|
|
|
|
|
async handle(m, meta) { |
|
|
|
|
|
try { |
|
|
const { nome, numeroReal, texto, replyInfo, ehGrupo } = meta; |
|
|
const mp = this.bot.messageProcessor; |
|
|
const parsed = mp.parseCommand(texto); |
|
|
if (!parsed) return false; |
|
|
|
|
|
const senderId = numeroReal; |
|
|
const sock = this.bot.sock; |
|
|
|
|
|
|
|
|
const isOwner = () => { |
|
|
try { return this.config.isDono(senderId, nome); } catch { return false; } |
|
|
}; |
|
|
|
|
|
const cmd = parsed.comando; |
|
|
const args = parsed.args; |
|
|
const full = parsed.textoCompleto; |
|
|
|
|
|
|
|
|
if (!mp.checkRateLimit(senderId)) { |
|
|
await sock.sendMessage(m.key.remoteJid, { text: 'โฐ Vocรช estรก usando comandos muito rรกpido. Aguarde.' }, { quoted: m }); |
|
|
return true; |
|
|
} |
|
|
|
|
|
|
|
|
const ownerOnly = async (fn) => { |
|
|
if (!isOwner()) { |
|
|
await sock.sendMessage(m.key.remoteJid, { text: '๐ซ Comando restrito ao dono.' }, { quoted: m }); |
|
|
return true; |
|
|
} |
|
|
return await fn(); |
|
|
}; |
|
|
|
|
|
switch (cmd) { |
|
|
case 'ping': |
|
|
await sock.sendMessage(m.key.remoteJid, { text: `๐ Pong! Uptime: ${Math.floor(process.uptime())}s` }, { quoted: m }); |
|
|
return true; |
|
|
|
|
|
case 'perfil': |
|
|
case 'profile': |
|
|
case 'info': |
|
|
try { |
|
|
const uid = m.key.participant || m.key.remoteJid; |
|
|
const nomeReg = this.bot.apiClient.getRegisterName ? this.bot.apiClient.getRegisterName(uid) : 'Nรฃo registrado'; |
|
|
const level = this.bot.levelSystem.getGroupRecord(m.key.remoteJid, uid, true).level || 0; |
|
|
const xp = this.bot.levelSystem.getGroupRecord(m.key.remoteJid, uid, true).xp || 0; |
|
|
const txt = `๐ค *Perfil:* ${nomeReg}\n๐ฎ Nรญvel: ${level}\nโญ XP: ${xp}`; |
|
|
await sock.sendMessage(m.key.remoteJid, { text: txt }, { quoted: m }); |
|
|
} catch (e) { } |
|
|
return true; |
|
|
|
|
|
case 'registrar': |
|
|
case 'register': |
|
|
case 'reg': |
|
|
try { |
|
|
|
|
|
const dbFolder = path.join(this.config.DATABASE_FOLDER, 'datauser'); |
|
|
if (!fs.existsSync(dbFolder)) fs.mkdirSync(dbFolder, { recursive: true }); |
|
|
const regPath = path.join(dbFolder, 'registered.json'); |
|
|
if (!fs.existsSync(regPath)) fs.writeFileSync(regPath, JSON.stringify([], null, 2)); |
|
|
|
|
|
if (!full.includes('|')) { |
|
|
await sock.sendMessage(m.key.remoteJid, { text: 'Uso: #registrar Nome|Idade' }, { quoted: m }); |
|
|
return true; |
|
|
} |
|
|
const [nomeUser, idadeStr] = full.split('|').map(s => s.trim()); |
|
|
const idade = parseInt(idadeStr,10); |
|
|
if (!nomeUser || isNaN(idade)) { await sock.sendMessage(m.key.remoteJid, { text: 'Formato invรกlido.' }, { quoted: m }); return true; } |
|
|
|
|
|
const registered = JSON.parse(fs.readFileSync(regPath, 'utf8') || '[]'); |
|
|
const senderJid = m.key.participant || m.key.remoteJid; |
|
|
if (registered.find(u=>u.id===senderJid)) { await sock.sendMessage(m.key.remoteJid, { text: 'โ
Vocรช jรก estรก registrado!' }, { quoted: m }); return true; } |
|
|
|
|
|
const serial = (Date.now().toString(36) + Math.random().toString(36).slice(2,10)).toUpperCase(); |
|
|
const time = new Date().toISOString(); |
|
|
registered.push({ id: senderJid, name: nomeUser, age: idade, time, serial, registeredAt: Date.now() }); |
|
|
fs.writeFileSync(regPath, JSON.stringify(registered, null, 2)); |
|
|
|
|
|
|
|
|
this.bot.levelSystem.getGroupRecord(m.key.remoteJid, senderJid, true); |
|
|
await sock.sendMessage(m.key.remoteJid, { text: 'โ
Registrado com sucesso!' }, { quoted: m }); |
|
|
} catch (e) { this.bot.logger && this.bot.logger.error('registrar error', e); } |
|
|
return true; |
|
|
|
|
|
case 'level': |
|
|
case 'nivel': |
|
|
case 'rank': |
|
|
try { |
|
|
const gid = m.key.remoteJid; |
|
|
if (!String(gid).endsWith('@g.us')) { await sock.sendMessage(gid, { text: '๐ต Level funciona apenas em grupos.' }, { quoted: m }); return true; } |
|
|
const sub = (args[0]||'').toLowerCase(); |
|
|
if (['on','off','status'].includes(sub)) { |
|
|
return await ownerOnly(async () => { |
|
|
const settingsPath = this.config.JSON_PATHS?.leveling || null; |
|
|
if (settingsPath) { |
|
|
const toggles = this.bot.apiClient.loadJSON ? this.bot.apiClient.loadJSON(settingsPath) : {}; |
|
|
if (sub === 'on') { toggles[gid]=true; this.bot.apiClient.saveJSON && this.bot.apiClient.saveJSON(settingsPath, toggles); await sock.sendMessage(gid,{text:'โ
Level ativado'},{quoted:m}); } |
|
|
else if (sub === 'off') { delete toggles[gid]; this.bot.apiClient.saveJSON && this.bot.apiClient.saveJSON(settingsPath, toggles); await sock.sendMessage(gid,{text:'๐ซ Level desativado'},{quoted:m}); } |
|
|
else { await sock.sendMessage(gid,{text:`โน๏ธ Status: ${toggles[gid] ? 'Ativo' : 'Inativo'}`},{quoted:m}); } |
|
|
} else { |
|
|
await sock.sendMessage(gid,{text:'โ ๏ธ Configuraรงรฃo de leveling nรฃo encontrada'},{quoted:m}); |
|
|
} |
|
|
return true; |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
const uid = m.key.participant || m.key.remoteJid; |
|
|
const rec = this.bot.levelSystem.getGroupRecord(gid, uid, true); |
|
|
const req = this.bot.levelSystem.requiredXp(rec.level); |
|
|
const pct = req === Infinity ? 100 : Math.min(100, Math.floor((rec.xp/req)*100)); |
|
|
const msg = `๐ LEVEL\n๐ค @${uid.split('@')[0]}\n๐ Nรญvel: ${rec.level}\nโญ XP: ${rec.xp}/${req}\nProgresso: ${pct}%`; |
|
|
await sock.sendMessage(gid, { text: msg, contextInfo: { mentionedJid: [uid] } }, { quoted: m }); |
|
|
} catch (e) { } |
|
|
return true; |
|
|
|
|
|
case 'antilink': |
|
|
try { |
|
|
return await ownerOnly(async () => { |
|
|
const sub2 = (args[0]||'').toLowerCase(); |
|
|
const gid = m.key.remoteJid; |
|
|
if (sub2 === 'on') { this.bot.moderationSystem.toggleAntiLink(gid, true); await sock.sendMessage(gid,{text:'๐ ANTI-LINK ATIVADO'},{quoted:m}); } |
|
|
else if (sub2 === 'off') { this.bot.moderationSystem.toggleAntiLink(gid, false); await sock.sendMessage(gid,{text:'๐ ANTI-LINK DESATIVADO'},{quoted:m}); } |
|
|
else { await sock.sendMessage(gid,{text:`Status: ${this.bot.moderationSystem.isAntiLinkActive(gid) ? 'Ativo' : 'Inativo'}`},{quoted:m}); } |
|
|
return true; |
|
|
}); |
|
|
} catch (e) {} |
|
|
return true; |
|
|
|
|
|
case 'mute': |
|
|
try { |
|
|
return await ownerOnly(async () => { |
|
|
const target = (m.message?.extendedTextMessage?.contextInfo?.mentionedJid||[])[0] || replyInfo?.participantJidCitado; |
|
|
if (!target) { await sock.sendMessage(m.key.remoteJid,{text:'Marque ou responda o usuรกrio'},{quoted:m}); return true; } |
|
|
const res = this.bot.moderationSystem.muteUser(m.key.remoteJid, target, 5); |
|
|
await sock.sendMessage(m.key.remoteJid,{text:`๐ Mutado por ${res.minutes} minutos`},{quoted:m}); |
|
|
return true; |
|
|
}); |
|
|
} catch (e) {} |
|
|
return true; |
|
|
|
|
|
case 'desmute': |
|
|
try { return await ownerOnly(async ()=>{ const target = (m.message?.extendedTextMessage?.contextInfo?.mentionedJid||[])[0] || replyInfo?.participantJidCitado; if (!target) { await sock.sendMessage(m.key.remoteJid,{text:'Marque ou responda o usuรกrio'},{quoted:m}); return true;} this.bot.moderationSystem.unmuteUser(m.key.remoteJid,target); await sock.sendMessage(m.key.remoteJid,{text:'๐ Usuรกrio desmutado'},{quoted:m}); return true; }); } catch(e){} |
|
|
return true; |
|
|
|
|
|
case 'sticker': |
|
|
case 's': |
|
|
case 'fig': |
|
|
try { |
|
|
|
|
|
const quoted = m.message?.extendedTextMessage?.contextInfo?.quotedMessage; |
|
|
const imageMsg = m.message?.imageMessage || quoted?.imageMessage; |
|
|
const stickerMsg = quoted?.stickerMessage; |
|
|
if (stickerMsg) { |
|
|
const stickerBuf = await this.bot.mediaProcessor.downloadMedia(stickerMsg, 'sticker'); |
|
|
if (stickerBuf) { |
|
|
await sock.sendMessage(m.key.remoteJid, { sticker: stickerBuf }, { quoted: m }); |
|
|
} else { |
|
|
await sock.sendMessage(m.key.remoteJid, { text: 'โ Erro ao baixar sticker.' }, { quoted: m }); |
|
|
} |
|
|
return true; |
|
|
} |
|
|
if (imageMsg) { |
|
|
const buf = await this.bot.mediaProcessor.downloadMedia(imageMsg, 'image'); |
|
|
const res = await this.bot.mediaProcessor.createStickerFromImage(buf, { packName: this.config.STICKER_PACK || 'Akira Pack', author: nome }); |
|
|
if (res && res.sucesso && res.buffer) { |
|
|
await sock.sendMessage(m.key.remoteJid, { sticker: res.buffer }, { quoted: m }); |
|
|
} else { |
|
|
await sock.sendMessage(m.key.remoteJid, { text: 'โ Erro ao criar sticker' }, { quoted: m }); |
|
|
} |
|
|
return true; |
|
|
} |
|
|
await sock.sendMessage(m.key.remoteJid, { text: 'Envie/Responda uma imagem ou sticker' }, { quoted: m }); |
|
|
} catch (e) { } |
|
|
return true; |
|
|
|
|
|
case 'play': |
|
|
try { |
|
|
if (!full) { await sock.sendMessage(m.key.remoteJid, { text: 'Uso: #play <link ou termo>' }, { quoted: m }); return true; } |
|
|
await sock.sendMessage(m.key.remoteJid, { text: 'โณ Processando mรบsica...' }, { quoted: m }); |
|
|
const res = await this.bot.mediaProcessor.downloadYouTubeAudio(full); |
|
|
if (res.error) { await sock.sendMessage(m.key.remoteJid, { text: `โ ${res.error}` }, { quoted: m }); return true; } |
|
|
await sock.sendMessage(m.key.remoteJid, { audio: res.buffer, mimetype: 'audio/mpeg', ptt: false, fileName: `${res.title || 'music'}.mp3` }, { quoted: m }); |
|
|
} catch (e) {} |
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case 'help': |
|
|
case 'menu': |
|
|
case 'comandos': |
|
|
case 'ajuda': |
|
|
try { |
|
|
const menuText = `โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
โ ๐ค AKIRA BOT V21 - MENU COMPLETO ๐ค โ |
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
|
|
|
๐ฑ *PREFIXO:* \`${this.config.PREFIXO}\` |
|
|
|
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
๐จ MรDIA & CRIATIVIDADE (Todos) |
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
\`#sticker\` - Criar sticker de imagem |
|
|
\`#s\` ou \`#fig\` - Aliases para #sticker |
|
|
\`#play <nome/link>\` - Baixar mรบsica do YouTube |
|
|
\`#ping\` - Testar latรชncia do bot |
|
|
|
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
๐ค รUDIO INTELIGENTE (Novo) |
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
โข Respondo รกudio automaticamente em PV |
|
|
โข Em grupos: mencione "Akira" ou responda ao รกudio |
|
|
โข Transcriรงรฃo interna (NUNCA mostra no chat) |
|
|
โข Resposto em รกudio automรกtico |
|
|
|
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
๐ MODERAรรO (Apenas Isaac Quarenta) |
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
\`#antilink on\` - Ativar anti-link |
|
|
\`#antilink off\` - Desativar anti-link |
|
|
\`#antilink status\` - Ver status |
|
|
\`#mute @usuรกrio\` - Mutar por 5 min (ou reply) |
|
|
\`#desmute @usuรกrio\` - Desmutar (ou reply) |
|
|
\`#level on\` - Ativar sistema de nรญveis |
|
|
\`#level off\` - Desativar sistema de nรญveis |
|
|
\`#level status\` - Ver status do level |
|
|
|
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
๐ฎ UTILIDADES (Todos) |
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
\`#perfil\` ou \`#info\` - Ver seu perfil |
|
|
\`#registrar Nome|Idade\` - Registrar no bot |
|
|
\`#level\` - Ver seu nรญvel e XP |
|
|
|
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
๐ฌ CONVERSA NORMAL |
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
โ
Mencione "Akira" em grupos |
|
|
โ
Ou responda minhas mensagens para conversar |
|
|
โ
IA sempre disponรญvel em PV |
|
|
|
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
โ ๏ธ INFORMAรรES IMPORTANTES |
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
๐ Comandos de grupo: Apenas Isaac Quarenta |
|
|
๐ Sistema de XP automรกtico ao enviar mensagens |
|
|
๐ Suba de nรญvel conversando (automaticamente) |
|
|
๐ก๏ธ Anti-spam e proteรงรฃo contra abuso |
|
|
๐ค STT: Deepgram (200h/mรชs gratuito) |
|
|
๐ TTS: Google Text-to-Speech |
|
|
|
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
๐ฐ *Quer apoiar o projeto?* |
|
|
Digite: \`#donate\` ou \`#doar\` |
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
|
|
|
*Desenvolvido com โค๏ธ por Isaac Quarenta*`; |
|
|
|
|
|
await sock.sendMessage(m.key.remoteJid, { text: menuText }, { quoted: m }); |
|
|
} catch (e) { |
|
|
this.bot.logger?.error('Erro no comando menu:', e); |
|
|
} |
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case 'donate': |
|
|
case 'doar': |
|
|
case 'apoia': |
|
|
case 'doacao': |
|
|
try { |
|
|
const donateText = `โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
โ โค๏ธ APOIE O PROJETO AKIRA BOT โค๏ธ โ |
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
|
|
|
๐ *Vocรช gosta do Akira?* |
|
|
|
|
|
Seu apoio nos ajuda a manter: |
|
|
โ
Bot online 24/7 |
|
|
โ
Novas funcionalidades |
|
|
โ
Sem publicidades |
|
|
โ
Gratuito para todos |
|
|
|
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
๐ฐ FORMAS DE APOIAR |
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
|
|
|
๐ *PIX (IMEDIATO):* |
|
|
E-mail: akira.bot.dev@gmail.com |
|
|
Chave: akira.bot.dev@gmail.com |
|
|
|
|
|
โ *COMPRE UM CAFร (Ko-fi):* |
|
|
https://ko-fi.com/isaacquarenta |
|
|
|
|
|
๐ณ *PAYPAL:* |
|
|
https://paypal.me/isaacquarenta |
|
|
|
|
|
๐ *QUALQUER VALOR AJUDA!* |
|
|
Desde R$ 5 atรฉ quanto vocรช quiser contribuir |
|
|
|
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
๐ AGRADECIMENTOS ESPECIAIS |
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
|
|
|
Todos que contribuem receberรฃo: |
|
|
โจ Meu sincero agradecimento |
|
|
โจ Suporte prioritรกrio |
|
|
โจ Novas features primeiro |
|
|
โจ Reconhecimento especial |
|
|
โจ Status VIP no bot |
|
|
|
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
๐ IMPACTO DA SUA DOAรรO |
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
|
|
|
R$ 5 = Mantรฉm o bot 1 dia online |
|
|
R$ 20 = Semana completa |
|
|
R$ 50 = Mรชs inteiro |
|
|
R$ 100+ = Mรชs + desenvolvimento de features |
|
|
|
|
|
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ |
|
|
|
|
|
*Desenvolvido com โค๏ธ por Isaac Quarenta* |
|
|
|
|
|
_Obrigado por apoiar um projeto feito com paixรฃo!_ ๐`; |
|
|
|
|
|
await sock.sendMessage(m.key.remoteJid, { text: donateText }, { quoted: m }); |
|
|
} catch (e) { |
|
|
this.bot.logger?.error('Erro no comando donate:', e); |
|
|
} |
|
|
return true; |
|
|
|
|
|
default: |
|
|
return false; |
|
|
} |
|
|
} catch (err) { |
|
|
try { await this.bot.sock.sendMessage(m.key.remoteJid, { text: 'โ Erro no comando.' }, { quoted: m }); } catch {} |
|
|
return true; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
module.exports = CommandHandler; |
|
|
|