HumbleBundle - Unredeemed Game List Compiler

Compiles a list of the unredeemed games

  1. // ==UserScript==
  2. // @name HumbleBundle - Unredeemed Game List Compiler
  3. // @description Compiles a list of the unredeemed games
  4. // @version 2024.07.22.19.42
  5. // @author MetalTxus
  6. // @namespace https://github.com/jesuscc1993
  7.  
  8. // @icon https://cdn.humblebundle.com/static/hashed/46cf2ed85a0641bfdc052121786440c70da77d75.png
  9. // @match https://www.humblebundle.com/home/keys
  10. // @require https://code.jquery.com/jquery-3.6.1.min.js
  11. // ==/UserScript==
  12.  
  13. /* globals jQuery */
  14.  
  15. (() => {
  16. 'use strict';
  17.  
  18. let games;
  19.  
  20. const compileGamesList = () => {
  21. games = [];
  22.  
  23. jQuery('#hide-redeemed:not(:checked)').click();
  24. jQuery('.jump-to-page[data-index="0"]').click();
  25.  
  26. setTimeout(processPage, 150);
  27. };
  28.  
  29. const processPage = () => {
  30. const names = jQuery('.game-name h4')
  31. .get()
  32. .map((e) => e.textContent);
  33. names.sort();
  34. names.forEach((name) => {
  35. const link = name.includes('Humble Choice')
  36. ? name
  37. .toLowerCase()
  38. .replace(
  39. /(.*?)\s(.*?)\s.*/,
  40. `https://www.humblebundle.com/membership/$1-$2`
  41. )
  42. : `https://store.steampowered.com/search/?term=${encodeURI(name)}`;
  43.  
  44. games.push(`
  45. <li>
  46. <a href="${link}" target="_blank">
  47. ${name}
  48. </a>
  49. </li>
  50. `);
  51. });
  52.  
  53. const nextPage = jQuery('.jump-to-page.current').next();
  54. if (nextPage.length) {
  55. jQuery('.jump-to-page.current').next().click();
  56. processPage();
  57. } else {
  58. outputGames();
  59. }
  60. };
  61.  
  62. const outputGames = () => {
  63. const html = `
  64. <!DOCTYPE html>
  65. <html>
  66. <head>
  67. <title>Unredeemed HumbleBundle Games List</title>
  68. <link href="https://cdn.humblebundle.com/static/hashed/46cf2ed85a0641bfdc052121786440c70da77d75.png" rel="icon" />
  69. <style>
  70. ul {
  71. list-style: none;
  72. margin: 0;
  73. padding: 0;
  74. }
  75. </style>
  76. </head>
  77.  
  78. <body>
  79. <ul>
  80. ${games.join('')}
  81. </ul>
  82.  
  83. <p>
  84. <small>Unredeemed games count: ${games.length}</small>
  85. </p>
  86. </body>
  87. </html>
  88. `;
  89. downloadFile(html, 'unredeemed-humblebundle-games-list.html', 'text/plain');
  90. };
  91.  
  92. const downloadFile = (content, fileName, type) => {
  93. const file = new Blob([content], { type });
  94. const href = URL.createObjectURL(file);
  95. jQuery(`<a href="${href}" download="${fileName}">`)[0].click();
  96. };
  97.  
  98. const initialize = () => {
  99. jQuery('head').append(`
  100. <style>
  101. .generate-list-button {
  102. background:#f1f3f6;
  103. border:1px solid #ccc;
  104. padding:0 12px;
  105. }
  106. </style>
  107. `);
  108.  
  109. const button = jQuery(`
  110. <button class="generate-list-button">
  111. Compile unredeemed games list
  112. </button>
  113. `);
  114. button.click(compileGamesList);
  115. jQuery('.search').before(button);
  116. };
  117.  
  118. setTimeout(initialize, 150);
  119. })();