您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Displays various informations from YATA's API
当前为
- // ==UserScript==
- // @name YATA
- // @namespace yata.yt
- // @version 0.12
- // @grant GM_addStyle
- // @description Displays various informations from YATA's API
- // @author Kivou [2000607]
- // @grant GM.xmlHttpRequest
- // @match https://www.torn.com/factions.php*
- // @match https://www.torn.com/preferences.php*
- // @match https://www.torn.com/profiles.php*
- // @icon https://yata.yt/media/yata-small.png
- // @require https://gf.qytechs.cn/scripts/477604-kiv-lib/code/kiv-lib.js?version=1266053
- // @run-at document-end
- // @license WTFPL
- // ==/UserScript==
- // Copyright © 2023 Kivou [2000607] <contact@yata.yt>
- // This work is free. You can redistribute it and/or modify it under the
- // terms of the Do What The Fuck You Want To Public License, Version 2,
- // as published by Sam Hocevar. See http://www.wtfpl.net/ for more details.
- // ------------- //
- // SETUP API KEY //
- // ------------- //
- const display_status = (element) => {
- const key = localStorage.getItem('key');
- let innerHTML = "";
- innerHTML += `<div>`;
- innerHTML += `<b>[YATA]</b> API key used <span style="font-family: monospace; font-weight: bold;">${key}</span>`;
- if (key) {
- innerHTML += ` | Status <b id="yata-status" style="color: var(--default-green-color); font-weight: bold;">enabled</b>`;
- innerHTML += ` | Click <span id="yata-api-key-rm" class="t-blue" style="cursor: pointer;">here to disable</span> the script`;
- } else {
- innerHTML += ` | Status <b id="yata-status" style="color: var(--default-red-color); font-weight: bold;">disabled</b>`;
- innerHTML += ` | Click on a key to enable the script`;
- }
- innerHTML += `</div>`;
- innerHTML += `<div class="clear"></div>`;
- innerHTML += `<hr class="page-head-delimiter m-top10">`;
- element.innerHTML = innerHTML;
- };
- waitFor(document, "div.preferences-container").then(div => {
- let injected = false;
- const display_element = document.createElement("div");
- div.insertAdjacentElement('beforebegin', display_element);
- // triggered by clicking on crimes tab
- const callback = (mutations, observer) => {
- [...mutations].forEach(mutation => {
- [...mutation.addedNodes].filter(n => n.className && n.className.includes("keyRow___")).forEach(node => {
- const key_node = node.querySelector("input");
- key_node.style.cursor = "pointer";
- // if(!localStorage.getItem('key')) {
- // localStorage.setItem('key', key_node.value);
- // document.getElementById("yata-api-key").innerHTML = localStorage.getItem('key')
- // }
- });
- });
- if (!injected) {
- display_status(display_element);
- injected = true;
- }
- };
- const observer = new MutationObserver(callback);
- observer.observe(div, { childList: true, subtree: true });
- document.querySelector("div.content-wrapper").addEventListener('click', e => {
- const button = e.target;
- if (button.tagName == 'INPUT' && button.id.includes('key-row')) {
- localStorage.setItem('key', button.value);
- }
- else if (button.tagName == 'SPAN' && button.id == 'yata-api-key-rm') {
- localStorage.clear();
- }
- display_status(display_element);
- });
- });
- // -------------- //
- // OC: NNB + rank //
- // -------------- //
- const display_nnb = (members, player) => {
- const urlParams = new URLSearchParams(player.children[0].children[0].href.split("?")[1]);
- const lvl = player.children[1].innerText.trim();
- if (members.members && members.members.hasOwnProperty(urlParams.get("XID"))) {
- const m = members.members[urlParams.get("XID")];
- if (m.nnb_share > 0) {
- player.children[1].innerHTML = `<span>#<b>${m.crimes_rank}</b> / <b>${m.nnb}</b> / ${lvl}</span>`;
- } else if (m.nnb_share < 0) {
- player.children[1].innerHTML = `<span title="Not on YATA">#<b>${m.crimes_rank}</b> / <b>!</b> / ${lvl}</span>`;
- } else {
- player.children[1].innerHTML = `<span title="Not sharing NNB">#<b>${m.crimes_rank}</b> / <b>?</b> / ${lvl}</span>`;
- }
- } else {
- player.children[1].innerHTML = `<span title="Not found">#<b>?</b> / <b>err</b> / ${lvl}</span>`;
- }
- };
- waitFor(document, "div#faction-crimes").then(div => {
- const key = localStorage.getItem('key');
- if (!key) { return; }
- const profile_url = new URLSearchParams(window.location.search);
- const target_id = profile_url.get("XID");
- gmGet(`https://yata.yt/api/v1/faction/members/?key=${key}`, 'nnb').then(members => {
- // triggered if directly landing on crimes
- div.querySelectorAll("ul.details-list, ul.plans-list").forEach(ul => {
- ul.querySelectorAll("ul.item").forEach(player => {
- display_nnb(members, player);
- });
- });
- div.querySelectorAll("ul.title li.level").forEach(t => {
- t.innerHTML = 'Rank / NNB / Level';
- });
- // triggered by clicking on crimes tab
- const callback = (mutations, observer) => {
- [...mutations].forEach(mutation => {
- [...mutation.addedNodes].filter(n => n.className && n.className.includes("faction-crimes-wrap")).forEach(node => {
- node.querySelectorAll("ul.details-list, ul.plans-list").forEach(ul => {
- const ocs = ul.querySelectorAll("ul.item");
- console.log(`[yata] displaying NNB for OC: ${ocs.length}`);
- ocs.forEach(player => {
- display_nnb(members, player);
- });
- });
- node.querySelectorAll("ul.title li.level").forEach(t => {
- t.innerHTML = 'Rank / NNB / Level';
- });
- });
- });
- };
- const observer = new MutationObserver(callback);
- observer.observe(div, { childList: true });
- }).catch(error => {
- alert(`[yata] ${error.message}`);
- if (error.message == "Incorrect key") {
- localStorage.removeItem('key');
- }
- });
- });
- // ---------------------- //
- // PROFILE //
- // ---------------------- //
- waitFor(document, "a.profile-button-report").then(a => {
- const div = document.getElementById("profileroot");
- const key = localStorage.getItem('key');
- const profile_url = new URLSearchParams(a.href.split("?")[1]);
- const target_id = profile_url.get("userID");
- if (!target_id) { return; }
- if (!key) { return; }
- gmGet(`https://yata.yt/api/v1/bs/${target_id}/?key=${key}`, `bs-${target_id}`).then(bs => {
- let innerHTML = "";
- innerHTML += `<hr class="page-head-delimiter m-top10 m-bottom10">`;
- innerHTML += `<div>`;
- innerHTML += `<b>[YATA]</b> <b>Battle stats</b> ${floatFormat(bs[target_id].total, 3)}`;
- innerHTML += ` | <b>Build</b> ${bs[target_id].type} (${bs[target_id].skewness}%)`;
- innerHTML += `</div>`;
- innerHTML += `<hr class="page-head-delimiter m-top10 m-bottom10">`;
- innerHTML += `<div class="clear"></div>`;
- const bs_node = document.createElement("div");
- bs_node.innerHTML = innerHTML;
- div.querySelector("div.profile-wrapper").insertAdjacentElement('afterend', bs_node);
- console.log(`[yata] battle stats estimate on profile page: ${target_id}`);
- }).catch(error => {
- alert(`[yata] ${error.message}`);
- if (error.code == 4) {
- localStorage.removeItem('key');
- }
- });
- });
- // -------------------------- //
- // FACTIONS: Helper functions //
- // -------------------------- //
- const bse_html = (id, bs) => {
- if (!bs.hasOwnProperty("type")) {
- return `<a style="text-decoration: none; display: inline-block;" href="/loader.php?sid=attack&user2ID=${id}" target="_blank"><span title='${bs["message"]}' style="color: var(--default-red-color);">err</span></a>`;
- }
- let color = "var(--default-blue-color)";
- if (bs.type == "Offensive" && bs.skewness > 20) {
- color = "var(--default-red-color)";
- } else if (bs.type == "Defensive" && bs.skewness > 20) {
- color = "var(--default-green-color)";
- }
- const title = `Total stats: ${bs.total.toLocaleString("en-GB")} Build: ${bs.type} (${bs.skewness}%)`;
- return `<a style="text-decoration: none; display: inline-block;" href="/loader.php?sid=attack&user2ID=${id}" target="_blank"><span title="${title}" style="color: ${color};">${floatFormat(bs.total, 3)}</span></a>`;
- };
- // ---------------------- //
- // FACTIONS: Members list //
- // ---------------------- //
- const members_list_filter = (div) => {
- if (div.tagName != "DIV") { return false; }
- if (div.classList.contains("faction-info-wrap")) { return true; }
- return Boolean(div.querySelector("div.faction-info-wrap"));
- };
- const members_list_display = (members, key) => {
- console.log(`[yata] battle stats estimate for members list: ${members.length}`);
- [...members].forEach(member => {
- const url = new URLSearchParams(member.querySelector("div.member.icons").querySelector("div[class^=userWrap]").querySelector("a[class^=linkWrap]").href.split("?")[1]);
- const member_id = url.get("XID");
- gmGet(`https://yata.yt/api/v1/bs/${member_id}/?key=${key}`, `bs-${member_id}`).then(bs => {
- const node = document.createElement("span");
- node.innerHTML = bse_html(member_id, bs[member_id]);
- node.style.width = "4em";
- // member.querySelector("div.member-icons").insertAdjacentElement('afterbegin', node);
- member.querySelector("div.position").insertAdjacentElement('afterbegin', node);
- }).catch((error) => {
- const node = document.createElement("span");
- node.innerHTML = bse_html(member_id, error);
- node.style.width = "4em";
- // member.querySelector("div.member-icons").insertAdjacentElement('afterbegin', node);
- member.querySelector("div.position").insertAdjacentElement('afterbegin', node);
- });
- });
- };
- // -------------- //
- // FACTIONS: Wars //
- // -------------- //
- const wars_list_filter = (node) => {
- if (node.tagName != "DIV") { return false; }
- return node.tagName == "DIV" && node.classList.contains("faction-war");
- };
- const wars_list_display = (members, type, key) => {
- console.log(`[yata] battle stats estimate for ${type}: ${members.length}`);
- [...members].forEach(member => {
- // STEP 1: get target ID
- let member_id = undefined;
- if (type == "wall") {
- const url = new URLSearchParams(
- member.querySelector("a.user.name").href.split("?")[1]
- );
- member_id = url.get("XID");
- } else {
- const url = new URLSearchParams(
- member.querySelector("div.member.icons")
- .querySelector("div[class^=userWrap]")
- .querySelector("a[class^=linkWrap]").href.split("?")[1]
- );
- member_id = url.get("XID");
- }
- // STEP 2: make call
- gmGet(`https://yata.yt/api/v1/bs/${member_id}/?key=${key}`, `bs-${member_id}`).then(bs => {
- const node = document.createElement("span");
- node.innerHTML = bse_html(member_id, bs[member_id]);
- if (type == "wall") {
- // replace attack link
- node.style.paddingRight = "0.5em";
- member.children[4].innerHTML = node.outerHTML;
- } else if (type == "rank-right") {
- // prepend to level
- node.style.paddingRight = "1em";
- member.children[1].insertAdjacentElement('afterbegin', node);
- } else if (type == "rank-left") {
- // replace link
- node.style.paddingRight = "0.5";
- member.children[4].innerHTML = node.outerHTML;
- } else {
- // replace attack link
- node.style.paddingRight = "0.5em";
- member.children[5].innerHTML = node.outerHTML;
- }
- }).catch((error) => {
- const node = document.createElement("span");
- node.innerHTML = bse_html(member_id, error);
- if (type == "wall") {
- // replace attack link
- node.style.paddingRight = "0.5em";
- member.children[4].innerHTML = node.outerHTML;
- } else if (type == "rank-right") {
- // prepend to level
- node.style.paddingRight = "1em";
- member.children[1].insertAdjacentElement('afterbegin', node);
- } else if (type == "rank-left") {
- // replace link
- node.style.paddingRight = "0.5";
- member.children[4].innerHTML = node.outerHTML;
- } else {
- // replace attack link
- node.style.paddingRight = "0.5em";
- member.children[5].innerHTML = node.outerHTML;
- }
- });
- });
- };
- const chain_list_filter = (node) => {
- if (node.tagName != "UL") { return false; }
- return node.tagName == "UL" && node.classList.contains("chain-attacks-list");
- };
- const chain_list_display = (attacks, key) => {
- console.log(`[yata] battle stats estimate for chain: ${attacks.length}`);
- const _f = (e) => { return Boolean(e.querySelector("div.right-player div[class^=userInfoBox]")); };
- [...attacks].filter(_f).forEach(attack => {
- const target = attack.querySelector("div.right-player");
- const url = new URLSearchParams(
- target.querySelector("div.member.icons")
- .querySelector("div[class^=userWrap]")
- .querySelector("a[class^=linkWrap]").href.split("?")[1]
- );
- const target_id = url.get("XID");
- const respect = attack.querySelector("div.respect");
- gmGet(`https://yata.yt/api/v1/bs/${target_id}/?key=${key}`, `bs-${target_id}`).then(bs => {
- const node = document.createElement("span");
- node.innerHTML = bse_html(target_id, bs[target_id]);
- node.style.float = 'right';
- respect.insertAdjacentElement('beforeend', node);
- }).catch((error) => {
- const node = document.createElement("span");
- node.innerHTML = bse_html(target_id, error);
- node.style.float = 'right';
- respect.insertAdjacentElement('beforeend', node);
- });
- });
- };
- // ------------------- //
- // FACTIONS: observers //
- // ------------------- //
- const callback_factions = (key) => {
- return (mutations, observer) => {
- const tab = window.location.hash.replace("#/tab=", "");
- if (["territory", "rank", "upgrades", "armoury", "controls"].includes(tab)) { return; }
- [...mutations].forEach(mutation => {
- [...mutation.addedNodes].forEach(node => {
- // members list
- if (members_list_filter(node)) {
- const members = node.querySelectorAll("li.table-row");
- if (members.length) { members_list_display(members, key); }
- }
- // chains
- if (chain_list_filter(node)) {
- chain_list_display(node.childNodes, key);
- // observe new attacks
- const callback_chain = (key) => {
- return (mutations, observer) => {
- [...mutations].forEach(mutation => {
- const attacks = [...mutation.addedNodes];
- chain_list_display(attacks, key);
- });
- };
- };
- const walls_observer = new MutationObserver(callback_chain(key));
- walls_observer.observe(node, { childList: true });
- }
- // wars
- if (wars_list_filter(node)) {
- // 2 lists for RW, 1 for walls and 1 for raids
- [...node.querySelectorAll("div.members-cont > ul.members-list")].forEach(faction => {
- const members = faction.querySelectorAll("li.your, li.enemy");
- if (tab.includes("rank")) { // RW
- if (members[0].classList.contains("your")) {
- wars_list_display(members, "rank-right", key);
- } else {
- wars_list_display(members, "rank-left", key);
- }
- } else if (tab.includes("raid")) { // Raids
- wars_list_display(members, "raid", key);
- } else { // walls
- wars_list_display(members, "wall", key);
- // observe wall jumps
- const callback_walls = (key) => {
- return (mutations, observer) => {
- const _f = (e) => { return e.className.includes("your") || e.className.includes("enemy"); };
- [...mutations].forEach(mutation => {
- const members = [...mutation.addedNodes].filter(_f);
- wars_list_display(members, "wall", key);
- });
- };
- };
- const walls_observer = new MutationObserver(callback_walls(key));
- walls_observer.observe(faction, { childList: true });
- }
- });
- }
- });
- });
- };
- };
- waitFor(document, "div#factions").then(factions => {
- const key = localStorage.getItem('key');
- if (!key) { return; }
- const obs = new MutationObserver(callback_factions(key));
- obs.observe(factions, { childList: true, subtree: true });
- });
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址