您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a list of members available for OC2.0, and adds a notifier to the sidebar if you are not in an OC.
当前为
// ==UserScript== // @name OC 2.0 Helper // @namespace Violentmonkey Scripts // @match https://www.torn.com/* // @version 1.4 // @author whatdoesthespacebardo / callmericky [3299880] // @description Adds a list of members available for OC2.0, and adds a notifier to the sidebar if you are not in an OC. // @grant GM_registerMenuCommand // @grant GM.setValue // @grant GM.getValue // @license GNU GPLv3 // ==/UserScript== /* * All edits can be done from the dropdown menu from your browser's userscript extension * If the dropdown menu doesn't work, you can still manually add your API key here */ var APIKey = ""; /* ============================================= * STOP CHANGING THINGS FROM THIS POINT ONWARD =============================================== */ const PDA_APIKey = "###PDA-APIKEY###" let memberInfo = {}; let pageURL = $(location).attr("href"); let totalMembers = 0; let availableMembers = 0; let activeMembers = 0; let userInfo = {}; let _isWindowSmall = window.matchMedia("(max-width: 784px)") if (!isPDA()) { const menu_command_1 = GM_registerMenuCommand("Set API Key (Limited + faction access)", menuCommand) } async function getAPIKey() { if (isPDA()) { APIKey = PDA_APIKey return PDA_APIKey } else { return await GM.getValue("CMR_OC2_APIKey", null) .then(function(data) { APIKey = data return data }) } } function isPDA() { const PDATestRegex = !/^(###).+(###)$/.test(PDA_APIKey); return PDATestRegex; } function menuCommand(event) { let _userKey = window.prompt("OC 2.0 participation and notifier\n- Requires a minimal API key with faction access\n\nSet API Key:", APIKey) if ((_userKey == null || _userKey == "")) { window.alert("OC 2.0 participation and notifier\nYou did not set an API Key - this script will not run") } else { GM.setValue("CMR_OC2_APIKey", _userKey) } } function checkCrimesPage(pageURL) { if (pageURL.search("step=your") > 0 && pageURL.search("tab=crimes") > 0) { return true; } else { return false; } } function getUserID() { let _profileLink = $(".settings-menu > .link > a")[0] let _matchregex = /profiles\.php.+XID=(\d+)/i let _userID = _matchregex.exec(_profileLink) return _userID[1] } async function getFactionMembers() { return await $.getJSON(`https://api.torn.com/v2/faction/members?key=${APIKey}&striptags=true`) .then(function(data) { return data; }); } async function getCrimesList() { return await $.getJSON(`https://api.torn.com/v2/faction/crimes?key=${APIKey}&cat=available&offset=0`) .then(function(data) { return data; }); } function checkMembersInCrimes(_members, _crimes) { //put all member ids into a list for (i = 0; i < (_members.members).length; i++) { if (_members.members[i].status.state == "Fallen") { //skip fallen members } else if (_members.members[i].position == "Recruit") { //skip recruits since they can't join OC } else { memberInfo[_members.members[i].id] = { "name": _members.members[i].name, "last_action": _members.members[i].last_action.relative, "status": _members.members[i].status.description } } } totalMembers = (_members.members).length; activeMembers = 0 //if this doesn't reset, hashchange will cause the following part to re-fire and get activemembers count wrong. //go through crime list for (i = 0; i < (_crimes.crimes).length; i++) { //if crime is not initiated, it will be null for initiated_at. No point looking for members because there won't be any. if (_crimes.crimes[i].initiated_at) { for (j=0; j<(_crimes.crimes[i].slots).length; j++) if (_crimes.crimes[i].slots[j].user_id) { memberInfo[_crimes.crimes[i].slots[j].user_id].crimeInfo = { "crimeName": _crimes.crimes[i].name, "crimeDifficulty": _crimes.crimes[i].difficulty, "crimeId": _crimes.crimes[i].id, "crimePosition": _crimes.crimes[i].slots[j].position, "crimeSuccess": _crimes.crimes[i].slots[j].success_chance } activeMembers = activeMembers + 1; if ((_crimes.crimes[i].slots[j].user_id) == getUserID()) { userInfo = memberInfo[_crimes.crimes[i].slots[j].user_id] } } } } availableMembers = totalMembers - activeMembers; } function putMemberInfoIntoTable() { if ($(".OC2-memberTable .OC2-tablecell")[0]) { return } for (var _key of Object.keys(memberInfo)) { let _outputAvail = "AVAILABLE" let _outputHTML = "" let _memberHighlight = "OC2-memberAvailable" if (memberInfo[_key].crimeInfo) { _outputAvail = `${memberInfo[_key].crimeInfo.crimePosition} of <a href="https://www.torn.com/factions.php?step=your&type=5#/tab=crimes&crimeId=${memberInfo[_key].crimeInfo.crimeId}">${memberInfo[_key].crimeInfo.crimeName}</a> (Lv ${memberInfo[_key].crimeInfo.crimeDifficulty})` _memberHighlight = "OC2-memberInCrime" } _outputHTML = (`<li class="table-cell ${_memberHighlight}"> <div class="OC2-tablecell OC2-tableMember">${memberInfo[_key].name} [${_key}]</div> <div class="OC2-tablecell OC2-tableAvailability">${_outputAvail}</div> <div class="OC2-tablecell OC2-tableStatus">${memberInfo[_key].status}</div> </li>`) //put all the members currently in crimes below if (memberInfo[_key].crimeInfo) { $(".OC2-memberTable ul.table-body").append(_outputHTML) } else { $(".OC2-memberTable ul.table-body").prepend(_outputHTML) } $(".OC2-memberTableFooter").text(`${availableMembers} / ${totalMembers} members available (${activeMembers} in an OC)`) } styleTable() } function generateInsertHTML() { _insertHTML = (` <div class="category-wrap OC2-memberViewer m-top10"> <div class="title-black top-round t-overflow">OC 2.0 Member Overview <span class="hideInfoButton">Show all members</span></div> <div class="cont-gray OC2-memberTable"><ul class="table-body"> </ul></div> <div class="OC2-memberTableFooter"></div> </div>`) $("div#faction-crimes").before(_insertHTML) $("span.hideInfoButton").on("click", event => { toggleMemberView() }) styleTable() } function toggleMemberView() { if ($(".hideInfoButton").hasClass("text-hide")) { $(".hideInfoButton").text("Show all members") $(".hideInfoButton").removeClass("text-hide") } else { $(".hideInfoButton").text("Hide active members") $(".hideInfoButton").addClass("text-hide") } $(".OC2-memberInCrime").toggle() } function styleTable() { $(".OC2-memberTable ul.table-body").css({ "display": "flex", "flex-direction": "column" }) $(".OC2-memberTable a").css({ "color": "rgb(116, 192, 252)", "text-decoration": "none" }) $(".OC2-memberTable li.table-cell").css({ "display": "flex", "flex-direction": "row" }) $(".OC2-memberTable li.OC2-memberAvailable").css({ "font-weight": "bold" }) $(".OC2-memberTable li.OC2-memberInCrime").css({ "color": "rgb(153, 153, 153)", }) $(".OC2-memberTable div").css({ "font-size": "11px", "line-height": "11px", "padding": "5px 5px 5px 10px" }) $(".OC2-memberTable div.OC2-tablecell").css({ "display": "inline" }) $(".OC2-memberTable div.OC2-tableMember").css({ "width": "200px" }) $(".OC2-memberTable div.OC2-tableAvailability").css({ "width": "250px", }) $(".OC2-memberTable div.OC2-tableCrimeSlot").css({ "width": "100px" }) $(".OC2-memberTable div.OC2-tableStatus").css({ "width": "200px" }) $(".OC2-memberTableFooter").css({ "border-radius": "0 0 5px 5px", "background-color": "rgb(51, 51, 51)", "padding": "5px 5px 5px 10px", "text-align": "center" }) $(".hideInfoButton").css({ "position": "absolute", "right": "10px", "cursor": "pointer" }) //light mode styling if ($("body").css("background-color") == "rgb(204, 204, 204)") { $(".OC2-memberTable a").css({ "color": "#006699", }) $(".OC2-memberTableFooter").css({ "background-color": "rgb(242, 242, 242)" }) } if (_isWindowSmall.matches) { styleTableSmallScreen() } } function styleTableSmallScreen() { $(".OC2-memberTable div.OC2-tableCrimeSlot").css({ "display": "none" }) $(".OC2-memberTable div.OC2-tableStatus").css({ "display": "none" }) } function insertOCNotifier() { let _userNotice = (`<a href="https://www.torn.com/factions.php?step=your#/tab=crimes"><span class="OC2-redtext">No active OC.</span></a>`) if (userInfo.crimeInfo) { _userNotice = (`<span class="OC2-normaltext"><a href="https://www.torn.com/factions.php?step=your&type=5#/tab=crimes&crimeId=${userInfo.crimeInfo.crimeId}">${userInfo.crimeInfo.crimePosition} of ${userInfo.crimeInfo.crimeName} (Lv ${userInfo.crimeInfo.crimeDifficulty})</a></span>`) } let _insertHTML = (`<div class="OC2-sidebarNotice"><a href="https://www.torn.com/factions.php?step=your#/tab=crimes"><span style="font-weight: bold">OC 2.0:</span></a> ${_userNotice} </div>`) $('div[class^="sidebar_"] div[class^="user-information_"] div[class^="toggle-block_"] div[class^="toggle-content_"] div[class^="content_"]').append(_insertHTML) styleOCNotifier() } function styleOCNotifier() { $(".OC2-sidebarNotice a").css({ "text-decoration": "none", "color": "inherit" }) $(".OC2-sidebarNotice .OC2-redtext").css({ "text-decoration": "none", "color": "rgb(255, 121, 76)" }) } /* if page is the crimes 2.0 page * -> if memberViewer table does NOT exist, get data and fill table * -> otherwise, show the table * -> otherwise, hide the table */ async function hashChangeFunction() { let pageURL = $(location).attr("href"); if (checkCrimesPage(pageURL)) { //insert member overview if (!$(".OC2-memberViewer")[0]) { generateInsertHTML(); putMemberInfoIntoTable(); } else { $(".OC2-memberViewer").show() } } else { if ($(".OC2-memberViewer")[0]) { $(".OC2-memberViewer").hide(); } } $(".OC2-memberInCrime").hide(); } async function runOnceFunction() { //exit if API key doesn't exist await getAPIKey() .then(function(data) { if (APIKey == null || APIKey == "") { return; } }) //get data const [_memberData, _crimesData] = await Promise.all([ getFactionMembers(), getCrimesList() ]) //analyze data checkMembersInCrimes(_memberData, _crimesData) if (!$(".OC2-sidebarNotice")[0]) { insertOCNotifier() } let pageURL = $(location).attr("href"); if (checkCrimesPage(pageURL)) { //insert member overview if (!$(".OC2-memberViewer")[0]) { generateInsertHTML(); } else { $(".OC2-memberViewer").show() } } putMemberInfoIntoTable(); $(".OC2-memberInCrime").hide(); } async function viewTableWhileTraveling() { await getAPIKey() .then(function(data) { console.log("APIKey runOnceFunction", APIKey) if (APIKey == null || APIKey == "") { return; } }) let _factionInfo = await $.getJSON(`https://api.torn.com/v2/faction/basic?key=${APIKey}`) .then(function(data) { return data; }); let pageURL = $(location).attr("href") waitForElm('div#react-root').then((elm) => { if ($(".OC2-memberTable")[0]) { return } if (pageURL.search("ID="+_factionInfo.basic.id) > 0) { var _insertHTML = (` <div class="category-wrap OC2-memberViewer m-top10"> <div class="title-black top-round t-overflow">OC 2.0 Member Overview <span class="hideInfoButton">Show all members</span></div> <div class="cont-gray OC2-memberTable"><ul class="table-body"> </ul></div> <div class="OC2-memberTableFooter"></div> </div>`) $(elm).before(_insertHTML) $("span.hideInfoButton").on("click", event => { toggleMemberView() }) styleTable() } }) } //waitForElm from stackoverflow https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists function waitForElm(selector) { return new Promise(resolve => { if (document.querySelector(selector)) { return resolve(document.querySelector(selector)); } const observer = new MutationObserver(mutations => { if (document.querySelector(selector)) { observer.disconnect(); resolve(document.querySelector(selector)); } }); // If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336 observer.observe(document.body, { childList: true, subtree: true }); }); } runOnceFunction() $(window).on('hashchange', hashChangeFunction); if (($(body).attr("data-traveling") == "true") || ($(body).attr("data-traveling") == true)) { viewTableWhileTraveling() } _isWindowSmall.addEventListener("change", function() { styleTable() });
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址