Torn War Stuff Enhanced

Show travel status and hospital time and sort by hospital time on war page. Fork of https://greasyfork.org/en/scripts/448681-torn-war-stuff

当前为 2025-03-08 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Torn War Stuff Enhanced
// @namespace    namespace
// @version      0.6a
// @description  Show travel status and hospital time and sort by hospital time on war page. Fork of https://greasyfork.org/en/scripts/448681-torn-war-stuff
// @author       xentac
// @license      MIT
// @match       *.torn.com/factions.php*
// @grant        GM_addStyle
// ==/UserScript==

// TODO: Make a preferences page where you can enter your API key and choose absolute times or timers
const APIKEY = "API_KEY_HERE";
const sort_enemies = true;

GM_addStyle(`
.warstuff_highlight {
  background-color: #afa5 !important;
}
`);

setInterval(() => {
  const warDIV = document.querySelector("DIV.faction-war");
  if (warDIV) replaceEnemyInfo(warDIV);
}, 15000);

const observer = new MutationObserver((mutations) => {
  for (const mutation of mutations) {
    for (const node of mutation.addedNodes) {
      if (node.classList && node.classList.contains("faction-war")) {
        replaceEnemyInfo(node);
      }
    }
  }
});

function pad_with_zeros(n) {
  if (n < 10) {
    return "0" + n;
  }
  return n;
}

const wrapper = document.body; //.querySelector('#mainContainer')
observer.observe(wrapper, { subtree: true, childList: true });

const hospital_timers = new Map();

async function replaceEnemyInfo(node) {
  hospital_timers.forEach((k, v) => {
    clearInterval(v);
    hospital_timers[k] = undefined;
  });
  const enemy_LIs = node.querySelectorAll("LI.enemy");
  const enemy_faction_id = enemy_LIs[0]
    .querySelector(`A[href^='/factions.php']`)
    .href.split("ID=")[1];
  const enemy_basic = await fetch(
    `https://api.torn.com/faction/${enemy_faction_id}?selections=basic&key=${APIKEY}`,
  )
    .then((r) => r.json())
    .catch(console.error);
  enemy_LIs.forEach((li) => {
    const status_DIV = li.querySelector("DIV.status");
    const enemy_id = li
      .querySelector(`A[href^='/profiles.php']`)
      .href.split("ID=")[1];
    const enemy_status = enemy_basic.members[enemy_id].status;
    li.setAttribute("data-until", enemy_status.until);
    enemy_status.description = enemy_status.description
      .replace("South Africa", "SA")
      .replace("Cayman Islands", "CI")
      .replace("United Kingdom", "UK")
      .replace("Argentina", "Arg")
      .replace("Switzerland", "Switz");
    switch (enemy_status.state) {
      case "Abroad":
      case "Traveling":
        if (enemy_status.description.includes("Traveling to ")) {
          li.setAttribute("data-sortA", "4");
          status_DIV.innerText =
            "► " + enemy_status.description.split("Traveling to ")[1];
        } else if (enemy_status.description.includes("In ")) {
          li.setAttribute("data-sortA", "3");
          status_DIV.innerText = enemy_status.description.split("In ")[1];
        } else if (enemy_status.description.includes("Returning")) {
          li.setAttribute("data-sortA", "2");
          status_DIV.innerText =
            "◄ " + enemy_status.description.split("Returning to Torn from ")[1];
        } else if (enemy_status.description.includes("Traveling")) {
          li.setAttribute("data-sortA", "5");
          status_DIV.innerText = "Traveling";
        }
        break;
      case "Hospital":
        li.setAttribute("data-sortA", "1");
        if (hospital_timers[enemy_id]) {
          clearInterval(hospital_timers[enemy_id]);
          hospital_timers[enemy_id] = null;
        }
        hospital_timers[enemy_id] = setInterval(() => {
          const hosp_time_remaining = Math.round(
            enemy_status.until - new Date().getTime() / 1000,
          );
          if (hosp_time_remaining <= 0) {
            li.classList.remove("warstuff_highlight");
            return;
          }
          const s = Math.floor(hosp_time_remaining % 60);
          const m = Math.floor((hosp_time_remaining / 60) % 60);
          const h = Math.floor(hosp_time_remaining / 60 / 60);
          const time_string = `${pad_with_zeros(h)}:${pad_with_zeros(m)}:${pad_with_zeros(s)}`;
          status_DIV.innerText = time_string;

          if (hosp_time_remaining < 300) {
            li.classList.add("warstuff_highlight");
          } else {
            li.classList.remove("warstuff_highlight");
          }
        }, 250);
        break;
      default:
        li.setAttribute("data-sortA", "0");
        break;
    }
  });
  if (sort_enemies) {
    const enemy_UL = document
      .querySelector("LI.enemy")
      .closest("UL.members-list");
    Array.from(enemy_LIs)
      .sort((a, b) => {
        return (
          a.getAttribute("data-sortA") - b.getAttribute("data-sortA") ||
          a.getAttribute("data-until") - b.getAttribute("data-until")
        );
      })
      .forEach((li) => enemy_UL.appendChild(li));
  }
}