Steam, Card sets viewer

Happy trading 1:1 card sets

目前为 2018-11-30 提交的版本。查看 最新版本

// ==UserScript==
// @name         Steam, Card sets viewer
// @name:ja      Steam, Card sets viewer
// @namespace    http://tampermonkey.net/
// @version      1.0.2
// @description  Happy trading 1:1 card sets
// @description:ja  Happy trading 1:1 card sets
// @author       You
// @require      http://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js
// @match        https://steamcommunity.com/tradeoffer/*
// @grant        GM.xmlHttpRequest
// @runat        document-end
// @nowrap
// ==/UserScript==

(function() {
    'use strict';

    var $ = jQuery.noConflict();
    var getBadgeInfoUrl = "https://www.steamcardexchange.net/api/request.php?GetBadgePrices_Member";
    var CacheKey = "BadgeInformatinCache";
    var MaxBadgeLevel = 5;

    function escapeHtml (string) {
        if(typeof string !== 'string') {
            return string;
        }
        return string.replace(/[&'`"<>]/g, function(match) {
            return {
                '&': '&amp;',
                "'": '&#x27;',
                '`': '&#x60;',
                '"': '&quot;',
                '<': '&lt;',
                '>': '&gt;',
            }[match]
        });
    }

    function getSteamInventory () {
        var inv = g_ActiveInventory;
        if (!inv) throw "Error: Not found inventory";
        if (!inv.initialized) throw "Error: Inventory is unloaded";
        if (inv.appid != "753") throw "Error: Inventory isn't Steam Inventory";
        if (!inv.rgInventory) throw "Error: Inventory is unloaded";

        console.log("Inventory loaded");
        return inv;
    }

    function main(inventory) {
        var sets = {};
        var isSelfInventory = $("#inventory_select_your_inventory").hasClass("active");
        var isExtraOnly = $("#DisplayExtraOnlyCheckbox")[0].checked;
        var rgInventory = inventory.rgInventory;

        function onLoadBadgeInformation(xhr, cache) {
            var badges = cache || JSON.parse(xhr.responseText);
            if (!cache) {
                localStorage[CacheKey] = xhr.responseText;
            }
            console.log(badges);

            var fee, set;
            var data = badges.data;

            // Add badge information to sets variable
            for (var i = 0; i < data.length; i++) {
                set = sets[data[i][0][0]];
                if (!set) continue;

                // Appid (market_fee_app) have been already added
                // data[i][0][0]
                set.title = data[i][0][1];
                set.cardsInSet = data[i][1];
                set.badgeValue = data[i][2];
                set.yourLevel = parseInt(data[i][3]);
                // Updated timestamp isn't necessary
                // data[i][4]
                set.fullSetQuantity = 0;
                set.hasFullSet = false;
            }

            // Count complete card sets
            for (fee in sets) {
                set = sets[fee];

                var totalCards = 0;
                var cardsCount = 0;
                var minQty = Number.MAX_VALUE;

                for (var hash in set.items) {
                    var item = set.items[hash];
                    minQty = Math.min(minQty, item.quantity);
                    cardsCount++;
                    totalCards += item.quantity;
                }
                set.totalCards = totalCards;
                if (set.cardsInSet > 0 && set.cardsInSet == cardsCount) {
                    set.hasFullSet = true;
                    set.fullSetQuantity = minQty;
                    if (isSelfInventory) {
                        var extraQuantity = set.fullSetQuantity - (MaxBadgeLevel - set.yourLevel);
                        set.extraQuantity = extraQuantity > 0 ? extraQuantity : 0;
                        set.necessaryQuantity = 0;
                    } else {
                        set.extraQuantity = 0;
                        set.necessaryQuantity = Math.min(MaxBadgeLevel - set.yourLevel, set.fullSetQuantity);
                    }
                } else {
                    set.hasFullSet = false;
                    set.fullSetQuantity = 0;
                    set.extraQuantity = 0;
                    set.necessaryQuantity = 0;
                }
            }

            var displayList = [];
            for (fee in sets) {
                set = sets[fee];
                if (!set.hasFullSet) continue;
                if (isSelfInventory && isExtraOnly && set.extraQuantity <= 0) continue;
                if (!isSelfInventory && isExtraOnly && set.necessaryQuantity <= 0) continue;

                displayList.push(set);
            }

            // sort by title
            displayList.sort(function (a, b) {
                return a.title > b.title ? 1 : -1;
            });

            var textBuilder = "";
            var markdownBuilder = "";
            var htmlBuilder = "";

            for (var k = 0; k < displayList.length; k++) {
                set = displayList[k];
                var qty = set.fullSetQuantity;
                if (isExtraOnly) {
                    qty = isSelfInventory ? set.extraQuantity : set.necessaryQuantity;
                }
                var setUrl = inventory.owner.strProfileURL + "/gamecards/" + set.appId + "/";
                var perValue = Math.round(parseFloat(set.badgeValue.replace("$", "")) / set.cardsInSet * 1000) / 1000;

                // Add content as text to pre tag so don't need to html-escape
                textBuilder += "{qty}x {title}\n"
                    .replace("{qty}", qty)
                    .replace("{title}", set.title);
                // Add content as text to pre tag so don't need to html-escape
                markdownBuilder += "{qty}x [{title}]({url}) ({cards})\n"
                    .replace("{qty}", qty)
                    .replace("{title}", set.title)
                    .replace("{url}", setUrl)
                    .replace("{cards}", set.cardsInSet);
                // Append content as html to body so need to html-escape variables
                htmlBuilder += "<div>{qty}x <a href='{url}' target='_blank'>{title}</a> ({cards} as {value} / ${pervalue} each) <button data-fee='{fee}' class='AddSetToTradeButton'>Add to trade</button></div>"
                    .replace("{qty}", qty)
                    .replace("{title}", escapeHtml(set.title))
                    .replace("{url}", setUrl)
                    .replace("{fee}", set.appId)
                    .replace("{cards}", set.cardsInSet)
                    .replace("{value}", set.badgeValue)
                    .replace("{pervalue}", perValue);
            }

            $("<div />")
                .append("<div><a class='SwitchSetList'>Text</a><a class='SwitchSetList'>Markdown</a><a class='SwitchSetList'>Html</a><a class='CloseSetList'>Close</a></div>")
                .append($("<pre />").addClass("SetListText").text(textBuilder))
                .append($("<pre />").addClass("SetListMarkdown").text(markdownBuilder))
                .append($("<div />").addClass("SetListHtml").append(htmlBuilder))
                .attr("id", "SetListContainer")
                .addClass("VisibleText")
                .appendTo("body");

            $(".SwitchSetList").click(function (ev) {
                ev.preventDefault();
                ev.stopPropagation();

                $("#SetListContainer")
                    .removeClass("VisibleText")
                    .removeClass("VisibleMarkdown")
                    .removeClass("VisibleHtml")
                    .addClass("Visible" + $(this).text());
            });

            $(".CloseSetList").click(function (ev){
                ev.preventDefault();
                ev.stopPropagation();

                $("#SetListContainer").remove();
            });

            $(".AddSetToTradeButton").click(function (ev) {
                ev.preventDefault();
                ev.stopPropagation();

                var fee = $(this).attr("data-fee");
                var targetSet = sets[fee];
                var targets = [];
                for (var hash in targetSet.items) {
                    var instances = targetSet.items[hash].instances;
                    for (var i = 0; i < instances.length; i++) {
                        var $c = $((isSelfInventory ? "#your_slots" : "#their_slots") + " #item753_6_" + instances[i]);
                        if ($c.length == 0) {
                            targets.push(instances[i]);
                            break;
                        }
                        if (i == instances.length - 1) {
                            alert("Cards aren't enough to add complete set");
                            return;
                        }
                    }
                }
                for (var n = 0; n < targets.length; n++) {
                    MoveItemToTrade($("#item753_6_" + targets[n])[0]);
                }
            });
        }

        function onErrorBadgeInformation(xhr) {
            console.log("Couldn't get badge information. You need to log in to steamcardexchange.net.");
        }

        for (var instanceid in rgInventory) {
            var item = rgInventory[instanceid];

            // Check whether item type is card
            var isCard = false;
            for (var i = 0; i < item.tags.length; i++) {
                if (item.tags[i].category == "item_class") {
                    // item_class_2 is type of trading card
                    if (item.tags[i].internal_name == "item_class_2") {
                        isCard = true;
                    }
                    break;
                }
            }
            if (!isCard) continue;

            if (!sets[item.market_fee_app]) {
                sets[item.market_fee_app] = {
                    appId: item.market_fee_app,
                    cardsInSet: -1,
                    items: {}
                };
            }
            if (!sets[item.market_fee_app].items[item.market_hash_name]) {
                sets[item.market_fee_app].items[item.market_hash_name] = {
                    hash: item.market_hash_name,
                    quantity: 1,
                    instances: [instanceid],
                };
            } else {
                sets[item.market_fee_app].items[item.market_hash_name].quantity++;
                sets[item.market_fee_app].items[item.market_hash_name].instances.push(instanceid);
            }
        }
        console.log(sets);

        try {
            var cache = JSON.parse(localStorage[CacheKey]);
        } catch (error) {
            cache = null;
        }

        if (cache) {
            onLoadBadgeInformation(null, cache);
        } else {
            GM.xmlHttpRequest({
                url: getBadgeInfoUrl,
                method: "GET",
                onerror: onErrorBadgeInformation,
                onload: onLoadBadgeInformation
            });
        }
    }

    var $controllerContainer = $("<div />").appendTo("#inventory_box");;

    $("<button />")
        .append("<span>List card sets</span>")
        .addClass("btn_darkblue_white_innerfade btn_small new_trade_offer_btn")
        .css({ margin: "10px 12px" })
        .click(function () {
        try {
            var inv = getSteamInventory();
            main(inv);
        } catch (error) {
            alert(error);
        }
    })
        .appendTo($controllerContainer);

    $("<button />")
        .append("<span>Clear badge cache</span>")
        .addClass("btn_darkblue_white_innerfade btn_small new_trade_offer_btn")
        .css({ margin: "10px 12px" })
        .click(function () {
        delete localStorage[CacheKey];
    })
        .appendTo($controllerContainer);

    $("<input />").attr({ type: "checkbox", id: "DisplayExtraOnlyCheckbox" }).appendTo($controllerContainer);
    $("<label />").attr({ for: "DisplayExtraOnlyCheckbox" }).text("Extra/Necessary only").appendTo($controllerContainer);

    $("<style />").text(function () {/*
    #SetListContainer .SetListText,
    #SetListContainer .SetListMarkdown,
    #SetListContainer .SetListHtml {
        display: none;
    }

    #SetListContainer.VisibleText .SetListText,
    #SetListContainer.VisibleMarkdown .SetListMarkdown,
    #SetListContainer.VisibleHtml .SetListHtml {
        display: block;
    }
    #SetListContainer {
        position: fixed;
        z-index: 10000;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        background: #000000dd;
        overflow-y: scroll;
        padding: 24px 40px;
    }
    #SetListContainer > div {
        margin-bottom: 24px;
    }
    .SwitchSetList {
        margin-right: 8px;
    }
    */}.toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1]).appendTo("head");

    // Your code here...
    // .toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1];
})();

QingJ © 2025

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