akra35567 commited on
Commit
481bd99
·
verified ·
1 Parent(s): aca7f54

Create baileys_bot.js

Browse files
Files changed (1) hide show
  1. baileys_bot.js +202 -0
baileys_bot.js ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // baileys_bot.js
2
+ const {
3
+ default: makeWASocket,
4
+ useMultiFileAuthState,
5
+ DisconnectReason,
6
+ fetchLatestBaileysVersion,
7
+ Browsers,
8
+ delay
9
+ } = require('@whiskeysockets/baileys');
10
+ const pino = require('pino');
11
+ const qrcode = require('qrcode-terminal');
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+ const axios = require('axios');
15
+ const config = require('./config');
16
+ const logger = require('./utils/logger');
17
+
18
+ // === USUÁRIO PRIVILEGIADO (HARDCODED) ===
19
+ const PRIVILEGED_USER = {
20
+ nome: 'Isaac Quarenta',
21
+ numero: '244937035662' // sem @s.whatsapp.net
22
+ };
23
+
24
+ // Diretórios
25
+ const SESSION_DIR = config.AUTH_DIR;
26
+ fs.mkdirSync(SESSION_DIR, { recursive: true });
27
+
28
+ // Logger
29
+ const log = logger.child({ module: 'baileys' });
30
+
31
+ // API Akira
32
+ const API_URL = `${config.API_BASE_URL}${config.API_ROUTE_PREFIX}/akira`;
33
+
34
+ // Simular digitação
35
+ async function simulateTyping(sock, jid, duration = 1000) {
36
+ await sock.presenceSubscribe(jid);
37
+ await delay(500);
38
+ await sock.sendPresenceUpdate('composing', jid);
39
+ await delay(duration);
40
+ await sock.sendPresenceUpdate('paused', jid);
41
+ }
42
+
43
+ // Função: é Isaac Quarenta?
44
+ function isIsaacQuarenta(numero, nome) {
45
+ const cleanNumero = numero.replace(/[^0-9]/g, '');
46
+ const cleanNome = (nome || '').toLowerCase();
47
+
48
+ return cleanNumero.endsWith(PRIVILEGED_USER.numero) ||
49
+ cleanNome.includes('isaac') && cleanNome.includes('quarenta');
50
+ }
51
+
52
+ // Bot principal
53
+ async function startBot() {
54
+ const { version } = await fetchLatestBaileysVersion();
55
+ const { state, saveCreds } = await useMultiFileAuthState(SESSION_DIR);
56
+
57
+ const sock = makeWASocket({
58
+ version,
59
+ auth: state,
60
+ printQRInTerminal: false,
61
+ logger: pino({ level: 'silent' }),
62
+ browser: Browsers.macOS('Desktop'),
63
+ markOnlineOnConnect: true,
64
+ keepAliveIntervalMs: 30_000,
65
+ syncFullHistory: false,
66
+ });
67
+
68
+ let qrDisplayed = false;
69
+
70
+ sock.ev.on('connection.update', async (update) => {
71
+ const { connection, lastDisconnect, qr } = update;
72
+
73
+ if (qr && !qrDisplayed) {
74
+ qrDisplayed = true;
75
+ log.warn('QR CODE GERADO! Escaneie com o WhatsApp:');
76
+ qrcode.generate(qr, { small: true });
77
+ console.log('\nQR CODE ACIMA - ESCANEIE AGORA!\n');
78
+ }
79
+
80
+ if (connection === 'close') {
81
+ const shouldReconnect = lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut;
82
+ log.error(`Conexão fechada. Reconectando: ${shouldReconnect}`);
83
+
84
+ if (shouldReconnect) {
85
+ setTimeout(startBot, 5000);
86
+ } else {
87
+ log.error('Sessão desconectada. Apague ./data/sessions e reinicie.');
88
+ process.exit(1);
89
+ }
90
+ } else if (connection === 'open') {
91
+ log.info('Bot conectado com sucesso!');
92
+ qrDisplayed = false;
93
+ }
94
+ });
95
+
96
+ sock.ev.on('creds.update', saveCreds);
97
+
98
+ // === MENSAGENS ===
99
+ sock.ev.on('messages.upsert', async (m) => {
100
+ const msg = m.messages[0];
101
+ if (!msg.message || msg.key.fromMe) return;
102
+
103
+ const from = msg.key.remoteJid;
104
+ const isGroup = from.endsWith('@g.us');
105
+ const sender = msg.pushName || 'Usuário';
106
+ const participant = msg.key.participant || from;
107
+ const numeroLimpo = participant.replace('@s.whatsapp.net', '');
108
+
109
+ // === DETECÇÃO DE TIPO ===
110
+ let text = '';
111
+ let isMedia = false;
112
+ let mediaType = null;
113
+ let isReply = false;
114
+ let quotedMsg = null;
115
+ let isMentioned = false;
116
+
117
+ const msgType = Object.keys(msg.message)[0];
118
+ if (msgType === 'conversation' || msgType === 'extendedTextMessage') {
119
+ text = msg.message.conversation || msg.message.extendedTextMessage?.text || '';
120
+ } else if (msgType.includes('image')) { isMedia = true; mediaType = 'imagem'; }
121
+ else if (msgType.includes('video')) { isMedia = true; mediaType = 'vídeo'; }
122
+ else if (msgType.includes('audio')) { isMedia = true; mediaType = 'áudio'; }
123
+ else if (msgType.includes('sticker')) { isMedia = true; mediaType = 'sticker'; }
124
+
125
+ if (msg.message?.extendedTextMessage?.contextInfo?.quotedMessage) {
126
+ isReply = true;
127
+ quotedMsg = msg.message.extendedTextMessage.contextInfo.quotedMessage;
128
+ }
129
+
130
+ const mentionedJids = msg.message?.extendedTextMessage?.contextInfo?.mentionedJid || [];
131
+ isMentioned = mentionedJids.some(jid => jid.includes(sock.user.id.split(':')[0]));
132
+
133
+ // === VERIFICA SE É ISAAC QUARENTA ===
134
+ const ehIsaac = isIsaacQuarenta(numeroLimpo, sender);
135
+ if (ehIsaac) {
136
+ log.info(`MENSAGEM DE ISAAC QUARENTA (${numeroLimpo}) → Tom formal ativado.`);
137
+ }
138
+
139
+ // === LÓGICA DE ATIVAÇÃO ===
140
+ let shouldRespond = false;
141
+
142
+ if (!isGroup) {
143
+ shouldRespond = !!text;
144
+ } else {
145
+ const lowerText = text.toLowerCase();
146
+ const hasTrigger = lowerText.includes('akira');
147
+ const isBotReply = isReply && quotedMsg?.fromMe;
148
+ const isDirectMention = isMentioned;
149
+
150
+ shouldRespond = hasTrigger || isBotReply || isDirectMention;
151
+ if (isMedia && !text && !isBotReply) shouldRespond = false;
152
+ }
153
+
154
+ if (!shouldRespond) return;
155
+
156
+ // === PAYLOAD PARA API (com privilégio forçado para Isaac) ===
157
+ const payload = {
158
+ usuario: sender,
159
+ numero: numeroLimpo,
160
+ mensagem: text || `[${mediaType} enviada]`,
161
+ is_privileged_user: ehIsaac || config.isPrivilegedNumber(participant), // ← PRIORIDADE: Isaac
162
+ is_reply: isReply,
163
+ mensagem_original: isReply ? (quotedMsg?.conversation || quotedMsg?.extendedTextMessage?.text || '') : '',
164
+ nome_completo: ehIsaac ? PRIVILEGED_USER.nome : undefined // ← contexto extra
165
+ };
166
+
167
+ try {
168
+ const typingDuration = Math.min(1000 + text.length * 20, 5000);
169
+ await simulateTyping(sock, from, typingDuration);
170
+
171
+ const res = await axios.post(API_URL, payload, {
172
+ timeout: config.API_TIMEOUT,
173
+ headers: { 'Content-Type': 'application/json' }
174
+ });
175
+
176
+ const resposta = res.data.resposta || 'Sem resposta.';
177
+
178
+ const sendOpts = { quoted: (isGroup || isReply) ? msg : null };
179
+ await sock.sendMessage(from, { text: resposta }, sendOpts);
180
+
181
+ log.info(`Resposta para ${ehIsaac ? 'ISAAC QUARENTA' : sender} (${from}): ${resposta.substring(0, 50)}...`);
182
+
183
+ } catch (err) {
184
+ log.error(`Erro API: ${err.message}`);
185
+ const fallback = ehIsaac
186
+ ? 'Desculpe, Isaac. Estou com instabilidade técnica. Tento novamente em breve.'
187
+ : 'Desculpa, estou com problemas. Tenta depois.';
188
+ await sock.sendMessage(from, { text: fallback }, { quoted: msg });
189
+ }
190
+ });
191
+ }
192
+
193
+ // Iniciar
194
+ startBot().catch(err => {
195
+ log.error(`Erro fatal: ${err.message}`);
196
+ process.exit(1);
197
+ });
198
+
199
+ process.on('SIGINT', () => {
200
+ log.info('Bot encerrado.');
201
+ process.exit(0);
202
+ });