// ==UserScript== // @name Nexus Download Collection // @namespace NDC // @version 0.8.8 // @description Download every mods of a collection in a single click // @author Drigtime // @match https://next.nexusmods.com/*/collections* // @icon https://www.google.com/s2/favicons?sz=64&domain=nexusmods.com // @grant GM.xmlHttpRequest // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM.setValue // @grant GM.getValue // @grant GM_addStyle // @connect next.nexusmods.com // @connect nexusmods.com // @downloadURL none // ==/UserScript== // MDI : https://pictogrammers.com/library/mdi/ // MDI : https://github.com/MathewSachin/Captura/blob/master/src/Captura.Core/MaterialDesignIcons.cs GM_addStyle(` .bottom-auto { bottom: auto; } .left-auto { left: auto; } .right-0 { right: 0px; } .top-0 { top: 0px; } .translate-y-\\[2rem\\] { --tw-translate-y: 2rem; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } .min-h-7 { min-height: 1.75rem; } .w-11 { width: 2.75rem; } .w-20{ width:5rem; } .w-32 { width: 8rem; } .w-52 { width: 13rem; } @media (min-width: 768px) { .sm\\:rounded-none { border-radius: 0; } .sm\\:gap-0 { gap: 0; } .sm\\:w-52 { width: 13rem; } .sm\\:justify-start { justify-content: flex-start; } } `); /** CORSViaGM BEGINING */ const CORSViaGM = document.body.appendChild( Object.assign(document.createElement("div"), { id: "CORSViaGM" }), ); addEventListener("fetchViaGM", (e) => GM_fetch(e.detail.forwardingFetch)); CORSViaGM.init = (window) => { if (!window) throw new Error("The `window` parameter must be passed in!"); window.fetchViaGM = fetchViaGM.bind(window); // Support for service worker window.forwardingFetch = new BroadcastChannel("forwardingFetch"); window.forwardingFetch.onmessage = async (e) => { const req = e.data; const { url } = req; const res = await fetchViaGM(url, req); const response = await res.blob(); window.forwardingFetch.postMessage({ type: "fetchResponse", url, response, }); }; window._CORSViaGM?.inited?.done(); const info = "🙉 CORS-via-GM initiated!"; console.info(info); return info; }; function GM_fetch(p) { GM_xmlhttpRequest({ ...p.init, url: p.url, method: p.init.method || "GET", onload: (responseDetails) => p.res(new Response(responseDetails.response, responseDetails)), }); } function fetchViaGM(url, init) { let _r; const p = new Promise((r) => { _r = r; }); p.res = _r; p.url = url; p.init = init || {}; dispatchEvent( new CustomEvent("fetchViaGM", { detail: { forwardingFetch: p } }), ); return p; } CORSViaGM.init(window); /** CORSViaGM END */ const convertSize = (sizeInKB) => { // if size is greater than 1GB convert to GB, else in MB const sizeInMB = sizeInKB / 1024; const sizeInGB = sizeInMB / 1024; return sizeInGB >= 1 ? `${sizeInGB.toFixed(2)} GB` : `${sizeInMB.toFixed(2)} MB`; }; class NDC { mods = { all: [], mandatory: [], optional: [], }; constructor(gameId, collectionId) { this.element = document.createElement("div"); this.gameId = gameId; this.collectionId = collectionId; this.pauseBetweenDownload = 5; this.downloadMethod = NDCDownloadButton.DOWNLOAD_METHOD_VORTEX; this.downloadButton = new NDCDownloadButton(this); this.progressBar = new NDCProgressBar(this); this.console = new NDCLogConsole(this); } async init() { this.pauseBetweenDownload = await GM.getValue("pauseBetweenDownload", 5); this.downloadMethod = await GM.getValue( "downloadMethod", NDCDownloadButton.DOWNLOAD_METHOD_VORTEX, ); this.element.innerHTML = ` `; const response = await this.fetchMods(); if (!response) { this.element.innerHTML = '