// ==UserScript==
// @name hwmAdvancedMenu
// @namespace Tamozhnya1
// @author Tamozhnya1
// @description Расширенное меню
// @version 1.6
// @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", "[]"));
if(lastForumTreads.length > 0) {
html += getMenuItemTemplate('javascript:void(0);', "");
}
html += lastForumTreads.reduce((t, x) => t + getMenuItemTemplate(`/forum_messages.php?tid=${x.threadId}${x.pageIndex ? `&page=${x.pageIndex}` : ""}`, x.threadName, "", `forumReference${x.threadId}`), "");
forumsContainer.insertAdjacentHTML('afterend', html);
Array.from(document.querySelectorAll(`span[id^='forumReference']`)).forEach(x => x.addEventListener("click", deleteForumReferenceMenuItem));
}
// После чатов добавим быстрые ссылки
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 deleteForumReferenceMenuItem(e) {
//e.stopPropagation();
e.preventDefault();
const threadId = e.target.id.replace("forumReference", "");
//console.log(`threadId: ${threadId}`)
const lastForumTreads = JSON.parse(GM_getValue("LastForumTreads", "[]")).filter(x => x.threadId != threadId);
GM_setValue("LastForumTreads", JSON.stringify(lastForumTreads));
const menuItem = isNewInterface ? getParent(e.target, "a") : getParent(e.target, "li");
//console.log(menuItem)
menuItem.remove();
}
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 == newThread.pageIndex);
if(thisThread) {
window.scrollTo(0, thisThread.scrollPosition);
}
newThread.scrollPosition = window.scrollY;
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) => {
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));
}
});
}
}
function getMenuItemTemplate(href, text, title, deleteId) {
if(text.length > 30) {
if(!title) {
title = text;
}
text = text.substring(0, 30) + "...";
}
if(!isNewInterface) {
if(text == "") {
return "<hr>";
}
let deleteElementText = "";
if(deleteId) {
deleteElementText = `<span id="${deleteId}" title='${isEn ? "Delete" : "Удалить"}' style="cursor: pointer; display: inline; color: yellow;">[x]</span>`;
}
return `<li><a href='${href}' title='${title || ""}' style="">${text}${deleteElementText}</a></li>`;
} else {
let deleteElementText = "";
if(deleteId) {
deleteElementText = `<span id="${deleteId}" title='${isEn ? "Delete" : "Удалить"}' style="cursor: pointer; display: inline; float: right;">[x]</span>`;
}
return `<a href='${href}' title='${title || ""}' style='text-decoration: none;'><div style='${text == "" ? "padding: 0; height: 2px;" : ""}'>${text}${deleteElementText}</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); }