Torn Chat Banking Helper

Makes faction chat messages relating to banking withdrawals into clickable links that direct you to the give-to-user page with the requesters ID and Money ammount prefilled to help make banking requests a bit smoother.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name        Torn Chat Banking Helper
// @namespace   Violentmonkey Scripts
// @match       https://www.torn.com/*
// @grant       none
// @version     1.02
// @author      Bilbosaggings[2323763]
// @description Makes faction chat messages relating to banking withdrawals into clickable links that direct you to the give-to-user page with the requesters ID and Money ammount prefilled to help make banking requests a bit smoother.
// @license     MIT
// ==/UserScript==

const scriptKey = 'TornChatBankingHelper';

function waitForElement(selector, target = document.body) {
  return new Promise((resolve) => {
    if (target.querySelector(selector)) {
      resolve(target.querySelector(selector));
    }

    const observer = new MutationObserver(() => {
      if (target.querySelector(selector)) {
        resolve(target.querySelector(selector));
        observer.disconnect();
      }
    });

    observer.observe(target, {
      subtree: true,
      childList: true,
    });
  });
}

const log = (...args) => console.log(`[${scriptKey}]: `, ...args);

const err = (...args) => console.error(`[${scriptKey}]: `, ...args);

const processCurrentMessages = async (chatElement) => {
  const messages = await waitForElement('[class^="list"]', chatElement);

  if (!messages) return;

  const children = messages.children;

  if (!children) return;

  for (let i = 0; i < children.length; i++) handleMessage(children[i]);
};

const watchForNewMessages = async (chatElement) => {
  // const messages = chatElement.querySelector('[class^="list"]');
  const messages = await waitForElement('[class^="list"]', chatElement);

  const observer = new MutationObserver(() => {
    processCurrentMessages(chatElement);
  });

  observer.observe(messages, {
    childList: true,
    subtree: true,
  });

  return observer;
};

const handleMessage = async (messageElement) => {
  const getValueFromBankString = (message) => {
    if (!message) return null;

    const regex = /\b(\d{1,3}(?:,\d{3})+|\d+(?:\.\d+)?)([kmb]?)\b/gi;

    const matches = [...message.matchAll(regex)];

    if (!matches.length) return null;

    const targetMatch =
      matches.find((m) => ['k', 'm', 'b'].includes(m[2])) ??
      matches[matches.length - 1];

    const [, value, sign] = targetMatch;

    let numericValue = parseFloat(value.replace(/,/g, ''));

    switch (sign) {
      case 'k':
        numericValue *= 1000;
        break;
      case 'm':
        numericValue *= 1000000;
        break;
      case 'b':
        numericValue *= 1000000000;
        break;
    }

    return numericValue;
  };

  if (!messageElement) return;

  const message = await waitForElement('[class*="message"]', messageElement);

  if (!message) return;

  if (message.getAttribute(scriptKey) === 'true') return;

  message.setAttribute(scriptKey, 'true');

  const messageText = message.innerText;
  const normalised = messageText.trim().toLowerCase();

  const searchStrings = ['bank', 'banke', 'banker', 'bankers'];
  const isMessageForBanker = searchStrings.some((string) =>
    normalised.includes(string),
  );

  if (!isMessageForBanker) return;

  const moneyValue = getValueFromBankString(normalised);

  if (!moneyValue) return;

  const sender = messageElement.querySelector('[class*="sender_"]');

  const senderId = sender.href ? sender.href.split('XID=')[1] : 0;

  if (senderId === 0) return;

  // const paymentLink = `https://www.torn.com/factions.php?step=your#/tab=controls&addMoneyTo=${senderId}&money=${moneyValue}`;
  const paymentLink = `https://www.torn.com/factions.php?step=your#/tab=controls&giveMoneyTo=${senderId}&money=${moneyValue}`;

  // log("New Message: ", { message: messageText, link: paymentLink })

  setTimeout(() => {
    message.innerHTML = `<a href="${paymentLink}" style="color:inherit">${message.innerText}</a>`;
    messageElement.style.border = '1.5px solid green';
  }, 0);
};

(() => {
  let factionChat = null;
  let factionChatObserver = null;

  const detach = () => {
    if (
      !factionChatObserver ||
      typeof factionChatObserver.disconnect !== 'function'
    )
      return; //Pda fix

    factionChatObserver.disconnect();
    factionChatObserver = null;
    log('Disconnected Message Observer');
  };

  const chatObserver = new MutationObserver(() => {
    const chat = document.querySelector('[id^="faction-"]');

    if (chat && !factionChat) {
      log('Chat is now visible');
      factionChat = chat;

      try {
        log('Processing Current Messages');
        processCurrentMessages(factionChat);
      } catch (error) {
        err('Error Processing Current Messages: ', error);
      } finally {
        log('Finished Processing Current Messages');
      }

      if (factionChatObserver) detach();

      try {
        log('Watching For New Messages In Faction Chat');
        factionChatObserver = watchForNewMessages(factionChat);
      } catch (error) {
        err('Error Watching For New Messages: ', error);
      }
    }
    if (!chat && factionChat) {
      log('Chat is not visible');
      factionChat = null;
      detach();
    }
  });

  chatObserver.observe(document.body, {
    subtree: true,
    childList: true,
  });
})();