🏠 Home 

VGMLoaderX

Automatically downloads albums from KHInsider without an account.

// ==UserScript==
// @name               VGMLoaderX
// @name:de            VGMLoaderX
// @name:en            VGMLoaderX
// @namespace          sun/userscripts
// @version            1.0.26
// @description        Automatically downloads albums from KHInsider without an account.
// @description:de     Lädt Alben von KHInsider automatisch und ohne Account herunter.
// @description:en     Automatically downloads albums from KHInsider without an account.
// @compatible         chrome
// @compatible         edge
// @compatible         firefox
// @compatible         opera
// @compatible         safari
// @homepageURL        https://forgejo.sny.sh/sun/userscripts
// @supportURL         https://forgejo.sny.sh/sun/userscripts/issues
// @contributionURL    https://liberapay.com/sun
// @contributionAmount €1.00
// @author             Sunny <[email protected]>
// @include            https://downloads.khinsider.com/game-soundtracks/album/*
// @match              https://downloads.khinsider.com/game-soundtracks/album/*
// @connect            vgmdownloads.com
// @connect            vgmsite.com
// @connect            vgmtreasurechest.com
// @run-at             document-end
// @inject-into        page
// @grant              GM.xmlHttpRequest
// @grant              GM_xmlhttpRequest
// @noframes
// @require            https://unpkg.com/@zip.js/zip.js/dist/zip.js
// @require            https://unpkg.com/file-saver
// @require            https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @icon               https://forgejo.sny.sh/sun/userscripts/raw/branch/main/icons/VGMLoaderX.ico
// @copyright          2021-present, Sunny (https://sny.sh/)
// @license            Hippocratic License; https://forgejo.sny.sh/sun/userscripts/src/branch/main/LICENSE.md
// ==/UserScript==
(() => {
for (const x of document.querySelectorAll('a[href^="/cp/add_album/"]')) {
x.addEventListener("click", (e) => {
e.preventDefault();
let format = Array(
...document.querySelectorAll("#songlist_header th[align=right]"),
).map((x) => x.textContent);
if (format.length === 1) {
format = format[0];
} else {
const input = prompt(
`Please enter your desired format (one of ${format.join(", ")}):`,
format[0],
);
if (!input) return;
if (!format.includes(input.toUpperCase())) {
format = format[0];
alert(`Invalid format supplied. Using ${format} instead.`);
} else {
format = input;
}
}
const element = document.getElementsByClassName("albumMassDownload")[0];
element.style.height = "auto";
element.style.marginBottom = "2em";
const input = eval(
document
.querySelector("#pageContent script")
.textContent.slice(5, -3)
.replace("function", "function x")
.replace("return p}", "return p}x"),
);
const mediaPath = input.match(/mediaPath='(.+?)'/)[1];
const tracks = JSON.parse(
input.match(/tracks=(\[.+?,\])/)[1].replace(",]", "]"),
);
const output = tracks.map(
(x) =>
`${
mediaPath + x.file.split(".").slice(0, -1).join(".")
}.${format.toLowerCase()}`,
);
const names = tracks.map((x) => x.name);
const blobWriter = new zip.BlobWriter("application/zip");
const writer = new zip.ZipWriter(blobWriter);
function forSync(i) {
element.innerHTML = `Downloading track ${i + 1} of ${output.length} (${names[i] || `Track ${i + 1}`})...`;
GM.xmlHttpRequest({
method: "GET",
url: output[i],
responseType: "blob",
onload: async (response) => {
await writer.add(
decodeURIComponent(output[i].split("/").pop()),
new zip.BlobReader(response.response),
);
if (output[i + 1]) {
forSync(i + 1);
} else {
await writer.close();
const blob = await blobWriter.getData();
saveAs(
blob,
`${document.getElementsByTagName("h2")[0].textContent}.zip`,
);
element.innerHTML =
"Album successfully downloaded. ZIP file has been passed to the browser.";
}
},
});
}
forSync(0);
});
}
})();