Reveals all game keys on Humble Bundle download pages with one click
Size
4.7 KB
Version
1.0.1
Created
Dec 8, 2025
Updated
5 days ago
1// ==UserScript==
2// @name Humble Bundle Key Revealer
3// @description Reveals all game keys on Humble Bundle download pages with one click
4// @version 1.0.1
5// @match https://*.humblebundle.com/*
6// @icon https://cdn.humblebundle.com/static/hashed/47e474eed38083df699b7dfd8d29d575e3398f1e.ico
7// ==/UserScript==
8(function() {
9 'use strict';
10
11 console.log('Humble Bundle Key Revealer extension loaded');
12
13 function createRevealAllButton() {
14 // Check if we're on a downloads page with keys
15 const keyFields = document.querySelectorAll('.js-keyfield.keyfield.enabled');
16
17 if (keyFields.length === 0) {
18 console.log('No keys found on this page');
19 return;
20 }
21
22 console.log(`Found ${keyFields.length} keys to reveal`);
23
24 // Find the key container to add our button
25 const keyContainer = document.querySelector('.key-container.wrapper');
26
27 if (!keyContainer) {
28 console.log('Key container not found');
29 return;
30 }
31
32 // Check if button already exists
33 if (document.getElementById('reveal-all-keys-btn')) {
34 console.log('Button already exists');
35 return;
36 }
37
38 // Create the reveal all button
39 const revealButton = document.createElement('button');
40 revealButton.id = 'reveal-all-keys-btn';
41 revealButton.textContent = '🔑 Reveal All Keys';
42 revealButton.style.cssText = `
43 background: linear-gradient(135deg, #cc2929 0%, #a02020 100%);
44 color: white;
45 border: none;
46 padding: 12px 24px;
47 font-size: 16px;
48 font-weight: bold;
49 border-radius: 4px;
50 cursor: pointer;
51 margin-bottom: 20px;
52 box-shadow: 0 2px 4px rgba(0,0,0,0.2);
53 transition: all 0.3s ease;
54 display: inline-block;
55 `;
56
57 // Add hover effect
58 revealButton.addEventListener('mouseenter', () => {
59 revealButton.style.transform = 'translateY(-2px)';
60 revealButton.style.boxShadow = '0 4px 8px rgba(0,0,0,0.3)';
61 });
62
63 revealButton.addEventListener('mouseleave', () => {
64 revealButton.style.transform = 'translateY(0)';
65 revealButton.style.boxShadow = '0 2px 4px rgba(0,0,0,0.2)';
66 });
67
68 // Add click handler to reveal all keys
69 revealButton.addEventListener('click', () => {
70 console.log('Revealing all keys...');
71
72 const keyFieldsToReveal = document.querySelectorAll('.js-keyfield.keyfield.enabled');
73 let revealedCount = 0;
74
75 keyFieldsToReveal.forEach((keyField, index) => {
76 // Add a small delay between clicks to avoid overwhelming the page
77 setTimeout(() => {
78 keyField.click();
79 revealedCount++;
80 console.log(`Revealed key ${revealedCount}/${keyFieldsToReveal.length}`);
81
82 // Update button text with progress
83 if (revealedCount === keyFieldsToReveal.length) {
84 revealButton.textContent = '✅ All Keys Revealed!';
85 revealButton.style.background = 'linear-gradient(135deg, #28a745 0%, #1e7e34 100%)';
86
87 // Reset button after 3 seconds
88 setTimeout(() => {
89 revealButton.textContent = '🔑 Reveal All Keys';
90 revealButton.style.background = 'linear-gradient(135deg, #cc2929 0%, #a02020 100%)';
91 }, 3000);
92 } else {
93 revealButton.textContent = `Revealing... (${revealedCount}/${keyFieldsToReveal.length})`;
94 }
95 }, index * 200); // 200ms delay between each click
96 });
97 });
98
99 // Insert the button at the top of the key container
100 keyContainer.insertBefore(revealButton, keyContainer.firstChild);
101 console.log('Reveal All Keys button added successfully');
102 }
103
104 // Wait for the page to load
105 function init() {
106 // Try to create the button immediately
107 createRevealAllButton();
108
109 // Also observe for dynamic content loading
110 const observer = new MutationObserver(() => {
111 createRevealAllButton();
112 });
113
114 // Observe the body for changes
115 if (document.body) {
116 observer.observe(document.body, {
117 childList: true,
118 subtree: true
119 });
120 }
121 }
122
123 // Start when DOM is ready
124 if (document.readyState === 'loading') {
125 document.addEventListener('DOMContentLoaded', init);
126 } else {
127 init();
128 }
129
130})();