hwmAdvancedMenu

Расширенное меню

当前为 2023-12-18 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name           hwmAdvancedMenu
// @namespace      Tamozhnya1
// @author         Tamozhnya1
// @description    Расширенное меню
// @version        1.3
// @include        *heroeswm.ru/*
// @include        *lordswm.com/*
// @exclude        */rightcol.php*
// @exclude        */ch_box.php*
// @exclude        */chat*
// @exclude        */ticker.html*
// @exclude        */frames*
// @exclude        */brd.php*
// @license        MIT
// ==/UserScript==

if(!this.GM_getValue) {
    this.GM_getValue = function(key, def) { return localStorage[key] || def; };
    this.GM_setValue = function(key, value) { localStorage[key] = value; };
    this.GM_deleteValue = function(key) { return delete localStorage[key]; };
}
const StoredForumTreadsAmount = 10;
const playerIdMatch = document.cookie.match(/pl_id=(\d+)/);
if(!playerIdMatch) {
    return;
}
const PlayerId = playerIdMatch[1];
const isEn = document.documentElement.lang == "en";
const isNewInterface = document.querySelector("div#hwm_header") ? true : false;

main();
function main() {
    processHouses();
    processQuickLinks();
    processForum();
    // После рынка вставим ссылки на ресурсы, с задержкой в пол секунды
    const auctionRef = isNewInterface ? document.querySelector("div.sh_dd_container a[href='auction.php']") : getParent(document.querySelector("li > a[href='auction.php']"), "li");
    if(auctionRef) {
        let resourcesShowTimer;
        let resourcesShown = false;
        const resources = [ { type: "1", name: isEn ? 'Wood' : 'Древесина' }, { type: "2", name: isEn ? 'Ore' : 'Руда' }, { type: "3", name: isEn ? 'Mercury' : 'Ртуть' }, { type: "4", name: isEn ? 'Sulfur' : 'Сера' }, { type: "5", name: isEn ? 'Crystals' : 'Кристаллы' }, { type: "6", name: isEn ? 'Gems' : 'Самоцветы' } ];
        auctionRef.addEventListener("mouseover", function() { if(!resourcesShown) resourcesShowTimer = setTimeout(function() {
            const html = resources.reduce((t, x) => t + getMenuItemTemplate(`auction.php?cat=res&sort=0&type=${x.type}`, `  ${x.name}`), "");
            auctionRef.insertAdjacentHTML('afterend', html);
            resourcesShown = true;
        }, 500) } );
        auctionRef.addEventListener("mouseout", function() { clearTimeout(resourcesShowTimer); });
    }
    // После передачи ресурсов вставим основные ссылки персонажа
    const transferRef = isNewInterface ? document.querySelector("div.sh_dd_container a[href='transfer.php']") : getParent(document.querySelector("li > a[href='transfer.php']"), "li");
    if(transferRef) {
        const personalReferences = [
            { href: `el_transfer.php`, text: isEn ? 'Transfer elements' : 'Передача элементов' },
            { href: 'javascript:void(0);', text: "" },
            { href: `pl_info.php?id=${PlayerId}`, text: isEn ? 'Character' : 'Персонаж' },
            { href: `pl_transfers.php?id=${PlayerId}`, text: isEn ? 'Transfer log' : 'Протокол передач' },
            { href: `pl_warlog.php?id=${PlayerId}`, text: isEn ? 'Combat log' : 'Протокол боев' },
            { href: `pl_cardlog.php?id=${PlayerId}`, text: isEn ? 'Game log' : 'Протокол игр' },
            { href: `friends.php`, text: isEn ? 'Your friends' : 'Ваши друзья' },
            { href: `ephoto_albums.php`, text: isEn ? 'Your photos' : 'Ваш фотоальбом' },
            { href: 'javascript:void(0);', text: "" },
            { href: `logout.php?${Math.round( Math.random()* 100000 )}`, text: isEn ? 'Logout' : 'Выход' }
        ];
        const html = personalReferences.reduce((t, x) => t + getMenuItemTemplate(x.href, x.text), "");
        transferRef.insertAdjacentHTML('afterend', html);
    }
    // Расширение карты
    const mapMenuContainer = isNewInterface ? document.querySelector("div.sh_dd_container a[href='map.php?st=hs']") : getParent(document.querySelector("li > a[href='map.php?st=hs']"), "li");
    if(mapMenuContainer) {
        const housesInfo = JSON.parse(GM_getValue(`PlayerHouses${PlayerId}`, "{}"));
        let mapExtenders = Object.keys(housesInfo).map(x => ({ href: `house_info.php?id=${x}`, text: housesInfo[x].replace(" ", " ") }));
        // Арендованные дома. Берутся из скрипта Transporter
        for(let locationNumber = 1; locationNumber <= 27; locationNumber++) {
            const guestInfo = JSON.parse(GM_getValue(`GuestInfo${locationNumber}`, "{}"));
            for(const key in guestInfo) {
                mapExtenders = [...mapExtenders, { href: `house_info.php?id=${key}`, text: guestInfo[key].HostInfo, title: `до ${(new Date(guestInfo[key].ExpireDate)).toLocaleString()}` }];
            }
        }
        //
        mapExtenders = [...mapExtenders, { href: 'javascript:void(0);', text: "" }, { href: 'ecostat.php', text: isEn ? 'Economic statistics' : 'Эконом. статистика' }];
        const html = mapExtenders.reduce((t, x) => t + getMenuItemTemplate(x.href, x.text, x.title), "");
        //console.log(mapExtenders)
        mapMenuContainer.insertAdjacentHTML('afterend', html);
    }
    // Добавим форумов и дейли
    const forumsContainer = isNewInterface ? document.querySelector("div.sh_dd_container a[href='forum.php#t1']") : getParent(document.querySelector("li > a[href='forum.php#t1']"), "li");
    if(forumsContainer) {
        const forumExtenders = [
            { href: `forum_thread.php?id=${isEn ? '103' : '3'}`, text: isEn ? 'Ideas and suggestions' : 'Идеи и предложения' },
            { href: `forum_thread.php?id=${isEn ? '121' : '22'}`, text: isEn ? 'Smiths and Ench. services' : 'Услуги кузнецов и оруж.' },
            { href: 'javascript:void(0);', text: "" },
            { href: `${isEn ? 'http://daily.heroeswm.ru/newscom.php' : 'http://daily.heroeswm.ru/'}`, text: isEn ? 'HWM Daily ENG' : 'Геройская лента' }
        ];
        let html = forumExtenders.reduce((t, x) => t + getMenuItemTemplate(x.href, x.text), "");
        const lastForumTreads = JSON.parse(GM_getValue("LastForumTreads", "[]"));
        html += lastForumTreads.reduce((t, x) => t + getMenuItemTemplate(`/forum_messages.php?tid=${x.threadId}${x.pageIndex ? `&page=${x.pageIndex}` : ""}`, x.threadName), "");
        forumsContainer.insertAdjacentHTML('afterend', html);
    }
    // После чатов добавим быстрые ссылки
    const framesContainer = isNewInterface ? document.querySelector("div.sh_dd_container a[href='frames.php?room=4']") : getParent(document.querySelector("li > a[href='frames.php?room=4']"), "li");
    if(framesContainer) {
        //GM_deleteValue(`QuickLinks${PlayerId}`);
        let quickLinks = JSON.parse(GM_getValue(`QuickLinks${PlayerId}`, "[]")).filter(x => x.Name != "" && x.Refernce != "");
        if(quickLinks.length > 0) {
            quickLinks = [{ Refernce: "javascript:void(0);", Name: "" }, ...quickLinks];
            const html = quickLinks.reduce((t, x) => t + getMenuItemTemplate(x.Refernce, x.Name), "");
            framesContainer.insertAdjacentHTML('afterend', html);
        }
    }
}
function processForum() {
    if(location.pathname == '/forum_messages.php') {
        if(GM_getValue("LastForumTreads", "[]")) {
            const saved = JSON.parse(GM_getValue("LastForumTreads"));
            if(!Array.isArray(saved)) {
                GM_deleteValue("LastForumTreads");
            }
        }
        //https://www.heroeswm.ru/forum_messages.php?tid=2964583&page=5
        const threadId = getUrlParamValue(location.href, "tid");
        const pageIndex = getUrlParamValue(location.href, "page");
        const threadName = document.querySelector(`a[href='forum_messages.php?tid=${threadId}'`).innerText;
        const newThread = { threadId: threadId, pageIndex: pageIndex || 0, threadName: threadName, viewTime: Date.now() };
        let lastForumTreads = JSON.parse(GM_getValue("LastForumTreads", "[]"));
        const thisThread = lastForumTreads.find(x => x.threadId == newThread.threadId && x.pageIndex || 0 == newThread.pageIndex || 0);
        if(thisThread) {
            window.scrollTo(0, thisThread.scrollPosition); 
        }
        newThread.scrollPosition = window.scrollY;
        //console.log(newThread)
        lastForumTreads = lastForumTreads.filter(x => x.threadId != newThread.threadId);
        lastForumTreads.unshift(newThread);
        lastForumTreads = lastForumTreads.slice(0, StoredForumTreadsAmount);
        GM_setValue("LastForumTreads", JSON.stringify(lastForumTreads));
        
        document.addEventListener("scroll", (event) => {
            //console.log("scroll")
            const lastForumTreads = JSON.parse(GM_getValue("LastForumTreads", "[]"))
            const scrolledTread = lastForumTreads.find(x => x.threadId == newThread.threadId);
            if(scrolledTread) {
                scrolledTread.scrollPosition = window.scrollY;
                GM_setValue("LastForumTreads", JSON.stringify(lastForumTreads));
                //console.log(scrolledTreads)
            }
        });
        //console.log(lastForumTreads);
    }
}
function refrefhStoredForumTreads(newThread) {
    
}
function getMenuItemTemplate(href, text, title) { return !isNewInterface ? `<li>${text != "" ? `<a href='${href}'${!title ? "" : ` title='${title}'`}>${text}</a>` : "<hr>"}</li>` : `<a href='${href}'${!title ? "" : ` title='${title}'`} style='text-decoration:none;'><div${text == "" ? " style='padding: 0; height: 2px;'" : ""}>${text}</div></a>`; }
function processHouses() {
    if(location.pathname == "/pl_info_realty.php" && getUrlParamValue(location.href, "id") == PlayerId) {
        const housesInfo = Array.from(document.querySelectorAll("a[href^='house_info.php']")).reduce((t, x) => ({...t, [getUrlParamValue(x.href, "id")]: getParent(x, "tr").cells[4].innerText }), {});
        //console.log(housesInfo);
        GM_setValue(`PlayerHouses${PlayerId}`, JSON.stringify(housesInfo));
    }
}
function processQuickLinks() {
    if(location.pathname == "/pers_navlinks.php") {
        const tbody = getParent(document.querySelector("form[action='pers_navlinks.php']"), "tbody");
        const tr = addElement("tr", tbody);
        const td = addElement("td", tr);
        const table = addElement("table", td);
        
        const quickLinkAmount = 10;
        let quickLinks = JSON.parse(GM_getValue(`QuickLinks${PlayerId}`, `[${Array(quickLinkAmount).fill('{"Name":"","Refernce":""}').join()}]`));
        if(quickLinks.length != quickLinkAmount) {
            GM_deleteValue(`QuickLinks${PlayerId}`);
            quickLinks = JSON.parse(`[${Array(quickLinkAmount).fill('{"Name":"","Refernce":""}').join()}]`);
        }
        //console.log(quickLinks)
        let i = 0;
        for(const quickLink of quickLinks) {
            const html = `
<tr>
    <td>
        <input id="linkName${i}" name="linkName" type="text" style="width: 200px;" />
        <input id="linkValue${i}" name="linkValue" type="text" style="width: 300px;" />
    </td>
</tr>`;
            table.insertAdjacentHTML('beforeend', html);
            table.querySelector(`#linkName${i}`).value = quickLink.Name;
            table.querySelector(`#linkValue${i}`).value = quickLink.Refernce;
            table.querySelector(`#linkName${i}`).addEventListener("change", saveQuickLinks);
            table.querySelector(`#linkValue${i}`).addEventListener("change", saveQuickLinks);
            i++;
        }
    }
}
function saveQuickLinks() {
    const quickLinks = Array.from(document.querySelectorAll("input[name=linkName]")).map(x => ({ Name: x.value, Refernce: document.getElementById(x.id.replace("linkName", "linkValue")).value }));
    //console.log(quickLinks)
    GM_setValue(`QuickLinks${PlayerId}`, JSON.stringify(quickLinks));
}
function addElement(type, parent, data, insertFirst = false) {
    let el = createElement(type, data);
    if(parent) {
        if(insertFirst) {
            parent.insertBefore(el, parent.firstChild);
        } else {
            parent.appendChild(el);
        }
    }
    return el;
}
function createElement(type, data) {
    let el = document.createElement(type);
    if(data) {
        for(let key in data) {
            if(key == "innerText" || key == "innerHTML") {
                el[key] = data[key];
            } else {
                el.setAttribute(key, data[key]);
            }
        }
    }
    return el;
}
function getParent(element, parentType, number = 1) {
    if(!element) {
        return;
    }
    let result = element;
    let foundNumber = 0;
    while(result = result.parentNode) {
        if(result.nodeName.toLowerCase() == parentType.toLowerCase()) {
            foundNumber++;
            if(foundNumber == number) {
                return result;
            }
        }
    }
}
function getUrlParamValue(url, paramName) { return (new URLSearchParams(url.split("?")[1])).get(paramName); }