[HWM] GuildTimersOnMain

Таймеры для гильдии охотников, наёмников, воров и лидеров

2022-01-24 기준 버전입니다. 최신 버전을 확인하세요.

// ==UserScript==
// @name         [HWM] GuildTimersOnMain
// @namespace    [HWM] GuildTimersOnMain
// @version      0.2.8
// @description  Таймеры для гильдии охотников, наёмников, воров и лидеров
// @author       Komdosh
// @include      http*://*.heroeswm.ru/home.php*
// @include      http*://*.heroeswm.ru/map.php*
// @include      http*://*.heroeswm.ru/mercenary_guild.php*
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
  'use strict';
  const GUILDS_INFO_MERCENARY = 'GUILDS_INFO_MERCENARY';
  const GUILDS_INFO_HUNTER = 'GUILDS_INFO_HUNTER';
  const GUILDS_INFO_LEADER = 'GUILDS_INFO_LEADER';
  const GUILDS_INFO_THIEF = 'GUILDS_INFO_THIEF';

  if (/map.php/.test(location.href)) {
    const hunterInfo = getWithExpiry(GUILDS_INFO_HUNTER);
    if (hunterInfo != null && hunterInfo === '-1') {
      localStorage.removeItem(GUILDS_INFO_HUNTER);
    }
    const thiefInfo = getWithExpiry(GUILDS_INFO_THIEF);
    if (thiefInfo != null && thiefInfo === '-1') {
      localStorage.removeItem(GUILDS_INFO_THIEF);
    }
    return;
  } else if (/mercenary_guild.php/.test(location.href)) {
    const mercenaryInfo = getWithExpiry(GUILDS_INFO_MERCENARY);
    if (mercenaryInfo != null && mercenaryInfo === '-1') {
      localStorage.removeItem(GUILDS_INFO_MERCENARY);
    }
    return;
  } else if (/leader_guild.php/.test(location.href)) {
    const leaderInfo = getWithExpiry(GUILDS_INFO_LEADER);
    if (leaderInfo != null && leaderInfo === '-1') {
      localStorage.removeItem(GUILDS_INFO_LEADER);
    }
    return;
  }

  const isThiefsAvailable = parseInt(Array.from(document.querySelectorAll('.home_guild_text'))
    .find(el => el.innerText === 'Воров').parentElement.querySelector('.home_text_exp').innerText) > 0;

  const userInfo = getUserInfo();

  const guildsInfoDiv = document.createElement('div');
  guildsInfoDiv.className += "home_container_block";
  guildsInfoDiv.style = "align-items: left;";

  const guildsInfoHeader = document.createElement('div');
  guildsInfoHeader.className += "global_container_block_header global_a_hover";
  guildsInfoHeader.innerHTML = 'Таймеры';
  guildsInfoDiv.append(guildsInfoHeader);

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

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

  workerGuild.before(guildsInfoDiv);

  const loading = document.createElement('span');
  loading.innerText = 'Данные обновляются...';
  guildsInfoContentDiv.append(loading);

  requestHunterInfo();
  requestMercenaryInfo();
  if (isThiefsAvailable) {
    requestThiefInfo(userInfo.id);
  }
  requestLeadersInfo();

//***************************************************************************
  function requestLeadersInfo() {
    request('leader', 'Новое задание через ', "/leader_guild.php",
      GUILDS_INFO_LEADER,
      'ГЛ',
      '<a href="leader_guild.php" style="text-decoration:underline">Все противники найдены</a>',
      'Требуется лидер',
      (respDoc, timerDiv) => {
        const nextTime = respDoc.querySelector('#next_lg');
        if(nextTime == null){
            return 0;
        }
        const script = nextTime.parentElement.getElementsByTagName('script')[0];

        const scriptDeltaText = script.text.match(/Delta2 = (\d+)/);

        if (scriptDeltaText == null) {
          return 0;
        } else {
          return parseInt(scriptDeltaText[1]);
        }
      });
  }

//***************************************************************************
  function requestHunterInfo() {
    request('hunter', 'Охота будет доступна через ', "/map.php",
      GUILDS_INFO_HUNTER,
      'ГО',
      '<a href="map.php" style="text-decoration:underline">Новая охота</a>',
      'Охотники зовут на помощь',
      (respDoc, timerDiv) => {
        const script = document.querySelector('#map_right_block_inside').getElementsByTagName('script')[0];

        const scriptDeltaText = script.text.match(/Delta2 = (\d+)/);

        if (scriptDeltaText == null) {
          return 0;
        } else {
          return parseInt(scriptDeltaText[1]);
        }
      });
  }

//***************************************************************************
  function requestMercenaryInfo() {
    request('mercenary', 'Новое задание через ', "/mercenary_guild.php", GUILDS_INFO_MERCENARY,
      'ГН',
      '<a href="mercenary_guild.php" style="text-decoration:underline">Новое задание</a>',
      'Наёмникам требуется герой!',
      (respDoc, timerDiv) => {
        const taskMessageDiv = respDoc.querySelector('table:not([align="center"])').querySelector('table:not([align="center"], [class="wbwhite"])');

        if (taskMessageDiv == null) {
          return 0;
        } else {
          const taskMessage = taskMessageDiv.querySelector('td').innerText;
          return parseInt(taskMessage.split('\u0447\u0435\u0440\u0435\u0437 ')[1].split(' ')[0]) * 60;
        }
      });
  }

//***************************************************************************
  function requestThiefInfo(userId) {
    request('thief', 'Новое задание через ', `/pl_warlog.php?id=${userId}`, GUILDS_INFO_THIEF,
      'ГВ',
      '<a href="map.php" style="text-decoration:underline">Новое задание</a>',
      'Воры замышляют новое нападение!',
      (respDoc, timerDiv) => {
        const battles = respDoc.querySelector('div[class="global_a_hover"]').innerHTML.split('br');

        let nextTime = 1000 * 60 * 60;
        if (isPremium()) {
          nextTime *= 0.7;
        }
        for (const battle of battles) {
          if (/\u041A\u0430\u0440\u0430\u0432\u0430\u043D/.test(battle)) { // Караван
            if (/<b>\u041A\u0430\u0440\u0430\u0432\u0430\u043D/.test(battle)) {
              let battleDate = battles[0].split('>')[1].split('<')[0];
              const battleDateSplit = battleDate.split('-');
              battleDate = battleDateSplit[1] + '-' + battleDateSplit[0] + '-' + battleDateSplit[2];
              const thiefDateTime = new Date(battleDate);

              return Math.floor(((thiefDateTime.getTime() + nextTime) - Date.now()) / 1000);
            } else {
              return 0;
            }
          }
        }
        return 0;
      });
  }

  function request(domId, taskHtml, link, localStorageName, notifyMeLinkName, newTaskInstantlyDom, notifyText, processor) {
    const timerDiv = document.createElement('div');
    timerDiv.id = domId;
    guildsInfoContentDiv.append(timerDiv);

    const expiration = getWithExpiry(localStorageName);

    const notifyMeLink = document.createElement('a');
    notifyMeLink.style = 'cursor: pointer';

    let isNotify = localStorage.getItem(`${localStorageName}_SETTINGS`) === 'true';

    notifyMeLink.innerHTML = isNotify ? `<b>${notifyMeLinkName}</b>: ` : `${notifyMeLinkName}: `;

    notifyMeLink.onclick = () => {
      isNotify = !isNotify;

      toggleNotification(isNotify,
        notifyMeLink,
        notifyMeLinkName);

      localStorage.setItem(`${localStorageName}_SETTINGS`, isNotify);
    };

    const wrapper = document.createElement('span');
    wrapper.append(notifyMeLink);

    if (expiration != null) {
      if (loading != null) {
        loading.remove();
      }

      if (expiration === '-1') {
        timerDiv.append(createElementFromTextAndAppend(wrapper, newTaskInstantlyDom));
        return;
      }

      toggleNotification(isNotify,
        notifyMeLink,
        notifyMeLinkName);

      const delay = Math.floor((expiration - Date.now()) / 1000);
      initTimer(delay, timerDiv, createElementFromTextAndAppend(wrapper, taskHtml), () => {
        timerFinished(isNotify, notifyText, timerDiv, createElementFromTextAndAppend(wrapper, newTaskInstantlyDom));
      });
      return;
    }
    const xhr = new XMLHttpRequest();
    xhr.open('GET', encodeURI(link));
    xhr.overrideMimeType('text/xml; charset=windows-1251');
    xhr.onload = function () {
      if (xhr.status === 200) {
        const div = document.createElement('div');
        div.id = 'kom-' + domId;
        div.style.display = 'none';
        div.innerHTML = xhr.responseText;
        document.getElementsByTagName('body')[0].appendChild(div);
        const respDoc = document.getElementById('kom-' + domId);
        if (loading != null) {
          loading.remove();
        }
        const delta = processor(respDoc, timerDiv);
        if (delta > 0) {
          const expiration = Date.now() + delta * 1000;

          setWithExpiry(localStorageName, expiration, expiration);

          toggleNotification(isNotify,
            notifyMeLink,
            notifyMeLinkName);

          initTimer(delta, timerDiv, createElementFromTextAndAppend(wrapper, taskHtml), () => {
            timerFinished(isNotify, notifyText, timerDiv, createElementFromTextAndAppend(wrapper, newTaskInstantlyDom));
          });
        } else {
          setWithExpiry(localStorageName, '-1', Date.now() + 60 * 60 * 1000);
          timerDiv.append(createElementFromTextAndAppend(wrapper, newTaskInstantlyDom));
        }

        respDoc.remove();
      } else {
        console.log('Request failed.  Returned status of ' + xhr.status);
      }
    };
    xhr.send();
  }

//***************************************************************************
  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 initTimer(Delta, timerDiv, html, onTimeEnd) {
    const timeSpan = document.createElement('span');
    html.append(timeSpan);

    function print_time(t) {
      if (t < 0) t = 0;

      const min = Math.floor(t / 60);
      const sec = t % 60;
      let s = '';

      if (min) s = min + ' ' + 'мин. ';
      s = s + sec + ' ' + 'с. ';

      timeSpan.innerText = ' ' + s;
      if (timerDiv.firstChild != null) {
        timerDiv.replaceChild(html, timerDiv.firstChild);
      } else {
        timerDiv.append(html);
      }
    }

    const Refresh = () => {
      if (Timer >= 0) clearTimeout(Timer);
      Delta = Delta - 1;
      print_time(Delta);
      if (Delta >= 0) {
        Timer = setTimeout(Refresh, 1000);
      } else {
        onTimeEnd();
      }
    }

    let Timer = setTimeout(Refresh, 1000);
    print_time(Delta);
  }

//*******************
  function getUserInfo() {
    const infoLink = document.querySelector('center>a[href^=pl_info]');
    const infoLinkValues = infoLink.href.split("id=");

    return {id: infoLinkValues[infoLinkValues.length - 1], name: infoLink.innerText};
  }

//*******************
  function isPremium() {
    return document.querySelector('a[href="shop.php?cat=potions#vip"]') != null;
  }

//***************************************************************************
  function toggleNotification(isNotify, notifyMeLink, notifyMeLinkName) {
    if (isNotify) {
      notifyMeLink.innerHTML = `<b>${notifyMeLinkName}</b>: `;
      notifyMeLink.title = 'Уведомление: включено';
    } else {
      notifyMeLink.innerHTML = `${notifyMeLinkName}: `;
      notifyMeLink.title = 'Уведомление: выключено';
    }
  }

//***************************************************************************
  function notifyAfter(text) {
    if (delay == -1) {
      return null;
    }
    var notify = alert;

    const cancellation = setTimeout(() => {
      notify(text);
    }, 1000);

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

    return cancellation;
  }

//***************************************************************************
  function createElementFromTextAndAppend(wrapper, html) {
    const span = document.createElement('span');
    span.innerHTML = html.trim();
    wrapper.append(span);
    return wrapper;
  }

//***************************************************************************
  function timerFinished(isNotify, notifyText, timerDiv, finishedHtml) {
    if (isNotify) {
      notifyAfter(notifyText);
    }
    let child = timerDiv.lastElementChild;
    while (child) {
      timerDiv.removeChild(child);
      child = timerDiv.lastElementChild;
    }
    timerDiv.append(finishedHtml)
  }
})();

长期地址
遇到问题?请前往 GitHub 提 Issues,或加Q群1031348184

赞助商

Fishcpy

广告

Rainyun

注册一下就行

Rainyun

一年攒够 12 元