CurseForge Direct Download

Provide a direct download link for files in CurseForge

  1. // ==UserScript==
  2. // @name CurseForge Direct Download
  3. // @namespace FaustVXCurseForge
  4. // @version 1.2.2
  5. // @description Provide a direct download link for files in CurseForge
  6. // @author FaustVX
  7. // @match https://legacy.curseforge.com/*
  8. // @match https://www.curseforge.com/*
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=curseforge.com
  10. // @grant none
  11. // @supportURL https://gist.github.com/FaustVX/e5320dff2648abe3809403160628fa26#comments
  12. // @contributionURL https://www.paypal.com/donate/?cmd=_donations&business=jonathan-035@hotmail.fr&item_name=TamperMonkey+CurseForge+DDL
  13. // @license MIT
  14. // ==/UserScript==
  15.  
  16. const run = function() {
  17. 'use strict';
  18.  
  19. function createURL(fileId, fileName) {
  20. return "https://mediafilez.forgecdn.net/files/" + Number(fileId.slice(0, 4)) + "/" + Number(fileId.slice(4)) + "/" + encodeURIComponent(fileName);
  21. }
  22.  
  23. function changeTag(node, tag) {
  24. const clone = createElement(tag)
  25. for (const attr of node.attributes) {
  26. clone.setAttributeNS(null, attr.name, attr.value)
  27. }
  28. while (node.firstChild) {
  29. clone.appendChild(node.firstChild)
  30. }
  31. node.replaceWith(clone)
  32. return clone
  33. }
  34.  
  35. function createElement(tag) {
  36. return document.createElementNS(tag === 'svg' ? 'http://www.w3.org/2000/svg' : 'http://www.w3.org/1999/xhtml', tag)
  37. }
  38.  
  39. var fileId = window.location.href.split('/')[7];
  40. if (window.location.href.split('/')[2].startsWith("legacy")) {
  41. const column = document.getElementsByTagName("article")[0].children[1].firstElementChild;
  42. changeTag(column.lastElementChild, "a").href = createURL(fileId, column.lastElementChild.innerText);
  43. } else {
  44. const section = document.getElementsByClassName("section-file-name")[0];
  45. const a = changeTag(section.lastElementChild, "a");
  46. a.href = createURL(fileId, section.lastElementChild.innerText);
  47. }
  48. };
  49.  
  50. // Convenience function to execute your callback only after an element matching readySelector has been added to the page.
  51. // based on https://github.com/Tampermonkey/tampermonkey/issues/1279#issuecomment-875386821
  52. function runWhenReady(readySelector, callback) {
  53. let lastLocation = "";
  54. const tryNow = function() {
  55. if (lastLocation !== window.location.href && document.querySelector(readySelector)) {
  56. lastLocation = window.location.href;
  57. try {
  58. callback();
  59. } catch { }
  60. }
  61. setTimeout(tryNow, 250);
  62. };
  63. tryNow();
  64. }
  65.  
  66. runWhenReady(".section-file-name,article", run);