hwmTime

Время с секундами

目前為 2023-12-18 提交的版本,檢視 最新版本

// ==UserScript==
// @name           hwmTime
// @author         Tamozhnya1
// @namespace      Tamozhnya1
// @description    Время с секундами
// @version        5.2
// @include        *heroeswm.ru/*
// @include        *lordswm.com/*
// @exclude        */rightcol.php*
// @exclude        */ch_box.php*
// @exclude        */chat*
// @exclude        */ticker.html*
// @exclude        */frames*
// @exclude        */brd.php*
// @grant          GM_deleteValue
// @grant          GM_getValue
// @grant          GM_setValue
// @grant 		   GM.xmlHttpRequest
// @license        MIT
// ==/UserScript==

this.GM_getValue = this.GM_getValue || function(key, def) { return localStorage[key] || def; };
this.GM_setValue = this.GM_setValue || function(key, value) { localStorage[key] = value; };
this.GM_deleteValue = this.GM_deleteValue || function(key) { return delete localStorage[key]; };
let timePanel;
let online;

main();
function main() {
    const timePanelData = findTimePanel();
    if(!timePanelData) {
        return;
    }
    timePanel = timePanelData.TimePanel;
    online = timePanelData.Online;
    timePanel.addEventListener("click", showSettings);
    validateSavedInterval(timePanelData.PageEnterHours, timePanelData.PageEnterMinutes);
    bindTimePanel();
    requestServerTime();
}
function validateSavedInterval(pageEnterHours, pageEnterMinutes) {
    if(!GM_getValue("ClientServerTimeDifference")) {
        GM_deleteValue("LastClientServerTimeDifferenceRequestDate");
    }
    let badServerTimeApproximation = !validateEstimatedTimeByPageEnterTime(pageEnterHours, pageEnterMinutes);
    if(badServerTimeApproximation) {
        const nowDate = new Date();
        GM_setValue("ClientServerTimeDifference", nowDate.getTime() - new Date(nowDate.getFullYear(), nowDate.getMonth(), nowDate.getDate(), pageEnterHours, pageEnterMinutes).getTime());
        GM_deleteValue("LastClientServerTimeDifferenceRequestDate");
    }
}
function findTimePanel() {
    const isNewInterface = document.querySelector("div.mm_item") ? true : false;
    if(isNewInterface) {
        const timeTemplate = /(\d+):(\d+)(:\d{2})?/;
        let div1 = document.querySelector("div.sh_extra.sh_extra_right");
        let divs = div1.querySelectorAll("div");
        for(const div of divs) {
            if(/\d+:\d+(:\d{2})?/.test(div.innerHTML)) {
                let timeText = timeTemplate.exec(div.innerText);
                console.log([div.innerHTML, div.innerText, timeText]);
                let pageEnterHours = parseInt(timeText[1]);
                let pageEnterMinutes = parseInt(timeText[2]);
                return { TimePanel: div, PageEnterHours: pageEnterHours, PageEnterMinutes: pageEnterMinutes, Online: "" };
            }
        }
    } else {
        const timeContainer = getParent(document.querySelector("td > a[href='https://gvdplayer.com/player.html']"), "td");
        if(timeContainer) {
            online = (/([^,]*)(, \d+ online.*)/.exec(timeContainer.innerHTML))[2];
            const timeText = /(\d+):(\d+)(:\d{2})?, \d+ online/.exec(timeContainer.firstChild.textContent);
            const pageEnterHours = parseInt(timeText[1]);
            const pageEnterMinutes = parseInt(timeText[2]);
            return { TimePanel: timeContainer, PageEnterHours: pageEnterHours, PageEnterMinutes: pageEnterMinutes, Online: online };
        }
        // 
        // for(const currentCell of document.getElementsByTagName('td')) {
            // if(currentCell.innerHTML.indexOf("<td") != -1 || currentCell.innerHTML.search(timeAndOnlineTemplate) == -1) {
                // continue;
            // }
            // online = (/([^,]*)(, \d+ online.*)/.exec(currentCell.innerHTML))[2];
            // let timeText = timeAndOnlineTemplate.exec(currentCell.innerHTML);
            // let pageEnterHours = parseInt(timeText[1]);
            // let pageEnterMinutes = parseInt(timeText[2]);
            // return { TimePanel: currentCell, PageEnterHours: pageEnterHours, PageEnterMinutes: pageEnterMinutes, Online: online };
        // }
    }
    const timeAndOnlineTemplate = /(\d+):(\d+)(:\d{2})?, \d+ online/;
    for(const currentCell of document.querySelectorAll('span')) {
        if(currentCell.innerHTML.indexOf("<span") != -1 || currentCell.innerHTML.search(timeAndOnlineTemplate) == -1) {
            continue;
        }
        online = (/([^,]*)(, \d+ online.*)/.exec(currentCell.innerHTML))[2];
        let timeText = timeAndOnlineTemplate.exec(currentCell.innerHTML);
        let pageEnterHours = parseInt(timeText[1]);
        let pageEnterMinutes = parseInt(timeText[2]);
        return { TimePanel: currentCell, PageEnterHours: pageEnterHours, PageEnterMinutes: pageEnterMinutes, Online: online };
    }
}
function validateEstimatedTimeByPageEnterTime(pageEnterHours, pageEnterMinutes) {
    const serverDate = getServerDate();
    if(serverDate.getHours() == pageEnterHours && serverDate.getMinutes() == pageEnterMinutes) {
        return true; // Правильным результатом считаем точное совпадение часов и минут, с учетом того, что нам нужна точность до милисекунды
    }
    return false;
}
async function requestServerTime() {
    if(parseInt(GM_getValue("LastClientServerTimeDifferenceRequestDate", 0)) + 60 * 60 * 1000 < Date.now()) {
        GM_setValue("LastClientServerTimeDifferenceRequestDate", Date.now());
        const responseText = await getRequestText("/time.php");
        const responseParcing = /now (\d+)/.exec(responseText); //responseText: now 1681711364 17-04-23 09:02
        if(responseParcing) {
            GM_setValue("ClientServerTimeDifference", Date.now() - (parseInt(responseParcing[1]) * 1000 + parseInt(GM_getValue("hwmTimeAddingIntervalMilliseconds", 0))));
        }
    } else {
        setTimeout(requestServerTime, 60 * 60 * 1000);
    }
}
function bindTimePanel() {
    const serverDate = getServerDate();
    timePanel.innerHTML = serverDate.getHours() + ':' + ( (serverDate.getMinutes() < 10) ? '0' : '' ) + serverDate.getMinutes() + ':' + (serverDate.getSeconds() < 10 ? '0' : '') + serverDate.getSeconds() + online;
    setTimeout(bindTimePanel, 1000);
}
function getServerDate() { return new Date(getServerTime()); }
function getServerTime() { return Date.now() - parseInt(GM_getValue("ClientServerTimeDifference", 0)); }
function showSettings() {
    if(showPupupPanel(GM_info.script.name)) {
       return; 
    }
    const fieldsMap = [];
    const isEn = document.documentElement.lang == "en";
    fieldsMap.push(["ClientServerLastRequestedTimeDifferenceMilliseconds:", `${parseInt(GM_getValue("ClientServerTimeDifference", 0))}`]);
    fieldsMap.push(["LastClientServerSyncDate:", `${new Date(parseInt(GM_getValue("LastClientServerTimeDifferenceRequestDate", 0))).toLocaleString()}`]);
    
    const hwmTimeAddingIntervalInput = createElement("input", { id: "hwmTimeAddingIntervalInput", type: "number", value: `${ GM_getValue("hwmTimeAddingIntervalMilliseconds", 0) }`, onfocus: `this.select();` });
    hwmTimeAddingIntervalInput.addEventListener("change", function() { GM_setValue("hwmTimeAddingIntervalMilliseconds", parseInt(this.value)); }, false);
    
    fieldsMap.push([`${isEn ? 'Add time to page loading (ms.)' : "Добавлять время на загрузку страницы (мс.)"}`, hwmTimeAddingIntervalInput]);

    const hwmTimeRestartScriptSubmit = createElement("input", { id: "hwmTimeRestartScriptSubmit", type: "submit", value: `${isEn ? 'Restart the script' : "Перезапустить скрипт"}` });
    hwmTimeRestartScriptSubmit.addEventListener("click", reset, false);
    fieldsMap.push([hwmTimeRestartScriptSubmit]);
    
    createPupupPanel(GM_info.script.name, "Настройки " + GM_info.script.name, fieldsMap);
}
function reset() {
    GM_deleteValue("ClientServerTimeDifference");
    GM_deleteValue("LastClientServerTimeDifferenceRequestDate");
    hidePupupPanel(GM_info.script.name);
    main();
}
function createPupupPanel(panelName, panelTitle, fieldsMap) {
    let backgroundPopupPanel = addElement("div", document.body, { id: panelName + "1", style: "position: absolute; left: 0pt; width: 100%; background: none repeat scroll 0% 0% gray; opacity: 0.5; top: 0px; height: 100%; display: block; z-index: 200;" });
    backgroundPopupPanel.addEventListener("click", function() { hidePupupPanel(panelName); }, false);
 
    let popupPanel = addElement("div", document.body, { id: panelName + "2", style: `position: absolute; width: 650px; background: none repeat scroll 0% 0%; background-image: linear-gradient(to right, #eea2a2 0%, #bbc1bf 19%, #57c6e1 42%, #b49fda 79%, #7ac5d8 100%); left: ${((document.body.offsetWidth - 650) / 2)}px; top: 150px; display: block; z-index: 200; border: 4mm ridge rgba(211, 220, 50, .6);` });
    let contentDiv = addElement("div", popupPanel, { id: panelName + "3", style: "border: 1px solid #abc; padding: 5px; margin: 2px; display: flex; flex-wrap: wrap;" });
    
    if(panelTitle) {
        addElement("b", contentDiv, { innerText: panelTitle, style: "text-align: center; margin: auto; width: 90%; display: block;" });
    }
    let divClose = addElement("div", contentDiv, {id: panelName + "close", title: "Close", innerText: "x", style: "border: 1px solid #abc; width: 15px; height: 15px; text-align: center; cursor: pointer;" });
    divClose.addEventListener("click", function() { hidePupupPanel(panelName); }, false);
    
    addElement("div", contentDiv, { style: "flex-basis: 100%; height: 0;"});
    
    if(fieldsMap) {
        let contentTable = addElement("table", contentDiv);
        for(let rowData of fieldsMap) {
            if(rowData.length == 0) { // Спомощью передачи пустой стороки-массива, указываем, что надо начать новую таблицу после брейка
                addElement("div", contentDiv, { style: "flex-basis: 100%; height: 0;"});
                contentTable = addElement("table", contentDiv);
                continue;
            }
            const row = addElement("tr", contentTable);
            for(let cellData of rowData) {
                const cell = addElement("td", row);
                if(cellData) {
                    if(typeof(cellData) == "string") {
                        cell.innerText = cellData;
                    } else {
                        cell.appendChild(cellData);    
                    }
                }
            }
        }
    }
    return contentDiv;
}
function showPupupPanel(panelName) {
    let backgroundPopupPanel = document.getElementById(panelName + "1");
    let popupPanel = document.getElementById(panelName + "2");
    if(backgroundPopupPanel) {
        backgroundPopupPanel.style.display = popupPanel.style.display = 'block';
        return true;
    }
    return false;
}
function hidePupupPanel(panelName) {
    let backgroundPopupPanel = document.getElementById(panelName + "1");
    let popupPanel = document.getElementById(panelName + "2");
    backgroundPopupPanel.style.display = popupPanel.style.display = 'none';
}
function addElement(type, parent, data) {
    let el = createElement(type, data);
    if(parent) {
        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 getRequestText(url, overrideMimeType = "text/html; charset=windows-1251") {
    return new Promise((resolve, reject) => {
        GM.xmlHttpRequest({ method: "GET", url: url, overrideMimeType: overrideMimeType,
            onload: function(response) { resolve(response.responseText); },
            onerror: function(error) { reject(error); }
        });
    });
}
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;
            }
        }
    }
}