[HWM] SmithsGuildOnHome

Информация о гильдии кузнецов/оружейников на странице персонажа.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         [HWM] SmithsGuildOnHome
// @namespace    [HWM] SmithsGuildOnHome
// @version      0.4.0
// @description  Информация о гильдии кузнецов/оружейников на странице персонажа.
// @author       Komdosh
// @include      http*://*.heroeswm.ru/*
// @grant        none
// @license      MIT
// ==/UserScript==


const SMITHS_GUILD_SETTINGS = 'SMITHS_GUILD_SETTINGS';
const SMITHS_GUILD_PARALLEL_WORK = 'SMITHS_GUILD_PARALLEL_WORK';
const SMITHS_GUILD_INFO_FIRST = 'SMITHS_GUILD_INFO_V4_1';
const SMITHS_GUILD_INFO_SECOND = 'SMITHS_GUILD_INFO_V4_2';

const SMITHS_GUILD_NOTIFICATION_IS_SHOWN = 'SMITHS_GUILD_NOTIFICATION_IS_SHOWN_V2';

const SMITH_FREE = '\u041A\u0443\u0437\u043D\u0438\u0446\u0430 \u0441\u0432\u043E\u0431\u043E\u0434\u043D\u0430!'; // Кузница свободна

if (!/home.php/.test(location.href)) {
    initNotificationsOnNonHome();
    return;
}

const smithsLevel = level("https://dcdn.heroeswm.ru/i/pl_info/icons/guild_blacksmiths.png");
const modLevel = level("https://dcdn.heroeswm.ru/i/pl_info/icons/guild_armourers.png");

const parallelWork = smithsLevel == 9 || modLevel == 5;
localStorage.setItem(SMITHS_GUILD_PARALLEL_WORK, parallelWork);

const smithGuildInfoContentDiv = createSmithsInfoDOM();

let finishScript = false;
let savedGuildInfo = getWithExpiry(SMITHS_GUILD_INFO_FIRST);
if (savedGuildInfo != null) {
    displaySmithsGuildInfo(savedGuildInfo.workedOnText, savedGuildInfo.timeToFinishText, savedGuildInfo.finishTimeValues);
    if (!parallelWork) {
        return;
    }
    finishScript = true;
} else {
    localStorage.removeItem(SMITHS_GUILD_INFO_SECOND);
}

savedGuildInfo = getWithExpiry(SMITHS_GUILD_INFO_SECOND);
if (savedGuildInfo != null) {
    smithGuildInfoContentDiv.append(document.createElement('hr'));

    displaySmithsGuildInfo(savedGuildInfo.workedOnText, savedGuildInfo.timeToFinishText, savedGuildInfo.finishTimeValues);
    finishScript = true;
} else {
    localStorage.removeItem(SMITHS_GUILD_INFO_FIRST);
}

if (finishScript) {
    return;
}

requestSmithInfo();


//***************************************************************************
function createSmithsInfoDOM() {
    const smithGuildInfoDiv = document.createElement('div');
    smithGuildInfoDiv.className += "home_container_block";
    smithGuildInfoDiv.style = "align-items: left;"

    const smithGuildInfoHeader = document.createElement('div');
    smithGuildInfoHeader.className += "global_container_block_header global_a_hover";

    smithGuildInfoHeader.innerHTML = '<a href="/mod_workbench.php"">\u0413\u0438\u043B\u044C\u0434\u0438\u044F \u041A\u0443\u0437\u043D\u0435\u0446\u043E\u0432</a>'; //Гильдия Кузнецов
    smithGuildInfoDiv.append(smithGuildInfoHeader);

    const notifyMeLink = document.createElement('a');
    notifyMeLink.style = 'cursor: pointer';
    notifyMeLink.id = 'smithGuildNotifier';
    smithGuildInfoHeader.append(notifyMeLink);

    const smithGuildInfoContentDiv = document.createElement('div');
    smithGuildInfoContentDiv.className += "home_inside_margins global_a_hover";
    smithGuildInfoDiv.append(smithGuildInfoContentDiv);

    const workerGuild = document.querySelector(".home_work_block");

    workerGuild.after(smithGuildInfoDiv);

    return smithGuildInfoContentDiv;
}

//***************************************************************************
function requestSmithInfo() {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', encodeURI("/mod_workbench.php"));
    xhr.overrideMimeType('text/xml; charset=windows-1251');
    xhr.onload = function () {
        if (xhr.status === 200) {
            const div = document.createElement('div');
            div.id = 'kom-smiths';
            div.style.display = 'none';
            div.innerHTML = xhr.responseText;
            document.getElementsByTagName('body')[0].appendChild(div);
            const respDoc = document.getElementsByTagName('body')[0].lastChild;
            if (!/\u0418\u0434\u0435\u0442 \u0440\u0430\u0431\u043E\u0442\u0430 \u043D\u0430\u0434/.test(respDoc.innerText)) { //Идёт работа над
                const noWorkSpan = document.createElement('span');
                noWorkSpan.innerHTML += SMITH_FREE;
                smithGuildInfoContentDiv.append(noWorkSpan);
                return;
            }

            const documentSmithTables = Array.from(respDoc.querySelectorAll("table[align=center]"));
            const smithTable = documentSmithTables[documentSmithTables.length - 1];
            const {
                workedOnText,
                finishTimeValues,
                expiration
            } = saveSmithsTable(smithTable, SMITHS_GUILD_INFO_FIRST);

            displaySmithsGuildInfo(workedOnText, expiration, finishTimeValues);

            if(parallelWork){
                const anotherSmithTable = documentSmithTables[documentSmithTables.length - 2]

                if (anotherSmithTable.querySelector("td[colspan]").innerText.trim() !== '') {
                    const {
                        workedOnText,
                        finishTimeValues,
                        expiration
                    } = saveSmithsTable(anotherSmithTable, SMITHS_GUILD_INFO_SECOND);
                    smithGuildInfoContentDiv.append(document.createElement('hr'));
                    displaySmithsGuildInfo(workedOnText, expiration, finishTimeValues);
                }
            }
            respDoc.remove();
        } else {
            console.log('Request failed.  Returned status of ' + xhr.status);
        }
    };
    xhr.send();
}

//***************************************************************************
function displaySmithsGuildInfo(workedOnText, timeToFinishText, finishTimeValues) {
    const notifyMeLink = document.querySelector("#smithGuildNotifier");
    let notificationCancellation = null;
    let isNotify = localStorage.getItem(SMITHS_GUILD_SETTINGS, 'false') == 'true';

    notificationCancellation = createCancellableNotificationWithLink(isNotify, notificationCancellation, notifyMeLink, timeToFinishText - Date.now());
    notifyMeLink.onclick = () => {
        isNotify = !isNotify;
        notificationCancellation = createCancellableNotificationWithLink(isNotify, notificationCancellation, notifyMeLink, timeToFinishText - Date.now());
        localStorage.setItem(SMITHS_GUILD_SETTINGS, isNotify);
    };

    const workedOnSpan = document.createElement('span');
    workedOnSpan.innerText = workedOnText;
    smithGuildInfoContentDiv.append(workedOnSpan);

    smithGuildInfoContentDiv.append(document.createElement('br'));

    const timeToFinishSpan = document.createElement('span');

    timeToFinishSpan.innerHTML = '\u0412 \u0440\u0435\u043C\u043E\u043D\u0442\u0435: \u0435\u0449\u0435 ' + formatFinishedTime(timeToFinishText); // В ремонте ещё
    smithGuildInfoContentDiv.append(timeToFinishSpan);

    smithGuildInfoContentDiv.append(document.createElement('br'));

    const finishTimeSpan = document.createElement('span');
    const finishTimeText = finishTimeValues[0];
    const finishDateTimeText = finishTimeValues[1];
    finishTimeSpan.innerHTML = finishTimeText + ': <a href="/mod_workbench.php" style="text-decoration:underline;">' + finishDateTimeText + '</a>';

    smithGuildInfoContentDiv.append(finishTimeSpan);
}

//***************************************************************************
function saveSmithsTable(smithTable, smithGuildInfoName) {
    const workedOnText = smithTable.querySelector("td[colspan]").innerText.trim();
    const finishTimeValues = smithTable.querySelector("td>table").querySelector("td").innerText.split(': ');

    const expiration = parseGuildDateTime(finishTimeValues[1]).getTime() + 1000 * 60;
    localStorage.setItem(SMITHS_GUILD_NOTIFICATION_IS_SHOWN, 'false');
    setWithExpiry(smithGuildInfoName, {
        workedOnText: workedOnText,
        timeToFinishText: expiration,
        finishTimeValues: finishTimeValues,
    }, expiration);
    return {workedOnText, finishTimeValues, expiration};
}

//***************************************************************************
function formatFinishedTime(finishTime) {
    const diff = finishTime - Date.now();
    const diffDays = Math.floor(diff / 86400000); // days
    const diffHrs = Math.floor((diff % 86400000) / 3600000); // hours
    const diffMins = Math.round(((diff % 86400000) % 3600000) / 60000); // minutes

    let dateString = '';
    if (diffDays > 0) {
        dateString += diffDays + ' \u0434. ';
    }
    if (diffHrs > 0) {
        dateString += diffHrs + ' \u0447. ';
    }
    if (diffMins > 0) {
        dateString += diffMins + ' \u043C\u0438\u043D.';
    }

    if(dateString == ''){
        const diffSecs = Math.round((((diff % 86400000) % 3600000) % 60000)/1000); // seconds
        dateString += diffSecs + ' \u0441\u0435\u043a.';
    }

    return dateString;
}

//***************************************************************************
function parseGuildDateTime(dateString) {
    dateString = dateString.split(' ');
    const datef = dateString[0].split('-');
    const date = new Date(datef[1] + '-' + datef[0] + '-' + (new Date().getFullYear()));
    const time = dateString[1].split(':');
    date.setHours(time[0], time[1], 0);
    return date;
}

//***************************************************************************
function setWithExpiry(key, value, expirationTime) {
    const item = {
        value: value,
        expiry: expirationTime,
    }
    localStorage.setItem(key, JSON.stringify(item))
}

//***************************************************************************
function getWithExpiry(key) {
    const itemStr = localStorage.getItem(key);
    // if the item doesn't exist, return null
    if (!itemStr) {
        return null
    }
    const item = JSON.parse(itemStr);
    const now = new Date();
    // compare the expiry time of the item with the current time
    if (now.getTime() > item.expiry) {
        // If the item is expired, delete the item from storage
        // and return null
        localStorage.removeItem(key);
        return null
    }
    return item.value
}

//***************************************************************************
function createCancellableNotificationWithLink(isNotify, notificationCancellation, notifyMeLink, delay) {
    if (isNotify) {
        notifyMeLink.innerHTML = '&nbsp(!)';
        notifyMeLink.title = 'Уведомление об окончании работ: включено';
    } else {
        notifyMeLink.innerHTML = '&nbsp(#)';
        notifyMeLink.title = 'Уведомление об окончании работ: выключено';
    }

    return createCancellableNotification(isNotify, notificationCancellation, delay);
}

function createCancellableNotification(isNotify, notificationCancellation, delay) {
    if (localStorage.getItem(SMITHS_GUILD_NOTIFICATION_IS_SHOWN) == 'true') {
        return null;
    }
    if (isNotify) {
        notificationCancellation = notifyAfter(delay, SMITH_FREE);
    } else {
        if (notificationCancellation != null) {
            clearTimeout(notificationCancellation);
        }
    }
    return notificationCancellation;
}

//***************************************************************************
function notifyAfter(delay, text) {
    let notify = alert;
    let cancellation = null;

    cancellation = setTimeout(() => {
        localStorage.setItem(SMITHS_GUILD_NOTIFICATION_IS_SHOWN, 'true');
        notify(text)
    }, delay > 0 ? delay : 1000);

    Notification.requestPermission((permission) => {
        if (permission === 'granted') {
            notify = (text) => new Notification(text);
        }
    });

    return cancellation;
}

//***************************************************************************
function level(link) {
    const levelText = document.body.querySelector('img[src="' + link + '"]').parentElement.parentElement.querySelector('#bartext').innerText;

    return parseInt(levelText);
}

//***************************************************************************
function initNotificationsOnNonHome() {
    const isNotify = localStorage.getItem(SMITHS_GUILD_SETTINGS, 'false') == 'true';
    const parallelWork = localStorage.getItem(SMITHS_GUILD_PARALLEL_WORK, 'false') == 'true';


    const savedGuildInfoFirst = getWithExpiry(SMITHS_GUILD_INFO_FIRST);
    if (savedGuildInfoFirst == null) {
        return;
    }
    createCancellableNotification(isNotify, null, savedGuildInfoFirst.timeToFinishText - Date.now());

    if (!parallelWork) {
        return;
    }

    const savedGuildInfoSecond = getWithExpiry(SMITHS_GUILD_INFO_SECOND);
    if (savedGuildInfoSecond == null) {
        return;
    }
    createCancellableNotification(isNotify, null, savedGuildInfoSecond.timeToFinishText - Date.now());

    return;
}