Auctionhouse Filter

Filter the auction house for only the weapons you desire

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Auctionhouse Filter
// @namespace    http://tampermonkey.net/
// @version      0.91
// @description  Filter the auction house for only the weapons you desire
// @author       olesien
// @match        https://www.torn.com/amarket*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=torn.com
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';
    //Styles
    GM_addStyle ( `
   #auction-filter {
      border-radius: 10px;
      margin-bottom: 10px;
   }

   #auction-filter .filter-button {
      background-color: #333333;
      display: block;
      color: white;
      padding: 10px;
      border-radius: 10px;
   }

   #auction-filter .filter-button:hover {
      cursor: pointer;
      background-color: #333434;
   }

   #auction-filter .filter-form {
      display: flex;
      flex-flow: row wrap;
      padding: 10px;
   }

   #auction-filter .filter-div {
       padding: 5px;
       display: inline-block;
       width: 100px;
   }

   #auction-filter .filter-text {
       padding: 10px;
   }

   #auction-filter .field-form {
       display: flex;
   }

   #auction-filter .field-form .field-container {
           display: flex;
           align-items: center;
           gap: 10px;
   }

   #auction-filter .field-form .field-container input {
        padding: 5px;
        margin-left: 10px;
        width: 50px;
   }

   #auction-filter .filter-flex {
        display: flex;
        justify-content: space-even;
        flex-flow: row wrap;
        padding: 0.5rem;
   }

  `);
    //https://stackoverflow.com/questions/3219758/detect-changes-in-the-dom
    const observeDOM = (function(){
        const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

        return function( obj, callback ){
            if( !obj || obj.nodeType !== 1 ) return;

            if( MutationObserver ){
                // define a new observer
                var mutationObserver = new MutationObserver(callback)

                // have the observer observe foo for changes in children
                mutationObserver.observe( obj, { childList:true, subtree:true })
                return mutationObserver
            }

            // browser support fallback
            else if( window.addEventListener ){
                obj.addEventListener('DOMNodeInserted', callback, false)
                obj.addEventListener('DOMNodeRemoved', callback, false)
            }
        }
    })();

    window.addEventListener(
        "load",
        function () {
            //DOM has loaded

            setTimeout(() => {
                const auctionHouseTabsEl = document.querySelector("#auction-house-tabs");

                //Create item box
                const divEl = document.createElement("div");
                divEl.id = "auction-filter";
                divEl.className = "cont-gray";
                //Append to box
                auctionHouseTabsEl.insertBefore(divEl, auctionHouseTabsEl.firstChild);

                doIt();
                renderSettings();

                const pagination = document.querySelector(".pagination-wrap");
                observeDOM( pagination, function(m){
                    doIt();
                });
            }, 200);
        }, false);

    const bonusString = ".bonus-attachment-";
    const normalBonuses = ["demoralized", "freeze", "blindfire", "poisoned", "burning", "laceration", "severeburning", "spray", "emasculate", "hazardous", "storage", "toxin"]
    const rwBonuses = ["achilles", "assassinate", "backstab", "berserk", "bleed", "blindside", "bloodlust", "comeback", "conserve",
                       "cripple", "crusher", "cupid", "deadeye", "deadly", "disarm", "doubletap", "doubleedged", "empower", "eviscerate","execute", "expose",
                       "finale", "focus", "frenzy", "fury", "grace", "homerun", "irradiate", "motivation", "paralyzed", "parry", "penetrate", "plunder", "powerful","proficience",
                       "puncture", "quicken", "rage", "revitalize", "roshambo", "slow", "smurf", "specialist", "stricken", "stun", "suppress", "sureshot",
                       "throttle", "warlord", "weaken", "windup", "wither"]

    function renderSettings() {
        const divEl = document.getElementById("auction-filter");
        divEl.innerHTML =""; //Clear
        const hiddenString = localStorage.getItem('auction-filter-hidden');
        let hidden = hiddenString ? JSON.parse(hiddenString) : hiddenString;
        const pEl = document.createElement("button");
        pEl.className = "filter-button";

        const clickEvent = pEl.addEventListener("click", async (e) => {
            await localStorage.setItem('auction-filter-hidden', JSON.stringify(!hidden));
            renderSettings();
            pEl.removeEventListener(clickEvent); //Prevent duplicate listeners
        });

        pEl.innerText = `Filters`;
        //Add text
        divEl.appendChild(pEl);

        if (!hidden) {
            const textEl = document.createElement("p");
            textEl.innerText = "Bonus type";
            textEl.className = "filter-text";
            divEl.appendChild(textEl);

            const formEl = document.createElement("div");
            formEl.className = "filter-form";
            const setCheckbox = (value, title, main) => {
                const divEl = document.createElement("div");
                divEl.className = "filter-div";

                const checked = localStorage.getItem('checked-rw-' + value);
                const inputEl = document.createElement("input");
                inputEl.type = "checkbox";
                inputEl.id = "rw-" + value;
                inputEl.name = "rw-" + value;
                //inputEl.value = bonus;
                inputEl.checked = checked;

                inputEl.addEventListener('change', async function() {
                    if (!this.checked) {
                        await localStorage.removeItem('checked-rw-' + value);
                    } else {
                        await localStorage.setItem('checked-rw-' + value, String(this.checked));
                    }

                    doIt();
                });

                const labelEl = document.createElement("label");
                labelEl.for = "rw-" + value;
                labelEl.innerText = title
                labelEl.style.paddingLeft = "5px";
                labelEl.className = "t-gray-6";

                divEl.appendChild(inputEl);
                divEl.appendChild(labelEl);

                main.appendChild(divEl);
            }
            rwBonuses.forEach(bonus => {
                setCheckbox(bonus, bonus, formEl);
            })

            //Append to div
            divEl.appendChild(formEl);

            //One of US
            const miscEl = document.createElement("div");
            miscEl.className = "filter-flex";

            //Min damage / acc
            const dmgaccEl = document.createElement("div");
            const textEl2 = document.createElement("p");
            textEl2.innerText = "Min damage / accuracy ";
            textEl2.className = "filter-text";
            dmgaccEl.appendChild(textEl2);

            const formEl2 = document.createElement("div");
            formEl2.className = "field-form";
            const createField = (name, initial) => {
                const fieldContainer = document.createElement("div");
                fieldContainer.className = "field-container";

                const label = document.createElement("label");
                label.innerText = name;
                label.className = "filter-text";

                const input = document.createElement("input");
                input.type = "number";
                input.value = initial ?? "";
                label.appendChild(input);
                fieldContainer.appendChild(label);
                return {fieldContainer, input};
            }
            //Damage
            const damage = localStorage.getItem('auction-filter-damage');
            const {fieldContainer, input: damageInput} = createField("Damage", damage);

            //Accuracy
            const accuracy = localStorage.getItem('auction-filter-accuracy');
            const {fieldContainer: fieldContainer2, input: accuracyInput} = createField("Accuracy", accuracy);

            damageInput.addEventListener('input', async (e) => {
                console.log(damageInput.value);
                const value = Number(damageInput.value)
                if (!value || value <= 0 || value > 9999) {
                    await localStorage.removeItem('auction-filter-damage');
                } else {
                    await localStorage.setItem('auction-filter-damage', String(value));
                }
                doIt();
            });

            accuracyInput.addEventListener('input', async (e) => {
                console.log(accuracyInput.value);
                const value = Number(accuracyInput.value)
                if (!value || value <= 0 || value > 9999) {
                    await localStorage.removeItem('auction-filter-accuracy');
                } else {
                    await localStorage.setItem('auction-filter-accuracy', String(value));
                }
                doIt();
            });

            //append
            formEl2.appendChild(fieldContainer);
            formEl2.appendChild(fieldContainer2);

            dmgaccEl.appendChild(formEl2);
            miscEl.appendChild(dmgaccEl);

            //Rarity
            const rarityEl = document.createElement("div");
            const textEl3 = document.createElement("p");
            textEl3.innerText = "Rarity types ";
            textEl3.className = "filter-text";


            const formEl3 = document.createElement("div");
            formEl3.className = "field-form";

            setCheckbox("normal", "normal", formEl3);
            setCheckbox("yellow", "yellow", formEl3);
            setCheckbox("orange", "orange", formEl3);
            setCheckbox("red", "red", formEl3);

            rarityEl.appendChild(textEl3);

            rarityEl.appendChild(formEl3);

            miscEl.appendChild(rarityEl);

            divEl.appendChild(miscEl);

        }
    }
    function doIt() {
        const minDamage = localStorage.getItem('auction-filter-damage');
        const minAccuracy = localStorage.getItem('auction-filter-accuracy');

        const normal = localStorage.getItem('checked-rw-normal');
        const yellow = localStorage.getItem('checked-rw-yellow');
        const orange = localStorage.getItem('checked-rw-orange');
        const red = localStorage.getItem('checked-rw-red');

        const weaponsTabEl = document.querySelector(".ui-corner-top");
        if (!weaponsTabEl.classList.contains("active")) return;
        const auctionHouseTabsEl = document.querySelector("#auction-house-tabs");

        //const chosenBonuses = ["warlord", "weaken"]
        let chosenBonuses = rwBonuses.reduce((chosenBonuses, bonus) => {
            const checked = localStorage.getItem('checked-rw-' + bonus);
            if (checked) return [...chosenBonuses, bonus];
            return chosenBonuses;
        }, []);

        if (chosenBonuses.length === 0) chosenBonuses = rwBonuses;
        //Grab items
        const items = Array.from(auctionHouseTabsEl.querySelector(".items-list").children);

        items.forEach((itemEl) => {
            //#FF0000 <- Red
            //#FF8000 <- Orange
            //#FFBF00 <- Yellow
            if (itemEl.classList.contains("clear")) return;
            const hasRightBonuses = chosenBonuses.reduce((hasBonus, bonus) => {
                if (hasBonus) return hasBonus;
                return !!itemEl.querySelector(bonusString + bonus); //!! = convert to boolean true/false
            }, false);
            console.log(itemEl);
            const [damage, accuracy] = Array.from(itemEl.querySelector(".infobonuses").querySelectorAll(".label-value"))
            console.log(damage, accuracy);
            const hasMinDamage = Number(damage.innerText) >= Number(minDamage ?? 0);
            const hasMinAccuracy = Number(accuracy.innerText) >= Number(minAccuracy ?? 0);
            let hasRightRarity = false;
            const imgEl = itemEl.querySelector(".item-plate");
            const color = imgEl?.dataset?.color;
            if (!imgEl || !color) {
                //Default
                console.log("BELOW IS UNKNOWN");
                console.log(imgEl);
                hasRightRarity = true;
            } else {
                if (color === "FF0000" && red) hasRightRarity = true;
                if (color === "FF8000" && orange) hasRightRarity = true;
                if (color === "FFBF00" && yellow) hasRightRarity = true;
                if (color !== "FF0000" && color !== "FF8000" && color !== "FFBF00" && normal) hasRightRarity = true;
                if (!normal && !yellow && !orange && !red) hasRightRarity = true; //Unset
            }
            if (!hasRightBonuses || !hasMinDamage || !hasMinAccuracy || !hasRightRarity) {
                itemEl.style.display = "none";
            } else {
                itemEl.style.display = "inherit";
            }
        });
    }
})();