Torn Bazaar Filler

On "Fill" click autofills bazaar item price with lowest bazaar price currently minus $1, fills max items, checks item checkboxes.

目前为 2023-08-19 提交的版本。查看 最新版本

// ==UserScript==
// @name         Torn Bazaar Filler
// @namespace    https://github.com/SOLiNARY
// @version      0.1
// @description  On "Fill" click autofills bazaar item price with lowest bazaar price currently minus $1, fills max items, checks item checkboxes.
// @author       Ramin Quluzade, Silmaril [2665762]
// @license      MIT License
// @match        https://www.torn.com/bazaar.php
// @require      https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js
// @run-at       document-idle
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    const bazaarUrl = "https://api.torn.com/market/{itemId}?selections=bazaar&key={apiKey}";
    let apiKey = localStorage.getItem("silmaril-torn-bazaar-filler-apikey");

    // TornPDA support for GM_addStyle
    let GM_addStyle = function (s) {
        let style = document.createElement("style");
        style.type = "text/css";
        style.innerHTML = s;
        document.head.appendChild(style);
    };

    GM_addStyle(`
.btn-wrap.torn-bazaar-fill-qty-price {
	float: right;
    margin-left: auto;
}

div.title-wrap div.name-wrap {
	display: flex;
    justify-content: flex-end;
}
`);


    var observerTarget = $(".content-wrapper")[0];
    var observerConfig = { attributes: false, childList: true, characterData: false, subtree: true };

    var observer = new MutationObserver(function(mutations) {
        $("ul.ui-tabs-nav").on("click", "li:not(.ui-state-active):not(.ui-state-disabled):not(.m-show)", function() {
            observer.observe(observerTarget, observerConfig);
        });

        let containerItems = $("ul.items-cont li.clearfix");
        containerItems.find("div.title-wrap div.name-wrap").each(function(){
            let isParentRowDisabled = this.parentElement.parentElement.classList.contains("disabled");
            let alreadyHasFillBtn = this.querySelector(".btn-wrap.torn-bazaar-fill-qty-price") != null;
            if (!alreadyHasFillBtn && !isParentRowDisabled){
                insertFillBtn(this);
            }
        });

        if($("div.amount").length) {
            observer.disconnect();
        }
    });
    observer.observe(observerTarget, observerConfig);

    function insertFillBtn(element){
        const outerSpan = document.createElement('span');
        outerSpan.className = 'btn-wrap torn-bazaar-fill-qty-price';

        const innerSpan = document.createElement('span');
        innerSpan.className = 'btn';

        const inputElement = document.createElement('input');
        inputElement.type = 'submit';
        inputElement.value = 'Fill';
        inputElement.className = 'torn-btn';

        innerSpan.appendChild(inputElement);
        outerSpan.appendChild(innerSpan);

        element.appendChild(outerSpan);
        $(outerSpan).on("click", "input", function() {
            checkApiKey();
            fillQuantityAndPrice(this);
            event.stopPropagation();
        });
    }

    function getQuantity(element){
        let rgx = /x(\d+)$/;
        let quantityText = $(element).parent().parent().prev().text();
        let match = rgx.exec(quantityText);
        let quantity = match === null ? 1 : match[1];
        return quantity;
    }

    function fillQuantityAndPrice(element){

        let amountDiv = element.parentElement.parentElement.parentElement.parentElement.parentElement.querySelector("div.amount-main-wrap");
        let priceInputs = amountDiv.querySelectorAll("div.price div input");
        let keyupEvent = new Event("keyup", {bubbles: true});
        let inputEvent = new Event("input", {bubbles: true});

        let image = element.parentElement.parentElement.parentElement.parentElement.querySelector("div.image-wrap img");
        let numberPattern = /\/(\d+)\//;
        let match = image.src.match(numberPattern);
        let extractedItemId = 0;
        if (match) {
            extractedItemId = parseInt(match[1], 10);
        } else {
            console.error("[TornBazaarFiller] ItemId not found!");
        }

        let requestUrl = bazaarUrl
        .replace("{itemId}", extractedItemId)
        .replace("{apiKey}", apiKey);

        fetch(requestUrl)
            .then(response => response.json())
            .then(data => {
            let lowBallPrice = data.bazaar[0].cost - 1;
            priceInputs[0].value = lowBallPrice;
            priceInputs[1].value = lowBallPrice;
            priceInputs[0].dispatchEvent(inputEvent);
        })
            .catch(error => {
            console.error("[TornBazaarFiller] Error fetching data:", error);
        });

        let isQuantityCheckbox = amountDiv.querySelector("div.amount.choice-container") !== null;
        if (isQuantityCheckbox){
            amountDiv.querySelector("div.amount.choice-container input").click();
        } else {
            let quantityInput = amountDiv.querySelector("div.amount input");
            quantityInput.value = quantity;
            quantityInput.dispatchEvent(keyupEvent);
        }
    }

    function checkApiKey(){
        if (apiKey == null){
            let userInput = prompt("Please enter a PUBLIC Api Key, it will be used to get current bazaar prices:");
            if (userInput !== null) {
                apiKey = userInput;
                localStorage.setItem("silmaril-torn-bazaar-filler-apikey", userInput);
            } else {
                console.error("[TornBazaarFiller] User cancelled the Api Key input.");
            }
        }
    }
})();

QingJ © 2025

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