饰品比例列表计算

饰品比例列表计算查看

目前為 2020-09-12 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         饰品比例列表计算
// @namespace    sourcewater
// @version      0.1.2
// @description  饰品比例列表计算查看
// @author       sourcewater
// @match        https://buff.163.com/market/?game=*
// @match        https://www.c5game.com/dota.html*
// @match        https://www.c5game.com/csgo/default/*
// @match        https://www.igxe.cn/dota2/*
// @match        https://www.igxe.cn/csgo/*
// @grant        GM_xmlhttpRequest
// ==/UserScript==

(function() {

    let log={
        DEBUG:1,
        INFO:5,
        level:1,
        setLevel:function(level){
            this.level=level;
        },
        log:function(msg,level,prefix){
            let date=new Date();
            let time=date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
            if(level>=this.level){
                console.log(prefix+time+" >>>> "+msg);
            }
        },
        info:function (msg){
            this.log(msg,this.INFO,"info: ");
        },
        debug:function(msg){
            this.log(msg,this.DEBUG,"debug: ");
        }
    };
    log.setLevel(log.INFO);
    let priceCSSEle=document.createElement("style");
    priceCSSEle.setAttribute("type","text/css");
    const displaySuccessClass="s_s_s_s_display_success";
    const itemidAttr="s_s_s_s_item_id";
    const successAttr="s_s_s_s_success";
    const linkRegAttr="s_s_s_s_click_register";
    const contentChangeAttr="s_s_s_s_content_change";
    const progressDivId="s_s_s_s_progress_div";
    const progressDivAttr="s_s_s_s_progress_init_success";
    const waitingDivId="s_s_s_s_waiting_div";
    const appidList={"csgo":730,"dota2":570};
    const buffUrlReg=/buff\.163\.com\//;
    const c5UrlReg=/c5game\.com\//;
    const igxeUrlReg=/igxe\.cn/;
    const timeout=6000;
    let index=0;
    let progressDivEle=document.createElement("div");
    progressDivEle.setAttribute("id",progressDivId);
    progressDivEle.setAttribute("style","border-radius:4px; border: 4px solid white; text-align: center;position: absolute;left: 50%;top: 55%;transform: translate(-50%, -50%);background:white;padding:5px;");
    progressDivEle.innerHTML=`
	<p>
	  <strong>正在初始化</strong><br>
	  <progress style="width:200px;height:25px;"></progress>
	</p>
	`;
    document.body.appendChild(progressDivEle);
    let priceCSS=`
        .s_s_s_s_display_success{
            display:block;
        }
        .s_s_s_s_cell_right,
        .s_s_s_s_cell_link,
        .s_s_s_s_cell_after_fee,
        .s_s_s_s_cell_rate,
        .s_s_s_s_cell_rate_high{
            width:50px;
            text-align:right;
        }
        .s_s_s_s_cell_left{
            display:inline-block;
            width:50px;
            text-align:left;
        }
        .s_s_s_s_cell_right{
            color:#eea20e;
        }
        .s_s_s_s_cell_link{
            color:black;
        }
        .s_s_s_s_cell_rate{
            color:green;
        }
        .s_s_s_s_cell_rate_high{
            color:red;
        }
    `;
    let customPriceCss;
    if(buffUrlReg.test(window.location.href)){
        customPriceCss=`
        .s_s_s_s_cell_left{
            color:black;
        }
        .s_s_s_s_display_success{
            margin-left:15px;
            height:167px;
        }
        .s_s_s_s_cell_after_fee{
            color:purple;
        }
        `;
    }else if(c5UrlReg.test(window.location.href)){
        customPriceCss=`
        .s_s_s_s_cell_left{
            color:white;
        }
        .s_s_s_s_display_success{
            margin-left:15px;
            height:205px;
        }
        .s_s_s_s_cell_after_fee{
            color:#55aa88;
        }
        `;
    }else if(igxeUrlReg.test(window.location.href)){
        customPriceCss=`
        .s_s_s_s_cell_left{
            color:white;
        }
        .s_s_s_s_display_success{
            margin-left:15px;
            height:205px;
        }
        .s_s_s_s_cell_after_fee{
            color:#55aa88;
        }
        `;
    }
    priceCSSEle.innerHTML=priceCSS+customPriceCss;
    document.head.appendChild(priceCSSEle);
    function checkInitCalculate(){
        if(!progressDivEle.getAttribute(progressDivAttr)){
            initCalculate();
            return;
        }
        log.info("init successfully!");
    }
    function initCalculate(){
        setTimeout(function(){checkInitCalculate();},timeout);
        let steamMarketUrl="https://steamcommunity.com/market/";
        let walletVariable="var g_rgWalletInfo = ";
        GM_xmlhttpRequest({
            url: steamMarketUrl,
            method: 'GET',
            //timeout:10000,
            onload: function(res){
                if(res.status === 200){
                    let html=res.responseText;
                    walletVariable+=html.match(/var g_rgWalletInfo(.|\n)*?(\{+?(.|\n)*?\}+?)+/)[2];
                    let varScriptEle=document.createElement("script");
                    varScriptEle.setAttribute("type","text/javascript");
                    varScriptEle.innerHTML=walletVariable;
                    document.body.appendChild(varScriptEle);
                    let calculateJSUrl="https://steamcommunity-a.akamaihd.net/public/javascript/economy_common.js?v=tsXdRVB0yEaR&l=schinese&_cdn=china_pinyuncloud";
                    GM_xmlhttpRequest({
                        url: calculateJSUrl,
                        method: 'GET',
                        //timeout:10000,
                        onload: function(res){
                            if(res.status === 200){
                                let calculateScript=res.responseText;
                                let calScriptEle=document.createElement("script");
                                calScriptEle.setAttribute("type","text/javascript");
                                calScriptEle.innerHTML=calculateScript;
                                document.head.appendChild(calScriptEle);
                                progressDivEle.setAttribute(progressDivAttr,"success");
                                start(window.location.href);
                                document.body.removeChild(progressDivEle);
                            }else{
                                log.info("initCalculate(): 访问Steam市场错误!");
                            }
                        },onerror : function(err){
                            log.info("initCalculate(): 访问Steam市场超时!");
                        },ontimeout : function(err){
                            log.info("initCalculate(): 访问超时");
                        }
                    });
                }else{
                    log.info("initCalculate(): 访问Steam市场错误!");
                }
            },onerror : function(err){
                log.info("initCalculate(): 访问Steam市场超时!");
            },ontimeout : function(err){
                log.info("initCalculate(): 访问超时");
            }
        });

    }
    initCalculate();
    function getPriceValueAsInt(value){
        if(isNaN(value)){
            value=parseFloat(value);
        }
        return (parseInt(value*100)).toString();
    }
    function receivePrice(price){
        if(typeof price != 'undefined'){
            return (getPriceValueAsInt(price)-parseInt(CalculateFeeAmount(getPriceValueAsInt(price),g_rgWalletInfo["wallet_publisher_fee_percent_default"]).fees))/100;
        }
        return 0;
    }
    function queryPrice(currentIndex,appid,name,updateView,args){
        log.info("new task index: "+currentIndex);
        if(currentIndex<index){
            log.debug("stop previous check update for index: "+currentIndex);
            return;
        }
        function checkUpdate(currentIndex,item_nameid,steamUrl,element){
            if(currentIndex<index){
                log.debug("stop previous check update for index: "+currentIndex);
                return;
            }
            if(!args.element.getAttribute(successAttr)){
                update(item_nameid,steamUrl);
                log.debug("retry get price >>>> "+item_nameid);
            }
            log.debug(item_nameid+" >>>> get price finish!");
        }
        function update(item_nameid,steamUrl){
            if(currentIndex<index){
                log.debug("stop previous check update for index: "+currentIndex);
                return;
            }
            let buyPrice=-1;
            let sellPrice=-1;
            setTimeout(function(){checkUpdate(currentIndex,item_nameid,steamUrl,args.element);},timeout);
            log.debug(`update: "https://steamcommunity.com/market/itemordershistogram?country=CN&language=schinese&currency=23&item_nameid=${item_nameid}&two_factor=0"`);
            GM_xmlhttpRequest({
                url: `https://steamcommunity.com/market/itemordershistogram?country=CN&language=schinese&currency=23&item_nameid=${item_nameid}&two_factor=0`,
                method: 'GET',
                //timeout:10000,
                responseType: 'json',
                onload: function(res){
                    if(res.status === 200){
                        let data=JSON.parse(res.responseText);
                        if(data.success==1){
                            if(data.buy_order_graph.length>0&&data.buy_order_graph[0].length>0){
                                buyPrice=data.buy_order_graph[0][0];
                            }
                            if(data.sell_order_graph.length>0&&data.sell_order_graph[0].length>0){
                                sellPrice=data.sell_order_graph[0][0];
                            }
                            args.sellPrice=sellPrice;
                            args.buyPrice=buyPrice;
                            args.steamUrl=steamUrl;
                            updateView(args);
                        }
                    }else{
                        log.info("update(): "+res.status+" :访问Steam市场错误!");
                    }
                },onerror : function(err){
                    log.info("update(): 访问Steam市场超时!");
                },ontimeout : function(err){
                    log.info("update(): 访问超时");
                }
            });
        }
        function checkFetchInfo(currentIndex,item_nameid){
            if(currentIndex<index){
                log.debug("stop previous check fetch info for index: "+currentIndex);
                return;
            }
            if(!args.element.getAttribute(itemidAttr)){
                fetchInfo();
                log.debug("retry get item name id.");
            }
            log.debug(item_nameid+" >>>> get item name id finish!");
        }
        function fetchInfo(){
            let item_nameid="";
            if(currentIndex<index){
                log.debug("stop previous check update for index: "+currentIndex);
                return;
            }
            let steamUrl=`https://steamcommunity.com/market/listings/${appid}/${name}`;
            setTimeout(function(){checkFetchInfo(currentIndex,item_nameid);},timeout);
            GM_xmlhttpRequest({
                method: "get",
                url: steamUrl,
                //timeout:10000,
                async: false,
                onload: function(res){
                    if(res.status === 200){
                        let response=res.responseText;
                        let nameidMatchs=response.match(/Market_LoadOrderSpread\(.*?([\d]+).*?\);/);
                        log.debug("<nameidMatchs: "+nameidMatchs+">");
                        if(nameidMatchs){
                            item_nameid=nameidMatchs.length == 2 ? nameidMatchs[1] : "";
                            log.debug("<item_nameid: "+item_nameid+">");
                            if(item_nameid!=""){
                                args.element.setAttribute(itemidAttr,"success");
                                update(item_nameid,steamUrl);
                            }
                        }else{
                            args.element.querySelector("#"+waitingDivId).innerHTML=`<span style="color: red;display:block;text-align: center;position: relative;left: 50%;top: 50%;transform: translate(-50%, -50%);">此物品不在货架上。</span>`;
                            args.element.setAttribute(itemidAttr,"success");
                        }
                    }else{
                        log.info("Error Code: "+res.status);
                    }
                },onerror : function(err){
                    log.info("fetchInfo(): 访问Steam市场错误!");
                },ontimeout : function(err){
                    log.info("fetchInfo(): 访问超时");
                }
            });
        }
        fetchInfo();
    }
    function updateView(args){
        let purchasePrice,sellRate,buyRate;
        let priceSpan=document.createElement("span");
        let success=true;
        if(buffUrlReg.test(args.url)&&!args.element.getAttribute(successAttr)){
            purchasePrice=parseFloat(args.element.querySelector("strong.f_Strong").innerHTML.match(/[\d\.]/g).join(""));
        }else if(c5UrlReg.test(args.url)&&!args.element.getAttribute(successAttr)){
            purchasePrice=parseFloat(args.element.querySelector("span.price").innerHTML.match(/[\d\.]/g).join(""));
        }else if(igxeUrlReg.test(args.url)&&!args.element.getAttribute(successAttr)){
            purchasePrice=parseFloat(args.element.querySelector(".price.fl").textContent.match(/[\d\.]+/g).join(""));
        }else{
            success=false;
        }
        if(success){
            sellRate=(purchasePrice/receivePrice(args.sellPrice)).toFixed(2);
            buyRate=(purchasePrice/receivePrice(args.buyPrice)).toFixed(2);
            args.element.removeChild(args.element.querySelector("#"+waitingDivId));
            priceSpan.setAttribute("class",displaySuccessClass);
            let priceContent=`
                <br><span class="s_s_s_s_cell_left">卖出:</span><span class="s_s_s_s_cell_right">${(args.sellPrice == -1 ? "无" : args.sellPrice)}</span>
                <br><span class="s_s_s_s_cell_left">税后:</span><span class="s_s_s_s_cell_after_fee">${args.sellPrice == -1 ? "无" : receivePrice(args.sellPrice)}</span>
                <br><span class="s_s_s_s_cell_left">比例:</span><span class="${ sellRate > 0.7 ? "s_s_s_s_cell_rate_high": "s_s_s_s_cell_rate"}">${args.sellPrice == -1 ? "无" : sellRate}</span>
                <br><br><span class="s_s_s_s_cell_left">买入:</span><span class="s_s_s_s_cell_right">${(args.buyPrice == -1 ? "无" : args.buyPrice)}</span>
                <br><span class="s_s_s_s_cell_left">税后:</span><span class="s_s_s_s_cell_after_fee">${args.buyPrice == -1 ? "无" : receivePrice(args.buyPrice)}</span>
                <br><span class="s_s_s_s_cell_left">比例:</span><span class="${ buyRate > 0.9 ? "s_s_s_s_cell_rate_high": "s_s_s_s_cell_rate"}">${args.buyPrice == -1 ? "无" : buyRate}</span>
                <br><br>
                <span class="s_s_s_s_cell_link"><a href="${args.steamUrl}" target="_blank">Steam链接</a></span>
        `;
            priceSpan.innerHTML=priceContent;
            args.element.setAttribute(successAttr,"true");
            args.element.appendChild(priceSpan);
            log.debug("update view successfully!");
        }
    }
    function waitForElement(selector,task){
        if(document.querySelector(selector)){
            task();
        }else{
            setTimeout(function(){waitForElement(selector,task);},100);
        }
    }
    let missionStart=false;
    function start(url){
        let cards;
        let cardClass;
        let appid;
        if(buffUrlReg.test(url)){
            let buffCSGOReg=/game=csgo/;
            let buffDotaReg=/game=dota2/;
            if(buffCSGOReg.test(url)){
                cardClass=".card_csgo";
                appid=appidList.csgo;
            }else if(buffDotaReg.test(url)){
                cardClass=".card_dota2";
                appid=appidList.dota2;
            }
            waitForElement(cardClass,function(){
                cards=document.querySelector(cardClass).querySelectorAll("li");
                startQuery();
            });

        }else if(c5UrlReg.test(url)){
            let c5CSGOReg=/\/csgo\//;
            let c5DotaReg=/dota\.html/;
            cardClass=".list-item4";
            if(c5DotaReg.test(url)){
                appid=appidList.dota2;
            }else if(c5CSGOReg.test(url)){
                appid=appidList.csgo;
            }
            waitForElement(cardClass,function(){
                cards=document.querySelector(cardClass).querySelectorAll("li");
                startQuery();
            });
        }else if(igxeUrlReg.test(url)){
            let igxeCSGOReg=/\/csgo\//;
            let igxeDotaReg=/\/dota2\//;
            cardClass=".dataList";
            if(igxeDotaReg.test(url)){
                appid=appidList.dota2;
            }else if(igxeCSGOReg.test(url)){
                appid=appidList.csgo;
            }
            waitForElement(cardClass,function(){
                cards=document.querySelector(cardClass).querySelectorAll("a");
                startQuery();
            });
        }
        function startQuery(){
            ++index;
            if(buffUrlReg.test(url)){
                for(let i=0;i<cards.length;++i){
                    let progressEleDiv=document.createElement("div");
                    progressEleDiv.setAttribute("id",waitingDivId);
                    queryPrice(index,appid,cards[i].querySelector("a").title,updateView,{"url":url,"element":cards[i]});
                    cards[i].setAttribute("style","height:399px!important;");
                    progressEleDiv.setAttribute("style","width:208px;height:120px;");
                    progressEleDiv.innerHTML=`<progress style="text-align: center;position: relative;left: 50%;top: 50%;transform: translate(-50%, -50%);"></progress>`;
                    cards[i].appendChild(progressEleDiv);
                }
                let marketCard=document.querySelector("#j_market_card");
                if(!missionStart){
                    let marketCardConfig = { childList: true };
                    let observer = new MutationObserver(function(){
                        if(!document.querySelector(cardClass)){
                            if(!marketCard.getAttribute(contentChangeAttr)){
                                marketCard.setAttribute(contentChangeAttr,"true");
                            }
                        }
                    });
                    observer.observe(marketCard, marketCardConfig);
                    let marketCardConfigAttr={ attributes: true };
                    let observerAttr = new MutationObserver(function(){
                        if(marketCard.getAttribute(contentChangeAttr)){
                            marketCard.removeAttribute(contentChangeAttr);
                            start(window.location.href);
                        }
                    });
                    observerAttr.observe(marketCard, marketCardConfigAttr);
                    missionStart=true;
                }
            }else if(c5UrlReg.test(url)){
                for(let i=0;i<cards.length;++i){
                    let progressEleSpan=document.createElement("span");
                    progressEleSpan.setAttribute("style","height:205px;display:block;");
                    progressEleSpan.setAttribute("id",waitingDivId);
                    queryPrice(index,appid,cards[i].querySelector("img").alt,updateView,{"url":url,"element":cards[i]});
                    progressEleSpan.innerHTML=`<progress style="text-align: center;position: relative;left: 50%;top: 50%;transform: translate(-50%, -50%);"></progress>`;
                    cards[i].appendChild(progressEleSpan);
                }
            }else if(igxeUrlReg.test(url)){
                const itemEnNameAttr="s_s_s_s_item_enName_success";
                function checkGetEnNameAndQuery(appid,cnName,progressEleSpan,card){
                    if(!card.getAttribute(itemEnNameAttr)){
                        getEnNameAndQuery(appid,cnName,progressEleSpan,card);
                        log.debug("retry get en name");
                    }
                    log.debug("get en name for "+cnName+" successfully!");
                }
                function getEnNameAndQuery(appid,cnName,progressEleSpan,card){
                    setTimeout(function(){checkGetEnNameAndQuery(appid,cnName,progressEleSpan,card);},timeout);
                    GM_xmlhttpRequest({
                        url: `https://steamcommunity.com/market/search?appid=${appid}&q=${cnName}`,
                        method: 'GET',
                        onload: function(res){
                            if(res.status === 200){
                                let html=res.responseText;
                                let itemLinkListReg=/<a[\s]+?class="market_listing_row_link"[\s\S]*?<\/a>/g;
                                let itemNameSpanReg=/<span[\s\S]+?class="market_listing_item_name"[\s\S]*?>(.+?)<\/span>/;
                                let enNameReg=/<div[\s\S]+?class="market_listing_row market_recent_listing_row market_listing_searchresult"[\s\S]*?data-hash-name="(.+)"[\s\S]*?>/
                                let enName="";
                                let linkList=html.match(itemLinkListReg);
                                if(linkList){
                                    for(let i=0;i<linkList.length;++i){
                                        let matchCNName=linkList[i].match(itemNameSpanReg)[1];
                                        if(matchCNName==cnName){
                                            enName=linkList[i].match(enNameReg)[1];
                                            break;
                                        }
                                    }
                                    if(enName==""){
                                        progressEleSpan.innerHTML=`<span style="color: red;display:block;text-align: center;position: relative;left: 50%;top: 50%;transform: translate(-50%, -50%);">此物品不在货架上。</span>`;
                                        card.setAttribute(itemidAttr,"success");
                                    }else{
                                        queryPrice(index,appid,enName,updateView,{"url":url,"element":card});
                                    }
                                    card.setAttribute(itemEnNameAttr,"success");
                                }
                            }else{
                                log.info("startQuery(): 访问Steam市场错误!Code: "+res.status);
                            }
                        },onerror : function(err){
                            log.info("startQuery(): 访问Steam市场超时!");
                        },ontimeout : function(err){
                            log.info("startQuery(): 访问超时");
                        }
                    });
                }
                for(let i=0;i<cards.length;++i){
                    let progressEleSpan=document.createElement("span");
                    progressEleSpan.setAttribute("style","height:205px;display:block;");
                    progressEleSpan.setAttribute("id",waitingDivId);
                    let card=cards[i];
                    let cnName=card.querySelector(".name").title;
                    card.setAttribute("style","height: 450px;");
                    progressEleSpan.innerHTML=`<progress style="text-align: center;position: relative;left: 50%;top: 50%;transform: translate(-50%, -50%);"></progress>`;
                    card.appendChild(progressEleSpan);
                    getEnNameAndQuery(appid,cnName,progressEleSpan,card)
                }
            }
        }
    }
})();