Greasy Fork is available in English.

C5GAME挂饰品脚本

C5GAME新版页面挂饰品脚本

// ==UserScript==
// @name         C5GAME挂饰品脚本
// @namespace    http://tampermonkey.net/
// @version      1.0.5
// @description  C5GAME新版页面挂饰品脚本
// @author       lyzlyslyc
// @license      AGPL-3.0
// @match        http*://www.c5game.com/*
// @icon         https://www.c5game.com/favicon.ico
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @connect      www.c5game.com
// @connect      steamcommunity.com
// @connect      steamcommunity-a.akamaihd.net
// ==/UserScript==

(function() {
    'use strict';

    // 可更改参数
    let min_sell_num = 5;              //最小在售数量,在售大于等于该数量才会查询
    let high_sell_rate = 0.7;          //高出售比例阈值,大于该阈值的比例会显示为红色,小于阈值显示为绿色
    let high_buy_rate = 0.85;          //高求购比例阈值,大于该阈值的比例会显示为红色,小于阈值显示为绿色
    let auto_sort = 1;                 //查询完后自动排序,1出售比例升序,-1降序,2求购比例升序,-2降序,其他值不排序
    let rate_precision = 4;            //饰品详细页面的比例精度,精确到小数点后n位
    let max_request_num = 10;          //最大同时进行的请求数
    let request_interval_ms = 100;     //查询请求的发送间隔,单位毫秒
    let timeout_ms = 5000;             //查询超时的时长,单位毫秒,当超过这个时长会被认为请求超时


    //以下为代码实现,请勿轻易更改
    let list_div = null;
    let nextBtn = document.querySelector(".btn-next");
    let prevBtn = document.querySelector(".btn-prev");
    let cardListSelector = ".list .el-row";
    let appId;
    let priceCSSEle=document.createElement("style");
    let requests=[];
    let current_request_num = 0;
    let rateInfo = GM_getValue("exchangeRate");
    let communityInfo = GM_getValue("communityInfo");
    let currentPage = 1;
    let sortAsc = true;
    let sortKey = "sellsort";
    if(!communityInfo)communityInfo={};


    //商品详情页
    if(location.href.match(/c5game.com\/[^/]+\/(\d+)\/.*/)){
        console.log("c5挂刀脚本运行中:饰品详情页面");
        let c5ItemId = location.href.match(/c5game.com\/[^/]+\/(\d+)\/.*/)[1];
        if(!rateInfo){
            fetchCommunityInfo().then(checkAndUpdateRate).then(()=>{
                queryItemPage(document.querySelector(".check-market a").href);
            });
        }
        else checkAndUpdateRate().then(()=>{queryItemPage(document.querySelector(".check-market a").href)});
        let infoDiv = document.querySelector("main .bottom-info");
        infoDiv.style.marginTop = "";
        return;
    }
    else if(document.getElementById("market_index")!=null){
        console.log("c5挂刀脚本运行中:饰品搜索页面");

        //快速跳转插件
        let quickJumpInput = document.createElement("span");
        quickJumpInput.innerHTML = '第<input id="quickjump" style="width: 30px;margin: 4px;text-align:center;">页';
        quickJumpInput.style = `line-height: 36px;padding: 0 8px 0 8px;height: 36px;background: white;margin-left: 10px;font-weight: normal;font-size: medium;border-top-left-radius: 4px;border-bottom-left-radius: 4px;`;
        let quickJumpButton = document.createElement("button");
        quickJumpButton.type="button";
        quickJumpButton.className = "btn-next";
        quickJumpButton.style = "margin-left: 1px;";
        quickJumpButton.innerHTML = '<i class="el-icon el-icon-search"></i>';
        quickJumpButton.addEventListener("click",()=>{
            let page = document.getElementById("quickjump").value.replace(/[^\d]/g,"");
            document.getElementById("quickjump").value = page;
            if(page==="")return;
            else jumpToPage(page);
        });
        let pagination = document.querySelector("div.el-pagination");
        pagination.append(quickJumpInput);
        pagination.append(quickJumpButton);

        let notification = $nuxt.$notify.info({
            title:"C5挂刀脚本",
            message:"正在初始化...",
            duration:0
        })
        currentPage = document.querySelector("li.number.active").innerText;
        fetchCommunityInfo().then(checkAndUpdateRate).then(()=>{
            notification.close();
            initQueryPage();
            queryMain();
            setInterval(sendRequest,request_interval_ms);
        },()=>{
            notification.close();
        });
    }


    /********************函数实现***********************/

    /********************页面相关***********************/
    //初始化商品列表页面
    function initQueryPage(){
        GM_addStyle(`
            .s_s_s_s_cell_rate{color:green;}
            .s_s_s_s_cell_rate_high{color:red;}
            div[doquery=false] .li-btm {background: darkgray !important;}
        `);
        //翻页插件
        let asc = true;
        document.addEventListener("keydown",(e)=>{
            if(e.path[0].tagName=="INPUT")return;
            if(!(e.alterKey||e.shiftKey||e.ctrlKey)){
                switch(e.key){
                    case 'd':
                    case 'ArrowRight':
                        nextBtn.click();
                        break;
                    case 'ArrowLeft':
                    case 'a':
                        prevBtn.click();
                        break;
                    case '-':
                        if(sortKey=="sellsort")asc=!asc;
                        else sortKey="sellsort";
                        sort(asc,"sellsort");
                        break;
                    case '=':
                        if(sortKey=="buysort")asc=!asc;
                        else sortKey="buysort";
                        sort(asc,"buysort");
                        break;
                    default:
                        break;
                }
            }
        });

        //新页面加载完毕
        let observer = new MutationObserver((mutations)=>{
            mutations.forEach((m)=>{
                if(m.attributeName=="style"){
                    if(m.target.style.display=="none"){
                        requests = [];
                        currentPage = document.querySelector("li.number.active").innerText;
                        document.querySelectorAll(".ratio-div").forEach((e)=>{e.remove()});
                        //GM_setValue("c5_last_page",document.querySelector(".el-pager .active").innerText);
                        queryMain();
                    }
                }
            })
        });
        setTimeout(setObserver,100);
        function setObserver(){
            if(!document.querySelector(".list > .el-loading-mask")){setTimeout(setObserver,100);return}
            observer.observe(document.querySelector(".list > .el-loading-mask"),{attributes: true});
        }
    }

    //查询列表页面饰品信息
    function queryC5ItemInfoList(){
     return new Promise(function(resolve,reject){
         appId = __NUXT__.data[0].query.appId;
         let cards = document.querySelectorAll(".goodsCard");
         for(let i=0;i<cards.length;i++){
             //设置英文名
             let data = GM_getValue(cards[i].__vue__.item.itemId);
             if(!data)GM_setValue(cards[i].__vue__.item.itemId,`{"enName":"${cards[i].__vue__.item.marketHashName}"}`);
             //console.log(GM_getValue(cards[i].__vue__.item.itemId));
         }
         resolve();
     });
    }

    //获取饰品的英文名
    //queryC5ItemInfoList查询到的信息和当前页面实际的饰品可能存在出入
    //靠这个函数补充获取饰品的英文名
    function getEnName(c5ItemId){
        return new Promise(function(resolve,reject){
            let url = location.href.replace(/([^?]+)(\?.*)?/,`$1/${c5ItemId}/`);
            console.log(`getting hash name of c5ItemId ${c5ItemId}`);
            requests.push({
                url: url,
                timeout: timeout_ms,
                method: "get",
                onload: function (res) {
                    try{
                        resolve(res.responseText.match(/"https?:\/\/steamcommunity.com\/market\/listings\/\d+\/(.*?)"/)[1]);
                    }
                    catch(err){
                        console.log("获取hash name错误:", err);
                        err.statusText="获取hash name错误";
                        reject(err);
                    }
                },
                onerror: function (err) {
                    console.log("获取hash name错误:", err);
                    err.statusText="获取hash name错误";
                    reject(err);
                },
                ontimeout: function () {
                    let err = { "status": 408, "statusText": "获取hash name超时" };
                    console.log("获取hash name超时:", err);
                    reject(err);
                }
            });
        });
    }

    //列表页面排序
    function sort(asc,key){
        let cards = document.querySelector(cardListSelector);
        let list = Array.from(cards.querySelectorAll("div[doquery=true]"));
        list.sort((a,b)=>{
            let res = parseFloat(a.querySelector(".ratio-div")[key])-parseFloat(b.querySelector(".ratio-div")[key]);
            if(!asc)res*=-1;
            return res;
        });
        for(let i=list.length-1;i>=0;i--)cards.prepend(list[i]);
    }

    //页面快速跳转
    function jumpToPage(page){
        document.querySelector(".el-pagination").__vue__.handleCurrentChange(page);
    }

    /***************************饰品列表界面查询函数**************************/

    //获取steam社区登录信息和钱包信息
    function fetchCommunityInfo(){
        return new Promise((resolve,reject)=>{
            console.log("c5挂刀脚本:检查steam社区连通性...");
            GM_xmlhttpRequest({
                method: "get",
                url: "https://steamcommunity.com/market/",
                timeout: timeout_ms,
                onload: function (res) {
                    if (res && res.status == 200) {
                        if(res.responseText.match(/var +g_bLoggedIn += +(true|false);/i)[1]=="false"){
                            $nuxt.$notify.warning({
                                title: "C5挂刀脚本",
                                dangerouslyUseHTMLString: true,
                                message: '<h2>STEAM市场未登录</h2><a href="https://steamcommunity.com/login/home/" target="_blank">去登录</a>',
                                duration: 0
                            })
                            reject(false);
                            return;
                        }
                        communityInfo.g_walletCurrency = parseInt(res.responseText.match(/"wallet_currency":(\d+)/)[1]);
                        communityInfo.g_strLanguage = res.responseText.match(/g_strLanguage = "([^"]+)"/)[1];
                        communityInfo.g_strCountryCode = res.responseText.match(/g_strCountryCode = "([^"]+)"/)[1];
                        GM_setValue("communityInfo",communityInfo);
                        console.log("c5挂刀脚本steam社区信息:",communityInfo);
                        resolve();
                    } else {
                        console.log("检测steam连接性出错:状态错误", res);
                        $nuxt.$notify.error({
                            title: "C5挂刀脚本",
                            message: `检测steam连接性出错:状态错误${res.status}`,
                        })
                        reject(res);
                    }
                },
                onerror: function (err) {
                    console.log("检测steam连接性出错:连接错误", err);
                    $nuxt.$notify.error({
                        title: "C5挂刀脚本",
                        message: `检测steam连接性出错:连接错误${err}`,
                    })
                    reject(err);
                },
                ontimeout: function () {
                    console.log("检测steam连接性出错:尝试超时");
                    $nuxt.$notify.error({
                        title: "C5挂刀脚本",
                        message: `检测steam连接性出错:请求超时,请开启加速器后刷新页面。`,
                        duration: 0
                    })
                    reject();
                }
            });
        });
    }

    //检查并更新汇率信息
    function checkAndUpdateRate(force=false){
        return new Promise((resolve,reject)=>{
            rateInfo = GM_getValue("exchangeRate");
            console.log("c5挂刀脚本:正在检查汇率...");
            if((!force) && rateInfo && rateInfo.time_next_update_unix > Date.now() && rateInfo.currencyCode == communityInfo.g_walletCurrency){resolve();return;}
            console.log("c5挂刀脚本:正在更新汇率...");
            let msg = $nuxt.$notify.info({
                title:"C5挂刀脚本",
                message:"正在更新汇率...",
                duration:0
            })
            GM_xmlhttpRequest({
                // 10000元锚点
                url: `https://steamcommunity.com/market/listings/730/Souvenir%20Sawed-Off%20|%20Snake%20Camo%20(Well-Worn)/render/?query=&start=40&count=100&currency=${communityInfo.g_walletCurrency}`,
                // 热门锚点
                // url: `https://steamcommunity.com/market/listings/730/AWP%20|%20Redline%20(Minimal%20Wear)/render/?start=0&count=30&currency=${g_rgCurrencyData[helper_config.steamCurrency].eCurrencyCode}`,
                method: "get",
                timeout: timeout_ms,
                onload: function (response) {
                    let data = response.status == 200 ? JSON.parse(response.responseText) : {};
                    if (data.success && data.listinginfo["3296062994072312107"]) {
                        if (data.listinginfo["3296062994072312107"].converted_currencyid % 2000 != communityInfo.g_walletCurrency) {
                            return; // 对结果返回前的多次操作进行屏蔽,只取最后一次的结果
                        }
                        let timeUnix = Date.now();
                        rateInfo = {
                            FtoC: (data.listinginfo["3296062994072312107"].price / data.listinginfo["3296062994072312107"].converted_price).toFixed(6),
                            CtoF: (data.listinginfo["3296062994072312107"].converted_price / data.listinginfo["3296062994072312107"].price).toFixed(6),
                            currencyCode: communityInfo.g_walletCurrency,
                            time_next_update_unix: timeUnix + 10800000,
                            time_update_unix: timeUnix
                        }
                        GM_setValue("exchangeRate", rateInfo);
                        msg.close();
                        $nuxt.$notify.success({
                            title: "C5挂刀脚本",
                            message: `社区货币汇率已更新。`,
                        })
                        resolve();
                        return;
                    }
                    console.log("获取汇率时错误:", response);
                    reject();
                    return;
                },
                onerror: function (err) {
                    console.log("获取汇率失败:", err);
                    reject();
                },
                ontimeout: function () {
                    console.log("获取汇率超时");
                    reject();
                }
            });
        })
    }

    //查询主函数
    function queryMain(){
        //获取当前页面物品信息列表
        queryC5ItemInfoList().then((result)=>{
            let cards = document.querySelector(cardListSelector).children;
            let count;
            let c5price;
            let ratioDiv;
            let promises = [];
            let ignores = [];
            for(let i=0;i<cards.length;i++){
                //检查最低在售量
                count = cards[i].querySelector(".count");
                if(!count)count=0;
                else count = count.innerText.match(/\d+/)?count.innerText.match(/\d+/)[0]:0;
                if(count<min_sell_num)cards[i].setAttribute("doQuery",false);
                else cards[i].setAttribute("doQuery",true);

                //创建元素
                ratioDiv = document.createElement("div");
                ratioDiv.className = "d-flex d-b-s ratio-div";
                ratioDiv.innerHTML=`<div class="sellRatio" style="font-size: large;">查询商品steamId</div><div class="buyRatio"></div>`;
                cards[i].querySelector(".li-btm").appendChild(ratioDiv);

                if(cards[i].getAttribute("doQuery")=="false"){
                    ratioDiv.querySelector(".sellRatio").innerText="已忽略";
                    ignores.push(cards[i]);
                    continue;
                }

                //查询饰品
                c5price = cards[i].querySelector(".price").innerText.replace(/[^0-9.]/,"");
                promises.push(queryOne(cards[i].querySelector("a").href.match(/\/(\d+)\//)[1],parseFloat(c5price),ratioDiv));
            }
            for(let i=0;i<ignores.length;i++)document.querySelector(cardListSelector).append(ignores[i]);
            Promise.all(promises).then(()=>{
                switch(auto_sort){
                    case 1:
                        sort(true,"sellsort");
                        sortKey="sellsort";
                        sortAsc=true;
                        break;
                    case 2:
                        sort(true,"buysort");
                        sortKey="buysort";
                        sortAsc=true;
                        break;
                    case -1:
                        sort(false,"sellsort");
                        sortKey="sellsort";
                        sortAsc=false;
                        break;
                    case 2:
                        sort(false,"buysort");
                        sortKey="buysort";
                        sortAsc=false;
                        break;
                    default:
                        break;
                }
            })
        });
    }

    //查询单个饰品,并更新查询结果div
    function queryOne(c5ItemId,c5price,ratioDiv){
        //查询饰品steamID然后查询订单信息
        return getSteamItemInfo(c5ItemId,appId).then((json)=>{
            ratioDiv.querySelector(".sellRatio").innerText="查询物品订单中";
            return getItemOrder(json);
        }).then((res)=>{
            //求购比例
            let steamBuyRatio = (c5price*rateInfo.CtoF / calcfee(parseFloat(res.highest_buy_order)) * 100).toFixed(2);
            //出售比例
            let steamSellRatio = (c5price*rateInfo.CtoF / calcfee(parseFloat(res.lowest_sell_order)) * 100).toFixed(2);
            let sellDiv = ratioDiv.querySelector(".sellRatio");
            let buyDiv = ratioDiv.querySelector(".buyRatio");
            if(steamSellRatio<high_sell_rate)sellDiv.classList.add("s_s_s_s_cell_rate")
            else sellDiv.classList.add("s_s_s_s_cell_rate_high")
            sellDiv.innerText=steamSellRatio;
            if(steamBuyRatio<high_buy_rate)buyDiv.classList.add("s_s_s_s_cell_rate")
            else buyDiv.classList.add("s_s_s_s_cell_rate_high")
            buyDiv.innerText=steamBuyRatio;
            ratioDiv.sellsort = steamSellRatio;
            ratioDiv.buysort = steamBuyRatio;
        },(err)=>{
            ratioDiv.querySelector(".sellRatio").innerText=err.statusText;
            ratioDiv.querySelector(".sellRatio").classList.add("text-red");
            ratioDiv.querySelector(".sellRatio").style.fontWeight = "bold";
            let parent = ratioDiv.parentNode;
            while(parent&&(parent.getAttribute("doquery")===null))parent = parent.parentNode;
            if(parent)parent.setAttribute("doquery","false");
        });
    }

    //获取物品在steam社区的itemid,后续使用itemid获取物品价格信息
    function getSteamItemInfo(c5ItemId,appId){
        return new Promise(function(resolve,reject){
            let data = GM_getValue(c5ItemId);
            let steamItemId;
            let json;
            if(!data){
                //获取英文名,然后获取id
                getEnName(c5ItemId).then((enName)=>{
                    GM_setValue(c5ItemId,`{"enName":"${enName}"}`);
                    console.log(GM_getValue(c5ItemId));
                    return getSteamItemInfo(c5ItemId,appId);
                }).then(resolve,reject);
                return;
            }
            else{
                json = JSON.parse(data);
                if(json.steamItemId)steamItemId=json.steamItemId;
            }
            if(steamItemId){
                resolve(json);
                return;
            }
            else if (steamItemId === null) {
                reject({ status: 404, statusText: "物品不在货架上" });
            }

            //console.log(`Getting steamItemId of ${json.enName}`);
            let request = {
                url: encodeURI(`https://steamcommunity.com/market/listings/${appId}/${json.enName}`),
                timeout: timeout_ms,
                method: "get",
                onload: function (res) {
                    if (res.status == 200) {
                        let html = res.responseText;
                        try {
                            steamItemId = /Market_LoadOrderSpread\(\s?(\d+)\s?\)/.exec(html)[1];
                        } catch (error) {
                            json.steamItemId=null;
                            GM_setValue(c5ItemId, JSON.stringify(json));
                            res.status = 404;
                            res.statusText = "物品不在货架上";
                            console.log("获取itemID状态异常:", res);
                            reject(res);
                            return;
                        }
                        json.steamItemId=steamItemId;
                        GM_setValue(c5ItemId, JSON.stringify(json));
                        //console.log(steamItemId);
                        resolve(json);
                    }
                    else if(res.status == 429){
                        res.statusText = "请求过于频繁";
                        console.log("获取itemID状态异常:", res);
                        reject(res);
                    }
                    else {
                        console.log("获取itemID状态异常:", res);
                        reject(res);
                    }
                },
                onerror: function (err) {
                    console.log("获取itemID错误:", err);
                    err.statusText = "获取itemID错误";
                    reject(err);
                },
                ontimeout: function () {
                    let err = { "status": 408, "statusText": "连接steam超时" };
                    console.log("获取itemID超时:", err);
                    reject(err);
                }
            };
            requests.push(request);
        })
    }

    //获取饰品订单报价信息
    function getItemOrder(steamItemInfo){
        return new Promise(function(resolve,reject){
            //console.log(`getting order info of steamItemId ${steamItemId}`);
            requests.push({
                url: `https://steamcommunity.com/market/itemordershistogram?country=${communityInfo.g_strCountryCode}&language=${communityInfo.g_strLanguage}&currency=${communityInfo.g_walletCurrency}&item_nameid=${steamItemInfo.steamItemId}&two_factor=0`,
                headers: {
                    "referer": encodeURI(`https://steamcommunity.com/market/listings/${appId}/${steamItemInfo.enName}`),
                    "X-Requested-With": "XMLHttpRequest",
                    "Host": "steamcommunity.com",
                    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35"
                },
                timeout: timeout_ms,
                method: "get",
                onload: function (res) {
                    if (res.status == 200) {
                        resolve(JSON.parse(res.responseText));
                    } else if(res.status == 429){
                        res.statusText = "请求过于频繁";
                        console.log("访问steamorder状态状态异常:", res);
                        reject(res);
                    }
                    else {
                        console.log("访问steamorder状态异常:", res);
                        if(res.statusText==="")res.statusText="查询steamorder出错";
                        reject(res);
                    }
                },
                onerror: function (err) {
                    console.log("访问steamorder列表出错:", err);
                    err.statusText = "访问steamorder出错";
                    reject(err);
                },
                ontimeout: function () {
                    let err = { "status": 408, "statusText": "连接steam超时" };
                    console.log("访问steamorder超时", err);
                    reject(err);
                }
            });
        })
    }

    //发送请求线程,限制最大同时请求数量
    function sendRequest(){
        if(requests.length==0)return;
        if(current_request_num<max_request_num){
            let request = requests.shift();
            let onload = request.onload;
            let onerror = request.onerror;
            let ontimeout = request.ontimeout;

            //特殊时期,steam市场对该请求有限制
            if(request.url.match(/itemordershistogram/)!=null&&current_request_num>=1){
                requests.push(request);
                return;
            }

            request.onload = (res)=>{
                current_request_num--;
                onload(res);
            }
            request.onerror = (res)=>{
                current_request_num--;
                onerror(res);
            }
            request.ontimeout = ()=>{
                current_request_num--;
                ontimeout();
            }
            GM_xmlhttpRequest(request);
            //console.log("Sending request");
            current_request_num++;
        }
    }

    //计算手续费,p是无小数点的价格(价格*100)
    function calcfee(p){
        var pnofee = Math.max(Math.floor(p/1.15),1);
        var vfee = Math.max(Math.floor(pnofee*0.1),1);
        var pfee = Math.max(Math.floor(pnofee*0.05),1);
        var i = 0;
        while((pnofee + vfee + pfee) != p && i < 100) {
            if((pnofee + vfee + pfee) > p) {
                pnofee--;
            }
            if((pnofee + vfee + pfee) < p) {
                pnofee++;
            }
            vfee = Math.max(Math.floor(pnofee*0.1),1);
            pfee = Math.max(Math.floor(pnofee*0.05),1);
            i++;
        }
        return pnofee;
    }

    /***************************饰品界面函数部分****************************/
    /***********************部分代码来自AFKOUT大佬**************************/

    //饰品界面查询函数
    function queryItemPage(itemUrl){
        get24MarketSell(itemUrl);
        initCalculator();
        GM_xmlhttpRequest({
            method: "GET",
            url: itemUrl,
            timeout:timeout_ms,
            onload: function(res){
                if(res.status == "200" &&res.responseText!=="null"){
                    try{
                        var nameid = res.responseText.match(/Market_LoadOrderSpread\( (\d+)/)[1];
                    }
                    catch(err){
                        if(res.responseText.indexOf('market_listing_nav_container') != -1){
                            steamxj();
                            return;
                        }
                    }
                    //console.log("https://steamcommunity.com/market/itemordershistogram?country=" + g_strCountryCode + "&language=" + g_strLanguage + "&currency=" + g_walletCurrency + "&item_nameid=" + nameid)
                    GM_xmlhttpRequest({
                        timeout:timeout_ms,
                        method: "GET",
                        url: "https://steamcommunity.com/market/itemordershistogram?country=" + communityInfo.g_strCountryCode + "&language=" + communityInfo.g_strLanguage + "&currency=" + communityInfo.g_walletCurrency + "&item_nameid=" + nameid,
                        headers: {
                            "referer": itemUrl,
                            "X-Requested-With": "XMLHttpRequest",
                            "Host": "steamcommunity.com",
                            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35"
                        },
                        responseType: "json",
                        onload: function(data){
                            var obj = data.response;
                            if(obj){
                                if(!obj.lowest_sell_order&&!obj.highest_buy_order){
                                    return;
                                }

                                GM_addStyle(`.price > div{ margin-top:4px;font-size:16px; }
                                        .ls, .hb {color:#e46409; }
                                        .lsnf, .hbnf {color:#7ccc35; }
                                        .lsr, .hbr {color:#1ee44a; }
                                        .price > div > span{ text-align:center;display:-moz-inline-box; display:inline-block; width:110px;}
                                        .titleafk { font-size:14px; }
                                        .titleafk > strong:nth-child(1) { margin-left:90px; }
                                        .titleafk > strong:nth-child(2) { margin-left:70px; }
                                        .afkout { float:left;width:280px;margin-top:15px; }
                                        .afkout strong { color:#afb0b2;font-size: 15px}
                                       `);

                                var outDiv = document.createElement("div");
                                outDiv.className = "afkout";

                                outDiv.innerHTML =`<div class="titleafk">
                                            <strong>出售</strong><strong>求购</strong>
                                            </div>
                                            <div class="price">
                                            <div><strong>价格:</strong><span class="ls"></span><span class="hb"></span></div>
                                            <div><strong>税后:</strong><span class="lsnf"></span><span class="hbnf"></span></div>
                                            <div><strong>比例:</strong><span class="lsr"></span><span class="hbr"></span></div>
                                            </div>
                                         `;

                                let infoDiv = document.querySelector("main .bottom-info");
                                document.querySelector("main").insertBefore(outDiv,infoDiv);

                                if(obj.lowest_sell_order){
                                    var lowest_sell_order = parseInt(obj.lowest_sell_order);
                                    document.querySelector("span.ls").innerText=obj.price_prefix + " " + lowest_sell_order/100 + " " + obj.price_suffix;
                                    var lsnofee = calcfee(lowest_sell_order);
                                    document.querySelector("span.lsnf").innerText=obj.price_prefix + " " + lsnofee/100 + " " + obj.price_suffix;
                                }

                                if(obj.highest_buy_order){
                                    var highest_buy_order = parseInt(obj.highest_buy_order);
                                    document.querySelector("span.hb").innerText=obj.price_prefix + " " + highest_buy_order/100 + " " + obj.price_suffix;
                                    var hbnofee = calcfee(highest_buy_order);
                                    document.querySelector("span.hbnf").innerText=obj.price_prefix + " " + hbnofee/100 + " " + obj.price_suffix;
                                }
                                let siteprice = getFloat(document.querySelector("div.onsale-table-content > :nth-child(1) .text-price").innerText);
                                document.querySelector("span.lsr").innerText=(siteprice*100/lsnofee*rateInfo.CtoF).toFixed(rate_precision);
                                document.querySelector("span.hbr").innerText=(siteprice*100/hbnofee*rateInfo.CtoF).toFixed(rate_precision);

                                document.getElementById("calcPrice").value = document.querySelector("span.ls").innerText;
                                document.getElementById("calcCost").value = siteprice;
                                var e = document.createEvent("HTMLEvents");
                                e.initEvent("input",true,true);
                                document.getElementById("calcPrice").dispatchEvent(e);

                            }
                        },
                        ontimeout:steam302,
                        onerror: steam302
                    });
                }
            },
            ontimeout:steam302,
            onerror: steam302
        });
    }

    //获取24小时成交量
    function get24MarketSell(itemUrl){
        let oriLink = itemUrl.split('/');
        let appid = parseInt(oriLink[oriLink.length-2]);
        oriLink = oriLink[oriLink.length-1];
        GM_xmlhttpRequest({
            method: "get",
            url: `https://steamcommunity.com/market/priceoverview/?appid=${appid}&market_hash_name=${oriLink}`,
            headers: {
                "referer": `https://steamcommunity.com/market/listings/${appid}/${oriLink}`,
                "X-Requested-With": "XMLHttpRequest",
                "Host": "steamcommunity.com",
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35"
            },
            responseType: "json",
            timeout: timeout_ms,
            onload: function (result) {
                result = result.response;
                result.volume=result.volume?result.volume:'0';
                var volume = '';
                if (result.success) {
                    volume = `在 <span>24</span> 小时内卖出了 <span class="text-green">${parseInt(result.volume.replace(/\, ?/gi, ''))}</span> 个`;
                }
                let oriDesc = document.querySelector("main");
                let newDesc = document.createElement('div');
                newDesc.style="margin-top:15px";
                newDesc.setAttribute('class', 'text-grey');
                newDesc.innerHTML = volume;
                oriDesc.appendChild(newDesc);
            }
        });
    }

    function initCalculator(){
        //计算器
        let calculator = document.createElement("div");
        calculator.className = "calc";
        calculator.style = "position: fixed;top: 20%;left: 20px;width: 150px;height: 100px;z-index: 999;background-color: #2C3040;color: white;font-weight: 600;height:fit-content;";
        calculator.innerHTML =
            "<p class=\"calcP\" style=\"\">售价 <input class=\"calcInput\" id=\"calcPrice\" autocomplete='off'></p>"+
            "<p class=\"calcP\">比例 <input class=\"calcInput\" id=\"calcRatio\" autocomplete='off'></p>"+
            "<p class=\"calcP\">进价 <input class=\"calcInput\" id=\"calcCost\" autocomplete='off'></p>";
        GM_addStyle(`
                                    p.calcP {margin-left: 10px;margin-top: 15px;margin-bottom: 15px;}
                                    input.calcInput {width: 90px;color: black;padding: unset;}
                                `);
        document.body.appendChild(calculator);
        document.getElementById("calcPrice").oninput = function(){
            this.value = correctInput(this.value);
            if(this.value === ""|| parseFloat(this.value) == 0){
                document.getElementById("calcRatio").value="";
                return;
            }
            let priceNoFee = calcfee((parseFloat(this.value*100)).toFixed(0))/100;
            let ratio = parseFloat(correctInput(document.getElementById("calcCost").value))*rateInfo.CtoF/priceNoFee;
            document.getElementById("calcRatio").value = ratio.toFixed(rate_precision);
        };
        document.getElementById("calcRatio").oninput = function(){
            this.value = correctInput(this.value);
            if(this.value === "" || parseFloat(this.value) == 0){
                document.getElementById("calcPrice").value="";
                return;
            }
            let priceNoFee = correctInput(document.getElementById("calcCost").value)/parseFloat(this.value)*rateInfo.CtoF;
            document.getElementById("calcPrice").value = calcOriPrice((priceNoFee*100).toFixed(0))/100;
        };
        document.getElementById("calcCost").oninput = function(){
            this.value = correctInput(this.value);
            if(this.value === "" || parseFloat(this.value) == 0){
                document.getElementById("calcRatio").value="";
                return;
            }
            let priceNoFee = calcfee((parseFloat(document.getElementById("calcPrice").value*100)).toFixed(0))/100;
            let ratio = this.value*rateInfo.CtoF/priceNoFee;
            document.getElementById("calcRatio").value = ratio.toFixed(rate_precision);
        };
    }

    function getFloat(str){
        try{
            str = str.replace(/[^0-9\.,]/g,"");
            var f = parseFloat(str.match(/[\d]{1,}(\.\d+)?/)[0]);
        }
        catch(err){
            return 0;
        }
        return f;
    }

    function correctInput(input){
        var f = input.replaceAll(/[^0-9.]/g,"");
        var index = f.indexOf(".");
        if(index!=-1){
            f = f.substr(0,index+1)+f.substr(index+1).replace(".","");
        }
        return f;
    }

    function calcOriPrice(pNoFee){
        var p = (pNoFee*1.15).toFixed(0);
        var calcP = calcfee(p);
        while(calcP!=pNoFee){
            if(calcP>pNoFee){
                p--;
            }
            if(calcP<pNoFee){
                p++;
            }
            calcP = calcfee(p);
        }
        return p;
    }

    function steam302(){
        var s302 = document.createElement("div");
        s302.style="color:#FF0000;margin-top:15px";
        s302.innerHTML=`<span class="glyphicon glyphicon-remove"></span><strong>查询超时,建议使用<a target="_blank" href="https://steamcn.com/t339527-1-1" style="color:#0b84d3">Steam302</a></strong>`;
        let infoDiv = document.querySelector("main .bottom-info");
        document.querySelector("main").insertBefore(s302,infoDiv);
    }

    function steamxj(){
        var xj = document.createElement("div");
        xj.style="color:#FF0000;margin-top:15px";
        xj.innerHTML=`<strong>物品不在货架上</strong>`;
        let infoDiv = document.querySelector("main .bottom-info");
        document.querySelector("main").insertBefore(xj,infoDiv);
    }

})();