Mug protection

Warns if you are actively selling items in Bazaar or Item Market.

当前为 2024-12-08 提交的版本,查看 最新版本

// ==UserScript==
// @name         Mug protection
// @namespace    Nurv.IronNerd.me
// @version      0.1
// @description  Warns if you are actively selling items in Bazaar or Item Market.
// @author       Nurv [669537]
// @match        https://www.torn.com/*
// @exclude      https://www.torn.com/loader.php?sid=attack*
// @exclude      https://www.torn.com/pc.php*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @license      Copyright IronNerd.me
// ==/UserScript==

(function () {
    'use strict';

    async function getApiKey() {
        return await GM_getValue('tornApiKey', null);
    }

    async function getGhostId() {
        return await GM_getValue('ghostId', null);
    }

    function setGhostId() {
        const ghostId = prompt("Enter Ghost Friend ID:");
        if (ghostId) {
            GM_setValue('ghostId', ghostId);
            alert(`Ghost Friend ID set to: ${ghostId}`);
        } else {
            alert("No Ghost Friend ID set.");
        }
    }

    function setApiKey() {
        const apiKey = prompt("Enter your Torn API key:");
        if (apiKey) {
            GM_setValue('tornApiKey', apiKey);
            alert("API key saved successfully.");
        } else {
            alert("No API key entered.");
        }
    }

    GM_registerMenuCommand('Set API Key', setApiKey);
    GM_registerMenuCommand('Set Ghost Friend ID', setGhostId);

    async function addGhostIcon() {
        const ghostId = await getGhostId();
        const tradeUrl = ghostId
            ? `https://www.torn.com/trade.php#step=start&userID=${ghostId}`
            : "https://www.torn.com/trade.php";

        const ghostIconHtml = `
            <li class="icon-ghost">
                <a href="${tradeUrl}" aria-label="Ghost Friend" tabindex="0" style="color: white;" data-is-tooltip-opened="false">
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="24px" height="24px">
                        <path d="M12 2C7.59 2 4 5.59 4 10c0 3.91 2.82 7.19 6.68 7.89l.32.06v3.15l-1.32-1.32-.71-.71-.71.71-1.82 1.83v-5.35c.58.25 1.19.4 1.82.49v4.55l2.53-2.53c.22-.22.51-.34.82-.34h1.03c.31 0 .6.12.82.34l2.53 2.53v-4.55c.63-.09 1.24-.24 1.82-.49v5.35l-1.82-1.83-.71-.71-.71.71-1.32 1.32V18l.32-.06C17.18 17.19 20 13.91 20 10c0-4.41-3.59-8-8-8zm-3 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm6 0c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/>
                    </svg>
                </a>
            </li>
        `;

        const statusIcons = document.querySelector(".status-icons___gPkXF");
        if (statusIcons) {
            statusIcons.insertAdjacentHTML("beforeend", ghostIconHtml);
            console.log("Ghost Friend icon added.");
        }
    }

    function isInHospital() {
        const hospitalIcon = document.querySelector("li[class*='icon15'] a[aria-label*='Hospital']");
        return hospitalIcon !== null;
    }

    async function displayBanner(message, isApiMessage = false) {
        console.log("Displaying Banner:", message);

        removeBanner();

        $("body").append(`
            <div id="selling-warning-banner" style="background-color: red; position: fixed; top: 0; width: 100%; z-index: 99999; padding: 12px; text-align: center; color: white; font-weight: bold; cursor: pointer;">
                <a href="https://www.torn.com/item.php#medical-items" target="_blank" style="color: white; text-decoration: none;">
                    ${message}
                </a>
            </div>
        `);

        setTimeout(() => {
            removeBanner();
        }, 7000);
    }

    function removeBanner() {
        const banner = $("#selling-warning-banner");
        if (banner.length) {
            banner.remove();
            console.log("Banner removed.");
        }
    }

    function calculateTotal(items, key = "amount") {
        return items.reduce((sum, item) => sum + (item.price * (item[key] || 1)), 0);
    }

    function fetchApiData(url) {
        console.log("Fetching API Data:", url);
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: "GET",
                url: url,
                onload: function (response) {
                    if (response.status === 200) {
                        try {
                            const data = JSON.parse(response.responseText);
                            console.log("API Data Received:", data);
                            resolve(data);
                        } catch (error) {
                            console.error("Failed to parse API response:", error);
                            reject(error);
                        }
                    } else {
                        console.error(`API call failed: ${response.status} - ${response.statusText}`);
                        reject(new Error(`API call failed: ${response.status}`));
                    }
                },
                onerror: function () {
                    console.error("API request error");
                    reject(new Error("Error in API request"));
                },
            });
        });
    }

    async function checkSellingStatus() {
        console.log("Executing checkSellingStatus...");

        if (isInHospital()) {
            console.log("User is in the hospital. Adding Ghost Friend icon.");
            await addGhostIcon();
            return;
        }

        const apiKey = await getApiKey();
        console.log("API Key:", apiKey || "Not Set");

        const bazaarSelector = "li[class*='icon35'] a[aria-label*='Bazaar: You have items in your bazaar']";
        const itemMarketSelector = "li[class*='icon36'] a[aria-label*='Item Market: You have items up for sale']";

        const isBazaarActive = document.querySelector(bazaarSelector) !== null;
        const isItemMarketActive = document.querySelector(itemMarketSelector) !== null;

        console.log("Bazaar Active:", isBazaarActive, "Item Market Active:", isItemMarketActive);

        if (!isBazaarActive && !isItemMarketActive) {
            console.log("No active selling detected.");
            return;
        }

        if (apiKey) {
            try {
                const bazaarValue = isBazaarActive
                    ? await fetchApiData(`https://api.torn.com/user/?selections=bazaar&key=${apiKey}`)
                          .then(data => calculateTotal(data.bazaar || [], "quantity"))
                          .catch(err => 0)
                    : 0;

                const itemMarketValue = isItemMarketActive
                    ? await fetchApiData(`https://api.torn.com/v2/user/itemmarket?key=${apiKey}&offset=0`)
                          .then(data => calculateTotal(data.itemmarket || [], "amount"))
                          .catch(err => 0)
                    : 0;

                const totalValue = bazaarValue + itemMarketValue;

                if (totalValue > 0) {
                    await displayBanner(`You have items worth $${totalValue.toLocaleString()} actively listed. Consider Self-Hosping to avoid being mugged!`);
                }
            } catch (error) {
                console.error("Error fetching or processing API data:", error);
            }
        } else {
            // Fallback message
            if (isBazaarActive) {
                await displayBanner("You are actively selling items in the Bazaar. <a href='https://www.torn.com/item.php#medical-items' style='color: white;'>Consider Self-Hosping to avoid being mugged!</a>");
            }
            if (isItemMarketActive) {
                await displayBanner("You are actively selling items in the Item Market. <a href='https://www.torn.com/item.php#medical-items' style='color: white;'>Consider Self-Hosping to avoid being mugged!</a>");
            }
        }
    }

    $(document).ready(() => {
        checkSellingStatus();
    });
})();