Trade Chat Timer on Button

Show a timer that shows the time left to post next message.

目前为 2024-05-28 提交的版本。查看 最新版本

// ==UserScript==
// @name         Trade Chat Timer on Button
// @namespace    http://tampermonkey.net/
// @version      1.0
// @author       Weav3r
// @description  Show a timer that shows the time left to post next message.
// @match        https://www.torn.com/*
// ==/UserScript==

const STORAGE_KEY = "localStorage__Trade_Chat_Timer__Do_Not_Edit";

if (!Document.prototype.find)
    Object.defineProperties(Document.prototype, {
        find: {
            value(selector) {
                return document.querySelector(selector);
            },
            enumerable: false
        },
        findAll: {
            value(selector) {
                return document.querySelectorAll(selector);
            },
            enumerable: false
        }
    });

if (!Element.prototype.find)
    Object.defineProperties(Element.prototype, {
        find: {
            value(selector) {
                return this.querySelector(selector);
            },
            enumerable: false
        },
        findAll: {
            value(selector) {
                return this.querySelectorAll(selector);
            },
            enumerable: false
        }
    });

async function waitFor(sel, parent = document) {
    return new Promise((resolve) => {
        const intervalID = setInterval(() => {
            const el = parent.find(sel);
            if (el) {
                resolve(el);
                clearInterval(intervalID);
            }
        }, 500);
    });
}

(async () => {
    await waitFor("head style");

    document.head.insertAdjacentHTML("beforeend", `<style>
    #chatRoot [class*="minimized-menu-item__"][title="Trade"].time-left {
        position: relative;
        background-size: cover;
        background-position: center;
    }
    #chatRoot [class*="minimized-menu-item__"][title="Trade"].time-complete {
        position: relative;
        background-size: cover;
        background-position: center;
        background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect x="5" y="5" width="90" height="90" stroke="green" stroke-width="10" fill="none"/></svg>');
    }
    </style>`);

    let tradeChatButton = await waitFor("#chatRoot [class*='minimized-menu-item__'][title='Trade']");

    let tradeChat;

    if (tradeChatButton.className.includes("minimized-menu-item--open__")) {
        tradeChat = await getTradeChat();
        tradeChat.find("textarea").addEventListener("keydown", (e) => {
            if (e.key === "Enter" && !isTimerActive()) {
                window.localStorage.setItem(STORAGE_KEY, Date.now());
            }
        });
    }

    tradeChatButton.addEventListener("click", async () => {
        if (!tradeChatButton.className.includes("minimized-menu-item--open__"))
            tradeChat = await getTradeChat();
        if (!tradeChat) return;

        tradeChat.find("textarea").addEventListener("keydown", (e) => {
            if (e.key === "Enter" && !isTimerActive()) {
                window.localStorage.setItem(STORAGE_KEY, Date.now());
            }
        });
    });

    func();
    setInterval(func, 1000);

    function func() {
        if (!window.localStorage.getItem(STORAGE_KEY))
            window.localStorage.setItem(STORAGE_KEY, Date.now());

        const timestamp = parseInt(window.localStorage.getItem(STORAGE_KEY));
        if (timestamp > 0) {
            const timeLeft = Math.floor(60 - ((Date.now() - timestamp) / 1000));
            const button = tradeChatButton;
            if (timeLeft > 0) {
                button.classList.remove("time-complete");
                button.classList.add("time-left");
                const percentage = timeLeft / 60;
                button.style.backgroundImage = `url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect x="5" y="5" width="90" height="90" stroke="red" stroke-width="10" fill="none" stroke-dasharray="360" stroke-dashoffset="${360 * (1 - percentage)}"/></svg>')`;
            } else {
                button.classList.add("time-complete");
                button.classList.remove("time-left");
                button.style.backgroundImage = `url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect x="5" y="5" width="90" height="90" stroke="green" stroke-width="10" fill="none"/></svg>')`;
            }
        }
    }

    function isTimerActive() {
        const timestamp = parseInt(window.localStorage.getItem(STORAGE_KEY));
        const timeLeft = Math.floor(60 - ((Date.now() - timestamp) / 1000));
        return timeLeft > 0;
    }
})();

async function getTradeChat() {
    await waitFor("#chatRoot [class*='chat-box-header__']");

    return [...document.findAll("#chatRoot [class*='chat-box-header__']")]
            .filter(x => x.textContent === "Trade")
            .map(x => x.closest("[class*='chat-box__']"))?.[0];
}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址