Greasy Fork 还支持 简体中文。

HumbleBundle Exporter

An easy way to export the games and the keys owned on HumbleBundle (Json format)

  1. // ==UserScript==
  2. // @name HumbleBundle Exporter
  3. // @match https://www.humblebundle.com/home/*
  4. // @require http://code.jquery.com/jquery-3.4.1.min.js
  5. // @version 0.5
  6. // @description An easy way to export the games and the keys owned on HumbleBundle (Json format)
  7. // @namespace https://greasyfork.org/users/462544
  8. // ==/UserScript==
  9.  
  10. /*
  11. * Global vars
  12. */
  13. const $$ = $.noConflict(true);
  14. var keys_exported = null;
  15.  
  16. /*
  17. * Funcs
  18. */
  19. function copy_to_clipboard(element) {
  20. let temp = $$("<textarea>");
  21. $$("body").append(temp);
  22. temp.val($$(element).text()).select();
  23. document.execCommand("copy");
  24. temp.remove();
  25. }
  26.  
  27. function json_sort_by_key(array, key) {
  28. return array.sort((a, b) => {
  29. var x = a[key].toLowerCase();
  30. var y = b[key].toLowerCase();
  31. return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  32. });
  33. }
  34.  
  35. function create_game_entry(name, platform, redeemed, key) {
  36. return {"name": name, "platform": platform, "redeemed": redeemed, "key": key};
  37. }
  38.  
  39. function export_keys() {
  40. if($$('.js-key-manager-holder .js-jump-to-page:first').text() != "1"){
  41. $$('.js-key-manager-holder .js-jump-to-page:nth-child(2)').click();
  42. }
  43.  
  44. var games = [];
  45. var loop = $$('.js-key-manager-holder .js-jump-to-page:nth-last-child(2)').html()*1;
  46.  
  47. for (i = 0; i < loop; i++){
  48. $$('tbody tr').each(function(){
  49. let name = $$(this).children('td.game-name').children('h4').attr('title');
  50. let platform = $$(this).children('td.platform').children('i').attr('title');
  51.  
  52. let keyfield = $$(this).find("div.keyfield")[0];
  53. if (keyfield == null) {
  54. return;
  55. }
  56.  
  57. let redeemed = $$(keyfield).attr('class').includes("redeemed");
  58. let key = "";
  59. if (redeemed) {
  60. key = $$(keyfield).attr("title")
  61. }
  62.  
  63. game_data = create_game_entry(name, platform, redeemed, key);
  64. games.push(game_data)
  65. });
  66.  
  67. // click next page button
  68. $$('.js-key-manager-holder .js-jump-to-page:last').click();
  69. }
  70.  
  71. json_sort_by_key(games, "name");
  72. return games;
  73. }
  74.  
  75. /*
  76. * UI
  77. */
  78. function init_ui()
  79. {
  80. let window_html = `
  81. <style>
  82. .modal {
  83. display: none; /* Hidden by default */
  84. position: fixed; /* Stay in place */
  85. z-index: 1; /* Sit on top */
  86. padding-top: 80px; /* Location of the box */
  87. left: 0;
  88. top: 0;
  89. width: 100%; /* Full width */
  90. height: 100%; /* Full height */
  91. background-color: rgb(0,0,0); /* Fallback color */
  92. background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
  93. }
  94.  
  95. .modal-content {
  96. background-color: #fefefe;
  97. margin: auto;
  98. padding: 10px;
  99. border: 1px solid #888;
  100. width: 60%;
  101. }
  102.  
  103. .controls-container {
  104. position: absolute;
  105. right: 20%;
  106. }
  107.  
  108. .status-container {
  109. position: absolute;
  110. left: 20%;
  111. }
  112.  
  113. .copy-btn, .status-text {
  114. color: #aaaaaa;
  115. font-size: 22px;
  116. font-weight: bold;
  117. }
  118.  
  119. .close {
  120. color: #aaaaaa;
  121. font-size: 22px;
  122. font-weight: bold;
  123. text-align: center;
  124. padding-left: 5px;
  125. }
  126.  
  127. .close:hover,
  128. .close:focus,
  129. .copy-btn:hover,
  130. .copy-btn:focus,
  131. .game-link:hover,
  132. .game-link:focus,
  133. .redeemed-link:hover,
  134. .redeemed-link:focus
  135. {
  136. color: #000;
  137. text-decoration: none;
  138. cursor: pointer;
  139. }
  140.  
  141. .json-data {
  142. border: 1px solid #888;
  143. margin-top: 40px;
  144. margin-left: 1px;
  145. margin-right: 1px;
  146. overflow: auto; /* Enable scroll if needed */
  147. height: 70vh;
  148. background-color: #DDD;
  149. }
  150. </style>
  151. <div id="KeysWindow" class="modal">
  152. <div class="modal-content">
  153. <div class="status-container">
  154. <span class="status-text">
  155. <span class="game-count"></span>
  156. <a class="game-link" target="#">games</a> found,
  157. <span class="redeemed-count"></span>
  158. <a class="redeemed-link" target="#">redeemed.</a>
  159. </span>
  160. </div>
  161. <div class="controls-container">
  162. <span class="copy-btn">[Copy]</span>
  163. <span class="close">[&times;]</span>
  164. </div>
  165. <pre class="json-data"></p>
  166. </div>
  167. </div>`;
  168. $$('body').append(window_html);
  169.  
  170. let button_html = $$('<button class="export-btn" style="margin-right: -20px">Export</button>');
  171. button_html.insertBefore('.js-key-search');
  172. /*
  173. * Events
  174. */
  175. $$('.close').click(() => {
  176. $$('#KeysWindow').css("display", "none");
  177. });
  178.  
  179. $$(".copy-btn").click(() => {
  180. copy_to_clipboard($$('.json-data'));
  181. });
  182.  
  183. $$('.game-link').click(() => {
  184. $$('.json-data').text(JSON.stringify(keys_exported, null, 2));
  185. });
  186.  
  187. $$('.redeemed-link').click(() => {
  188. let redeemed_games = keys_exported.filter(e => e.redeemed == true);
  189. $$('.json-data').text(JSON.stringify(redeemed_games, null, 2));
  190. });
  191.  
  192. $$('.export-btn').click(() => {
  193. keys_exported = export_keys();
  194.  
  195. $$('.json-data').text(JSON.stringify(keys_exported, null, 2));
  196. $$('.game-count').text(keys_exported.length);
  197.  
  198. let redeemed_count = keys_exported.filter(e => e.redeemed == true).length;
  199. $$('.redeemed-count').text(redeemed_count);
  200.  
  201. $$('#KeysWindow').css("display", "block");
  202. });
  203. }
  204.  
  205. function try_delayed_init() {
  206. window.setTimeout(() => {
  207. let already_init = $$('body').find('#KeysWindow')[0] ? true : false;
  208. if (location.href.includes("home/keys") && !already_init) {
  209. init_ui();
  210. }
  211. }, 150);
  212. }
  213.  
  214. /*
  215. * Main
  216. */
  217. (() => {
  218. $(window).load(() => {
  219. if (location.href.includes("home/keys")) {
  220. init_ui();
  221. } else {
  222. $("body").find(".tabbar-tab").each(function() {
  223. $(this).click(try_delayed_init);
  224. });
  225. }
  226. console.log("-- Script loaded");
  227. });
  228. })();