Torn Attack Networth Display

Shows target's networth on the attack page before attacking

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         Torn Attack Networth Display
// @namespace    torn.networth.attack
// @version      1.3
// @description  Shows target's networth on the attack page before attacking
// @match        https://www.torn.com/loader.php?sid=attack*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        unsafeWindow
// ==/UserScript==

(function () {
  'use strict';

  function getApiKey() {
    var pdaKey = '###PDA-APIKEY###';

    // If PDA replaced the placeholder, use that
    if (pdaKey !== '###PDA-APIKEY###') {
      return pdaKey;
    }

    // Browser fallback: check stored key
    try {
      var stored = GM_getValue('torn_api_key', '');
      if (stored) return stored;
    } catch (e) {
      // GM functions not available
    }

    // Prompt user once
    var win = (typeof unsafeWindow !== 'undefined') ? unsafeWindow : window;
    var input = win.prompt('Enter your Torn API key (public access is fine):');
    if (input && input.trim().length === 16) {
      try {
        GM_setValue('torn_api_key', input.trim());
      } catch (e) {
        // Can't persist, will ask again next time
      }
      return input.trim();
    }

    return null;
  }

  var API_KEY = getApiKey();
  if (!API_KEY) return;

  function getUserID() {
    const params = new URLSearchParams(window.location.search);
    return params.get('user2ID');
  }

  function formatMoney(amount) {
    if (amount >= 1e12) return '$' + (amount / 1e12).toFixed(2) + 'T';
    if (amount >= 1e9) return '$' + (amount / 1e9).toFixed(2) + 'B';
    if (amount >= 1e6) return '$' + (amount / 1e6).toFixed(2) + 'M';
    if (amount >= 1e3) return '$' + (amount / 1e3).toFixed(2) + 'K';
    return '$' + amount.toLocaleString();
  }

  function createDisplay(networth, status) {
    var container = document.createElement('div');
    container.id = 'nw-display';
    container.style.cssText =
      'padding: 8px 12px; margin: 8px 0; border-radius: 5px; font-size: 13px; font-weight: bold; text-align: center;';

    if (status === 'ok') {
      container.style.background = '#1a1a2e';
      container.style.color = '#e0e0e0';
      container.style.border = '1px solid #333';
      container.textContent = 'Networth: ' + formatMoney(networth);
    } else {
      container.style.background = '#2e1a1a';
      container.style.color = '#cc8888';
      container.style.border = '1px solid #442222';
      container.textContent = 'Networth: ' + status;
    }

    return container;
  }

  function injectDisplay(element) {
    // Insert above the Start fight button inside the dialog
    var dialogButtons = document.querySelector('[class*="dialogButtons"]');
    if (dialogButtons) {
      dialogButtons.parentNode.insertBefore(element, dialogButtons);
      return true;
    }

    // Fallback: insert at the top of the dialog wrapper
    var dialogWrapper = document.querySelector('[class*="dialogWrapper"]');
    if (dialogWrapper) {
      dialogWrapper.insertBefore(element, dialogWrapper.firstChild);
      return true;
    }

    return false;
  }

  function tryInject(element, attempts) {
    if (attempts <= 0) return;

    if (!injectDisplay(element)) {
      setTimeout(function () {
        tryInject(element, attempts - 1);
      }, 500);
    }
  }

  function init() {
    var userID = getUserID();
    if (!userID) return;

    var url =
      'https://api.torn.com/user/' +
      userID +
      '?selections=personalstats&stat=networth&key=' +
      API_KEY;

    fetch(url)
      .then(function (res) {
        return res.json();
      })
      .then(function (data) {
        if (data.error) {
          var display = createDisplay(null, 'API error: ' + data.error.error);
          tryInject(display, 10);
          return;
        }

        var networth = null;

        // Handle different response structures
        if (data.personalstats && data.personalstats.networth) {
          networth = data.personalstats.networth;
        } else if (data.personalstats && typeof data.personalstats.networth === 'number') {
          networth = data.personalstats.networth;
        }

        var display;
        if (networth !== null) {
          display = createDisplay(networth, 'ok');
        } else {
          display = createDisplay(null, 'Unavailable');
        }

        tryInject(display, 10);
      })
      .catch(function (err) {
        var display = createDisplay(null, 'Fetch failed');
        tryInject(display, 10);
      });
  }

  init();
})();