Nexus No Wait (Fork)

[Temporary fork] Download from Nexusmods.com without wait and redirect (support Manual/Vortex)

目前为 2020-02-18 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Nexus No Wait (Fork)
  3. // @description [Temporary fork] Download from Nexusmods.com without wait and redirect (support Manual/Vortex)
  4. // @namespace NexusNoWait
  5. // @include https://www.nexusmods.com/*/mods/*
  6. // @run-at document-idle
  7. // @grant GM.xmlHttpRequest
  8. // @grant GM_xmlhttpRequest
  9. // @version 1.5
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. var ajax_request_raw;
  14. if (typeof(GM_xmlhttpRequest) !== "undefined") {
  15. ajax_request_raw = GM_xmlhttpRequest;
  16. } else if (typeof(GM) !== "undefined" && typeof(GM.xmlHttpRequest) !== "undefined") {
  17. ajax_request_raw = GM.xmlHttpRequest;
  18. }
  19. var ajax_request = function(obj) {
  20. if (!ajax_request_raw) {
  21. console.log("Unable to request", obj);
  22. return;
  23. }
  24. var requestobj = {
  25. url: obj.url,
  26. method: obj.type,
  27. data: obj.data,
  28. headers: obj.headers,
  29. };
  30. var loadcb = function(result) {
  31. if (result.readyState !== 4)
  32. return;
  33. if (result.status !== 200) {
  34. return obj.error(result);
  35. } else {
  36. return obj.success(result.responseText);
  37. }
  38. };
  39. requestobj.onload = loadcb;
  40. requestobj.onerror = loadcb;
  41. ajax_request_raw(requestobj);
  42. };
  43. var btnError = function(button) {
  44. button.style.color = "red";
  45. button.innerText = 'ERROR';
  46. };
  47.  
  48. var btnSuccess = function(button) {
  49. button.style.color = "green";
  50. button.innerText = 'LOADING';
  51. };
  52. var click_listener = function(event) {
  53. var href = this.href;
  54. if (/[?&]file_id=/.test(href)) {
  55. event.preventDefault();
  56. var button = this;
  57.  
  58. button.style.color = "yellow";
  59. button.innerText = 'WAIT';
  60.  
  61. var game_id = document.getElementById("section").dataset.gameId;
  62. var search_params = new URL(href).searchParams;
  63. var file_id = search_params.get("file_id");
  64. if (!file_id)
  65. file_id = search_params.get("id"); // for ModRequirementsPopUp
  66.  
  67. if (!/[?&]nmm=/.test(href)) {
  68. ajax_request({
  69. type: "POST",
  70. url: "/Core/Libs/Common/Managers/Downloads?GenerateDownloadUrl",
  71. data: "fid=" + file_id + "&game_id=" + game_id,
  72. headers: {
  73. Origin: "https://www.nexusmods.com",
  74. Referer: href,
  75. "Sec-Fetch-Site": "same-origin",
  76. "X-Requested-With": "XMLHttpRequest",
  77. "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
  78. },
  79. success: function(data) {
  80. if (data) {
  81. try {
  82. data = JSON.parse(data);
  83.  
  84. if (data.url) {
  85. console.log('Success', data.url);
  86. btnSuccess(button);
  87. document.location.href = data.url;
  88. return;
  89. }
  90. } catch (e) {
  91. console.error(e);
  92. }
  93. }
  94. btnError(button);
  95. },
  96. error: function() {
  97. btnError(button);
  98. }
  99. });
  100. } else {
  101. ajax_request({
  102. type: "GET",
  103. url: href,
  104. headers: {
  105. Origin: "https://www.nexusmods.com",
  106. Referer: document.location.href,
  107. "Sec-Fetch-Site": "same-origin",
  108. "X-Requested-With": "XMLHttpRequest"
  109. },
  110. success: function(data) {
  111. if (data) {
  112. var xml = new DOMParser().parseFromString(data, "text/html");
  113. var slow = xml.getElementById("slowDownloadButton");
  114. var downloadUrl = slow.getAttribute("data-download-url");
  115. console.log('Success', downloadUrl);
  116. btnSuccess(button);
  117. document.location.href = downloadUrl;
  118. return;
  119. }
  120. btnError(button);
  121. },
  122. error: function(ajaxContext) {
  123. console.log(ajaxContext.responseText);
  124. btnError(button);
  125. }
  126. });
  127. }
  128.  
  129. var popup = $(this).parent();
  130. if (popup.hasClass('popup')) {
  131. popup.children("button").click();
  132. }
  133. return false;
  134. }
  135. };
  136. var add_click_listener = function(el) {
  137. el.addEventListener("click", click_listener, true);
  138. };
  139. var add_click_listeners = function(els) {
  140. for (var i = 0; i < els.length; i++) {
  141. add_click_listener(els[i]);
  142. }
  143. };
  144. add_click_listeners(document.querySelectorAll("a.btn"));
  145.  
  146. var observer = new MutationObserver(function(mutations, observer) {
  147. for (var i = 0; i < mutations.length; i++) {
  148. if (mutations[i].addedNodes) {
  149. for (var x = 0; x < mutations[i].addedNodes.length; x++) {
  150. var node = mutations[i].addedNodes[x];
  151. if (node.tagName === "A" && node.classList.contains("btn")) {
  152. add_click_listener(node);
  153. } else if (node.children && node.children.length > 0) {
  154. add_click_listeners(node.querySelectorAll("a.btn"));
  155. }
  156. }
  157. }
  158. }
  159. });
  160. observer.observe(document, {childList: true, subtree: true});
  161. })();