Size
15.9 KB
Version
1.1.9
Created
Oct 19, 2025
Updated
5 days ago
1// ==UserScript==
2// @name HypeDrop Auto Giveaway Joiner
3// @description A new userscript
4// @version 1.1.9
5// @match https://*.hypedrop.com/*
6// @icon https://www.hypedrop.com/assets/favicons/favicon-32x32.png
7// ==/UserScript==
8(function() {
9 'use strict';
10
11 console.log('HypeDrop Auto Giveaway Joiner iniciado');
12
13 // Configuración
14 const CHECK_INTERVAL = 2000; // Revisar cada 2 segundos
15 const BUTTON_SELECTORS = [
16 'button:contains("Join Giveaway")',
17 'button[data-test*="giveaway"]',
18 'button[class*="giveaway"]',
19 '.giveaway-button',
20 'button:contains("Unirse")',
21 'button:contains("Participar")',
22 '[data-testid*="giveaway"]',
23 'button:contains("Join")'
24 ];
25
26 let isMonitoring = true;
27 let clickCount = 0;
28 let lastClickedButton = null;
29 let lastClickTime = 0;
30
31 // Función para buscar el botón usando múltiples selectores
32 function findGiveawayButton() {
33 // Buscar específicamente por "Join Giveaway" solamente
34 const buttons = document.querySelectorAll('button, a, div[role="button"]');
35 for (const button of buttons) {
36 const text = button.textContent.trim().toLowerCase();
37 if (text.includes('join giveaway')) {
38 return button;
39 }
40 }
41
42 // Buscar por selectores específicos solo para Join Giveaway
43 const specificSelectors = [
44 'button[mat-flat-button][color="accent"]',
45 'button.mat-flat-button.mat-accent'
46 ];
47
48 for (const selector of specificSelectors) {
49 try {
50 const element = document.querySelector(selector);
51 if (element && element.offsetParent !== null) { // Verificar que sea visible
52 // Verificar si el texto del botón contiene específicamente "join giveaway"
53 const buttonText = element.textContent.trim().toLowerCase();
54 if (buttonText.includes('join giveaway')) {
55 return element;
56 }
57 }
58 } catch (error) {
59 // Ignorar errores de selector inválido
60 console.log('Selector inválido:', selector);
61 }
62 }
63
64 return null;
65 }
66
67 // Función para abrir el chat
68 async function openChat() {
69 try {
70 console.log('Intentando abrir el chat...');
71
72 // Buscar el botón del chat con selectores más específicos
73 const chatButton = document.querySelector('button[data-test="float-button-chat"]') ||
74 document.querySelector('button[cwchattoggle]') ||
75 document.querySelector('button[title="Open chat"]') ||
76 document.querySelector('button.floating-button.chat') ||
77 document.querySelector('button[title="Open Live Chat"]');
78
79 if (chatButton) {
80 console.log('Botón del chat encontrado:', chatButton);
81 console.log('Atributos del botón:', {
82 title: chatButton.title,
83 dataTest: chatButton.getAttribute('data-test'),
84 className: chatButton.className,
85 visible: chatButton.offsetParent !== null,
86 disabled: chatButton.disabled
87 });
88
89 // Verificar que el botón esté visible y habilitado
90 if (chatButton.offsetParent !== null && !chatButton.disabled) {
91 console.log('Haciendo click en el botón del chat...');
92 chatButton.click();
93
94 // Esperar un momento para que el chat se abra
95 await new Promise(resolve => setTimeout(resolve, 1500));
96
97 showNotification('Chat abierto', 'info');
98 console.log('Chat abierto exitosamente');
99 return true;
100 } else {
101 console.log('Botón del chat no está disponible - visible:', chatButton.offsetParent !== null, 'enabled:', !chatButton.disabled);
102 return false;
103 }
104 } else {
105 console.log('No se encontró el botón del chat');
106 // Intentar buscar cualquier botón que contenga "chat" en su texto o atributos
107 const allButtons = document.querySelectorAll('button');
108 console.log('Buscando entre', allButtons.length, 'botones...');
109 for (const btn of allButtons) {
110 const text = btn.textContent.toLowerCase();
111 const title = (btn.title || '').toLowerCase();
112 const className = (btn.className || '').toLowerCase();
113 if (text.includes('chat') || title.includes('chat') || className.includes('chat')) {
114 console.log('Botón relacionado con chat encontrado:', {
115 text: btn.textContent,
116 title: btn.title,
117 className: btn.className,
118 dataTest: btn.getAttribute('data-test')
119 });
120 }
121 }
122 return false;
123 }
124 } catch (error) {
125 console.error('Error al abrir el chat:', error);
126 return false;
127 }
128 }
129
130 // Función para hacer click en el botón
131 async function clickGiveawayButton(button) {
132 try {
133 console.log('¡Botón "Join Giveaway" encontrado! Haciendo click...', button);
134
135 // Scroll al botón para asegurar que esté visible
136 button.scrollIntoView({ behavior: 'smooth', block: 'center' });
137
138 // Esperar un momento para el scroll
139 await new Promise(resolve => setTimeout(resolve, 500));
140
141 // Hacer click
142 button.click();
143
144 clickCount++;
145 console.log(`Click realizado exitosamente. Total de clicks: ${clickCount}`);
146
147 // Guardar estadísticas
148 await GM.setValue('giveaway_clicks', clickCount);
149 await GM.setValue('last_click_time', Date.now());
150
151 // Mostrar notificación visual
152 showNotification('¡Giveaway joined exitosamente!', 'success');
153
154 } catch (error) {
155 console.error('Error al hacer click en el botón:', error);
156 showNotification('Error al hacer click en el botón', 'error');
157 }
158 }
159
160 // Función para mostrar notificaciones visuales
161 function showNotification(message, type = 'info') {
162 const notification = document.createElement('div');
163 notification.style.cssText = `
164 position: fixed;
165 top: 20px;
166 right: 20px;
167 background: ${type === 'success' ? '#4CAF50' : type === 'error' ? '#f44336' : '#2196F3'};
168 color: white;
169 padding: 15px 20px;
170 border-radius: 5px;
171 font-weight: bold;
172 z-index: 10000;
173 box-shadow: 0 4px 8px rgba(0,0,0,0.3);
174 font-family: Arial, sans-serif;
175 font-size: 14px;
176 `;
177 notification.textContent = message;
178 document.body.appendChild(notification);
179
180 // Remover después de 3 segundos
181 setTimeout(() => {
182 if (notification.parentNode) {
183 notification.parentNode.removeChild(notification);
184 }
185 }, 3000);
186 }
187
188 // Función principal de monitoreo
189 async function monitorForGiveawayButton() {
190 if (!isMonitoring) return;
191
192 try {
193 // PRIMERO: Asegurarse de que el chat esté abierto
194 await openChat();
195
196 // SEGUNDO: Buscar el botón de giveaway (que ahora debería estar visible)
197 const button = findGiveawayButton();
198
199 if (button) {
200 console.log('Botón encontrado, verificando si es clickeable...');
201
202 // Verificar si es el mismo botón que ya clickeamos recientemente
203 const currentTime = Date.now();
204 const timeSinceLastClick = currentTime - lastClickTime;
205
206 // Si es el mismo botón y han pasado menos de 30 segundos, no hacer click
207 if (lastClickedButton === button && timeSinceLastClick < 30000) {
208 console.log('Mismo botón detectado, esperando antes del próximo click...');
209 setTimeout(() => {
210 if (isMonitoring) {
211 monitorForGiveawayButton();
212 }
213 }, CHECK_INTERVAL);
214 return;
215 }
216
217 // Verificar si el botón está habilitado y visible
218 if (!button.disabled &&
219 button.offsetParent !== null &&
220 getComputedStyle(button).display !== 'none') {
221
222 // Verificar que el botón no tenga texto que indique que ya se unió
223 const buttonText = button.textContent.trim().toLowerCase();
224 if (buttonText.includes('joined') ||
225 buttonText.includes('ya participas') ||
226 buttonText.includes('already joined') ||
227 buttonText.includes('unido')) {
228 console.log('Botón indica que ya se unió, saltando...');
229 setTimeout(() => {
230 if (isMonitoring) {
231 monitorForGiveawayButton();
232 }
233 }, CHECK_INTERVAL);
234 return;
235 }
236
237 // Verificar si han pasado al menos 5 segundos desde el último click (para botones nuevos)
238 if (timeSinceLastClick < 5000) {
239 console.log('Esperando cooldown mínimo de 5 segundos...');
240 setTimeout(() => {
241 if (isMonitoring) {
242 monitorForGiveawayButton();
243 }
244 }, CHECK_INTERVAL);
245 return;
246 }
247
248 // Guardar referencia del botón y tiempo antes de hacer click
249 lastClickedButton = button;
250 lastClickTime = currentTime;
251
252 await clickGiveawayButton(button);
253
254 // Pausa más larga después de hacer click
255 setTimeout(() => {
256 if (isMonitoring) {
257 monitorForGiveawayButton();
258 }
259 }, 10000); // Esperar 10 segundos después de hacer click
260 return;
261 }
262 }
263
264 } catch (error) {
265 console.error('Error en el monitoreo:', error);
266 }
267
268 // Continuar monitoreando
269 setTimeout(() => {
270 if (isMonitoring) {
271 monitorForGiveawayButton();
272 }
273 }, CHECK_INTERVAL);
274 }
275
276 // Función para crear panel de control
277 function createControlPanel() {
278 const panel = document.createElement('div');
279 panel.id = 'giveaway-auto-clicker-panel';
280 panel.style.cssText = `
281 position: fixed;
282 top: 10px;
283 left: 10px;
284 background: rgba(0, 0, 0, 0.9);
285 color: white;
286 padding: 15px;
287 border-radius: 8px;
288 font-family: Arial, sans-serif;
289 font-size: 12px;
290 z-index: 9999;
291 min-width: 200px;
292 box-shadow: 0 4px 8px rgba(0,0,0,0.3);
293 `;
294
295 panel.innerHTML = `
296 <div style="font-weight: bold; margin-bottom: 10px;">🎁 Auto Giveaway Joiner</div>
297 <div>Estado: <span id="status" style="color: #4CAF50;">Activo</span></div>
298 <div>Clicks realizados: <span id="click-counter">0</span></div>
299 <div style="margin-top: 10px;">
300 <button id="toggle-btn" style="background: #f44336; color: white; border: none; padding: 5px 10px; border-radius: 3px; cursor: pointer;">Pausar</button>
301 <button id="reset-btn" style="background: #2196F3; color: white; border: none; padding: 5px 10px; border-radius: 3px; cursor: pointer; margin-left: 5px;">Reset</button>
302 </div>
303 `;
304
305 document.body.appendChild(panel);
306
307 // Event listeners para los botones
308 document.getElementById('toggle-btn').addEventListener('click', toggleMonitoring);
309 document.getElementById('reset-btn').addEventListener('click', resetStats);
310
311 return panel;
312 }
313
314 // Función para alternar el monitoreo
315 function toggleMonitoring() {
316 isMonitoring = !isMonitoring;
317 const statusEl = document.getElementById('status');
318 const toggleBtn = document.getElementById('toggle-btn');
319
320 if (isMonitoring) {
321 statusEl.textContent = 'Activo';
322 statusEl.style.color = '#4CAF50';
323 toggleBtn.textContent = 'Pausar';
324 toggleBtn.style.background = '#f44336';
325 monitorForGiveawayButton();
326 console.log('Monitoreo reanudado');
327 } else {
328 statusEl.textContent = 'Pausado';
329 statusEl.style.color = '#ff9800';
330 toggleBtn.textContent = 'Reanudar';
331 toggleBtn.style.background = '#4CAF50';
332 console.log('Monitoreo pausado');
333 }
334 }
335
336 // Función para resetear estadísticas
337 async function resetStats() {
338 clickCount = 0;
339 await GM.setValue('giveaway_clicks', 0);
340 document.getElementById('click-counter').textContent = '0';
341 showNotification('Estadísticas reseteadas', 'info');
342 }
343
344 // Función para actualizar el contador en el panel
345 function updateClickCounter() {
346 const counterEl = document.getElementById('click-counter');
347 if (counterEl) {
348 counterEl.textContent = clickCount;
349 }
350 }
351
352 // Inicialización
353 async function init() {
354 console.log('Inicializando HypeDrop Auto Giveaway Joiner...');
355
356 // Cargar estadísticas guardadas
357 clickCount = await GM.getValue('giveaway_clicks', 0);
358
359 // Crear panel de control
360 createControlPanel();
361 updateClickCounter();
362
363 // Mostrar notificación de inicio
364 showNotification('Auto Giveaway Joiner activado', 'success');
365
366 // Iniciar monitoreo
367 console.log('Iniciando monitoreo del botón "Join Giveaway"...');
368 monitorForGiveawayButton();
369 }
370
371 // Esperar a que la página cargue completamente
372 if (document.readyState === 'loading') {
373 document.addEventListener('DOMContentLoaded', init);
374 } else {
375 init();
376 }
377
378 // También observar cambios en el DOM para detectar contenido cargado dinámicamente
379 const observer = new MutationObserver((mutations) => {
380 mutations.forEach((mutation) => {
381 if (mutation.addedNodes.length > 0) {
382 // Verificar si se agregaron nuevos botones
383 const addedElements = Array.from(mutation.addedNodes).filter(node => node.nodeType === 1);
384 for (const element of addedElements) {
385 if (element.tagName === 'BUTTON' || element.querySelector('button')) {
386 // Se agregó un botón, el monitoreo regular lo detectará
387 break;
388 }
389 }
390 }
391 });
392 });
393
394 observer.observe(document.body, {
395 childList: true,
396 subtree: true
397 });
398
399})();