Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save wefalltomorrow/42095f51e9558b44edef39277930ca6d to your computer and use it in GitHub Desktop.
Save wefalltomorrow/42095f51e9558b44edef39277930ca6d to your computer and use it in GitHub Desktop.
Nexus Endorsement Manager - Fork
// ==UserScript==
// @name Nexus Endorsement Manager
// @version 1.2.0
// @description Adds buttons to the "My Nexus account" screen related to the mass endorsement and abstainment from endorsement of mods.
// @author pointfeev & wefalltomorrow
// @copyright 2021, pointfeev
// @license MIT
// @match *://*.nexusmods.com/users/myaccount*
// @match *://*.nexusmods.com/settings/preferences*
// @icon https://www.nexusmods.com/favicon.ico
// @grant none
// @namespace https://github.com/pointfeev
// @homepageURL https://gist.github.com/pointfeev/aa70c3d600698df40141c3a79ad9bf59
// @downloadURL https://update.greasyfork.org/scripts/437215/Nexus%20Endorsement%20Manager.user.js
// @updateURL https://update.greasyfork.org/scripts/437215/Nexus%20Endorsement%20Manager.meta.js
// ==/UserScript==
(function () {
'use strict';
var requests = [];
function endorse(i, item, positive) {
return new Promise(function (resolve, reject) {
if (item[12] !== positive) {
var request = $.ajax({
type: "POST",
url: "https://www.nexusmods.com/Core/Libs/Common/Managers/Mods?Endorse",
data: {
game_id: item[7],
mod_id: item[8],
positive: positive
},
dataType: 'json',
success: function (response) {
resolve(response);
requests.pop(request);
},
error: function (err) {
reject(err);
requests.pop(request);
}
});
requests.push(request);
} else {
resolve(); // Already in desired state
}
});
}
var working = false;
var working_on = "none";
var working_index = 0;
var aborting = false;
function work(positive, btn_text, original_text, count_func) {
if (aborting) return;
if (working) {
if (working_on === original_text) {
aborting = true;
btn_text.text("Aborting . . .");
requests.forEach(function (request) {
request.abort();
requests.pop(request);
});
working = false;
working_on = "none";
aborting = false;
btn_text.text(original_text);
}
return;
}
requests.forEach(function (request) {
request.abort();
requests.pop(request);
});
working = true;
working_on = original_text;
working_index++;
var current_working_index = working_index;
function active() {
return working && working_index === current_working_index;
}
btn_text.text("Requesting download history . . .");
new Promise(function (resolve, reject) {
var request = $.ajax({
type: "GET",
url: "https://www.nexusmods.com/Core/Libs/Common/Managers/Mods?GetDownloadHistory",
dataType: 'json',
success: function (response) {
resolve(response.data);
requests.pop(request);
},
error: function (err) {
reject(err);
requests.pop(request);
}
});
requests.push(request);
}).then(function (data) {
const delayInputValue = getDelay();
const originalCount = data.length;
const filteredData = data.filter(item => item[12] !== positive);
const skippedCount = originalCount - filteredData.length;
if (skippedCount > 0) {
console.log(`Skipped ${skippedCount} mods that were already ${positive ? 'endorsed' : 'not endorsed/abstained'}.`);
}
function processItems(index) {
if (!active() || index >= filteredData.length) {
btn_text.text(original_text + (skippedCount > 0 ? ` (Skipped ${skippedCount})` : ""));
working = false;
working_on = "none";
return;
}
const item = filteredData[index];
const modName = item[0] || `Mod ID ${item[8]}`;
endorse(index, item, positive).then(function (response) {
if (!active()) return;
console.log(`${positive ? 'Endorsed' : 'Abstained from'} \"${modName}\"`);
btn_text.text(count_func(filteredData.length - index - 1));
setTimeout(() => processItems(index + 1), delayInputValue);
}).catch(function (err) {
console.clear();
if (!active()) return;
console.error(`Error processing \"${modName}\":`, err);
btn_text.text(count_func(filteredData.length - index));
setTimeout(() => processItems(index), delayInputValue);
});
}
processItems(0);
btn_text.text(count_func(filteredData.length));
}).catch(function (err) {
console.clear();
if (!active()) return;
btn_text.text(original_text);
});
}
function create_icon(icon_id, icon_class) {
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
use.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "https://www.nexusmods.com/assets/images/icons/icons.svg#icon-" + icon_id);
$(svg).addClass("icon icon-" + icon_class);
svg.append(use);
return svg;
}
var btn_endorse_text = $("<span class='flex-label'>Endorse all mods</span>");
var btn_endorse_a = $("<a class='btn inline-flex' tabindex='0'></a>");
btn_endorse_a.append(create_icon("endorse", "endorse"), btn_endorse_text);
btn_endorse_a.click(() => work(1, btn_endorse_text, "Endorse all mods", count => `Endorsing ${count} mods . . .`));
var btn_endorse_li = $("<li></li>").append(btn_endorse_a);
if ($("#action-preview").length) {
btn_endorse_li.insertBefore("#action-preview");
} else {
let container = $("ul.subby.subforum.double");
if (container.length) container.first().prepend(btn_endorse_li);
}
var btn_abstain_text = $("<span class='flex-label'>Abstain from endorsing all mods</span>");
var btn_abstain_a = $("<a class='btn inline-flex' tabindex='0'></a>");
btn_abstain_a.append(create_icon("ignore", "endorse"), btn_abstain_text);
btn_abstain_a.click(() => work(0, btn_abstain_text, "Abstain from endorsing all mods", count => `Abstaining from endorsing ${count} mods . . .`));
var btn_abstain_li = $("<li></li>").append(btn_abstain_a);
btn_abstain_li.insertAfter(btn_endorse_li);
// Delay input UI
var delayContainer = document.createElement("li");
var delayLabel = document.createElement("label");
delayLabel.textContent = "Delay between requests (ms): ";
var delayInput = document.createElement("input");
delayInput.type = "number";
delayInput.min = "0";
delayInput.value = "1000";
delayInput.style.marginLeft = "5px";
delayInput.style.width = "80px";
delayInput.style.color = "black";
delayInput.style.backgroundColor = "white";
delayLabel.appendChild(delayInput);
delayContainer.appendChild(delayLabel);
if ($("#action-preview").length) {
$("#action-preview").before(delayContainer);
} else if (btn_abstain_li.parent().length) {
$(delayContainer).insertAfter(btn_abstain_li);
} else {
console.warn("Nexus Endorsement Manager: Could not find a suitable place for delay input.");
}
delayInput.addEventListener('input', () => {
const delay = getDelay();
console.log("New delay set: " + delay + " ms");
});
function getDelay() {
const value = delayInput.value;
if (value === "") return 1000;
const parsed = parseInt(value, 10);
return isNaN(parsed) || parsed < 0 ? 1000 : parsed;
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment