VGMLoaderX

Automatically downloads albums from KHInsider without an account.

目前为 2021-08-16 提交的版本,查看 最新版本

  1. // @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT
  2. /* eslint-env browser, greasemonkey */
  3. /* global zip, saveAs */
  4.  
  5. // ==UserScript==
  6. // @name VGMLoaderX
  7. // @name:de VGMLoaderX
  8. // @name:en VGMLoaderX
  9. // @namespace https://github.com/TheLastZombie/
  10. // @version 1.0.2
  11. // @description Automatically downloads albums from KHInsider without an account.
  12. // @description:de Lädt Alben von KHInsider automatisch und ohne Account herunter.
  13. // @description:en Automatically downloads albums from KHInsider without an account.
  14. // @homepageURL https://github.com/TheLastZombie/userscripts#vgmloaderx-
  15. // @supportURL https://github.com/TheLastZombie/userscripts/issues/new?labels=VGMLoaderX
  16. // @contributionURL https://ko-fi.com/rcrsch
  17. // @author TheLastZombie
  18. // @match https://downloads.khinsider.com/game-soundtracks/album/*
  19. // @connect vgmsite.com
  20. // @grant GM.xmlHttpRequest
  21. // @grant GM_xmlhttpRequest
  22. // @require https://cdn.jsdelivr.net/gh/gildas-lormeau/zip.js@7949db15556ebdbd076e543fd77134286ad6e4fc/dist/zip.min.js
  23. // @require https://cdn.jsdelivr.net/gh/eligrey/FileSaver.js@5bb701bd6ea05a02836daf8ef88ec350a1dd4d83/dist/FileSaver.min.js
  24. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
  25. // @icon https://raw.githubusercontent.com/TheLastZombie/userscripts/master/icons/VGMLoaderX.ico
  26. // @copyright 2021, TheLastZombie (https://github.com/TheLastZombie/)
  27. // @license MIT; https://github.com/TheLastZombie/userscripts/blob/master/LICENSE
  28. // ==/UserScript==
  29.  
  30. // ==OpenUserJS==
  31. // @author TheLastZombie
  32. // ==/OpenUserJS==
  33.  
  34. (function () {
  35. document.querySelectorAll('a[href^="https://downloads.khinsider.com/cp/add_album/"]').forEach(x => {
  36. x.addEventListener('click', e => {
  37. e.preventDefault()
  38.  
  39. let format = Array(...document.querySelectorAll('#songlist_header th[align=right]')).map(x => x.textContent)
  40. if (format.length === 1) {
  41. format = format[0]
  42. } else {
  43. const input = prompt('Please enter your desired format (one of ' + format.join(', ') + '):', format[0])
  44. if (!format.includes(input.toUpperCase())) {
  45. format = format[0]
  46. alert('Invalid format supplied. Using ' + format + ' instead.')
  47. } else {
  48. format = input
  49. }
  50. }
  51.  
  52. const element = document.getElementsByClassName('albumMassDownload')[0]
  53. element.style.height = 'auto'
  54. element.style.marginBottom = '2em'
  55.  
  56. // eslint-disable-next-line no-eval
  57. const input = eval(document
  58. .querySelector('#EchoTopic script')
  59. .textContent
  60. .slice(5, -3)
  61. .replace('function', 'function x')
  62. .replace('return p}', 'return p}x')
  63. )
  64. const mediaPath = input.match(/mediaPath='(.+?)'/)[1]
  65. const tracks = JSON.parse(input.match(/tracks=(\[.+?\])/)[1].replace(',]', ']'))
  66. const output = tracks.map(x => mediaPath + x.file.split('.').slice(0, -1).join('.') + '.' + format.toLowerCase())
  67. const names = tracks.map(x => x.name)
  68.  
  69. const blobWriter = new zip.BlobWriter('application/zip')
  70. const writer = new zip.ZipWriter(blobWriter)
  71.  
  72. function forSync (i) {
  73. element.innerHTML = 'Downloading track ' + (i + 1) + ' of ' + output.length + ' (' + names[i] + ')…'
  74. GM.xmlHttpRequest({
  75. method: 'GET',
  76. url: output[i],
  77. responseType: 'blob',
  78. onload: async response => {
  79. await writer.add(decodeURIComponent(output[i].split('/').pop()), new zip.BlobReader(response.response))
  80.  
  81. if (output[i + 1]) {
  82. forSync(i + 1)
  83. } else {
  84. await writer.close()
  85. const blob = await blobWriter.getData()
  86. saveAs(blob, document.getElementsByTagName('h2')[0].textContent + '.zip')
  87. element.innerHTML = 'Album successfully downloaded. ZIP file has been passed to the browser.'
  88. }
  89. }
  90. })
  91. }
  92. forSync(0)
  93. })
  94. })
  95. })()
  96.  
  97. // @license-end