// ==UserScript==
// @name hwmWidget
// @include /^https{0,1}:\/\/((www|qrator)\.heroeswm\.ru|178\.248\.235\.15)\/home\.php/
// @description Виджет для главной страницы ГВД
// @version 4.9
// @author Tamozhnya1
// @namespace Tamozhnya1
// @grant GM.xmlHttpRequest
// @grant unsafeWindow
// @grant GM_log
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_addStyle
// @license MIT
// ==/UserScript==
if(typeof GM_getValue != 'function') {
this.GM_getValue = function (key,def) { return localStorage[key] || def; };
this.GM_setValue = function (key,value) { return localStorage[key] = value; };
this.GM_deleteValue = function (key) { return delete localStorage[key]; };
}
const LotType = { Purchase: 1, Auction: 2 };
var ElementsTypes = { "42": "abrasive", "43": "snake_poison", "46": "tiger_tusk", "44": "ice_crystal", "45": "moon_stone", "40": "fire_crystal", "37": "meteorit", "41": "witch_flower", "39": "wind_flower", "78": "fern_flower", "38": "badgrib" }
var ElementNames = ["abrasive", "snake_poison", "tiger_tusk", "ice_crystal", "moon_stone", "fire_crystal", "meteorit", "witch_flower", "wind_flower", "fern_flower", "badgrib"];
var ResourcesTypes = { "wood": { Type: "1", ImageName: "wood" }, "ore": { Type: "2", ImageName: "ore" }, "mercury": { Type: "3", ImageName: "mercury" }, "sulphur": { Type: "4", ImageName: "sulfur" }, "crystal": { Type: "5", ImageName: "crystals" }, "gem": { Type: "6", ImageName: "gems" } };
var forumNames = { "2": "ОиФ", "10": "ВиП", "24": "Турниры", "3": "ИиП", "12": "БиП", "11": "ФВТ", "27": "Встречи", "14": "Обычные артефакты", "21": "Аренда", "22": "УКиО", "23": "ПЭСиП", "25": "ПЗ(Бои)", "13": "ПЗ(Финансы)", "7": "ТП", "8": "ОиС" };
const locations = {
1: [50,50,"Empire Capital","EmC","Столица Империи"],
2: [51,50,"East River","EsR","Восточная Река"],
3: [50,49,"Tiger Lake","TgL","Тигриное Озеро"],
4: [51,49,"Rogues' Wood","RgW","Лес Разбойников"],
5: [50,51,"Wolf Dale","WoD","Долина Волков"],
6: [50,48,"Peaceful Camp","PcC","Мирный Лагерь"],
7: [49,51,"Lizard Lowland","LzL","Равнина Ящеров"],
8: [49,50,"Green Wood","GrW","Зеленый Лес"],
9: [49,48,"Eagle Nest","EgN","Орлиное Гнездо"],
10: [50,52,"Portal Ruins","PoR","Руины Портала"],
11: [51,51,"Dragons' Caves","DrC","Пещеры Драконов"],
12: [49,49,"Shining Spring","ShS","Сияющий Родник"],
13: [48,49,"Sunny City","SnC","Солнечный Город"],
14: [52,50,"Magma Mines","MgM","Магма Шахты"],
15: [52,49,"Bear Mountain","BrM","Медвежья Гора"],
16: [52,48,"Fairy Trees","FrT","Магический Лес"],
17: [53,50,"Harbour City","HrC","Портовый Город"],
18: [53,49,"Mythril Coast","MfC","Мифриловый Берег"],
19: [51,52,"Great Wall","GtW","Великая Стена"],
20: [51,53,"Titans' Valley","TiV","Равнина Титанов"],
21: [52,53,"Fishing Village","FsV","Рыбачье село"],
22: [52,54,"Kingdom Castle","KiC","Замок Королевства"],
23: [48,48,"Ungovernable Steppe","UnS","Непокорная Степь"],
24: [51,48,"Crystal Garden","CrG","Кристальный Сад"],
25: [53,52,"East Island","EsI","Восточный Остров"],
26: [49,52,"The Wilderness","ThW","Дикие земли"],
27: [48,50,"Sublime Arbor","SbA","Великое Древо"]
};
const isEn = document.documentElement.lang == "en";
const Strings = { "ru": { BuyNow: "Купить сразу!" }, "en": { BuyNow: "Buy now!" } };
const LocalizedString = Strings[document.documentElement.lang];
const horizontalPadding = 25;
GM_addStyle(`
.hover-link:hover{ color: red }
.news-head {
text-decoration:none;
align-self: center;
border-radius: 1.5rem;
padding: 0.25rem .75rem;
}
.active {
background: #eae8dd;
}
.active:hover {
background: #eae8dd80;
}
.news-head__title {
display: inline;
font-size: 12px;
font-weight: normal;
cursor: pointer;
}
.news-head__switch {
cursor: pointer;
align-self: center;
color: #5D413A40;
margin-left:10px;
}
.news-head__settings {
cursor: pointer;
align-self: center;
color: #5D413A40;
margin-left:10px;
width: 1.5%;
}
.mrgn-l{
margin-left: 5px;
}
.flex {
display: flex;
}
.div-style {
margin: 0 auto 10px;
padding: 15px ${horizontalPadding}px 20px;
overflow: hidden;
min-width: 400px;
border-radius: 5px;
border: 0 #adadad solid;
background: url(../i/inv_im/corner_lt2.png) no-repeat top left, url(../i/inv_im/corner_rt2.png) no-repeat top right, url(../i/inv_im/corner_lb2.png) no-repeat bottom left, url(../i/inv_im/corner_rb2.png) no-repeat bottom right #f5f3ea;
background-size: 14px;
box-shadow: inset 0 0 0 1px #b19673, 0 2px 5px rgb(0 0 0 / 25%);
}
.res-style {
display: none;
justify-content: space-around;
height: 40px;
background-color: #eae8dd;
border-radius: 5px;
border: 0 #adadad solid;
margin-top: 10px;
}
.modal {
width: 100%;
height: 100%;
z-index: 1000;
position: fixed;
top:0;
left:0;
background: #00000050;
display: none;
align-items: center;
}
.modal-block {
display: flex;
width: 800px;
height: 500px;
z-index: 120;
margin: 0 auto;
position: relative;
border-radius: 5px;
border: 0 #adadad solid;
background: url(../i/inv_im/corner_lt2.png) no-repeat top left, url(../i/inv_im/corner_rt2.png) no-repeat top right, url(../i/inv_im/corner_lb2.png) no-repeat bottom left, url(../i/inv_im/corner_rb2.png) no-repeat bottom right #f5f3ea;
background-size: 14px;
box-shadow: inset 0 0 0 1px #b19673, 0 2px 5px rgb(0 0 0 / 25%);
padding: 15px;
align-items: flex-start;
flex-direction: column;
overflow: scroll;
}
.modal-block__head {
display: flex;
align-items: center;
}
.modal-block__text {
margin-top: 20px;
color: #6e6e6e;
}
.modal-block__btn {
padding: 5px 15px;
white-space: nowrap;
position: relative;
text-align: center;
color: #592C08;
background: url(../i/shop_images/art_btn_bg_gold.png) #DAB761;
background-size: 100% 100%;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border: 0 solid;
border-radius: 5px;
box-shadow: inset 0 0 0 1px #fce6b0, inset 0 0 0 2px #a78750, 0 0 0 1px rgb(0 0 0 / 13%);
cursor: pointer;
margin-left: 150px;
}
.modal-block__setting {
display: flex;
flex-wrap: wrap;
}
.modal-block__checkbox {
display: flex;
align-items: center;
margin: 0 8px 8px 5px;
padding: 0;
}
.clan-block {
flex-direction: column;
}
.clan-style {
display: inline-flex;
background-color: #adadad40;
padding: 3px 7px;
margin-left: 7px;
border: 0;
border-radius: 4px;
color: #592C08;
}
.res-style__elem {
align-self: center;
display: flex;
}
.text-title {
text-align:left;
padding-top: 6px;
}
@media screen and (min-width: 320px) and (max-width: 600px) {
.div-style {
width: auto;
}
.news-head__title {
font-size: 10px;
}
.res-style {
flex-wrap: wrap;
height: auto;
padding: 5px;
}
.res-style__elem {
margin: 0 10px 10px 0;
font-size: 12px;
}
.text-title {
font-size: 12px;
}
.news-head__settings {
width: 10%;
}
.modal-block {
width: 500px;
height: 800px;
}
}`);
const isNewPersonPage = document.querySelector("div#hwm_no_zoom") ? true : false;
const isMobileInterface = document.querySelector("div#btnMenuGlobal") ? true : false;
main();
async function main() {
//let widgetContainer = isNewPersonPage ? document.querySelector("body > center") : document.querySelector("body > center > table:nth-child(2) > tbody > tr > td > table > tbody > tr:nth-child(6) > td:nth-child(1)");
let widgetContainer = isNewPersonPage ? document.querySelector("div#hwm_no_zoom") : document.querySelector("body > center > table:nth-child(2) > tbody > tr > td > table > tbody > tr:nth-child(6) > td:nth-child(1)");
if(isMobileInterface) {
widgetContainer = isNewPersonPage ? document.querySelector("div#set_mobile_max_width") : document.querySelector("div#android_container > table > tbody > tr:nth-child(6) > td:nth-child(1)");
if(isNewPersonPage) {
widgetContainer.style.flexWrap = "wrap";
addElement("div", widgetContainer, { style: "flex-basis: 100%; height: 0;"});
}
}
let widthSnippet = "";
if(isNewPersonPage) {
const anchorRect = document.querySelector("div#set_mobile_max_width").getBoundingClientRect();
widthSnippet = ` style="width: ${anchorRect.width - horizontalPadding * 2 - 4}px;"`;
}
if(widgetContainer) {
let divOuterInnerHTML = `
<div class="div-style"${widthSnippet}>
<div class="flex">
<div id="hwmWidget" class="flex">
<div id="hwmWidgetDailyPreviewTab" class="news-head active">
<span>📰</span>
<h2 class="news-head__title" title="Новости HWM Daily">Новости HWM Daily</h2>
</div>
<h2 id="hwmWidgetPorumPreviewTab" class="news-head news-head__title mrgn-l" title="Последние темы форума">Последние темы форума</h2>
<h2 id="hwmWidgetClanLettersPreviewTab" class="news-head news-head__title mrgn-l" title="Клановая рассылка">Клановая рассылка</h2>
</div>
<span id="hwmWidgetSwitcher" class="news-head__switch"></span>
<span id="hwmWidgetSettings" class="news-head__settings" title="Настройки"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="cog" class="svg-inline--fa fa-cog fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M487.4 315.7l-42.6-24.6c4.3-23.2 4.3-47 0-70.2l42.6-24.6c4.9-2.8 7.1-8.6 5.5-14-11.1-35.6-30-67.8-54.7-94.6-3.8-4.1-10-5.1-14.8-2.3L380.8 110c-17.9-15.4-38.5-27.3-60.8-35.1V25.8c0-5.6-3.9-10.5-9.4-11.7-36.7-8.2-74.3-7.8-109.2 0-5.5 1.2-9.4 6.1-9.4 11.7V75c-22.2 7.9-42.8 19.8-60.8 35.1L88.7 85.5c-4.9-2.8-11-1.9-14.8 2.3-24.7 26.7-43.6 58.9-54.7 94.6-1.7 5.4.6 11.2 5.5 14L67.3 221c-4.3 23.2-4.3 47 0 70.2l-42.6 24.6c-4.9 2.8-7.1 8.6-5.5 14 11.1 35.6 30 67.8 54.7 94.6 3.8 4.1 10 5.1 14.8 2.3l42.6-24.6c17.9 15.4 38.5 27.3 60.8 35.1v49.2c0 5.6 3.9 10.5 9.4 11.7 36.7 8.2 74.3 7.8 109.2 0 5.5-1.2 9.4-6.1 9.4-11.7v-49.2c22.2-7.9 42.8-19.8 60.8-35.1l42.6 24.6c4.9 2.8 11 1.9 14.8-2.3 24.7-26.7 43.6-58.9 54.7-94.6 1.5-5.5-.7-11.3-5.6-14.1zM256 336c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z"></path></svg></span>
</div>
<div class="modal" id="hwmWidgetSettingsPanel">
<div class="modal-block">
<div class="modal-block__head">
<h3 class="modal-block__title">Настройки виджета</h3>
<button id="hwmWidgetSettingsPanelCloseButton" class="modal-block__btn">Закрыть</button>
</div>
<form>
<p class="modal-block__text">Выбор форума</p>
<div class="modal-block__setting">`;
for(const forumId in forumNames) {
divOuterInnerHTML += `<div class="modal-block__checkbox"><input type="radio" id="${forumId}" name="forum" ${GM_getValue("ForumId", "2") == forumId ? "checked" : ""}><label for="${forumId}">${forumNames[forumId]}</label></div>`;
}
divOuterInnerHTML += `</div>
</form>
<form>
<p class="modal-block__text">Выбор клана</p>
<div class="modal-block__setting clans-block">
</div>
</form>
<label for="ShowItemsAmountInput">Количество отображаемых сообщений</label><input type="number" id="ShowItemsAmountInput" value="${GM_getValue("ShowItemsAmount", 5)}" onfocus="this.select(); "/>
<label for="widgetPositionCheckbox">Положение виджета (вверху (если отмечено) / внизу)</label><input type="checkbox" id="widgetPositionCheckbox" />
</div>
</div>
<div id="hwmWidgetNewsPanel"></div>
<div id="hwmWidgetResourcesPanel" class="res-style"></div>
</div>
`;
widgetContainer.insertAdjacentHTML(gmGetBool("WidgetPosition") ? "afterbegin" : "beforeend", divOuterInnerHTML),
fillClansList();
const hwmWidgetSwitcher = document.getElementById('hwmWidgetSwitcher');
hwmWidgetSwitcher.addEventListener("click", function(event) { GM_setValue("Shown", 1 - Number(GM_getValue("Shown", 1))); show(); }, false);
const hwmSettings = document.getElementById('hwmWidgetSettings');
hwmSettings.addEventListener("click", function(event) {
document.querySelector("#hwmWidgetSettingsPanel").style.display = 'flex';
document.querySelector("html").style.overflowY = 'hidden';
}, false);
const hwmWidgetDailyPreviewTab = document.getElementById('hwmWidgetDailyPreviewTab');
hwmWidgetDailyPreviewTab.addEventListener("click", function(event) { GM_setValue("SecondClick", parseInt(GM_getValue("SelectedTab", 0)) == 0); GM_setValue("SelectedTab", 0); show(); }, false);
const hwmWidgetPorumPreviewTab = document.getElementById('hwmWidgetPorumPreviewTab');
hwmWidgetPorumPreviewTab.addEventListener("click", function(event) { GM_setValue("SecondClick", parseInt(GM_getValue("SelectedTab", 0)) == 1); GM_setValue("SelectedTab", 1); show(); }, false);
const hwmWidgetClanLettersPreviewTab = document.getElementById('hwmWidgetClanLettersPreviewTab');
hwmWidgetClanLettersPreviewTab.addEventListener("click", function(event) { GM_setValue("SecondClick", parseInt(GM_getValue("SelectedTab", 0)) == 2); GM_setValue("SelectedTab", 2); show(); }, false);
const closeSettings = document.getElementById('hwmWidgetSettingsPanelCloseButton');
document.getElementById("widgetPositionCheckbox").checked = gmGetBool("WidgetPosition");
closeSettings.addEventListener("click", function(event) {
document.querySelector("#hwmWidgetSettingsPanel").style.display = 'none';
document.querySelector("html").style.overflowY = 'overlay';
GM_setValue("ForumId", document.querySelector(`input[name='forum']:checked`).id);
const selectedClan = document.querySelector(".clans-block input[name='clan']:checked");
if(selectedClan) {
GM_setValue("ClanId", selectedClan.id);
} else {
GM_deleteValue("ClanId");
}
GM_setValue("ShowItemsAmount", document.getElementById("ShowItemsAmountInput").value);
GM_setValue("WidgetPosition", document.getElementById("widgetPositionCheckbox").checked);
show();
}, false);
GM_setValue("SecondClick", false);
show();
}
}
async function fillClansList() {
const doc = await getRequest(`https://www.heroeswm.ru/pl_clans.php`);
const clanInfos = Array.from(doc.querySelectorAll("td > li > a[href^='clan_info.php']")).map(x => { return { Id: getUrlParamValue(x.href, "id"), Name: x.firstChild.innerText }; });
if(clanInfos.length > 0) {
if(!GM_getValue("ClanId") || !clanInfos.find(x => x.Id == GM_getValue("ClanId"))) {
GM_setValue("ClanId", clanInfos[0].Id);
}
let clans = '';
for(const clanInfo of clanInfos) {
clans += `
<div class="modal-block__checkbox">
<input type="radio" id="${clanInfo.Id}" name="clan" ${clanInfo.Id == GM_getValue("ClanId") ? "checked" : ""}>
<label for="${clanInfo.Id}">#${clanInfo.Id} ${clanInfo.Name}</label>
</div>`;
}
document.querySelector(".clans-block").innerHTML = clans;
} else {
GM_deleteValue("ClanId");
document.querySelector(".clans-block").innerHTML = "Вы не состоите в кланах";
}
}
async function show() {
//console.log(`Shown: ${GM_getValue("Shown")}, SelectedTab: ${GM_getValue("SelectedTab")}, SecondClick: ${GM_getValue("SecondClick")}`);
if(gmGetBool("SecondClick")) {
switch(parseInt(GM_getValue("SelectedTab", 0))) {
case 0: window.open("https://daily.heroeswm.ru/", "_blank"); break;
case 1: window.open(`https://www.heroeswm.ru/forum_thread.php?id=${GM_getValue("ForumId", "2")}`, "_blank"); break;
case 2: window.open(`https://www.heroeswm.ru/sms_clans.php?clan_id=${GM_getValue("ClanId")}`, "_blank"); break;
}
return;
}
const shown = GM_getValue("Shown", 1);
const hwmWidgetSwitcher = document.getElementById('hwmWidgetSwitcher');
const newsPanel = document.getElementById("hwmWidgetNewsPanel");
const resourcesPanel = document.getElementById("hwmWidgetResourcesPanel");
if(shown == 0) {
hwmWidgetSwitcher.innerHTML = '<img src="https://dcdn3.heroeswm.ru/i/inv_im/btn_expand.svg" style="-webkit-transform: rotate(90deg); transform: rotate(90deg);">';
// <img src="https://dcdn3.heroeswm.ru/i/inv_im/btn_expand.svg" class="home_scroll_content_expand_sign inv_rotate90">
newsPanel.style.display = "none";
resourcesPanel.style.display = "none";
} else {
const hwmWidgetDailyPreviewTab = document.getElementById('hwmWidgetDailyPreviewTab');
const hwmWidgetPorumPreviewTab = document.getElementById('hwmWidgetPorumPreviewTab');
const hwmWidgetClanLettersPreviewTab = document.getElementById('hwmWidgetClanLettersPreviewTab');
hwmWidgetDailyPreviewTab.style.background = "#eae8dd00";
hwmWidgetPorumPreviewTab.style.background = "#eae8dd00";
hwmWidgetClanLettersPreviewTab.style.background = "#eae8dd00";
switch(parseInt(GM_getValue("SelectedTab", 0))) {
case 0: hwmWidgetDailyPreviewTab.style.background = "#eae8dd"; getDailyNews(); break;
case 1: hwmWidgetPorumPreviewTab.style.background = "#eae8dd"; getForumNews(); break;
case 2: hwmWidgetClanLettersPreviewTab.style.background = "#eae8dd"; getClanNews(); break;
}
hwmWidgetSwitcher.innerHTML = '<img src="https://dcdn3.heroeswm.ru/i/inv_im/btn_expand.svg" style="-webkit-transform: rotate(270deg); transform: rotate(270deg);">';
newsPanel.style.display = "block";
await getResources();
resourcesPanel.style.display = 'flex'
}
}
function trimming(string, l) {
//console.log(`string: ${string}, l: ${l}`);
var s = string;
if(string.length > l) {
for(var i = l; i >= 0; i--) {
if(string.charAt(i) == ' ') {
s = string.substr(0, i) + '...';
}
}
s = string.substr(0, l) + '...';
}
return s.replace(/&[^#]/g, "&").replace(/>/g, ">").replace(/</g, "<");
}
async function getElementLots() {
const doc = await getRequest(`https://www.heroeswm.ru/auction.php?cat=elements&sort=0`);
const firstLotRow = doc.querySelector("center > table:nth-child(2) > tbody > tr > td > table > tbody > tr:nth-child(2) > td:nth-child(2) > table > tbody > tr:nth-child(3)");
let arts = [];
let row = firstLotRow;
while(row = row.nextElementSibling) {
const art = parseLotRow(row);
if(art) {
arts.push(art);
}
}
const grouppedArts = groupBy(arts.filter(x => x.LotType == LotType.Purchase), "ArtId");
return grouppedArts;
}
function parseLotRow(row) {
if(!row || row.nodeName != "TR") {
return;
}
const goldImageElement = row.querySelector("img[src*='gold.png']");
if(!goldImageElement) {
return;
}
const lotPrice = parseFloat(goldImageElement.parentNode.nextElementSibling.innerText.replace(/,/g, ""));
let artId;
let lotAmount = 1;
const lotAmountExec = new RegExp(`(\\d+) ${isEn ? "pcs." : "шт."}`).exec(row.innerHTML);
//console.log(lotAmountExec);
if(lotAmountExec) {
lotAmount = parseInt(lotAmountExec[1]);
}
const lotType = row.innerHTML.includes(LocalizedString.BuyNow) ? LotType.Purchase : LotType.Auction;
const artImageRefElement = row.querySelector("a[href*='art_info.php']");
if(!artImageRefElement) {
const elementsList = Object.values(ElementsTypes).join("|");
const elementParse = (new RegExp(`gn_res/(${elementsList}).png`)).exec(row.innerHTML);
if(elementParse) {
artId = elementParse[1];
}
if(row.innerHTML.includes("house_cert")) {
const locationsList = Object.values(locations).map(x => x[2]).join("|");
const sertParse = (new RegExp(`<br>(${locationsList}) <b>`)).exec(row.innerHTML);
if(sertParse) {
artId = getSertIdByLocationName(sertParse[1]);
}
}
const resourcesList = Object.values(ResourcesTypes).map(x => x.ImageName).join("|");
const resourceParse = (new RegExp(`/(${resourcesList}).png`)).exec(row.innerHTML);
if(resourceParse) {
artId = "res_" + resourceParse[1];
}
if(row.innerHTML.includes("auc_dom")) {
const locationsList = Object.values(locations).map(x => x[2]).join("|");
const sertParse = (new RegExp(`<br>(${locationsList}) <b>`)).exec(row.innerHTML);
if(sertParse) {
artId = getHouseIdByLocationName(sertParse[1]);
}
}
if(row.innerHTML.includes("obj_share_pic")) {
const locationsList = Object.values(locations).map(x => x[2]).join("|");
const sertParse = (new RegExp(`<br>(${locationsList}) <b>`)).exec(row.innerHTML);
if(sertParse) {
artId = getShaIdByLocationName(sertParse[1]);
}
}
} else {
artId = getUrlParamValue(artImageRefElement.href, "id");
var artUid = getUrlParamValue(artImageRefElement.href, "uid");;
const strengthData = row.innerText.match(/\d+\/\d+/);
var restLotStrength = parseInt(strengthData[0].split("/")[0]);
var lotStrength = parseInt(strengthData[0].split("/")[1]);
}
const lotRef = row.querySelector("a[href^='auction_lot_protocol.php']");
const lotId = getUrlParamValue(lotRef.href, "id");
const imgR = row.querySelector("td:nth-child(1) > table > tbody > tr > td:nth-child(1) > img");
return { ArtUid: artUid, ArtId: artId, LotStrength: lotStrength, RestLotStrength: restLotStrength, LotPrice: lotPrice, LotType: lotType, LotAmount: lotAmount, LotId: lotId, ImageUrl: imgR.getAttribute('src'), Title: imgR.getAttribute('title') };
}
async function getResources() {
const resourcesPanel = document.getElementById("hwmWidgetResourcesPanel");
resourcesPanel.innerHTML = getWheelImage();
const grouppedArts = await getElementLots();
const elementsData = [];
for(const elementName of ElementNames)
{
const arts = grouppedArts[elementName]
if(arts.length == 0) {
continue;
}
const art = arts[0];
let price = art.LotPrice;
let secondLotPrice = price;
if(arts.length > 1) {
secondLotPrice = arts[1].LotPrice;
}
elementsData.push({ ElementName: elementName,
Price: price,
ImageUrl: art.ImageUrl,
Title: art.Title,
Diffrence: secondLotPrice - price,
AuctionUrl: `https://www.heroeswm.ru/auction.php?cat=elements&sort=0&art_type=${elementName}`,
NewAuctionUrl: `https://www.heroeswm.ru/auction_new_lot.php?${elementName}=${(price - 1)}`
});
}
//console.log(elementsData);
let res = "";
for(const elementData of elementsData)
{
res += `
<div class='res-style__elem'>
<div style='align-self: center;'>
<a class='hover-link' href='${elementData.NewAuctionUrl}' target='_blank'>
<img src='${elementData.ImageUrl}' width='20' heigth='20' border='0'>
</a>
</div>
<a class='hover-link' target='_. blank' style='text-decoration: none; align-self: center; margin-left: 5px; font-size: 9px;' href='${elementData.AuctionUrl}' title='Разница первого и второго лотов: ${elementData.Diffrence}'>${elementData.Price}</a>
<div style='${(elementData.Diffrence >= 150 ? 'display: inline-flex; background-color: #f33800; padding: 5px;margin-left: 5px; border: 0; border-radius: 4px; color: #fff;' : 'display: none;')}'>
<span title='' style='font-size: 8px; font-weight: bold;'>${elementData.Diffrence}</span>
</div>
</div>`;
}
resourcesPanel.innerHTML = res;
}
async function getClanNews() {
if(!GM_getValue("ClanId")) {
document.getElementById("hwmWidgetNewsPanel").innerHTML = "Вы не состоите в кланах";
return;
}
const doc = await getRequest(`https://www.heroeswm.ru/sms_clans.php?clan_id=${GM_getValue("ClanId")}`);
const letters = Array.from(doc.querySelectorAll("table.wbwhite a[href^='/sms_clans.php'][href*='read']")).map(x => { return {
Title: x.innerHTML,
Ref: x.href,
DateText: x.parentNode.previousElementSibling.innerHTML,
IsHot: (Date.now() - parseDate(x.parentNode.previousElementSibling.innerHTML, false, true).getTime()) / (1000 * 60 * 60) <= 12,
}; }).slice(0, parseInt(GM_getValue("ShowItemsAmount", 5)));
//console.log(letters);
//console.log(`letters: ${letters.length}`);
let clanLetters = "";
for(const letter of letters) {
clanLetters += `
<div class='text-title'>
<a class='hover-link' style='text-decoration:none; ${letter.IsHot ? "font-weight: bold; color: red;" : ""}' target='_blank' href='${letter.Ref}' title='${letter.Title}'>${letter.IsHot ? "📣 " : "• "}${letter.Title}</a>
<div class='clan-style'>
<span title='Дата' style='font-size:9px'>${letter.DateText}</span>
</div>
</div>
`;
}
document.getElementById("hwmWidgetNewsPanel").innerHTML = clanLetters;
}
async function getForumNews() {
const forumId = GM_getValue("ForumId", "2");
const doc = await getRequest(`https://www.heroeswm.ru/forum_thread.php?id=${forumId}`);
const messages = Array.from(doc.querySelectorAll("tr > td:nth-child(1) > a[href^='forum_messages.php']")).map(x => { return {
Fixed: getParent(x, "tr").querySelector("img[src*='skrepka.gif']") ? true : false,
Title: x.innerHTML,
Reference: x.href,
LastCommentReference: getParent(x, "tr").querySelector("a[href^='forum_messages.php'][href*='page=last']"),
CommentsAmount: parseInt(getParent(x, "tr").cells[2].innerHTML),
IsHot: parseInt(getParent(x, "tr").cells[2].innerHTML) <= 20
};}).filter(x => !x.Fixed).slice(0, parseInt(GM_getValue("ShowItemsAmount", 5)));
let forumNews = "";
for(const message of messages) {
forumNews += `
<div class='text-title'>
<a class='hover-link' style='text-decoration: none;${(message.IsHot ? ' font-weight: bold; color: #ff4d00' : '')}' target='_blank' href='${message.Reference}' title='${message.Title}'>${(message.IsHot ? "🔥" : "•")} ${message.Title}
</a>
<div style='display: inline-flex; background-color: #adadad40;padding: 3px 7px; margin-left: 7px; border: 0; border-radius: 4px; color: #592C08;'>
<a href="${message.LastCommentReference}" title='Количество комментариев. Перейти к последнему.' target='_blank' style='font-size: 9px'>${message.CommentsAmount}</a>
</div>
</div>`;
}
document.getElementById("hwmWidgetNewsPanel").innerHTML = forumNews;
}
function getDailyNews() {
const newsPanel = document.getElementById("hwmWidgetNewsPanel");
newsPanel.innerHTML = `${getWheelImage()} Загрузка списка новостей...`;
GM.xmlHttpRequest({method: "GET", url: "https://daily.heroeswm.ru/news4script.txt?" + Date.now(), headers: {
'User-agent': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1)',
'Accept': 'text/xml,text/html',
'Content-Type': 'text/plain; charset=windows-1251'
},
synchronous: false,
overrideMimeType: 'text/plain; charset=windows-1251',
onload: function(response) {
try {
const dailyUrlRegExp = /\/\/daily\.heroeswm\.ru\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*$/i;
const previousMessageIds = GM_getValue("PreviousDailyMessageIds", "").split("|");
const messages = JSON.parse('[["' + response.responseText.replace(/"/g, "\\\"").replace(/\n/g, '"],["').replace(/;;/g, '","').replace(/'/g, "'") + '"]]').filter(x => x.length == 6).map(x => { return {
Code: x[0],
ImageUrl: x[1],
Title: trimming(x[2], 255),
Url: x[3],
Id: x[4],
CommentsAmount: x[5],
IsHot: !previousMessageIds.includes(x[4])
};}).filter(x => dailyUrlRegExp.test(x.ImageUrl) && dailyUrlRegExp.test(x.Url) && /^[1-3]$/.test(x.Code));
GM_setValue("PreviousDailyMessageIds", messages.map(x => x.Id).join("|"));
//console.log(messages);
let newsText = "";
for(const message of messages) {
newsText += `
<div class='text-title'>
<a class='hover-link' style='text-decoration: none;${message.IsHot ? 'font-weight: bold; color:red' : ''}' target='_blank' href='${message.Url}'>${message.IsHot ? "⚡" : "•"} ${message.Title}</a>
<div style='display: inline-flex; background-color: #adadad40; padding: 3px 7px; margin-left: 7px; border: 0; border-radius: 4px; color: #592C08;'>
<span title='комментариев' style='font-size:9px'>${message.CommentsAmount}</span>
</div>
</div>`;
}
newsPanel.innerHTML = newsText;
} catch(e) {
newsPanel.innerHTML = `Ошибка при обработке данных: ${e}`;
}
},
onerror: function(response) { newsPanel.innerHTML = "Ошибка при получении данных с Daily"; }
});
}
function GM_addStyle(css) { addElement("style", document.head, { type: "text/css", innerHTML: css }); }
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 getWheelImage() { return '<img border="0" align="absmiddle" height="11" src="https://dcdn.heroeswm.ru/css/loading.gif">'; }
function getUrlParamValue(url, paramName) { return (new URLSearchParams(url.split("?")[1])).get(paramName); }
function groupBy(list, key) { return list.reduce(function(rv, item) { (rv[item[key]] = rv[item[key]] || []).push(item); return rv; }, {}); };
function getSertIdByLocationNumber(locationNumber) { return "sec_" + (locationNumber.toString()).padStart(2, "0"); }
function getSertIdByLocationName(locationName) {
const locationNumber = Object.keys(locations).find(x => locations[x][2] == locationName);
return getSertIdByLocationNumber(locationNumber);
}
function getHouseIdByLocationNumber(locationNumber) { return "dom_" + (locationNumber.toString()).padStart(2, "0"); }
function getHouseIdByLocationName(locationName) {
const locationNumber = Object.keys(locations).find(x => locations[x][2] == locationName);
return getHouseIdByLocationNumber(locationNumber);
}
function getRequest(url) {
return new Promise((resolve, reject) => {
GM.xmlHttpRequest({ method: "GET", url: url, overrideMimeType: "text/html; charset=windows-1251",
onload: function(response) { resolve((new DOMParser).parseFromString(response.responseText, "text/html")); },
onerror: function(error) { reject(error); }
});
});
}
function gmGetBool(valueName, defaultValue = false) {
const value = GM_getValue(valueName);
if(value) {
if(typeof(value) == "string") {
return value == "true";
}
if(typeof(value) == "boolean") {
return value;
}
}
return defaultValue;
}
function parseDate(dateString, isFuture = false, isPast = false) {
//console.log(dateString)
if(!dateString) {
return;
}
const dateStrings = dateString.split(" ");
let hours = 0;
let minutes = 0;
let seconds = 0;
const timePart = dateStrings.find(x => x.includes(":"));
if(timePart) {
var time = timePart.split(":");
hours = parseInt(time[0]);
minutes = parseInt(time[1]);
if(time.length > 2) {
seconds = parseInt(time[2]);
}
}
const now = new Date();
let year = now.getFullYear();
let month = now.getMonth();
let day = now.getDate();
const datePart = dateStrings.find(x => x.includes("-"));
if(datePart) {
const date = datePart.split("-");
month = parseInt(date[isEn ? (date.length == 3 ? 1 : 0) : 1]) - 1;
day = parseInt(date[isEn ? (date.length == 3 ? 2 : 1) : 0]);
if(date.length == 3) {
year = isEn ? parseInt(date[0]) : parseInt(date[2]);
if(year < 1000) {
year += Math.floor((new Date()).getFullYear() / 1000) * 1000;
}
} else {
if(isFuture && month == 0 && now.getMonth() == 11) {
year += 1;
}
}
}
if(dateStrings.length > 2) {
const letterDateExec = /(\d{2}):(\d{2}) (\d{2}) (.{3,4})/.exec(dateString);
if(letterDateExec) {
//console.log(letterDateExec)
day = parseInt(letterDateExec[3]);
//const monthNames = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'];
const monthShortNames = ['янв', 'фев', 'март', 'апр', 'май', 'июнь', 'июль', 'авг', 'сент', 'окт', 'ноя', 'дек'];
month = monthShortNames.findIndex(x => x.toLowerCase() == letterDateExec[4].toLowerCase());
if(isPast && (new Date(year, month, day, hours, minutes, seconds)).getTime() > Date.now()) {
year -= 1;
}
}
}
//console.log(`year: ${year}, month: ${month}, day: ${day}, time[0]: ${time[0]}, time[1]: ${time[1]}, ${new Date(year, month, day, parseInt(time[0]), parseInt(time[1]))}`);
return new Date(year, month, day, hours, minutes, seconds);
}
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;
}
}
}
}