VGMLoaderX

Automatically downloads albums from KHInsider without an account.

当前为 2024-02-24 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name VGMLoaderX
  3. // @name:de VGMLoaderX
  4. // @name:en VGMLoaderX
  5. // @namespace sun/userscripts
  6. // @version 1.0.22
  7. // @description Automatically downloads albums from KHInsider without an account.
  8. // @description:de Lädt Alben von KHInsider automatisch und ohne Account herunter.
  9. // @description:en Automatically downloads albums from KHInsider without an account.
  10. // @compatible chrome
  11. // @compatible edge
  12. // @compatible firefox
  13. // @compatible opera
  14. // @compatible safari
  15. // @homepageURL https://forgejo.sny.sh/sun/userscripts
  16. // @supportURL https://forgejo.sny.sh/sun/userscripts/issues
  17. // @contributionURL https://liberapay.com/sun
  18. // @contributionAmount €1.00
  19. // @author Sunny <sunny@sny.sh>
  20. // @include https://downloads.khinsider.com/game-soundtracks/album/*
  21. // @match https://downloads.khinsider.com/game-soundtracks/album/*
  22. // @connect vgmdownloads.com
  23. // @connect vgmsite.com
  24. // @run-at document-end
  25. // @inject-into page
  26. // @grant GM.xmlHttpRequest
  27. // @grant GM_xmlhttpRequest
  28. // @noframes
  29. // @require https://unpkg.com/@zip.js/zip.js/dist/zip.js
  30. // @require https://unpkg.com/file-saver
  31. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
  32. // @icon https://forgejo.sny.sh/sun/userscripts/raw/branch/main/icons/VGMLoaderX.ico
  33. // @copyright 2021-present, Sunny (https://sny.sh/)
  34. // @license For Good Eyes Only; https://forgejo.sny.sh/sun/userscripts/src/branch/main/LICENSE.md
  35. // ==/UserScript==
  36.  
  37. (function () {
  38. "use strict";
  39.  
  40. document.querySelectorAll('a[href^="/cp/add_album/"]').forEach((x) => {
  41. x.addEventListener("click", (e) => {
  42. e.preventDefault();
  43.  
  44. let format = Array(
  45. ...document.querySelectorAll("#songlist_header th[align=right]"),
  46. ).map((x) => x.textContent);
  47. if (format.length === 1) {
  48. format = format[0];
  49. } else {
  50. const input = prompt(
  51. "Please enter your desired format (one of " +
  52. format.join(", ") +
  53. "):",
  54. format[0],
  55. );
  56.  
  57. if (!input) return;
  58. if (!format.includes(input.toUpperCase())) {
  59. format = format[0];
  60. alert("Invalid format supplied. Using " + format + " instead.");
  61. } else {
  62. format = input;
  63. }
  64. }
  65.  
  66. const element = document.getElementsByClassName("albumMassDownload")[0];
  67. element.style.height = "auto";
  68. element.style.marginBottom = "2em";
  69.  
  70. const input = eval(
  71. document
  72. .querySelector("#pageContent script")
  73. .textContent.slice(5, -3)
  74. .replace("function", "function x")
  75. .replace("return p}", "return p}x"),
  76. );
  77.  
  78. const mediaPath = input.match(/mediaPath='(.+?)'/)[1];
  79. const tracks = JSON.parse(
  80. input.match(/tracks=(\[.+?,\])/)[1].replace(",]", "]"),
  81. );
  82. const output = tracks.map(
  83. (x) =>
  84. mediaPath +
  85. x.file.split(".").slice(0, -1).join(".") +
  86. "." +
  87. format.toLowerCase(),
  88. );
  89. const names = tracks.map((x) => x.name);
  90.  
  91. const blobWriter = new zip.BlobWriter("application/zip");
  92. const writer = new zip.ZipWriter(blobWriter);
  93.  
  94. function forSync(i) {
  95. element.innerHTML =
  96. "Downloading track " +
  97. (i + 1) +
  98. " of " +
  99. output.length +
  100. " (" +
  101. (names[i] || "Track " + (i + 1)) +
  102. ")…";
  103. GM.xmlHttpRequest({
  104. method: "GET",
  105. url: output[i],
  106. responseType: "blob",
  107. onload: async (response) => {
  108. await writer.add(
  109. decodeURIComponent(output[i].split("/").pop()),
  110. new zip.BlobReader(response.response),
  111. );
  112.  
  113. if (output[i + 1]) {
  114. forSync(i + 1);
  115. } else {
  116. await writer.close();
  117. const blob = await blobWriter.getData();
  118. saveAs(
  119. blob,
  120. document.getElementsByTagName("h2")[0].textContent + ".zip",
  121. );
  122. element.innerHTML =
  123. "Album successfully downloaded. ZIP file has been passed to the browser.";
  124. }
  125. },
  126. });
  127. }
  128. forSync(0);
  129. });
  130. });
  131. })();