HWM_ShowAvailableExchange

Показывает на странице ГЛ, если накопились существа на обмен

// ==UserScript==
// @name         HWM_ShowAvailableExchange
// @namespace    Небылица
// @version      1.6
// @description  Показывает на странице ГЛ, если накопились существа на обмен
// @author       Небылица
// @include      /^https{0,1}:\/\/((www|qrator)\.heroeswm\.ru|178\.248\.235\.15)\/(leader_guild|leader_army_exchange)\.php/
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

(function() {
    "use strict";

    // Вспомогательные функции
    function sendGETRequest(url, mimeType, callback){ // Универсалка для отправки GET-запроса к url с выставлением заданного MIME Type и исполнением функции callback при получении ответа
        var xhr = new XMLHttpRequest();
        xhr.open("GET", url, true);

        if (typeof mimeType === "string"){
            xhr.overrideMimeType(mimeType);
        }

        if (typeof callback === "function"){
            xhr.onreadystatechange = function(){
                if (xhr.readyState === 4 && xhr.status === 200){
                    callback.apply(xhr);
                }
            };
        }

        xhr.send();
    }
    function colorLink(){ // Раскрашивает ссылку на обмен
        document.querySelector("a[href='leader_army_exchange.php']").style.color = "blue";
    }
    function checkUnitPresenсe(list, monId){ // Проверка нахождения существа в формате "unit1" в списке юнитов (игнор-листе либо списке на обмен) в формате "unit1|unit2|"
        var monIdRegExp = new RegExp("(\?:\^\|\\|)" + monId + "\\|");
        return list.match(monIdRegExp) !== null;
    }
    function processHTML(exchangePageHTMLString, doColoring){ // Проверяет наличие стеков на обмен, по необходимости раскрашивает ссылку и запоминает результат и время
        var parser = new DOMParser(),
            exchangePageHTML = parser.parseFromString(exchangePageHTMLString, "text/html"),
            monIdInputs = exchangePageHTML.querySelectorAll("input[name='mon_id']");
        if (monIdInputs && exchangePageHTMLString.match(/Обменять\s\d/)){
            var ignoreList = GM_getValue("ignoreList" + plIdSubKey),
                exchangeAvailable = true; // так как кнопки обмена есть, по умолчанию true
            if (ignoreList){ // если игнор-листа нет, то так true и останется
                var monId,
                    i = 0,
                    maxI = monIdInputs.length;
                exchangeAvailable = false; // перед while'ом ставим false
                while (!exchangeAvailable && i<maxI){ // далее при нахождении первого юнита, которого нет в игнор-листе, прерываем цикл и запоминаем true
                    monId = monIdInputs[i].value;
                    if (!checkUnitPresenсe(ignoreList, monId)){
                        exchangeAvailable = true;
                    }
                    i++;
                }
            }

            if (exchangeAvailable && doColoring){
                colorLink();
            }
            GM_setValue("exchangeAvailable" + plIdSubKey, exchangeAvailable);
        } else{ // если кнопок обмена нет, то точно false
            GM_setValue("exchangeAvailable" + plIdSubKey, false);
        }

        GM_setValue("checkMoment" + plIdSubKey, currentMomentOnServer.getTime());
    }
    function checkExchangePage(){ // Отправка и обработка запроса к странице обменов
        sendGETRequest("leader_army_exchange.php", "text/html; charset=windows-1251", function(){
            processHTML(this.responseText, true);
        });
    }
    function recheckExchangePageWrapper(){ // Тайминговая обёртка для перепроверки после открытия свитка
        if (document.documentElement.innerText.match("Вы призвали: ")){
            checkExchangePage();
        } else{
            window.setTimeout(function(){recheckExchangePageWrapper();}, 1000);
        }
    }
    function processLeadershipTbody(ignoreList, monId, leadershipTbody, exchangeButton, HTMLString){ // Оформление и привязка событий на вкл./искл. юнитов из учёта по клику на лидерстве (HTMLString – код страницы обменов для перепроверки)
        if (checkUnitPresenсe(ignoreList, monId)){
            exchangeButton.disabled = true;
            leadershipTbody.title = "Юнит исключён из учёта доступных обменов. Нажмите, чтобы включить обратно.";
            leadershipTbody.firstChild.children[1].children[0].style.color = "red";

            leadershipTbody.onclick = function(){
                ignoreList = GM_getValue("ignoreList" + plIdSubKey).replace(monId + "|", "");
                GM_setValue("ignoreList" + plIdSubKey, ignoreList);
                processLeadershipTbody(ignoreList, monId, leadershipTbody, exchangeButton, HTMLString);
                processHTML(HTMLString, false);
            }
        } else{
            exchangeButton.disabled = false;
            leadershipTbody.title = "Юнит учитывается в числе доступных обменов. Нажмите, чтобы исключить.";
            leadershipTbody.firstChild.children[1].children[0].style.color = "black";

            leadershipTbody.onclick = function(){
                ignoreList = GM_getValue("ignoreList" + plIdSubKey) + monId + "|";
                GM_setValue("ignoreList" + plIdSubKey, ignoreList);
                processLeadershipTbody(ignoreList, monId, leadershipTbody, exchangeButton, HTMLString);
                processHTML(HTMLString, false);
            }
        }
    }
    //


    // получаем id текущего персонажа и кусок ключа по нему
    var plId = document.querySelector("li > a[href^='pl_hunter_stat.php']").getAttribute("href").split("id=")[1],
        plIdSubKey = "|#" + plId,
        i,
        maxI,
        // определяем текущий момент времени
        currentMoment = new Date(),
        currentMomentOnServer = new Date(Date.now() + currentMoment.getTimezoneOffset()*60000 + 10800000),
        // и создаём переменную-временной флаг
        checkMoment = GM_getValue("checkMoment" + plIdSubKey) || 0;

    switch (location.pathname){
        case "/leader_guild.php":
            if (currentMomentOnServer.getTime() - checkMoment > 300000){ // если предыдущая проверка была не менее, чем 5 минут назад
                // запрашиваем страницу обменов и обрабатываем результат
                checkExchangePage();

            } else{ // иначе раскрашиваем ссылку сразу при наличии положительного сохранённого значения
                if (GM_getValue("exchangeAvailable" + plIdSubKey)){
                    colorLink();
                }
            }

            // делаем открытие ссылки на обмены в новой вкладке, если есть задания
            if (document.querySelector("input[value='Пропустить']")){
                document.querySelector("a[href='leader_army_exchange.php']").setAttribute("target", "_blank");
            }

            // если есть свитки, то подвешиваем перепроверку при открытии
            maxI = 3;
            for (i=0;i<maxI;i++){
                var scroll = document.getElementById("scroll" + (i+1).toString());
                if (scroll && scroll.getAttribute("onclick")){scroll.addEventListener("click", function(){recheckExchangePageWrapper();});}
            }

            // если только что был собран отряд из частей, то делаем перепроверку
            if (location.href.match("ex_done=") || document.documentElement.innerHTML.match(":\s100\sЧастей\s")){
                checkExchangePage();
            }

            break;

        case "/leader_army_exchange.php":
            // на странице обменов проверяем всё время, без кулдаунов
            var exchangePageInnerHTML = document.documentElement.innerHTML;
            processHTML(exchangePageInnerHTML, false);

            // отрисовываем опцию удаления юнитов из учёта, если есть готовые к обмену
            var monIdInputs = document.querySelectorAll("input[name='mon_id']");
            if (monIdInputs){
                var monId,
                    monIds = "",
                    ignoreList = GM_getValue("ignoreList" + plIdSubKey) || "",
                    leadershipTbody,
                    exchangeButton;
                maxI = monIdInputs.length;

                for (i=0;i<maxI;i++){
                    monId = monIdInputs[i].value;
                    leadershipTbody = monIdInputs[i].parentElement.previousSibling.firstChild.firstChild;
                    exchangeButton = monIdInputs[i].nextSibling;

                    processLeadershipTbody(ignoreList, monId, leadershipTbody, exchangeButton, exchangePageInnerHTML);

                    monIds += (monId + "|"); // записываем все юниты с доступным обменом для последующей чистки игнор-листа
                }
            }

            // удаляем из игнор-листа юниты, которых нет на обмен
            var ignoreListArr = ignoreList.split("|").filter(function(element){return element !== "";});
            maxI = ignoreListArr.length;
            for (i=0;i<maxI;i++){
                monId = ignoreListArr[i];
                if (!checkUnitPresenсe(monIds, monId)){
                    GM_setValue("ignoreList" + plIdSubKey, ignoreList.replace(monId + "|", ""))
                }
            }

            break;
    }
})();