Skip to content

Instantly share code, notes, and snippets.

@FaustVX
Last active April 20, 2024 21:14
Show Gist options
  • Save FaustVX/e5320dff2648abe3809403160628fa26 to your computer and use it in GitHub Desktop.
Save FaustVX/e5320dff2648abe3809403160628fa26 to your computer and use it in GitHub Desktop.
CurseForge Direct Download
// ==UserScript==
// @name CurseForge Direct Download
// @namespace FaustVXCurseForge
// @version 1.2.2
// @description Provide a direct download link for files in CurseForge
// @author FaustVX
// @match https://legacy.curseforge.com/*
// @match https://www.curseforge.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=curseforge.com
// @grant none
// @updateURL https://gist.githubusercontent.com/FaustVX/e5320dff2648abe3809403160628fa26/raw/CurseForgeDDL.js
// @downloadURL https://gist.githubusercontent.com/FaustVX/e5320dff2648abe3809403160628fa26/raw/CurseForgeDDL.js
// @installURL https://gist.githubusercontent.com/FaustVX/e5320dff2648abe3809403160628fa26/raw/CurseForgeDDL.js
// @supportURL https://gist.github.com/FaustVX/e5320dff2648abe3809403160628fa26#comments
// @contributionURL https://www.paypal.com/donate/?cmd=_donations&business=jonathan-035@hotmail.fr&item_name=TamperMonkey+CurseForge+DDL
// @license MIT
// ==/UserScript==
const run = function() {
'use strict';
function createURL(fileId, fileName) {
return "https://mediafilez.forgecdn.net/files/" + Number(fileId.slice(0, 4)) + "/" + Number(fileId.slice(4)) + "/" + encodeURIComponent(fileName);
}
function changeTag(node, tag) {
const clone = createElement(tag)
for (const attr of node.attributes) {
clone.setAttributeNS(null, attr.name, attr.value)
}
while (node.firstChild) {
clone.appendChild(node.firstChild)
}
node.replaceWith(clone)
return clone
}
function createElement(tag) {
return document.createElementNS(tag === 'svg' ? 'http://www.w3.org/2000/svg' : 'http://www.w3.org/1999/xhtml', tag)
}
var fileId = window.location.href.split('/')[7];
if (window.location.href.split('/')[2].startsWith("legacy")) {
const column = document.getElementsByTagName("article")[0].children[1].firstElementChild;
changeTag(column.lastElementChild, "a").href = createURL(fileId, column.lastElementChild.innerText);
} else {
const section = document.getElementsByClassName("section-file-name")[0];
const a = changeTag(section.lastElementChild, "a");
a.href = createURL(fileId, section.lastElementChild.innerText);
}
};
// Convenience function to execute your callback only after an element matching readySelector has been added to the page.
// based on https://github.com/Tampermonkey/tampermonkey/issues/1279#issuecomment-875386821
function runWhenReady(readySelector, callback) {
let lastLocation = "";
const tryNow = function() {
if (lastLocation !== window.location.href && document.querySelector(readySelector)) {
lastLocation = window.location.href;
try {
callback();
} catch { }
}
setTimeout(tryNow, 250);
};
tryNow();
}
runWhenReady(".section-file-name,article", run);
@Aces-and-Jacks
Copy link

I get

<Error>
<style class="darkreader darkreader--safari-fallback">
html, body, body > :not(iframe) { background-color: #181a1b !important; border-color: #776e62 !important; color: #e8e6e3 !important; }
</style>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>

on the new site. but the legacy works fine

@FaustVX
Copy link
Author

FaustVX commented Sep 12, 2023

@Aces-and-Jacks

I get

<Error>
<style class="darkreader darkreader--safari-fallback">
html, body, body > :not(iframe) { background-color: #181a1b !important; border-color: #776e62 !important; color: #e8e6e3 !important; }
</style>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>

on the new site. but the legacy works fine

I've updated the script.
I tried with this file https://www.curseforge.com/minecraft/mc-mods/leos-backrooms-alpha/files/4749638, it didn't worked before the update.

@Aces-and-Jacks
Copy link

It works. Thank you for the fix

@FaustVX
Copy link
Author

FaustVX commented Sep 12, 2023

No problem.
Thank you for using my script 😄

@Aces-and-Jacks
Copy link

Aces-and-Jacks commented Sep 12, 2023

Also I was wondering. what's @updateURL for? I was thinking it's to update the script but wasn't sure.
since it's different than the script on greasy fork

@FaustVX
Copy link
Author

FaustVX commented Sep 12, 2023

I don't know very much Tamper Monkey and even less Greasy Fork.
But I think it's for Greasy Fork to know how to update my script.
I only modify the script on this current page, then Greasy Fork automatically store the script on their servers.

@Aces-and-Jacks
Copy link

ohh. Well I guess if greasy fork updates the script that's probably why it's not there

@FaustVX
Copy link
Author

FaustVX commented Sep 12, 2023

Yes, they scrap some ==UserScript== tags.
I added these URL, just because I saw these on other scripts.
I don't know the difference between these 3 tags.

@Aces-and-Jacks
Copy link

oh ok. well thanks for explaining it to me and thanks again for the help

@vanja-san
Copy link

For some reason my tempmonkey can't detect it as a userscript and opens it as a normal raw

@FaustVX
Copy link
Author

FaustVX commented Feb 27, 2024

@vanja-san
It didn't for me neither.
You should go to GreasyFork website: https://greasyfork.org/en/scripts/469426-curseforge-direct-download

@vanja-san
Copy link

@FaustVX 🫰😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment