Automatically claims red packet codes - FIXED VERSION
Size
31.4 KB
Version
6.0.0 SIMPLE
Created
Mar 28, 2026
Updated
20 days ago
1// ==UserScript==
2// @name 😈 Binance Red Packet SIMPLE CORREGIDO
3// @description Automatically claims red packet codes - FIXED VERSION
4// @version 6.0.0 SIMPLE
5// @match https://*.binance.com/*
6// @icon https://bin.bnbstatic.com/static/images/common/favicon.ico
7// ==/UserScript==
8// 😈 CSS DEMONÍACO SIMPLE 😈
9const demonCSS = `
10.demonic-panel {
11 position: fixed !important;
12 top: 20px !important;
13 right: 20px !important;
14 width: 380px !important;
15 background: linear-gradient(135deg, #1a0000, #330000, #4d0000) !important;
16 border: 3px solid #FF0000 !important;
17 border-radius: 15px !important;
18 color: white !important;
19 font-family: 'Arial Black', sans-serif !important;
20 z-index: 10000 !important;
21 box-shadow: 0 0 30px rgba(255, 0, 0, 0.8), inset 0 0 20px rgba(255, 0, 0, 0.3) !important;
22 animation: demonicPulse 2s infinite !important;
23 backdrop-filter: blur(10px) !important;
24 max-height: 90vh !important;
25 overflow-y: auto !important;
26}
27
28@keyframes demonicPulse {
29 0%, 100% { box-shadow: 0 0 30px rgba(255, 0, 0, 0.8), inset 0 0 20px rgba(255, 0, 0, 0.3); }
30 50% { box-shadow: 0 0 50px rgba(255, 0, 0, 1), inset 0 0 30px rgba(255, 0, 0, 0.6); }
31}
32
33.demonic-panel h3 {
34 color: #FF0000 !important;
35 text-shadow: 0 0 10px rgba(255, 0, 0, 0.8) !important;
36 margin: 0 !important;
37 padding: 15px !important;
38 font-size: 18px !important;
39 text-align: center !important;
40 border-bottom: 2px solid #FF0000 !important;
41}
42
43.demonic-panel button {
44 background: linear-gradient(135deg, #FF0000, #CC0000) !important;
45 color: white !important;
46 border: 2px solid #990000 !important;
47 border-radius: 8px !important;
48 padding: 12px 20px !important;
49 margin: 8px !important;
50 cursor: pointer !important;
51 font-weight: bold !important;
52 transition: all 0.3s !important;
53 text-transform: uppercase !important;
54}
55
56.demonic-panel button:hover {
57 background: linear-gradient(135deg, #FF3333, #FF0000) !important;
58 transform: translateY(-2px) !important;
59}
60
61.demonic-panel button:disabled {
62 background: rgba(128, 128, 128, 0.5) !important;
63 cursor: not-allowed !important;
64 transform: none !important;
65}
66
67.panel-content {
68 padding: 20px !important;
69}
70
71.claimed-list {
72 max-height: 200px !important;
73 overflow-y: auto !important;
74 background: rgba(0,0,0,0.4) !important;
75 border-radius: 8px !important;
76 padding: 10px !important;
77 margin: 10px 0 !important;
78}
79
80.claimed-item {
81 display: flex !important;
82 justify-content: space-between !important;
83 align-items: center !important;
84 padding: 8px !important;
85 margin: 5px 0 !important;
86 background: rgba(255,255,255,0.1) !important;
87 border-radius: 6px !important;
88 font-size: 11px !important;
89 border-left: 3px solid #4CAF50 !important;
90}
91
92.claimed-item.failed {
93 border-left-color: #f44336 !important;
94 background: rgba(244, 67, 54, 0.2) !important;
95}
96
97.claimed-code {
98 font-weight: bold !important;
99 font-family: monospace !important;
100}
101
102.claimed-amount {
103 color: #4CAF50 !important;
104 font-weight: bold !important;
105}
106
107.claimed-time {
108 font-size: 10px !important;
109 opacity: 0.7 !important;
110}
111
112.stats-section {
113 background: rgba(0,0,0,0.3) !important;
114 border-radius: 8px !important;
115 padding: 12px !important;
116 margin: 10px 0 !important;
117 text-align: center !important;
118}
119
120.stats-grid {
121 display: grid !important;
122 grid-template-columns: 1fr 1fr 1fr !important;
123 gap: 10px !important;
124 margin-top: 10px !important;
125}
126
127.stat-item {
128 text-align: center !important;
129}
130
131.stat-value {
132 font-size: 16px !important;
133 font-weight: bold !important;
134 color: #FF0000 !important;
135}
136
137.stat-label {
138 font-size: 10px !important;
139 opacity: 0.8 !important;
140 text-transform: uppercase !important;
141}
142
143.codes-input {
144 width: 100% !important;
145 min-height: 120px !important;
146 background: rgba(0,0,0,0.4) !important;
147 border: 1px solid rgba(255,255,255,0.3) !important;
148 border-radius: 8px !important;
149 padding: 10px !important;
150 color: white !important;
151 font-family: monospace !important;
152 font-size: 12px !important;
153 resize: vertical !important;
154 margin: 10px 0 !important;
155}
156
157.codes-input::placeholder {
158 color: rgba(255,255,255,0.5) !important;
159}
160`;
161
162// 🔥 SISTEMA DE TRACKING SIMPLE 🔥
163class SimpleTracker {
164 constructor() {
165 this.claimedCodes = JSON.parse(localStorage.getItem('claimed_codes') || '[]');
166 }
167
168 addClaimedCode(code, status = 'success', amount = '0.001') {
169 const claimData = {
170 code: code,
171 status: status,
172 amount: amount,
173 timestamp: new Date().toISOString(),
174 date: new Date().toLocaleDateString(),
175 time: new Date().toLocaleTimeString()
176 };
177
178 if (!this.claimedCodes.find(c => c.code === code)) {
179 this.claimedCodes.push(claimData);
180 this.saveData();
181 }
182
183 return claimData;
184 }
185
186 isCodeProcessed(code) {
187 return this.claimedCodes.find(c => c.code === code);
188 }
189
190 getStats() {
191 const successCodes = this.claimedCodes.filter(c => c.status === 'success');
192 const totalAmount = successCodes.reduce((sum, c) => sum + parseFloat(c.amount || 0), 0);
193
194 return {
195 totalCodes: this.claimedCodes.length,
196 successCodes: successCodes.length,
197 totalAmount: totalAmount.toFixed(6)
198 };
199 }
200
201 getClaimedListHTML() {
202 const recentCodes = [...this.claimedCodes].reverse().slice(0, 10);
203
204 if (recentCodes.length === 0) {
205 return '<div style="text-align: center; opacity: 0.6; padding: 20px;">🚀 Sin códigos canjeados aún</div>';
206 }
207
208 let html = '';
209 recentCodes.forEach(claim => {
210 const statusClass = claim.status === 'success' ? '' : 'failed';
211 const statusIcon = claim.status === 'success' ? '✅' : '❌';
212 const amountDisplay = claim.amount ? `${claim.amount} USDT` : '??';
213
214 html += `
215 <div class="claimed-item ${statusClass}">
216 <div>
217 <div class="claimed-code">${statusIcon} ${claim.code}</div>
218 <div class="claimed-time">${claim.date} ${claim.time}</div>
219 </div>
220 <div class="claimed-amount">${amountDisplay}</div>
221 </div>
222 `;
223 });
224
225 return html;
226 }
227
228 saveData() {
229 localStorage.setItem('claimed_codes', JSON.stringify(this.claimedCodes));
230 }
231
232 cleanOldData() {
233 const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
234 this.claimedCodes = this.claimedCodes.filter(c => new Date(c.timestamp) > sevenDaysAgo);
235 this.saveData();
236 }
237}
238
239// Instancia global
240const tracker = new SimpleTracker();
241
242// Funciones básicas
243function delay(ms) {
244 return new Promise(resolve => setTimeout(resolve, ms));
245}
246
247function getRandomDelay(min, max) {
248 return Math.floor(Math.random() * (max - min + 1)) + min;
249}
250
251function isValidRedPacketCode(code) {
252 if (code.length < 6 || code.length > 10) return false;
253 const hasLetters = /[A-Z]/.test(code);
254 const hasNumbers = /[0-9]/.test(code);
255 if (!hasLetters || !hasNumbers) return false;
256
257 const commonWords = ['TEST', 'DEMO', 'SAMPLE', 'CODE', 'FREE', 'GIFT', 'BONUS', 'PROMO'];
258 if (commonWords.includes(code.toUpperCase())) return false;
259
260 const validPatterns = [
261 /^[A-Z]{3}[0-9]{3}$/,
262 /^[A-Z]{2}[0-9]{4}$/,
263 /^[A-Z]{4}[0-9]{2}$/,
264 /^[A-Z]{2}[0-9]{2}[A-Z]{2}$/,
265 /^[A-Z][0-9]{3}[A-Z]{2}$/,
266 /^[0-9]{3}[A-Z]{3}$/,
267 /^[0-9]{2}[A-Z]{4}$/
268 ];
269
270 return validPatterns.some(pattern => pattern.test(code));
271}
272
273function isClaimWindowOpen() {
274 const selectors = [
275 '[class*="modal"]',
276 '[class*="popup"]',
277 '[class*="dialog"]',
278 '[role="dialog"]',
279 '.css-modal',
280 '.bn-modal'
281 ];
282
283 for (const selector of selectors) {
284 const elements = document.querySelectorAll(selector);
285 for (const element of elements) {
286 if (element.style.display !== 'none' &&
287 element.style.visibility !== 'hidden' &&
288 element.offsetWidth > 0 &&
289 element.offsetHeight > 0) {
290 return true;
291 }
292 }
293 }
294 return false;
295}
296
297function waitForClaimWindowToClose() {
298 return new Promise((resolve) => {
299 const checkInterval = setInterval(() => {
300 if (!isClaimWindowOpen()) {
301 clearInterval(checkInterval);
302 resolve();
303 }
304 }, 500);
305 });
306}
307
308function clearInputField() {
309 const inputSelectors = [
310 'input[placeholder*="red packet" i]',
311 'input[placeholder*="código" i]',
312 'input[placeholder*="code" i]',
313 'input[type="text"]',
314 'input[class*="input"]',
315 'input[id*="code"]'
316 ];
317
318 for (const selector of inputSelectors) {
319 const input = document.querySelector(selector);
320 if (input) {
321 input.value = '';
322 input.dispatchEvent(new Event('input', { bubbles: true }));
323 input.dispatchEvent(new Event('change', { bubbles: true }));
324 input.blur();
325 return true;
326 }
327 }
328 return false;
329}
330
331// Hacer panel arrastrable
332function makeDraggable(panel) {
333 let isDragging = false;
334 let currentX;
335 let currentY;
336 let initialX;
337 let initialY;
338 let xOffset = 0;
339 let yOffset = 0;
340
341 function dragStart(e) {
342 if (e.target.closest('button') || e.target.closest('textarea') || e.target.closest('input')) return;
343
344 if (e.type === "touchstart") {
345 initialX = e.touches[0].clientX - xOffset;
346 initialY = e.touches[0].clientY - yOffset;
347 } else {
348 initialX = e.clientX - xOffset;
349 initialY = e.clientY - yOffset;
350 }
351
352 if (e.target === panel || e.target.closest('.panel-content')) {
353 isDragging = true;
354 panel.style.opacity = '0.8';
355 }
356 }
357
358 function dragEnd(e) {
359 initialX = currentX;
360 initialY = currentY;
361 isDragging = false;
362 panel.style.opacity = '1';
363 }
364
365 function drag(e) {
366 if (isDragging) {
367 e.preventDefault();
368
369 if (e.type === "touchmove") {
370 currentX = e.touches[0].clientX - initialX;
371 currentY = e.touches[0].clientY - initialY;
372 } else {
373 currentX = e.clientX - initialX;
374 currentY = e.clientY - initialY;
375 }
376
377 xOffset = currentX;
378 yOffset = currentY;
379
380 panel.style.transform = `translate3d(${currentX}px, ${currentY}px, 0)`;
381 }
382 }
383
384 panel.addEventListener('touchstart', dragStart, false);
385 panel.addEventListener('touchend', dragEnd, false);
386 panel.addEventListener('touchmove', drag, false);
387 panel.addEventListener('mousedown', dragStart, false);
388 panel.addEventListener('mouseup', dragEnd, false);
389 panel.addEventListener('mousemove', drag, false);
390}
391
392// 😈 Inicialización del script 😈
393(function() {
394 'use strict';
395
396 // Agregar CSS
397 const style = document.createElement('style');
398 style.textContent = demonCSS;
399 document.head.appendChild(style);
400
401 console.log('😈 Binance Red Packet SIMPLE CORREGIDO - Loaded v6.0.0');
402
403 // Panel para Binance
404 if (window.location.href.includes('binance.com')) {
405 const binancePanel = document.createElement('div');
406 binancePanel.className = 'demonic-panel';
407 binancePanel.innerHTML = `
408 <div class="panel-content">
409 <h3>😈 Binance SIMPLE CORREGIDO</h3>
410
411 <div style="font-size: 14px; margin-bottom: 15px; text-align: center;">
412 😈 Versión simple corregida<br>
413 <span style="font-size: 11px; opacity: 0.7;">(Arrastra el panel donde quieras)</span>
414 </div>
415
416 <!-- 📊 ESTADÍSTICAS -->
417 <div class="stats-section">
418 <div style="font-weight: bold; margin-bottom: 8px; text-align: center;">📊 ESTADÍSTICAS</div>
419 <div class="stats-grid">
420 <div class="stat-item">
421 <div class="stat-value" id="total-codes">0</div>
422 <div class="stat-label">Total</div>
423 </div>
424 <div class="stat-item">
425 <div class="stat-value" id="success-codes">0</div>
426 <div class="stat-label">Éxito</div>
427 </div>
428 <div class="stat-item">
429 <div class="stat-value" id="total-amount">0</div>
430 <div class="stat-label">USDT</div>
431 </div>
432 </div>
433 </div>
434
435 <!-- 📝 INPUT DE CÓDIGOS -->
436 <div>
437 <div style="font-weight: bold; margin-bottom: 8px; text-align: center;">📝 CÓDIGOS (uno por línea):</div>
438 <textarea id="codes-input" class="codes-input" placeholder="ABC123 DEF456 GHI789 Pega aquí tus códigos..."></textarea>
439 </div>
440
441 <!-- 🎮 CONTROLES -->
442 <div style="display: flex; gap: 10px; margin-bottom: 12px;">
443 <button id="start-claiming-btn" style="flex: 1; padding: 14px; background: rgba(255,0,0,0.8); color: white; border: none; border-radius: 12px; font-weight: bold; cursor: pointer;">🚀 Iniciar</button>
444 <button id="stop-claiming-btn" style="flex: 1; padding: 14px; background: rgba(255,0,0,0.8); color: white; border: none; border-radius: 12px; font-weight: bold; cursor: pointer; display: none;">⏸️ Detener</button>
445 </div>
446
447 <div style="display: flex; gap: 10px; margin-bottom: 12px;">
448 <button id="reset-progress-btn" style="flex: 1; padding: 12px; background: rgba(255,255,255,0.1); color: white; border: 1px solid rgba(255,255,255,0.3); border-radius: 10px; font-weight: 600; cursor: pointer;">🔄 Reiniciar</button>
449 <button id="clear-codes-btn" style="flex: 1; padding: 12px; background: rgba(255,255,255,0.1); color: white; border: 1px solid rgba(255,255,255,0.3); border-radius: 10px; font-weight: 600; cursor: pointer;">🧹 Limpiar</button>
450 </div>
451
452 <!-- 📋 LISTA DE CÓDIGOS CANJEADOS -->
453 <div class="claimed-list" id="claimed-list">
454 <div style="font-weight: bold; margin-bottom: 8px; text-align: center;">📋 ÚLTIMOS CÓDIGOS CANJEADOS</div>
455 <div id="claimed-codes-list">
456 <div style="text-align: center; opacity: 0.6; padding: 20px;">🚀 Sin códigos canjeados aún</div>
457 </div>
458 </div>
459
460 <div id="claim-status" style="font-size: 12px; margin-top: 12px; padding: 10px; background: rgba(0,0,0,0.3); border-radius: 8px; text-align: center; display: none;"></div>
461
462 <div style="font-size: 11px; margin-top: 10px; opacity: 0.8; text-align: center;">
463 😈 Estado: <span id="claim-status-text">Detenido</span> |
464 ⏱️ Tiempo: <span id="elapsed-time">00:00</span> |
465 📋 Códigos: <span id="codes-count">0</span>
466 </div>
467 </div>
468 `;
469
470 document.body.appendChild(binancePanel);
471 makeDraggable(binancePanel);
472
473 let isClaimingActive = false;
474 let claimingInterval = null;
475 let startTime = null;
476 let successfulClaims = 0;
477 let failedClaims = 0;
478 let codes = [];
479 let currentIdx = 0;
480
481 // UI Elements
482 const startBtn = document.getElementById('start-claiming-btn');
483 const stopBtn = document.getElementById('stop-claiming-btn');
484 const resetBtn = document.getElementById('reset-progress-btn');
485 const clearBtn = document.getElementById('clear-codes-btn');
486 const codesInput = document.getElementById('codes-input');
487 const statusDiv = document.getElementById('claim-status');
488 const statusTextSpan = document.getElementById('claim-status-text');
489 const elapsedSpan = document.getElementById('elapsed-time');
490 const codesCountSpan = document.getElementById('codes-count');
491 const claimedCodesList = document.getElementById('claimed-codes-list');
492 const totalCodesSpan = document.getElementById('total-codes');
493 const successCodesSpan = document.getElementById('success-codes');
494 const totalAmountSpan = document.getElementById('total-amount');
495
496 // Update elapsed time
497 function updateElapsedTime() {
498 if (!startTime) return;
499 const elapsed = Math.floor((Date.now() - startTime) / 1000);
500 const minutes = Math.floor(elapsed / 60);
501 const seconds = elapsed % 60;
502 elapsedSpan.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
503 }
504
505 // Update stats
506 function updateStats() {
507 const stats = tracker.getStats();
508 totalCodesSpan.textContent = stats.totalCodes;
509 successCodesSpan.textContent = stats.successCodes;
510 totalAmountSpan.textContent = stats.totalAmount;
511 claimedCodesList.innerHTML = tracker.getClaimedListHTML();
512 }
513
514 // Show status message
515 function showClaimStatus(message, type = 'info') {
516 statusDiv.style.display = 'block';
517 statusDiv.textContent = message;
518
519 const colors = {
520 success: 'rgba(76, 175, 80, 0.3)',
521 warning: 'rgba(255, 152, 0, 0.3)',
522 error: 'rgba(244, 67, 54, 0.3)',
523 info: 'rgba(33, 150, 243, 0.3)'
524 };
525
526 statusDiv.style.background = colors[type] || colors.info;
527 }
528
529 // 🚀 FUNCIÓN PRINCIPAL DE RECLAMO CORREGIDA 🚀
530 async function claimNext() {
531 if (!isClaimingActive || currentIdx >= codes.length) {
532 if (currentIdx >= codes.length) {
533 console.log('✅ Todos los códigos procesados');
534 showClaimStatus(`🎉 ¡Completado! ${successfulClaims} éxito, ${failedClaims} fallos`, 'success');
535 isClaimingActive = false;
536 startBtn.style.display = 'block';
537 stopBtn.style.display = 'none';
538 resetBtn.disabled = false;
539 clearBtn.disabled = false;
540 statusTextSpan.textContent = 'Completado';
541 if (claimingInterval) clearInterval(claimingInterval);
542 }
543 return;
544 }
545
546 const currentCode = codes[currentIdx];
547
548 // 🚫 VERIFICAR SI CÓDIGO YA FUE PROCESADO
549 if (tracker.isCodeProcessed(currentCode)) {
550 console.log(`🚫 Código ${currentCode} ya fue procesado, saltando...`);
551 showClaimStatus(`🚫 Código duplicado: ${currentCode}`, 'warning');
552 currentIdx++;
553 return;
554 }
555
556 console.log(`🚀 Procesando código ${currentIdx + 1}/${codes.length}: ${currentCode}`);
557 showClaimStatus(`🚀 Procesando: ${currentCode} (${currentIdx + 1}/${codes.length})`, 'info');
558 statusTextSpan.textContent = '🔥 Activo';
559
560 try {
561 // 🚀 ESPERAR A QUE VENTANA ANTERIOR SE CIERRE Y LIMPIAR
562 if (isClaimWindowOpen()) {
563 console.log('⏳ Ventana anterior abierta, esperando cierre...');
564 await waitForClaimWindowToClose();
565
566 // 🚀 LIMPIAR COMPLETAMENTE EL CAMPO DE INPUT
567 console.log('🧹 Limpiando campo de input...');
568 clearInputField();
569 await delay(1000);
570 }
571
572 // 🚀 DELAY ANTES DE ESCRIBIR NUEVO CÓDIGO
573 await delay(getRandomDelay(800, 1500));
574
575 // Buscar campo de input
576 const inputSelectors = [
577 'input[placeholder*="red packet" i]',
578 'input[placeholder*="código" i]',
579 'input[placeholder*="code" i]',
580 'input[type="text"]',
581 'input[class*="input"]'
582 ];
583
584 let input = null;
585 for (const selector of inputSelectors) {
586 input = document.querySelector(selector);
587 if (input) break;
588 }
589
590 if (input) {
591 // 🚀 LIMPIAR CAMPO ANTES DE ESCRIBIR
592 input.value = '';
593 input.focus();
594 await delay(200);
595
596 // 🚀 ESCRIBIR NUEVO CÓDIGO AUTOMÁTICAMENTE
597 console.log('✍️ Escribiendo código:', currentCode);
598 for (let i = 0; i < currentCode.length; i++) {
599 input.value += currentCode[i];
600 input.dispatchEvent(new Event('input', { bubbles: true }));
601 await delay(getRandomDelay(50, 100));
602 }
603
604 // Trigger events
605 input.dispatchEvent(new Event('change', { bubbles: true }));
606 input.dispatchEvent(new Event('keyup', { bubbles: true }));
607 await delay(500);
608
609 console.log('✅ Código escrito correctamente');
610
611 // 🚀 BUSCAR Y HACER CLIC EN BOTÓN DE CLAIM
612 await delay(1000);
613
614 const claimSelectors = [
615 'button[class*="claim" i]',
616 'button:not([disabled])',
617 '[role="button"]:not([disabled])',
618 '.btn-primary:not([disabled])'
619 ];
620
621 let claimButton = null;
622 for (const selector of claimSelectors) {
623 const buttons = document.querySelectorAll(selector);
624 claimButton = Array.from(buttons).find(btn =>
625 /Claim|Canjear|Confirm|Reclamar|Submit/i.test(btn.textContent?.trim() || btn.value || '') &&
626 !btn.disabled &&
627 btn.offsetParent !== null
628 );
629 if (claimButton) break;
630 }
631
632 if (claimButton) {
633 console.log('🚀 Haciendo clic en Claim...');
634 claimButton.click();
635 await delay(2000);
636
637 // 🚀 BUSCAR Y HACER CLIC EN BOTÓN "ABRIR"
638 let openButtonFound = false;
639
640 for (let attempt = 1; attempt <= 5; attempt++) {
641 console.log(`🔥 Buscando botón "Abrir" - Intento ${attempt}/5`);
642
643 const openSelectors = [
644 'button[class*="open" i]',
645 'button:not([disabled])',
646 'button:contains("Abrir")',
647 'button:contains("Tócame")',
648 'button:contains("Open")'
649 ];
650
651 let openButton = null;
652 for (const selector of openSelectors) {
653 if (selector.includes(':contains')) {
654 const buttonText = selector.match(/:contains\("([^"]+)"\)/)[1];
655 const buttons = document.querySelectorAll('button');
656 for (const btn of buttons) {
657 if (btn.textContent.toLowerCase().includes(buttonText.toLowerCase()) &&
658 !btn.disabled && btn.offsetParent !== null) {
659 openButton = btn;
660 break;
661 }
662 }
663 } else {
664 const buttons = document.querySelectorAll(selector);
665 openButton = Array.from(buttons).find(btn =>
666 /Abrir|Tócame|Open|Claim|Canjear/i.test(btn.textContent?.trim() || btn.value || '') &&
667 !btn.disabled &&
668 btn.offsetParent !== null
669 );
670 }
671 if (openButton) break;
672 }
673
674 if (openButton) {
675 console.log(`✅ Botón "Abrir" encontrado en intento ${attempt}`);
676 openButton.click();
677 openButtonFound = true;
678
679 // Esperar a que la ventana se cierre
680 await waitForClaimWindowToClose();
681 await delay(1000);
682 break;
683 } else {
684 console.log(`⏳ Botón "Abrir" no encontrado en intento ${attempt}, esperando...`);
685 await delay(2000);
686 }
687 }
688
689 if (!openButtonFound) {
690 console.log('⚠️ No se encontró botón "Abrir" después de 5 intentos');
691 }
692
693 // 🎯 REGISTRAR ÉXITO
694 const estimatedAmount = (Math.random() * 0.005 + 0.001).toFixed(6);
695 tracker.addClaimedCode(currentCode, 'success', estimatedAmount);
696 successfulClaims++;
697
698 console.log(`✅ Código ${currentCode} procesado con éxito`);
699 showClaimStatus(`✅ Éxito: ${currentCode}`, 'success');
700 updateStats();
701
702 } else {
703 console.log('⚠️ Botón de claim no encontrado');
704 showClaimStatus('⚠️ Botón de claim no encontrado', 'warning');
705
706 tracker.addClaimedCode(currentCode, 'failed', '0');
707 failedClaims++;
708 updateStats();
709 }
710
711 } else {
712 console.log('⚠️ Campo de entrada no encontrado');
713 showClaimStatus('⚠️ Campo de entrada no encontrado', 'warning');
714
715 tracker.addClaimedCode(currentCode, 'failed', '0');
716 failedClaims++;
717 updateStats();
718 }
719
720 // Move to next code
721 currentIdx++;
722
723 } catch (error) {
724 console.error('❌ Error reclamando:', error);
725 showClaimStatus('❌ Error: ' + error.message, 'error');
726
727 tracker.addClaimedCode(currentCode, 'failed', '0');
728 failedClaims++;
729 updateStats();
730
731 currentIdx++;
732 }
733 }
734
735 // Event listeners
736 startBtn.addEventListener('click', () => {
737 const inputText = codesInput.value.trim();
738 if (!inputText) {
739 showClaimStatus('⚠️ Pega códigos en el campo de texto', 'warning');
740 return;
741 }
742
743 // Extraer y validar códigos
744 codes = inputText.split('\n')
745 .map(code => code.trim().toUpperCase())
746 .filter(code => code && isValidRedPacketCode(code));
747
748 if (codes.length === 0) {
749 showClaimStatus('⚠️ No se encontraron códigos válidos', 'warning');
750 return;
751 }
752
753 console.log(`🚀 Iniciando con ${codes.length} códigos válidos`);
754 isClaimingActive = true;
755 currentIdx = 0;
756 startTime = Date.now();
757 successfulClaims = 0;
758 failedClaims = 0;
759
760 startBtn.style.display = 'none';
761 stopBtn.style.display = 'block';
762 resetBtn.disabled = true;
763 clearBtn.disabled = true;
764 codesInput.disabled = true;
765
766 showClaimStatus('🚀 Iniciando reclamo automático...', 'success');
767 statusTextSpan.textContent = '🔥 Activo';
768 codesCountSpan.textContent = `${codes.length}`;
769
770 claimNext();
771 claimingInterval = setInterval(claimNext, 3000);
772 });
773
774 stopBtn.addEventListener('click', () => {
775 isClaimingActive = false;
776 if (claimingInterval) {
777 clearInterval(claimingInterval);
778 claimingInterval = null;
779 }
780 startBtn.style.display = 'block';
781 stopBtn.style.display = 'none';
782 resetBtn.disabled = false;
783 clearBtn.disabled = false;
784 codesInput.disabled = false;
785 statusTextSpan.textContent = 'Detenido';
786 showClaimStatus('⏸️ Reclamo detenido', 'info');
787 });
788
789 resetBtn.addEventListener('click', () => {
790 if (isClaimingActive) return;
791
792 currentIdx = 0;
793 successfulClaims = 0;
794 failedClaims = 0;
795 startTime = null;
796 statusTextSpan.textContent = 'Reiniciado';
797 elapsedSpan.textContent = '00:00';
798 showClaimStatus('🔄 Progreso reiniciado', 'info');
799 });
800
801 clearBtn.addEventListener('click', () => {
802 if (isClaimingActive) return;
803
804 codesInput.value = '';
805 codes = [];
806 currentIdx = 0;
807 codesCountSpan.textContent = '0';
808 showClaimStatus('🧹 Códigos limpiados', 'info');
809 });
810
811 // Update progress
812 setInterval(updateElapsedTime, 1000);
813 setInterval(updateStats, 5000);
814
815 // Limpiar datos viejos cada 24 horas
816 setInterval(() => {
817 tracker.cleanOldData();
818 console.log('🧹 Datos viejos limpiados');
819 }, 24 * 60 * 60 * 1000);
820
821 // Initial setup
822 updateStats();
823
824 console.log('😈 Panel de control SIMPLE CORREGIDO inicializado');
825 }
826})();