Advertisement
LeJonathan

Humblebundle Key Redeemer

Feb 20th, 2025
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name         Humble Monthly Key Redeemer
  3. // @version      2025-02-20
  4. // @description  This script will claim all keys and copy them to a csv file for you
  5. // @author       u/Sceptylos
  6. // @match        https://www.humblebundle.com/membership/*
  7. // @icon         https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net
  8. // @grant        unsafeWindow
  9. // ==/UserScript==
  10.  
  11. (function() {
  12.     'use strict';
  13.  
  14.     function createButton() {
  15.         let btn = document.createElement("button");
  16.         btn.innerText = "Start Auto-Claim";
  17.         btn.style.position = "fixed";
  18.         btn.style.bottom = "20px";
  19.         btn.style.right = "20px";
  20.         btn.style.padding = "10px 15px";
  21.         btn.style.background = "#28a745";
  22.         btn.style.color = "white";
  23.         btn.style.border = "none";
  24.         btn.style.borderRadius = "5px";
  25.         btn.style.cursor = "pointer";
  26.         btn.style.zIndex = "9999";
  27.         btn.style.fontSize = "16px";
  28.         btn.addEventListener("click", processChoices);
  29.         document.body.appendChild(btn);
  30.     }
  31.  
  32.     function convertToCSV(arr) {
  33.         const header = Object.keys(arr[0]).join(","); // CSV header (game,key)
  34.         const rows = arr.map(obj => Object.values(obj).join(",")); // Convert each object to CSV row
  35.         return [header, ...rows].join("\n");
  36.     }
  37.  
  38.     function downloadCSV(filename, csvData) {
  39.         const blob = new Blob([csvData], { type: "text/csv" });
  40.         const link = document.createElement("a");
  41.         link.href = URL.createObjectURL(blob);
  42.         link.download = filename;
  43.         document.body.appendChild(link);
  44.         link.click();
  45.         document.body.removeChild(link);
  46.     }
  47.  
  48.     async function processChoices() {
  49.         let master = [];
  50.         let keys = [];
  51.         let gotScammed = [];
  52.  
  53.         function sleep(ms) {
  54.             return new Promise(resolve => setTimeout(resolve, ms));
  55.         }
  56.  
  57.         async function openChoice(choice) {
  58.             return new Promise((resolve) => {
  59.                 let name = choice.querySelector('.content-choice-title')?.innerText.trim();
  60.                 console.log(`Opening modal for: ${name}`);
  61.  
  62.                 let openButton = choice.querySelector('.js-open-choice-modal');
  63.                 if (openButton) openButton.click();
  64.  
  65.                 let attempts = 0;
  66.                 let checkModal = setInterval(async function () {
  67.                     let modal = document.querySelector('.humblemodal-modal--open');
  68.  
  69.                     if (modal) {
  70.                         clearInterval(checkModal);
  71.                         console.log(`✅ Modal detected for: ${name}`);
  72.  
  73.                         var keyField = modal.querySelector('.keyfield-value')?.innerText.trim();
  74.  
  75.                         // If the game hasn't been redeemed yet, redeem it
  76.                         if (keyField?.includes("GET GAME ON STEAM")) {
  77.                             modal.querySelector('.js-keyfield').click();
  78.                             console.log(`⚠️ Trying to redeem key for ${name}, sleeping script for 30s to give the page time to load key`);
  79.                             await sleep(30000);
  80.                             keyField = modal.querySelector('.keyfield-value')?.innerText.trim();
  81.                         }
  82.  
  83.                         // Sort and figure out if we got our key or if we were scammed
  84.                         console.log(`🔑 Extracted key: "${keyField}"`);
  85.                         if (keyField?.includes("Keys are temporarily exhausted")) {
  86.                             gotScammed.push(name);
  87.                             console.log(`❌ Got scammed for: ${name}`);
  88.                             keyField = "Exhausted";
  89.                         } else if (keyField) {
  90.                             keys.push(`${name} :: ${keyField}`);
  91.                         } else {
  92.                             console.log(`⚠️ No key found for: ${name}`);
  93.                         }
  94.                         master.push({'game': name, 'key': keyField});
  95.  
  96.                         // Close modal
  97.                         let closeButton = modal.querySelector('.js-close-modal');
  98.                         if (closeButton) {
  99.                             closeButton.click();
  100.                             console.log(`Closing modal for: ${name}`);
  101.                         } else {
  102.                             console.log(`⚠️ Close button not found for: ${name}`);
  103.                         }
  104.  
  105.                         // Wait for modal to close before resolving
  106.                         let closeCheck = setInterval(() => {
  107.                             if (!document.querySelector('.humblemodal-modal--open')) {
  108.                                 clearInterval(closeCheck);
  109.                                 console.log(`✅ Modal closed for: ${name}`);
  110.                                 resolve();
  111.                             }
  112.                         }, 500);
  113.                     }
  114.  
  115.                     if (attempts++ > 50) { // Give up after ~5 seconds
  116.                         clearInterval(checkModal);
  117.                         console.log(`⚠️ Modal did not appear for: ${name}, skipping...`);
  118.                         master.push({'game': name, 'key': 'Retry later'});
  119.                         resolve();
  120.                     }
  121.                 }, 500);
  122.             });
  123.         }
  124.  
  125.         let choices = document.querySelectorAll('.content-choice');
  126.  
  127.         for (let i = 0; i < choices.length; i++) {
  128.             await openChoice(choices[i]); // Wait for each choice to complete
  129.             await new Promise((r) => setTimeout(r, 1000)); // Small delay
  130.         }
  131.  
  132.         console.log(' - - - - - - - - OUTPUT - - - - - - - ');
  133.         console.log("✅ Keys found:", keys);
  134.         console.log("❌ Got scammed:", gotScammed);
  135.         // Once all choices are processed, create & download CSV
  136.         const csvContent = convertToCSV(master);
  137.         const pathParts = window.location.pathname.split("/"); // Get parts of the URL path
  138.         const csv_name = pathParts[pathParts.length - 1]; // Last part is "april-2024"
  139.         downloadCSV("humblemonthly" + csv_name + ".csv", csvContent);
  140.     }
  141.  
  142.     // Add the button when the page loads
  143.     window.addEventListener('load', createButton);
  144. })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement