akra35567 commited on
Commit
69aac01
Β·
verified Β·
1 Parent(s): c335d2f

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +114 -857
index.js CHANGED
@@ -1,186 +1,98 @@
1
  /**
2
  * ═══════════════════════════════════════════════════════════════════════
3
- * AKIRA BOT V21 β€” ARQUITETURA OOP COMPLETA
4
- * ═══════════════════════════════════════════════════════════════════════
5
- * βœ… Arquitetura modular com 6+ classes especializadas
6
- * βœ… Conformidade completa com api.py payload
7
- * βœ… IntegraΓ§Γ£o com computervision.py
8
- * βœ… STT (Deepgram), TTS (Google), YT Download, Stickers
9
- * βœ… Sistema de moderaΓ§Γ£o avanΓ§ado
10
- * βœ… Rate limiting e proteΓ§Γ£o contra spam
11
- * βœ… Performance otimizada com cache e deduplicaΓ§Γ£o
12
- * βœ… GARANTIA: Responde SEMPRE em REPLY nos grupos (@g.us)
13
- * βœ… SIMULAÇÕES: DigitaΓ§Γ£o, GravaΓ§Γ£o, Ticks, PresenΓ§a (em BotCore)
14
- *
15
- * πŸ“ NOTA: Este arquivo delega a lΓ³gica para classes OOP:
16
- * - BotCore.js β†’ Processamento de mensagens e resposta
17
- * - PresenceSimulator.js β†’ SimulaΓ§Γ΅es de digitaΓ§Γ£o/Γ‘udio/ticks
18
- * - CommandHandler.js β†’ Processamento de comandos
19
- *
20
- * πŸ”— REFERÊNCIA RÁPIDA:
21
- * - LΓ³gica de REPLY: modules/BotCore.js linha ~426
22
- * - SimulaΓ§Γ΅es: modules/PresenceSimulator.js
23
- * - Comandos: modules/CommandHandler.js
24
- * - Config: modules/ConfigManager.js
25
- *
26
- * ⚑ HF SPACES DNS CORRECTIONS - CRÍTICO PARA QR CODE:
27
- * - ForΓ§a IPv4 para resolver web.whatsapp.com
28
- * - ConfiguraΓ§Γ£o DNS do Google (8.8.8.8) como fallback
29
  * ═══════════════════════════════════════════════════════════════════════
30
  */
31
 
32
  // ═══════════════════════════════════════════════════════════════════════
33
- // HF SPACES DNS CORRECTIONS - CORREÇÃO CRÍTICA PARA QR CODE
34
  // ═══════════════════════════════════════════════════════════════════════
35
- const dns = require('dns');
36
-
37
- // 1. Força IPv4 para todas as operaçáes DNS (CRÍTICO PARA HF SPACES)
38
- dns.setDefaultResultOrder('ipv4first');
39
-
40
- // 2. Sobrescreve resolve4 para usar fallback automΓ‘tico
41
- const originalResolve4 = dns.resolve4.bind(dns);
42
- dns.resolve4 = function(hostname, options, callback) {
43
- if (typeof options === 'function') {
44
- callback = options;
45
- options = { timeout: 10000, family: 4 };
46
- }
47
-
48
- originalResolve4(hostname, options, (err, addresses) => {
49
- if (err && (err.code === 'ENODATA' || err.code === 'ENOTFOUND' || err.code === 'EAI_AGAIN')) {
50
- console.log(`πŸ”„ DNS fallback para ${hostname}, tentando novamente...`);
51
- setTimeout(() => {
52
- originalResolve4(hostname, options, callback);
53
- }, 3000);
54
- } else {
55
- callback(err, addresses);
56
- }
57
- });
58
- };
59
 
60
  // ═══════════════════════════════════════════════════════════════════════
61
- // FIM DAS CORREÇÕES HF SPACES
62
  // ═══════════════════════════════════════════════════════════════════════
63
-
64
- // @ts-nocheck
65
  const express = require('express');
66
  const QRCode = require('qrcode');
67
- const ConfigManager = require('./modules/ConfigManager');
68
- const BotCore = require('./modules/BotCore');
69
-
70
- // ═══════════════════════════════════════════════════════════════════════
71
- // INICIALIZAÇÃO GLOBAL
72
- // ═══════════════════════════════════════════════════════════════════════
73
 
74
  const config = ConfigManager.getInstance();
75
  let botCore = null;
76
  let app = null;
77
  let server = null;
78
 
79
- /**
80
- * Inicializa o servidor Express
81
- */
 
82
  function initializeServer() {
83
  app = express();
84
  app.use(express.json());
85
 
86
- // ═══ Middleware para logging ═══
87
  app.use((req, res, next) => {
88
- const start = Date.now();
89
- const path = req.path;
90
- res.on('finish', () => {
91
- const duration = Date.now() - start;
92
- console.log(`[${new Date().toISOString()}] ${req.method} ${path} ${res.statusCode} ${duration}ms`);
93
- });
94
  next();
95
  });
96
 
97
- // ═══ Rota: Status ═══
98
  app.get('/', (req, res) => {
99
  if (!botCore) {
100
- return res.send(`
101
- <!DOCTYPE html>
102
- <html>
103
- <head>
104
- <title>πŸ€– Akira Bot V21 - Inicializando...</title>
105
- <style>
106
- body { background: #000; color: #ffaa00; font-family: 'Courier New', monospace; padding: 40px; line-height: 1.6; text-align: center; }
107
- h1 { color: #ffaa00; text-shadow: 0 0 10px #ffaa00; }
108
- .loading:after { content: '.'; animation: dots 1.5s steps(5, end) infinite; }
109
- @keyframes dots { 0%, 20% { content: '.'; } 40% { content: '..'; } 60% { content: '...'; } 80%, 100% { content: ''; } }
110
- </style>
111
- <meta http-equiv="refresh" content="3">
112
- </head>
113
- <body>
114
- <h1>πŸ€– AKIRA BOT V21</h1>
115
- <p>Inicializando o sistema<span class="loading"></span></p>
116
- <p>Por favor, aguarde alguns segundos</p>
117
- <p>Atualizando automaticamente</p>
118
- </body>
119
- </html>
120
- `);
121
  }
122
 
123
  const status = botCore.getStatus();
124
  const qr = botCore.getQRCode();
125
-
126
- // Se tem QR code mas ainda nΓ£o estΓ‘ conectado
127
  const hasQR = qr !== null && qr !== undefined;
128
-
129
  res.send(`
130
  <!DOCTYPE html>
131
  <html>
132
  <head>
133
  <title>πŸ€– Akira Bot V21</title>
 
 
134
  <style>
135
- body { background: #000; color: #0f0; font-family: 'Courier New', monospace; padding: 40px; line-height: 1.6; }
136
- h1 { text-align: center; color: #00ff00; text-shadow: 0 0 10px #00ff00; }
137
- .container { max-width: 600px; margin: 0 auto; background: #0a0a0a; padding: 20px; border: 2px solid #00ff00; border-radius: 5px; }
138
- .status { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #00ff00; }
139
- .label { font-weight: bold; }
140
- .links { text-align: center; margin-top: 20px; }
141
- a { color: #00ff00; text-decoration: none; margin: 0 15px; padding: 8px 16px; border: 1px solid #00ff00; border-radius: 5px; display: inline-block; transition: all 0.3s; }
142
- a:hover { background: #00ff00; color: #000; text-decoration: none; }
143
- .version { color: #0099ff; }
144
- .qr-indicator { background: ${hasQR ? '#00ff00' : '#ffaa00'}; color: #000; padding: 5px 10px; border-radius: 3px; font-weight: bold; margin-left: 10px; }
145
- .status-indicator { background: ${status.isConnected ? '#00ff00' : '#ff4444'}; color: #000; padding: 5px 10px; border-radius: 3px; font-weight: bold; margin-left: 10px; }
146
  </style>
147
  </head>
148
  <body>
149
- <div class="container">
150
  <h1>πŸ€– AKIRA BOT V21</h1>
151
- <div class="status">
152
- <span class="label">Status:</span>
153
- <span>${status.isConnected ? 'βœ… ONLINE' : '❌ OFFLINE'} <span class="status-indicator">${status.isConnected ? 'CONECTADO' : 'DESCONECTADO'}</span></span>
154
- </div>
155
- <div class="status">
156
- <span class="label">QR Code:</span>
157
- <span>${hasQR ? 'πŸ“± DISPONÍVEL' : '⏳ AGUARDANDO'} <span class="qr-indicator">${hasQR ? 'PRONTO' : 'GERANDO'}</span></span>
158
- </div>
159
- <div class="status">
160
- <span class="label">NΓΊmero:</span>
161
- <span>${status.botNumero}</span>
162
- </div>
163
- <div class="status">
164
- <span class="label">JID:</span>
165
- <span>${status.botJid || 'Desconectado'}</span>
166
- </div>
167
- <div class="status">
168
- <span class="label">Uptime:</span>
169
- <span>${status.uptime}s</span>
170
- </div>
171
- <div class="status version">
172
- <span class="label">VersΓ£o:</span>
173
- <span>${status.version}</span>
174
- </div>
175
- <div class="links">
176
- <a href="/qr">πŸ“± QR Code</a>
177
- <a href="/health">πŸ’š Health</a>
178
- <a href="/stats">πŸ“Š Stats</a>
179
- ${!status.isConnected ? '<a href="/force-qr">πŸ”„ ForΓ§ar QR</a>' : ''}
180
- <a href="/reset-auth" onclick="return confirm(\'Isso vai desconectar o bot e exigir novo login. Continuar?\')">πŸ”„ Reset Auth</a>
181
  </div>
182
- <div style="margin-top: 20px; text-align: center; color: #666; font-size: 12px;">
183
- Porta: ${config.PORT} | API: ${config.API_URL ? 'Conectada' : 'Desconectada'}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  </div>
185
  </div>
186
  </body>
@@ -188,766 +100,111 @@ function initializeServer() {
188
  `);
189
  });
190
 
191
- // ═══ Rota: QR Code ═══
192
  app.get('/qr', async (req, res) => {
193
- try {
194
- if (!botCore) {
195
- return res.status(503).send(`
196
- <html>
197
- <head>
198
- <meta http-equiv="refresh" content="3">
199
- <style>
200
- body { background: #000; color: #ffaa00; font-family: monospace; text-align: center; padding: 50px; }
201
- .loading:after { content: '.'; animation: dots 1.5s steps(5, end) infinite; }
202
- @keyframes dots { 0%, 20% { content: '.'; } 40% { content: '..'; } 60% { content: '...'; } 80%, 100% { content: ''; } }
203
- </style>
204
- </head>
205
- <body>
206
- <h1>πŸ”„ INICIALIZANDO BOT</h1>
207
- <p>O bot ainda estΓ‘ sendo inicializado<span class="loading"></span></p>
208
- <p>Por favor, aguarde alguns segundos</p>
209
- <p>Atualizando automaticamente em 3 segundos</p>
210
- <p><a href="/" style="color: #0f0;">← Voltar</a></p>
211
- </body>
212
- </html>
213
- `);
214
- }
215
-
216
- const status = botCore.getStatus();
217
- const qr = botCore.getQRCode();
218
-
219
- // Se jΓ‘ estΓ‘ conectado
220
- if (status.isConnected) {
221
- return res.send(`
222
- <html>
223
- <head>
224
- <style>
225
- body { background: #000; color: #0f0; font-family: monospace; text-align: center; padding: 50px; }
226
- .connected { color: #00ff00; font-size: 24px; margin: 20px 0; padding: 20px; border: 2px solid #00ff00; border-radius: 10px; }
227
- </style>
228
- </head>
229
- <body>
230
- <h1>βœ… BOT CONECTADO!</h1>
231
- <div class="connected">
232
- <p>βœ… <strong>ONLINE E OPERACIONAL</strong></p>
233
- <p>πŸ€– Nome: ${config.BOT_NAME}</p>
234
- <p>πŸ“± NΓΊmero: ${status.botNumero}</p>
235
- <p>πŸ”— JID: ${status.botJid || 'N/A'}</p>
236
- <p>⏱️ Uptime: ${status.uptime} segundos</p>
237
- </div>
238
- <p>O bot jΓ‘ estΓ‘ conectado ao WhatsApp e pronto para uso.</p>
239
- <p>Nenhum QR Code necessΓ‘rio agora.</p>
240
- <p><a href="/" style="color: #0f0;">← Voltar para PΓ‘gina Inicial</a></p>
241
- </body>
242
- </html>
243
- `);
244
- }
245
-
246
- // Se nΓ£o estΓ‘ conectado e nΓ£o tem QR
247
- if (!qr) {
248
- return res.send(`
249
- <html>
250
- <head>
251
- <meta http-equiv="refresh" content="5">
252
- <title>πŸ”„ Gerando QR Code - Akira Bot</title>
253
- <style>
254
- body {
255
- background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);
256
- color: #ffaa00;
257
- font-family: 'Courier New', monospace;
258
- text-align: center;
259
- padding: 40px;
260
- margin: 0;
261
- min-height: 100vh;
262
- }
263
- .container {
264
- max-width: 600px;
265
- margin: 0 auto;
266
- background: rgba(10, 10, 10, 0.9);
267
- padding: 40px;
268
- border: 2px solid #ffaa00;
269
- border-radius: 10px;
270
- box-shadow: 0 0 30px rgba(255, 170, 0, 0.3);
271
- }
272
- h1 {
273
- color: #ffaa00;
274
- text-shadow: 0 0 10px #ffaa00;
275
- margin-bottom: 30px;
276
- }
277
- .loading-container {
278
- margin: 30px 0;
279
- padding: 20px;
280
- }
281
- .spinner {
282
- width: 60px;
283
- height: 60px;
284
- border: 5px solid rgba(255, 170, 0, 0.3);
285
- border-top: 5px solid #ffaa00;
286
- border-radius: 50%;
287
- animation: spin 1s linear infinite;
288
- margin: 0 auto 20px;
289
- }
290
- @keyframes spin {
291
- 0% { transform: rotate(0deg); }
292
- 100% { transform: rotate(360deg); }
293
- }
294
- .loading-text:after {
295
- content: '.';
296
- animation: dots 1.5s steps(5, end) infinite;
297
- }
298
- @keyframes dots {
299
- 0%, 20% { content: '.'; }
300
- 40% { content: '..'; }
301
- 60% { content: '...'; }
302
- 80%, 100% { content: ''; }
303
- }
304
- .instructions {
305
- background: rgba(255, 170, 0, 0.1);
306
- border: 1px solid #ffaa00;
307
- border-radius: 5px;
308
- padding: 20px;
309
- margin: 30px 0;
310
- text-align: left;
311
- }
312
- a {
313
- color: #ffaa00;
314
- text-decoration: none;
315
- margin: 0 10px;
316
- padding: 8px 16px;
317
- border: 1px solid #ffaa00;
318
- border-radius: 5px;
319
- display: inline-block;
320
- transition: all 0.3s;
321
- }
322
- a:hover {
323
- background: #ffaa00;
324
- color: #000;
325
- text-decoration: none;
326
- }
327
- </style>
328
- </head>
329
- <body>
330
- <div class="container">
331
- <h1>πŸ”„ GERANDO QR CODE</h1>
332
-
333
- <div class="loading-container">
334
- <div class="spinner"></div>
335
- <h2 class="loading-text">Aguardando geraΓ§Γ£o do QR Code</h2>
336
- <p>Isso pode levar alguns segundos</p>
337
- </div>
338
-
339
- <div class="instructions">
340
- <h3>πŸ“‹ O QUE ESTÁ ACONTECENDO:</h3>
341
- <ul>
342
- <li>O bot estΓ‘ iniciando a conexΓ£o com o WhatsApp</li>
343
- <li>O servidor estΓ‘ solicitando um novo QR code</li>
344
- <li>O QR code serΓ‘ gerado automaticamente</li>
345
- <li>A pΓ‘gina serΓ‘ atualizada quando o QR code estiver pronto</li>
346
- </ul>
347
- <p><strong>Tempo estimado:</strong> 10-30 segundos</p>
348
- </div>
349
-
350
- <div style="margin-top: 30px;">
351
- <p>⏳ Atualizando automaticamente em 5 segundos</p>
352
- <div style="margin-top: 20px;">
353
- <a href="/qr" onclick="location.reload();">πŸ”„ Atualizar Agora</a>
354
- <a href="/">🏠 PÑgina Inicial</a>
355
- <a href="/force-qr">⚑ Forçar Geração</a>
356
- </div>
357
- </div>
358
- </div>
359
- </body>
360
- </html>
361
- `);
362
- }
363
-
364
- // Gerar imagem do QR code
365
- const img = await QRCode.toDataURL(qr, {
366
- errorCorrectionLevel: 'H',
367
- scale: 10,
368
- margin: 2,
369
- width: 400
370
- });
371
 
372
- res.send(`
373
- <html>
374
- <head>
375
- <meta http-equiv="refresh" content="30">
376
- <title>πŸ“± QR Code - Akira Bot</title>
377
- <style>
378
- body {
379
- background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);
380
- color: #0f0;
381
- font-family: 'Courier New', monospace;
382
- text-align: center;
383
- padding: 20px;
384
- margin: 0;
385
- min-height: 100vh;
386
- }
387
- .container {
388
- max-width: 800px;
389
- margin: 0 auto;
390
- background: rgba(10, 10, 10, 0.9);
391
- padding: 30px;
392
- border: 3px solid #00ff00;
393
- border-radius: 15px;
394
- box-shadow: 0 0 40px rgba(0, 255, 0, 0.4);
395
- }
396
- h1 {
397
- color: #00ff00;
398
- text-shadow: 0 0 15px #00ff00;
399
- margin-bottom: 20px;
400
- font-size: 2.5em;
401
- }
402
- .qr-container {
403
- margin: 30px auto;
404
- padding: 25px;
405
- background: #000;
406
- border: 4px solid #00ff00;
407
- border-radius: 15px;
408
- display: inline-block;
409
- box-shadow: 0 0 25px rgba(0, 255, 0, 0.5);
410
- }
411
- img {
412
- display: block;
413
- margin: 0 auto;
414
- max-width: 100%;
415
- height: auto;
416
- border-radius: 10px;
417
- }
418
- .status-badge {
419
- display: inline-block;
420
- background: #00ff00;
421
- color: #000;
422
- padding: 8px 20px;
423
- border-radius: 20px;
424
- font-weight: bold;
425
- margin: 15px 0;
426
- font-size: 1.2em;
427
- }
428
- .timer {
429
- color: #0099ff;
430
- font-size: 1.1em;
431
- margin: 20px 0;
432
- padding: 10px;
433
- background: rgba(0, 153, 255, 0.1);
434
- border-radius: 5px;
435
- display: inline-block;
436
- }
437
- .instructions {
438
- background: rgba(0, 255, 0, 0.1);
439
- border: 2px solid #00ff00;
440
- border-radius: 10px;
441
- padding: 25px;
442
- margin: 30px 0;
443
- text-align: left;
444
- }
445
- .instructions h3 {
446
- color: #00ff00;
447
- margin-top: 0;
448
- font-size: 1.4em;
449
- border-bottom: 1px solid #00ff00;
450
- padding-bottom: 10px;
451
- }
452
- .instructions ol {
453
- padding-left: 25px;
454
- font-size: 1.1em;
455
- }
456
- .instructions li {
457
- margin-bottom: 15px;
458
- padding: 5px 0;
459
- }
460
- .instructions strong {
461
- color: #00ff00;
462
- }
463
- .warning {
464
- color: #ffaa00;
465
- background: rgba(255, 170, 0, 0.1);
466
- border: 1px solid #ffaa00;
467
- border-radius: 5px;
468
- padding: 15px;
469
- margin: 20px 0;
470
- font-size: 0.9em;
471
- }
472
- .actions {
473
- margin: 30px 0;
474
- }
475
- a {
476
- color: #00ff00;
477
- text-decoration: none;
478
- margin: 10px;
479
- padding: 12px 24px;
480
- border: 2px solid #00ff00;
481
- border-radius: 8px;
482
- display: inline-block;
483
- font-weight: bold;
484
- transition: all 0.3s;
485
- font-size: 1.1em;
486
- }
487
- a:hover {
488
- background: #00ff00;
489
- color: #000;
490
- text-decoration: none;
491
- transform: translateY(-3px);
492
- box-shadow: 0 5px 15px rgba(0, 255, 0, 0.4);
493
- }
494
- .footer {
495
- margin-top: 40px;
496
- color: #666;
497
- font-size: 0.9em;
498
- border-top: 1px solid #333;
499
- padding-top: 20px;
500
- }
501
- </style>
502
- </head>
503
- <body>
504
- <div class="container">
505
- <h1>πŸ“± QR CODE DISPONÍVEL</h1>
506
-
507
- <div class="status-badge">
508
- βœ… QR CODE PRONTO PARA SCAN
509
- </div>
510
-
511
- <div class="timer">
512
- ⏳ VÑlido por 90 segundos | Atualizando em 30s
513
- </div>
514
-
515
- <div class="qr-container">
516
- <img src="${img}" alt="QR Code para conectar WhatsApp">
517
- </div>
518
-
519
- <div class="instructions">
520
- <h3>πŸ“‹ COMO CONECTAR:</h3>
521
- <ol>
522
- <li><strong>Abra o WhatsApp</strong> no seu celular</li>
523
- <li>Toque nos <strong>trΓͺs pontos</strong> β†’ <strong>Linked devices</strong></li>
524
- <li>Toque em <strong>Link a device</strong></li>
525
- <li><strong>Aponte a cΓ’mera</strong> para o QR Code acima</li>
526
- <li>Aguarde a confirmaΓ§Γ£o de conexΓ£o</li>
527
- </ol>
528
-
529
- <div class="warning">
530
- ⚠️ <strong>IMPORTANTE:</strong> Este QR code expira em 90 segundos.
531
- Se expirar, a pΓ‘gina serΓ‘ atualizada automaticamente com um novo cΓ³digo.
532
- </div>
533
- </div>
534
-
535
- <div class="actions">
536
- <a href="/qr" onclick="location.reload();">πŸ”„ Atualizar QR Code</a>
537
- <a href="/">🏠 PÑgina Inicial</a>
538
- <a href="/health">πŸ’š Status do Sistema</a>
539
- <a href="/force-qr">⚑ Forçar Novo QR</a>
540
- </div>
541
-
542
- <div class="footer">
543
- Akira Bot V21 | Sistema de conexΓ£o WhatsApp | Porta: ${config.PORT}
544
- </div>
545
- </div>
546
- </body>
547
- </html>
548
- `);
549
- } catch (error) {
550
- console.error('❌ Erro na rota /qr:', error);
551
- res.status(500).send(`
552
- <html>
553
- <head>
554
- <style>
555
- body { background: #000; color: #ff4444; font-family: monospace; text-align: center; padding: 50px; }
556
- </style>
557
- </head>
558
- <body>
559
- <h1>❌ ERRO AO GERAR QR CODE</h1>
560
- <p>Ocorreu um erro ao processar o QR code:</p>
561
- <p><strong>${error.message}</strong></p>
562
- <p style="margin-top: 30px;">
563
- <a href="/" style="color: #0f0; text-decoration: none; border: 1px solid #0f0; padding: 10px 20px; border-radius: 5px;">← Voltar</a>
564
- <a href="/qr" style="color: #ffaa00; text-decoration: none; border: 1px solid #ffaa00; padding: 10px 20px; border-radius: 5px; margin-left: 20px;">πŸ”„ Tentar Novamente</a>
565
- </p>
566
- </body>
567
- </html>
568
  `);
569
  }
570
- });
571
 
572
- // ═══ Rota: ForΓ§ar geraΓ§Γ£o de QR ═══
573
- app.get('/force-qr', async (req, res) => {
574
  try {
575
- if (!botCore) {
576
- return res.redirect('/qr');
577
- }
578
-
579
- console.log('πŸ”„ ForΓ§ando geraΓ§Γ£o de QR code via web...');
580
- await botCore._forceQRGeneration();
581
-
582
  res.send(`
583
- <html>
584
- <head>
585
- <meta http-equiv="refresh" content="2;url=/qr">
586
- <style>
587
- body { background: #000; color: #ffaa00; font-family: monospace; text-align: center; padding: 50px; }
588
- </style>
589
- </head>
590
- <body>
591
- <h1>⚑ FORΓ‡ANDO GERAÇÃO DE QR</h1>
592
- <p>Reiniciando conexΓ£o para gerar novo QR code...</p>
593
- <p>Redirecionando em 2 segundos</p>
594
- <p><a href="/qr" style="color: #0f0;">β†ͺ️ Ir para QR Code agora</a></p>
595
- </body>
596
- </html>
597
  `);
598
- } catch (error) {
599
- console.error('❌ Erro ao forçar QR:', error);
600
- res.redirect('/qr');
601
  }
602
  });
603
 
604
- // ═══ Rota: Health Check ═══
605
  app.get('/health', (req, res) => {
606
- if (!botCore) {
607
- return res.status(503).json({
608
- status: 'initializing',
609
- message: 'Bot ainda estΓ‘ inicializando',
610
- timestamp: new Date().toISOString()
611
- });
612
- }
613
-
614
- const status = botCore.getStatus();
615
- const qr = botCore.getQRCode();
616
-
617
- res.json({
618
- status: status.isConnected ? 'online' : 'offline',
619
- qr_available: qr !== null && qr !== undefined,
620
- timestamp: new Date().toISOString(),
621
- bot: {
622
- numero: status.botNumero,
623
- name: status.botName,
624
- version: status.version,
625
- jid: status.botJid || null,
626
- uptime: status.uptime
627
- },
628
- features: {
629
- stt: config.FEATURE_STT_ENABLED,
630
- tts: config.FEATURE_TTS_ENABLED,
631
- youtube: config.FEATURE_YT_DOWNLOAD,
632
- stickers: config.FEATURE_STICKERS,
633
- moderation: config.FEATURE_MODERATION,
634
- leveling: config.FEATURE_LEVELING,
635
- vision: config.FEATURE_VISION
636
- },
637
- server: {
638
- port: config.PORT,
639
- api_url: config.API_URL ? 'configured' : 'not_configured'
640
- }
641
- });
642
- });
643
-
644
- // ═══ Rota: EstatΓ­sticas ═══
645
- app.get('/stats', (req, res) => {
646
- if (!botCore) {
647
- return res.status(503).json({
648
- status: 'initializing',
649
- message: 'Bot ainda estΓ‘ inicializando',
650
- timestamp: new Date().toISOString()
651
- });
652
- }
653
-
654
- const stats = botCore.getStats();
655
  res.json({
656
- bot: stats,
657
- timestamp: new Date().toISOString()
658
- });
659
- });
660
-
661
- // ═══ Rota: Reset de cache ═══
662
- app.post('/reset-cache', (req, res) => {
663
- try {
664
- if (!botCore) {
665
- return res.status(503).json({
666
- status: 'error',
667
- message: 'Bot nΓ£o inicializado'
668
- });
669
- }
670
-
671
- botCore.audioProcessor.clearCache();
672
- botCore.mediaProcessor.clearCache();
673
- botCore.messageProcessor.clearCache();
674
-
675
- res.json({
676
- status: 'success',
677
- message: 'Caches foram resetados',
678
- timestamp: new Date().toISOString()
679
- });
680
- } catch (error) {
681
- res.status(500).json({
682
- status: 'error',
683
- message: 'Erro ao resetar caches',
684
- error: error.message
685
- });
686
- }
687
- });
688
-
689
- // ═══ Rota: Reset de autenticaΓ§Γ£o (forΓ§a novo login) ═══
690
- app.post('/reset-auth', (req, res) => {
691
- try {
692
- if (!botCore) {
693
- return res.status(503).json({
694
- status: 'error',
695
- message: 'Bot nΓ£o inicializado'
696
- });
697
- }
698
-
699
- const fs = require('fs');
700
- const authPath = botCore.config.AUTH_FOLDER;
701
-
702
- if (fs.existsSync(authPath)) {
703
- fs.rmSync(authPath, { recursive: true, force: true });
704
- botCore.isConnected = false;
705
- botCore.currentQR = null;
706
- botCore.BOT_JID = null;
707
- }
708
-
709
- // Reinicia a conexΓ£o
710
- setTimeout(() => {
711
- botCore.connect().catch(err => console.error('Erro ao reconectar:', err));
712
- }, 1000);
713
-
714
- res.json({
715
- status: 'success',
716
- message: 'Credenciais resetadas. FaΓ§a login novamente.',
717
- timestamp: new Date().toISOString()
718
- });
719
- } catch (error) {
720
- res.status(500).json({
721
- status: 'error',
722
- message: 'Erro ao resetar autenticaΓ§Γ£o',
723
- error: error.message
724
- });
725
- }
726
- });
727
-
728
- // ═══ Rota: Verificar PrivilΓ©gios ═══
729
- app.post('/check-privileges', (req, res) => {
730
- try {
731
- const { numero } = req.body;
732
-
733
- if (!numero) {
734
- return res.status(400).json({
735
- error: 'NΓΊmero obrigatΓ³rio'
736
- });
737
- }
738
-
739
- // Verificar privilΓ©gios via API interna
740
- const isPrivileged = config.isDono(numero, '');
741
-
742
- res.json({
743
- numero: numero,
744
- privilegiado: isPrivileged,
745
- timestamp: new Date().toISOString()
746
- });
747
- } catch (error) {
748
- res.status(500).json({
749
- error: 'Erro interno',
750
- message: error.message
751
- });
752
- }
753
- });
754
-
755
- // ═══ Rota: ModeraΓ§Γ£o ═══
756
- app.post('/moderation/toggle-antilink', (req, res) => {
757
- try {
758
- const { groupId, enable } = req.body;
759
-
760
- if (!groupId) {
761
- return res.status(400).json({ error: 'groupId Γ© obrigatΓ³rio' });
762
- }
763
-
764
- if (!botCore) {
765
- return res.status(503).json({
766
- status: 'error',
767
- message: 'Bot nΓ£o inicializado'
768
- });
769
- }
770
-
771
- const result = botCore.moderationSystem.toggleAntiLink(groupId, enable);
772
-
773
- res.json({
774
- status: 'success',
775
- groupId,
776
- antiLinkEnabled: result,
777
- timestamp: new Date().toISOString()
778
- });
779
- } catch (error) {
780
- res.status(500).json({
781
- status: 'error',
782
- error: error.message
783
- });
784
- }
785
- });
786
-
787
- // ═══ Rota: Debug - Status detalhado ═══
788
- app.get('/debug', (req, res) => {
789
- if (!botCore) {
790
- return res.json({
791
- status: 'not_initialized',
792
- timestamp: new Date().toISOString()
793
- });
794
- }
795
-
796
- const status = botCore.getStatus();
797
- const qr = botCore.getQRCode();
798
-
799
- res.json({
800
- bot_core_initialized: true,
801
- bot_status: status,
802
- qr_code: qr ? 'available' : 'not_available',
803
- qr_length: qr ? qr.length : 0,
804
- socket_state: botCore.sock ? 'created' : 'not_created',
805
- socket_ws_state: botCore.sock && botCore.sock.ws ? botCore.sock.ws.readyState : 'no_ws',
806
- config: {
807
- port: config.PORT,
808
- api_url: config.API_URL,
809
- auth_folder: config.AUTH_FOLDER
810
- },
811
- timestamp: new Date().toISOString()
812
- });
813
- });
814
-
815
- // ═══ Error handler ═══
816
- app.use((err, req, res, next) => {
817
- console.error('❌ Erro no servidor:', err);
818
- res.status(500).json({
819
- status: 'error',
820
- error: err.message || 'Erro desconhecido',
821
- timestamp: new Date().toISOString()
822
- });
823
- });
824
-
825
- // ═══ 404 handler ═══
826
- app.use((req, res) => {
827
- res.status(404).json({
828
- status: 'error',
829
- error: 'Rota nΓ£o encontrada',
830
- path: req.path,
831
  timestamp: new Date().toISOString()
832
  });
833
  });
834
 
 
835
  server = app.listen(config.PORT, '0.0.0.0', () => {
836
- console.log(`\n🌐 Servidor Express rodando na porta ${config.PORT}`);
837
- console.log(` πŸ“ Local: http://localhost:${config.PORT}`);
838
- console.log(` πŸ“ QR Code: http://localhost:${config.PORT}/qr`);
839
- console.log(` πŸ“ Health: http://localhost:${config.PORT}/health\n`);
840
  });
841
-
842
- return server;
843
  }
844
 
845
- /**
846
- * FunΓ§Γ£o principal
847
- */
 
848
  async function main() {
849
  try {
850
- console.log('\n' + '═'.repeat(70));
851
- console.log('πŸš€ INICIANDO AKIRA BOT V21');
852
- console.log('═'.repeat(70) + '\n');
853
 
854
- // ═══ Inicializa BotCore ═══
855
- console.log('πŸ”§ Inicializando BotCore...');
856
  botCore = new BotCore();
 
 
857
  await botCore.initialize();
858
- console.log('βœ… BotCore inicializado\n');
859
-
860
- // ═══ Inicializa servidor Express ═══
861
- console.log('🌐 Inicializando servidor web...');
862
  initializeServer();
863
- console.log('βœ… Servidor web pronto\n');
864
 
865
- // ═══ Conecta ao WhatsApp ═══
866
- console.log('πŸ”— Conectando ao WhatsApp...');
867
- console.log('⚠️ Aguarde a geração do QR code...');
868
- console.log('πŸ“± Acesse: http://localhost:' + config.PORT + '/qr');
869
- console.log('⏳ Pode levar alguns segundos para o QR code aparecer\n');
870
-
871
- // Conectar em background para nΓ£o bloquear
872
- botCore.connect().catch(error => {
873
- console.error('❌ Erro na conexão inicial:', error.message);
874
- console.log('πŸ”„ Tentando reconectar automaticamente...');
875
  });
876
 
877
- // ═══ Info final ═══
878
- console.log('βœ… Sistema inicializado com sucesso!');
879
- console.log('\n' + '═'.repeat(70));
880
- console.log('πŸ“‹ LINKS IMPORTANTES:');
881
- console.log('═'.repeat(70));
882
- console.log(`πŸ“Š Status: http://localhost:${config.PORT}`);
883
- console.log(`πŸ“± QR Code: http://localhost:${config.PORT}/qr`);
884
- console.log(`πŸ’š Health: http://localhost:${config.PORT}/health`);
885
- console.log(`πŸ› Debug: http://localhost:${config.PORT}/debug`);
886
- console.log('═'.repeat(70) + '\n');
887
-
888
- console.log('πŸ€– Aguardando conexΓ£o do WhatsApp...');
889
- console.log('πŸ”— Escaneie o QR code quando ele aparecer na pΓ‘gina web\n');
890
-
891
  } catch (error) {
892
- console.error('❌ ERRO FATAL NA INICIALIZAÇÃO:', error.message);
893
- console.error(error.stack);
894
-
895
- if (server) {
896
- server.close();
897
- }
898
-
899
  process.exit(1);
900
  }
901
  }
902
 
903
- /**
904
- * Graceful shutdown
905
- */
906
- function shutdown() {
907
- console.log('\nπŸ”΄ Recebido sinal de desligamento...');
908
-
909
- if (server) {
910
- console.log('🌐 Fechando servidor web...');
911
- server.close(() => {
912
- console.log('βœ… Servidor web fechado');
913
- process.exit(0);
914
- });
915
-
916
- setTimeout(() => {
917
- console.log('⚠️ Timeout no fechamento do servidor');
918
- process.exit(1);
919
- }, 5000);
920
- } else {
921
- process.exit(0);
922
- }
923
- }
924
 
925
- /**
926
- * Tratamento de erros nΓ£o capturados
927
- */
928
- process.on('unhandledRejection', (err) => {
929
- console.error('❌ UNHANDLED REJECTION:', err);
930
  });
931
 
932
  process.on('uncaughtException', (err) => {
933
- console.error('❌ UNCAUGHT EXCEPTION:', err);
934
- process.exit(1);
935
  });
936
 
937
- // ═══════════════════════════════════════════════════════════════════════
938
- // HANDLERS PARA SHUTDOWN
939
- // ═══════════════════════════════════════════════════════════════════════
940
- process.on('SIGINT', shutdown);
941
- process.on('SIGTERM', shutdown);
942
-
943
- // ═══════════════════════════════════════════════════════════════════════
944
- // INICIALIZAÇÃO
945
- // ═══════════════════════════════════════════════════════════════════════
946
  if (require.main === module) {
947
- main().catch(error => {
948
- console.error('❌ Erro ao iniciar:', error);
949
- process.exit(1);
950
- });
951
  }
952
 
953
  module.exports = { botCore, app, config };
 
1
  /**
2
  * ═══════════════════════════════════════════════════════════════════════
3
+ * AKIRA BOT V21 β€” ARQUITETURA PRINCIPAL (HF SPACES EDITION)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  * ═══════════════════════════════════════════════════════════════════════
5
  */
6
 
7
  // ═══════════════════════════════════════════════════════════════════════
8
+ // 1. CRÍTICO: INICIALIZA CORREÇÕES DE DNS ANTES DE TUDO
9
  // ═══════════════════════════════════════════════════════════════════════
10
+ // Isso forΓ§a o uso dos IPs diretos definidos no HFCorrections.js
11
+ // impedindo o erro ENOTFOUND/ENODATA no container.
12
+ const HFCorrections = require('./HFCorrections');
13
+ HFCorrections.configureDNS();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  // ═══════════════════════════════════════════════════════════════════════
16
+ // 2. IMPORTS E CONFIGURAÇÃO
17
  // ═══════════════════════════════════════════════════════════════════════
 
 
18
  const express = require('express');
19
  const QRCode = require('qrcode');
20
+ const ConfigManager = require('./ConfigManager');
21
+ const BotCore = require('./BotCore');
 
 
 
 
22
 
23
  const config = ConfigManager.getInstance();
24
  let botCore = null;
25
  let app = null;
26
  let server = null;
27
 
28
+ // ═══════════════════════════════════════════════════════════════════════
29
+ // 3. SERVIDOR EXPRESS (INTERFACE WEB)
30
+ // ═══════════════════════════════════════════════════════════════════════
31
+
32
  function initializeServer() {
33
  app = express();
34
  app.use(express.json());
35
 
36
+ // Middleware de log simples
37
  app.use((req, res, next) => {
38
+ // console.log(`[WEB] ${req.method} ${req.path}`); // Descomente para debug web
 
 
 
 
 
39
  next();
40
  });
41
 
42
+ // ROTA PRINCIPAL: Status visual
43
  app.get('/', (req, res) => {
44
  if (!botCore) {
45
+ return res.send('<h1 style="font-family:monospace">πŸš€ Inicializando Akira Bot... aguarde.</h1><meta http-equiv="refresh" content="3">');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  }
47
 
48
  const status = botCore.getStatus();
49
  const qr = botCore.getQRCode();
 
 
50
  const hasQR = qr !== null && qr !== undefined;
51
+
52
  res.send(`
53
  <!DOCTYPE html>
54
  <html>
55
  <head>
56
  <title>πŸ€– Akira Bot V21</title>
57
+ <meta http-equiv="refresh" content="5">
58
+ <meta name="viewport" content="width=device-width, initial-scale=1">
59
  <style>
60
+ body { background: #0d1117; color: #e6edf3; font-family: 'Consolas', monospace; padding: 20px; text-align: center; }
61
+ .card { background: #161b22; border: 1px solid #30363d; border-radius: 10px; padding: 20px; max-width: 600px; margin: 0 auto; }
62
+ h1 { color: #58a6ff; }
63
+ .status-box { padding: 10px; margin: 10px 0; border-radius: 5px; font-weight: bold; }
64
+ .online { background: rgba(46, 160, 67, 0.2); color: #3fb950; border: 1px solid #2ea043; }
65
+ .offline { background: rgba(248, 81, 73, 0.2); color: #f85149; border: 1px solid #f85149; }
66
+ .btn { display: inline-block; padding: 10px 20px; margin: 10px; background: #238636; color: white; text-decoration: none; border-radius: 5px; }
67
+ .footer { margin-top: 20px; font-size: 0.8em; color: #8b949e; }
 
 
 
68
  </style>
69
  </head>
70
  <body>
71
+ <div class="card">
72
  <h1>πŸ€– AKIRA BOT V21</h1>
73
+
74
+ <div class="status-box ${status.isConnected ? 'online' : 'offline'}">
75
+ STATUS: ${status.isConnected ? 'βœ… CONECTADO' : '❌ DESCONECTADO'}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  </div>
77
+
78
+ <p>
79
+ <strong>Bot:</strong> ${config.BOT_NAME}<br>
80
+ <strong>VersΓ£o:</strong> ${config.BOT_VERSION}
81
+ </p>
82
+
83
+ ${!status.isConnected ? `
84
+ <div style="margin: 20px 0;">
85
+ ${hasQR
86
+ ? '<a href="/qr" class="btn">πŸ“± ESCANEAR QR CODE</a>'
87
+ : '⏳ Gerando QR Code... aguarde...'}
88
+ </div>
89
+ <p style="color: #f85149">O QR Code expira rapidamente. Se sumir, aguarde ele recarregar.</p>
90
+ ` : `
91
+ <p>Bot operando normalmente.</p>
92
+ `}
93
+
94
+ <div class="footer">
95
+ Hugging Face Spaces β€’ Porta ${config.PORT}
96
  </div>
97
  </div>
98
  </body>
 
100
  `);
101
  });
102
 
103
+ // ROTA QR: Exibe apenas a imagem do QR
104
  app.get('/qr', async (req, res) => {
105
+ if (!botCore) return res.send('Inicializando...');
106
+
107
+ const qr = botCore.getQRCode();
108
+
109
+ if (botCore.isConnected) {
110
+ return res.send('<h2 style="color:green; font-family:monospace; text-align:center">βœ… BOT JÁ CONECTADO!</h2>');
111
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
+ if (!qr) {
114
+ return res.send(`
115
+ <div style="font-family:monospace; text-align:center">
116
+ <h2>πŸ”„ Gerando novo QR Code...</h2>
117
+ <p>Aguarde 5 segundos...</p>
118
+ <script>setTimeout(() => window.location.reload(), 3000);</script>
119
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  `);
121
  }
 
122
 
 
 
123
  try {
124
+ const img = await QRCode.toDataURL(qr, { scale: 8, margin: 4 });
 
 
 
 
 
 
125
  res.send(`
126
+ <div style="text-align:center; background: #fff; padding: 20px; height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center;">
127
+ <h2 style="font-family: sans-serif; margin-bottom: 20px;">Escaneie com o WhatsApp</h2>
128
+ <img src="${img}" style="max-width: 100%; border: 1px solid #ccc;">
129
+ <br>
130
+ <p style="font-family: sans-serif;">Atualiza automaticamente</p>
131
+ <script>setTimeout(() => window.location.reload(), 15000);</script>
132
+ </div>
 
 
 
 
 
 
 
133
  `);
134
+ } catch (e) {
135
+ res.status(500).send('Erro ao gerar imagem QR');
 
136
  }
137
  });
138
 
139
+ // ROTA HEALTH: Para uptime checks
140
  app.get('/health', (req, res) => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  res.json({
142
+ status: botCore?.isConnected ? 'online' : 'offline',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  timestamp: new Date().toISOString()
144
  });
145
  });
146
 
147
+ // Inicializa servidor
148
  server = app.listen(config.PORT, '0.0.0.0', () => {
149
+ console.log('\n' + '═'.repeat(50));
150
+ console.log(`🌐 SERVIDOR WEB INICIADO`);
151
+ console.log(`πŸ”— URL: http://localhost:${config.PORT}`);
152
+ console.log('═'.repeat(50) + '\n');
153
  });
 
 
154
  }
155
 
156
+ // ═══════════════════════════════════════════════════════���═══════════════
157
+ // 4. FUNÇÃO PRINCIPAL (MAIN LOOP)
158
+ // ═══════════════════════════════════════════════════════════════════════
159
+
160
  async function main() {
161
  try {
162
+ console.log('\n' + '═'.repeat(50));
163
+ console.log('πŸš€ INICIANDO AKIRA BOT V21 (HF SPACES)');
164
+ console.log('═'.repeat(50));
165
 
166
+ // 1. Instancia o BotCore
167
+ console.log('πŸ”§ Carregando nΓΊcleo...');
168
  botCore = new BotCore();
169
+
170
+ // 2. Inicializa pastas e componentes
171
  await botCore.initialize();
172
+
173
+ // 3. Sobe o servidor Web (para mostrar QR)
 
 
174
  initializeServer();
 
175
 
176
+ // 4. Conecta ao WhatsApp (em background)
177
+ // Usamos .catch para que erros de conexΓ£o nΓ£o derrubem o servidor web
178
+ console.log('πŸ”— Iniciando conexΓ£o com WhatsApp...');
179
+ botCore.connect().catch(err => {
180
+ console.error('❌ Erro na primeira tentativa de conexão:', err.message);
181
+ console.log('πŸ”„ O sistema tentarΓ‘ reconectar automaticamente...');
 
 
 
 
182
  });
183
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  } catch (error) {
185
+ console.error('❌ ERRO FATAL NO MAIN:', error);
 
 
 
 
 
 
186
  process.exit(1);
187
  }
188
  }
189
 
190
+ // ═══════════════════════════════════════════════════════════════════════
191
+ // 5. ENCERRAMENTO SEGURO
192
+ // ═══════════════════════════════════════════════════════════════════════
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
 
194
+ process.on('SIGINT', () => {
195
+ console.log('\nπŸ›‘ Encerrando bot...');
196
+ if (server) server.close();
197
+ process.exit(0);
 
198
  });
199
 
200
  process.on('uncaughtException', (err) => {
201
+ console.error('❌ ERRO NΓƒO TRATADO:', err);
202
+ // NΓ£o sai do processo para manter o container vivo se possΓ­vel
203
  });
204
 
205
+ // Executa
 
 
 
 
 
 
 
 
206
  if (require.main === module) {
207
+ main();
 
 
 
208
  }
209
 
210
  module.exports = { botCore, app, config };