Automatically extracts red packet codes from Telegram and claims them on Binance
Size
18.1 KB
Version
1.1.9
Created
Mar 22, 2026
Updated
26 days ago
1// ==UserScript==
2// @name Binance Red Packet Auto Claimer
3// @description Automatically extracts red packet codes from Telegram and claims them on Binance
4// @version 1.1.9
5// @match https://*.web.telegram.org/*
6// @match https://www.binance.com/es-MX/my/wallet/account/payment/cryptobox
7// @icon https://web.telegram.org/a/favicon.ico
8// @grant GM.getValue
9// @grant GM.setValue
10// @grant GM.deleteValue
11// ==/UserScript==
12(function() {
13 'use strict';
14
15 console.log('Binance Red Packet Auto Claimer - Extension loaded');
16
17 // Utility function to delay
18 function delay(ms) {
19 return new Promise(resolve => setTimeout(resolve, ms));
20 }
21
22 // ==================== TELEGRAM FUNCTIONALITY ====================
23
24 if (window.location.href.includes('web.telegram.org')) {
25 console.log('📡 Radar de alta precisión activado en Telegram...');
26
27 // Create control panel
28 const controlPanel = document.createElement('div');
29 controlPanel.id = 'telegram-extractor-panel';
30 controlPanel.style.cssText = `
31 position: fixed;
32 top: 80px;
33 right: 20px;
34 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
35 color: white;
36 padding: 20px;
37 border-radius: 12px;
38 box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
39 z-index: 10000;
40 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
41 min-width: 280px;
42 backdrop-filter: blur(10px);
43 `;
44
45 controlPanel.innerHTML = `
46 <div style="font-size: 16px; font-weight: bold; margin-bottom: 15px; display: flex; align-items: center; gap: 8px;">
47 <span style="font-size: 20px;">🎁</span>
48 Red Packet Extractor Ultra
49 </div>
50 <div style="font-size: 13px; margin-bottom: 15px; opacity: 0.9; line-height: 1.4;">
51 Escaneo automático cada segundo
52 </div>
53 <div id="codes-count" style="font-size: 14px; margin-bottom: 15px; padding: 10px; background: rgba(255,255,255,0.2); border-radius: 8px; text-align: center;">
54 <span style="font-size: 24px; font-weight: bold;" id="count-number">0</span>
55 <div style="font-size: 12px; margin-top: 4px; opacity: 0.9;">códigos encontrados</div>
56 </div>
57 <div id="last-code" style="font-size: 12px; margin-bottom: 15px; padding: 8px; background: rgba(255,255,255,0.15); border-radius: 6px; text-align: center; word-break: break-all;">
58 Esperando códigos...
59 </div>
60 <button id="clear-codes-btn" style="
61 width: 100%;
62 padding: 10px;
63 background: rgba(255,255,255,0.2);
64 color: white;
65 border: 1px solid rgba(255,255,255,0.3);
66 border-radius: 8px;
67 font-weight: 500;
68 cursor: pointer;
69 font-size: 13px;
70 transition: all 0.3s;
71 ">Limpiar Códigos</button>
72 <div id="status-message" style="font-size: 12px; margin-top: 12px; padding: 8px; background: rgba(255,255,255,0.15); border-radius: 6px; text-align: center; display: none;"></div>
73 `;
74
75 document.body.appendChild(controlPanel);
76
77 // Update count on load
78 (async () => {
79 const storedCodes = await GM.getValue('sync_codes', '[]');
80 const codes = JSON.parse(storedCodes);
81 document.getElementById('count-number').textContent = codes.length;
82 if (codes.length > 0) {
83 document.getElementById('last-code').textContent = 'Último: ' + codes[codes.length - 1];
84 }
85 })();
86
87 // Clear button handler
88 document.getElementById('clear-codes-btn').addEventListener('click', async () => {
89 await GM.setValue('sync_codes', '[]');
90 await GM.setValue('current_idx', 0);
91 document.getElementById('count-number').textContent = '0';
92 document.getElementById('last-code').textContent = 'Esperando códigos...';
93
94 const statusMsg = document.getElementById('status-message');
95 statusMsg.style.display = 'block';
96 statusMsg.style.background = 'rgba(255, 152, 0, 0.3)';
97 statusMsg.textContent = '✓ Todos los códigos limpiados';
98
99 setTimeout(() => {
100 statusMsg.style.display = 'none';
101 }, 2000);
102 });
103
104 // Auto-scan with improved detection
105 setInterval(async () => {
106 // Buscar en múltiples selectores para mayor cobertura
107 const messages = document.querySelectorAll('.message, .text-content, span, code, .monospace-text, .text-entity-code');
108 let codes = JSON.parse(await GM.getValue('sync_codes', '[]'));
109 let newFound = false;
110
111 messages.forEach(el => {
112 const text = el.textContent.trim();
113 // Filtro mejorado: Busca códigos de 8-10 caracteres alfanuméricos en mayúsculas
114 const matches = text.match(/\b[A-Z0-9]{8,10}\b/g);
115 if (matches) {
116 matches.forEach(code => {
117 if (!codes.includes(code)) {
118 codes.push(code);
119 newFound = true;
120 console.log('🎯 ¡Código detectado!: ' + code);
121
122 // Update UI
123 document.getElementById('count-number').textContent = codes.length;
124 document.getElementById('last-code').textContent = 'Último: ' + code;
125
126 // Show notification
127 const statusMsg = document.getElementById('status-message');
128 statusMsg.style.display = 'block';
129 statusMsg.style.background = 'rgba(76, 175, 80, 0.3)';
130 statusMsg.textContent = '✓ Nuevo código: ' + code;
131
132 setTimeout(() => {
133 statusMsg.style.display = 'none';
134 }, 3000);
135 }
136 });
137 }
138 });
139
140 if (newFound) {
141 await GM.setValue('sync_codes', JSON.stringify(codes));
142 }
143 }, 1000); // Escaneo cada segundo
144 }
145
146 // ==================== BINANCE FUNCTIONALITY ====================
147
148 if (window.location.href.includes('binance.com') && window.location.href.includes('/my/wallet/account/payment/cryptobox')) {
149 console.log('🚀 Auto-claimer activado en Binance...');
150
151 // Create control panel
152 const controlPanel = document.createElement('div');
153 controlPanel.id = 'binance-claimer-panel';
154 controlPanel.style.cssText = `
155 position: fixed;
156 top: 80px;
157 right: 20px;
158 background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
159 color: white;
160 padding: 20px;
161 border-radius: 12px;
162 box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
163 z-index: 10000;
164 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
165 min-width: 300px;
166 backdrop-filter: blur(10px);
167 `;
168
169 controlPanel.innerHTML = `
170 <div style="font-size: 16px; font-weight: bold; margin-bottom: 15px; display: flex; align-items: center; gap: 8px;">
171 <span style="font-size: 20px;">🎁</span>
172 Auto Claimer Ultra
173 </div>
174 <div style="font-size: 13px; margin-bottom: 15px; opacity: 0.9; line-height: 1.4;">
175 Reclamando automáticamente cada 4 segundos
176 </div>
177 <div id="progress-info" style="font-size: 14px; margin-bottom: 15px; padding: 12px; background: rgba(255,255,255,0.2); border-radius: 8px;">
178 <div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
179 <span>Progreso:</span>
180 <span id="progress-text" style="font-weight: bold;">0/0</span>
181 </div>
182 <div style="width: 100%; height: 8px; background: rgba(255,255,255,0.3); border-radius: 4px; overflow: hidden;">
183 <div id="progress-bar" style="width: 0%; height: 100%; background: white; transition: width 0.3s;"></div>
184 </div>
185 </div>
186 <div id="current-code" style="font-size: 12px; margin-bottom: 15px; padding: 8px; background: rgba(255,255,255,0.15); border-radius: 6px; text-align: center; word-break: break-all;">
187 Esperando inicio...
188 </div>
189 <button id="start-claiming-btn" style="
190 width: 100%;
191 padding: 12px;
192 background: white;
193 color: #f5576c;
194 border: none;
195 border-radius: 8px;
196 font-weight: bold;
197 cursor: pointer;
198 font-size: 14px;
199 transition: all 0.3s;
200 margin-bottom: 10px;
201 ">Iniciar Auto-Claim</button>
202 <button id="stop-claiming-btn" style="
203 width: 100%;
204 padding: 10px;
205 background: rgba(255,255,255,0.2);
206 color: white;
207 border: 1px solid rgba(255,255,255,0.3);
208 border-radius: 8px;
209 font-weight: 500;
210 cursor: pointer;
211 font-size: 13px;
212 transition: all 0.3s;
213 display: none;
214 ">Detener</button>
215 <button id="reset-progress-btn" style="
216 width: 100%;
217 padding: 10px;
218 background: rgba(255,255,255,0.2);
219 color: white;
220 border: 1px solid rgba(255,255,255,0.3);
221 border-radius: 8px;
222 font-weight: 500;
223 cursor: pointer;
224 font-size: 13px;
225 transition: all 0.3s;
226 ">Reiniciar Progreso</button>
227 <div id="claim-status" style="font-size: 12px; margin-top: 12px; padding: 8px; background: rgba(255,255,255,0.15); border-radius: 6px; text-align: center; display: none;"></div>
228 `;
229
230 document.body.appendChild(controlPanel);
231
232 let isClaimingActive = false;
233 let claimingInterval = null;
234
235 const startBtn = document.getElementById('start-claiming-btn');
236 const stopBtn = document.getElementById('stop-claiming-btn');
237 const resetBtn = document.getElementById('reset-progress-btn');
238 const progressText = document.getElementById('progress-text');
239 const progressBar = document.getElementById('progress-bar');
240 const currentCodeDiv = document.getElementById('current-code');
241 const statusDiv = document.getElementById('claim-status');
242
243 // Update progress display
244 async function updateProgress() {
245 const storedCodes = await GM.getValue('sync_codes', '[]');
246 const codes = JSON.parse(storedCodes);
247 const currentIdx = await GM.getValue('current_idx', 0);
248
249 progressText.textContent = `${currentIdx}/${codes.length}`;
250 const percentage = codes.length > 0 ? (currentIdx / codes.length) * 100 : 0;
251 progressBar.style.width = `${percentage}%`;
252 }
253
254 // Initial progress update
255 updateProgress();
256
257 // Claiming function
258 async function claimNext() {
259 if (!isClaimingActive) return;
260
261 let codes = JSON.parse(await GM.getValue('sync_codes', '[]'));
262 let currentIdx = await GM.getValue('current_idx', 0);
263
264 if (currentIdx >= codes.length) {
265 console.log('✅ Todos los códigos procesados');
266 statusDiv.style.display = 'block';
267 statusDiv.style.background = 'rgba(255, 152, 0, 0.3)';
268 statusDiv.textContent = '✓ ¡Todos los códigos reclamados!';
269 isClaimingActive = false;
270 startBtn.style.display = 'block';
271 stopBtn.style.display = 'none';
272 resetBtn.disabled = false;
273 resetBtn.style.opacity = '1';
274 if (claimingInterval) clearInterval(claimingInterval);
275 return;
276 }
277
278 const currentCode = codes[currentIdx];
279 console.log(`🎯 Reclamando código ${currentIdx + 1}/${codes.length}: ${currentCode}`);
280 currentCodeDiv.textContent = 'Reclamando: ' + currentCode;
281
282 try {
283 // Find input field
284 const input = document.querySelector('input[placeholder*="red packet"], input[placeholder*="código"]');
285 if (input) {
286 input.value = '';
287 input.focus();
288 input.value = currentCode;
289
290 // Trigger input events
291 input.dispatchEvent(new Event('input', { bubbles: true }));
292 input.dispatchEvent(new Event('change', { bubbles: true }));
293
294 console.log('✓ Código ingresado');
295 await delay(800);
296
297 // Find and click Claim button
298 const claimButton = Array.from(document.querySelectorAll('button')).find(btn =>
299 /Claim|Canjear|Confirm|Reclamar/i.test(btn.textContent.trim()) &&
300 !btn.classList.contains('inactive') &&
301 btn.getAttribute('aria-disabled') !== 'true'
302 );
303
304 if (claimButton) {
305 console.log('✓ Haciendo clic en Claim...');
306 claimButton.click();
307 await delay(2000);
308
309 // Look for "Open" button
310 const openButton = Array.from(document.querySelectorAll('button')).find(btn =>
311 /Open|Abrir/i.test(btn.textContent.trim())
312 );
313
314 if (openButton) {
315 console.log('✓ Abriendo paquete...');
316 openButton.click();
317 await delay(2000);
318
319 // Close popup
320 const closeButton = document.querySelector('button[aria-label="Close"], button.bn-modal-close, button[class*="close"]');
321 if (closeButton) {
322 closeButton.click();
323 await delay(1000);
324 }
325 }
326
327 statusDiv.style.display = 'block';
328 statusDiv.style.background = 'rgba(76, 175, 80, 0.3)';
329 statusDiv.textContent = `✓ Código ${currentIdx + 1}/${codes.length} reclamado`;
330 } else {
331 console.log('⚠ Botón Claim no encontrado');
332 statusDiv.style.display = 'block';
333 statusDiv.style.background = 'rgba(244, 67, 54, 0.3)';
334 statusDiv.textContent = '⚠ Botón no encontrado';
335 }
336 } else {
337 console.log('⚠ Campo de entrada no encontrado');
338 }
339
340 // Move to next code
341 currentIdx++;
342 await GM.setValue('current_idx', currentIdx);
343 await updateProgress();
344
345 } catch (error) {
346 console.error('❌ Error reclamando:', error);
347 statusDiv.style.display = 'block';
348 statusDiv.style.background = 'rgba(244, 67, 54, 0.3)';
349 statusDiv.textContent = '❌ Error: ' + error.message;
350
351 // Still move to next code
352 currentIdx++;
353 await GM.setValue('current_idx', currentIdx);
354 await updateProgress();
355 }
356 }
357
358 // Start claiming
359 startBtn.addEventListener('click', async () => {
360 isClaimingActive = true;
361 startBtn.style.display = 'none';
362 stopBtn.style.display = 'block';
363 resetBtn.disabled = true;
364 resetBtn.style.opacity = '0.5';
365
366 statusDiv.style.display = 'block';
367 statusDiv.style.background = 'rgba(33, 150, 243, 0.3)';
368 statusDiv.textContent = '⏳ Auto-claim iniciado...';
369
370 await claimNext();
371 claimingInterval = setInterval(claimNext, 4000); // Claim every 4 seconds
372 });
373
374 // Stop claiming
375 stopBtn.addEventListener('click', () => {
376 isClaimingActive = false;
377 if (claimingInterval) {
378 clearInterval(claimingInterval);
379 claimingInterval = null;
380 }
381 startBtn.style.display = 'block';
382 stopBtn.style.display = 'none';
383 resetBtn.disabled = false;
384 resetBtn.style.opacity = '1';
385
386 statusDiv.style.background = 'rgba(255, 152, 0, 0.3)';
387 statusDiv.textContent = '⏸ Detenido';
388 });
389
390 // Reset progress
391 resetBtn.addEventListener('click', async () => {
392 await GM.setValue('current_idx', 0);
393 await updateProgress();
394 currentCodeDiv.textContent = 'Esperando inicio...';
395
396 statusDiv.style.display = 'block';
397 statusDiv.style.background = 'rgba(255, 152, 0, 0.3)';
398 statusDiv.textContent = '✓ Progreso reiniciado';
399
400 setTimeout(() => {
401 statusDiv.style.display = 'none';
402 }, 2000);
403 });
404 }
405})();