您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Система уведомлений о защитах
当前为
// ==UserScript== // @name HWM_Def_Notifier // @namespace Рианти // @description Система уведомлений о защитах // @include http://www.heroeswm.ru/* // @version 1 // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_xmlhttpRequest // @grant GM_openInTab // @grant GM_addStyle // ==/UserScript== // <b><center><font color="red">Вы уже в заявке, ожидайте начала битвы!</font></center></b> try { var _notificationSound = 'http://hwm.mcdir.ru/sounds/and-a-happy-new-year-sms.mp3'; var _updateInterval = 1000 * 60 * 1; var _defPage = 'http://www.heroeswm.ru/mapwars.php'; var _defaultSettingRows = 2; var _defaultSettingRows2 = 4; var _defaultSettings = '{"dn_timeUntilDef0":"15","dn_playersEnrolled0":"0","dn_totalRows0":"0","dn_percLost0":"0","dn_uncloosed0":"0","dn_timeUntilDef1":"5","dn_playersEnrolled1":"0","dn_totalRows1":"0","dn_percLost1":"0","dn_uncloosed1":"0","dn_notify_interval":"600000","dn_rule_modifier":"false","dn_sound_alert":"true"}'; var _defaultSettings2 = '{"dn_timeUntilDef0":"5","dn_playersEnrolled0":"6","dn_totalRows0":"0","dn_percLost0":"0","dn_uncloosed0":"0","dn_timeUntilDef1":"2","dn_playersEnrolled1":"0","dn_totalRows1":"0","dn_percLost1":"0","dn_uncloosed1":"1","dn_timeUntilDef2":"10","dn_playersEnrolled2":"12","dn_totalRows2":"7","dn_percLost2":"0","dn_uncloosed2":"0","dn_timeUntilDef3":"15","dn_playersEnrolled3":"0","dn_totalRows3":"0","dn_percLost3":"45","dn_uncloosed3":"0","dn_notify_interval":"600000","dn_rule_modifier":"true","dn_sound_alert":"true"}'; var _tabId = Math.random().toString(); var _curCharID = document.querySelector('param[name="FlashVars"]').value.split('|')[3]; // will throw error if run on wrong page, thats ok. var _gmVars = { settingRows: 'dn_settingRows', timeSinceLastNotify: 'dn_timeSinceLastNotify', timeSinceLastUpdate: 'dn_timeSinceLastUpdate', lastActiveTab: 'dn_lastActiveTab', notifyCommand: 'dn_notifyCommand', bkSign: 'dn_bkSign_' + _curCharID } var _bkSign = GM_getValue(_gmVars.bkSign, 'null'); if (_bkSign == 'null') _bkSign = prompt('Вас приветствует мастер настройки скрипта уведомления о защитах!\n\nВведите номер и название своего клана. Сначала номер, через пробел название.\nБудьте внимательны, если введете неправильно, скрипт придется переустанавливать.\n\nПравильный ввод выглядит так:', '823 Ginger Tail'); if (_bkSign) GM_setValue(_gmVars.bkSign, _bkSign); else { alert ('Настройка не завершена :('); throw {message: 'HWM_Def_notifier: setup failed'}; } // Последующий сегмент кода отвечает за то, чтоб уведомления исходили только из последней активной вкладки, а не случайной. if (document.visibilityState == "visible") updateAsActiveTab(); document.addEventListener("visibilitychange", function(){ if (document.visibilityState == "visible") updateAsActiveTab(); }); checkForNotifyCommand(); } catch (e) { console.log (e) } function updateAsActiveTab(){ GM_setValue(_gmVars.lastActiveTab, _tabId); } function checkForNotifyCommand(){ var temp; if ((temp = GM_getValue(_gmVars.notifyCommand, '0')) != '0'){ if (GM_getValue(_gmVars.lastActiveTab, _tabId) == _tabId){ GM_setValue(_gmVars.notifyCommand, '0'); notify(temp); } else { setTimeout(function(){ var temp; if ((temp = GM_getValue(_gmVars.notifyCommand, '0')) != '0'){ GM_setValue(_gmVars.notifyCommand, '0'); notify(temp); } }, 2000); } } setTimeout(checkForNotifyCommand, 1000); } function sendNotifyCommand(message){ GM_setValue(_gmVars.notifyCommand, message); } // Конец сегмента. Отслылка уведомлений происходит только посредством вызова функции sendNotifyCommand. function findActiveDefs(doc){ var regexp = /<font color=(?:"red"|red)><b>([\d:]*)<\/b><\/font>(.*?)<br><\/td><\/tr>/g; var regexp2 = /\d\)/g; var page = doc.querySelector('body').innerHTML; var match, activeDefs = []; var time, playersEnrolled; var res, count, unclosed; while (match = regexp.exec(page)){ if (match[2].indexOf(_bkSign) == -1) continue; time = match[1]; playersEnrolled = match[2].split('pl_info').length - 1; activeDefs.push({time : time, playersEnrolled : playersEnrolled}); } for(var i = 0; i < activeDefs.length; i++){ count = 0; while(res = regexp2.exec(doc.querySelectorAll('td.wb:nth-child(3)')[i].innerHTML)) count++; activeDefs[i].totalRows = count; try { activeDefs[i].curPercLost = parseInt(document.querySelectorAll('td.wb:nth-child(2)')[i].innerHTML.match(/Захвачен врагом на (\d+)/)[1]); } catch (e) { activeDefs[i].curPercLost = 0; } unclosed = 0; if ( activeDefs[i].playersEnrolled % 3 > 0 || Math.ceil((activeDefs[i].totalRows * 3 - activeDefs[i].playersEnrolled) / 3) < document.querySelectorAll('td.wb:nth-child(2)')[i].innerHTML.split('[Вступить]').length - 1) unclosed = 1; activeDefs[i].unclosed = unclosed; } var temp = activeDefs.reduce(function(o, v, i) { o[i] = v; return o; }, {}); return activeDefs; } function getCurServerTime(doc){ var regexp = /([\d:]+), \d+ online /; var page = doc.querySelector('body').innerHTML; var time = page.match(regexp)[1]; return time; } function minutesDifference(time1, time2){ var t1 = time1.split(':'), t2 = time2.split(':'); if(parseInt(t1[0]) == 0) t1[0] = '24'; if(parseInt(t2[0]) == 0) t2[0] = '24'; var difMin = 60 * (parseInt(t2[0]) - parseInt(t1[0])) + parseInt(t2[1]) - parseInt(t1[1]); //console.log('minutesDifference', difMin); return difMin; } function requestPage (url, onloadHandler){ console.log('loading: ', url); try{ GM_xmlhttpRequest({ overrideMimeType: 'text/plain; charset=windows-1251', synchronous: false, url: url, method: "GET", onload: function(response){ onloadHandler(new DOMParser().parseFromString(response.responseText, 'text/html').documentElement); }, onerror: function(){ requestPage (url, onloadHandler) }, ontimeout: function(){ requestPage (url, onloadHandler) }, timeout: 5000 }); } catch (e) { console.log(e); } } function notifyRules(timeUntil, playersEnrolled, totalRows, percLost, unclosed){ //console.log('notifyRules', timeUntil, playersEnrolled, totalRows, percLost, unclosed); for (var i = 0; i < parseInt(GM_getValue(_gmVars.settingRows, _defaultSettingRows)); i++) if ( notifyCase(i, timeUntil, playersEnrolled, totalRows, percLost, unclosed) ) return true; return false; } function notifyCase(id, timeUntil, playersEnrolled, totalRows, percLost, unclosed){ var playersEnrolledReq = parseInt(_settings.getSetting('dn_playersEnrolled' + id)); if (_settings.getSetting('dn_rule_modifier') == 'true') playersEnrolledReq = Math.max(0, playersEnrolledReq - 3 * Math.floor(percLost / 15)); if(timeUntil > parseInt(_settings.getSetting('dn_timeUntilDef' + id))) return false; if(totalRows * 3 - playersEnrolled <= playersEnrolledReq) return false; if(parseInt(_settings.getSetting('dn_totalRows' + id)) != 0 && parseInt(_settings.getSetting('dn_totalRows' + id)) != totalRows) return false; if(parseInt(_settings.getSetting('dn_percLost' + id)) > percLost) return false; if(parseInt(_settings.getSetting('dn_uncloosed' + id)) == 1 && unclosed == 1) return false; return true; } function notify(message){ //console.log(_settings.getSetting('dn_sound_alert')); if (_settings.getSetting('dn_sound_alert')) new Audio(_notificationSound).play(); setTimeout(function(){ alert(message); if(document.location.href.indexOf(_defPage) == -1) GM_openInTab(_defPage); }, 100); } function main(){ if (parseInt(_settings.getSetting('dn_notify_interval')) == 0) return; if (parseInt(GM_getValue(_gmVars.timeSinceLastNotify, '0')) < new Date().getTime() - parseInt(_settings.getSetting('dn_notify_interval')) && parseInt(GM_getValue(_gmVars.timeSinceLastUpdate, '0')) < new Date().getTime() - _updateInterval){ requestPage(_defPage, function(doc){ try{ //console.log(doc); var sTime = getCurServerTime(doc); //console.log('time:',sTime ); var defs = findActiveDefs(doc); //console.log('defs:',defs ); for (var i = 0; i < defs.length; i++){ if (notifyRules(minutesDifference(sTime, defs[i].time), defs[i].playersEnrolled, defs[i].totalRows, defs[i].curPercLost, defs[i].unclosed)){ var message = 'Уведомление: защита в ' + defs[i].time; GM_setValue(_gmVars.timeSinceLastNotify, new Date().getTime()); sendNotifyCommand(message); break; } } GM_setValue(_gmVars.timeSinceLastUpdate, new Date().getTime()); } catch (e) { console.log(e); } }); GM_setValue(_gmVars.timeSinceLastUpdate, new Date().getTime()); } setTimeout(main, Math.max(parseInt(GM_getValue(_gmVars.timeSinceLastUpdate, '0')) - new Date().getTime() + (1 + 0.1 * Math.random()) * _updateInterval, parseInt(GM_getValue(_gmVars.timeSinceLastNotify, '0')) - new Date().getTime() + (1 + 0.1 * Math.random()) * parseInt(_settings.getSetting('dn_notify_interval')))); //console.log('checking in: ', Math.max(parseInt(GM_getValue(_gmVars.timeSinceLastUpdate, '0')) - new Date().getTime() + (1 + 0.01 * Math.random()) * _updateInterval, parseInt(GM_getValue(_gmVars.timeSinceLastNotify, '0')) - new Date().getTime() + (1 + 0.01 * Math.random()) * parseInt(_settings.getSetting('dn_notify_interval')))); } function addInterface(){ GM_addStyle('#settingsInner tr{position: relative; left: 6px;} .copyright td{text-align: right;font: 12px "Times New Roman",Times,serif;color: #000;}'); if (navigator.userAgent.toLowerCase().indexOf('chrome') == -1) GM_addStyle('#settingsInner {border-collapse: collapse;}'); else GM_addStyle('#settingsInner td {top: 21px!important; right: 0px!important;}'); var table = document.querySelector('td[align="center"][width="50%"]').parentElement.parentElement; var tr = document.createElement('tr'); tr.innerHTML = '<td></td><td align="middle"><span id="dn_settingBoxControl" style="cursor:pointer; color:blue;">Настройки уведомлений</span></td><td></td>'; table.appendChild(tr); document.getElementById('dn_settingBoxControl').onclick = function(){ var els = document.getElementsByClassName('dn_settingBox'); for(var i = 0; i < els.length; i++){ if(els[i].style.display == 'none') els[i].style.display = ''; else els[i].style.display = 'none'; } if(els[0].style.display != 'none'){ // Вкл/выкл таймер обновления страницы (взаимодействие со скриптом на странице) setTimeout("clearTimeout(Timer)", 0); } else { setTimeout("Timer=setTimeout('Refresh()', 1000);", 0); } } drawSettingsBox(); } function drawSettingsBox(drawAgain){ var table = document.querySelector('td[align="center"][width="50%"]').parentElement.parentElement; var t; if(t = document.getElementsByClassName('dn_settingBox')[0]) table.removeChild(t); var tr = document.createElement('tr'); tr.className = 'dn_settingBox'; if (!drawAgain) tr.style.display = 'none'; var row = settingsRow(); var inputRows = '<tr align="center"><td colspan="9"><i>Уведомлять если</i></td></tr>' + row; for (var i = 1; i < parseInt(GM_getValue(_gmVars.settingRows, _defaultSettingRows)); i++) inputRows += '<tr align="center"><td colspan="9"><i>или</i></td></tr>' + row; tr.innerHTML = '<td colspan="3"><form id="dn_settingsForm"><table id="settingsInner" align="center" style="border-width: 1px 1px 1px;border-style: solid solid solid;border-color: #000;width: 85%;">' + inputRows + '<tr style="padding-bottom: 7px;"><td colspan="6" align="left"><input type="button" id="dn_addRule" value="Добавить условие"> <input type="button" id="dn_reduceRule" value="Убрать условие"> <select class="dn_defaults" align="center"><option value="0">Готовые настройки</option><option value="1">Для активного защитника</option><option value="2">Для страхующего дефы</option></select></td><td colspan="3" align="right">Частота уведомлений: <select id="dn_notify_interval"></select></td></tr><tr><td colspan="7" align="left"><input type="checkbox" id="dn_rule_modifier" name="dn_rule_modifier"> <label for="dn_rule_modifier">Уменьшать требования к заполненности на 3 места за каждые 15% потерянного контроля</label></td><td colspan="2" align="right"><input type="checkbox" id="dn_sound_alert" name="dn_sound_alert" checked> <label for="dn_sound_alert">Звук уведомления</label></td></tr><tr class="copyright" style="border-top: 1px solid rgb(0, 0, 0); border-right: medium hidden; border-left: medium hidden; border-bottom: medium hidden;"><td style="position: relative; top: 1px; right: 6px; border-bottom: 0px none;" colspan="10" align="right">2015, © <a href="http://www.heroeswm.ru/pl_info.php?id=712329" target="_blank">Рианти</a></td></tr></table></form></td>'; table.appendChild(tr); fetchValuesToSettings(); document.getElementById('dn_addRule').onclick = addRow; document.getElementById('dn_reduceRule').onclick = reduceRow; document.querySelector('select[class="dn_defaults"]').onchange = setDefaults; } function settingsRow(){ function Setting(header, inputType, inputClass){ this.header = header; this.inputType = inputType; this.inputClass = inputClass; }; var settings = [ new Setting('Времени до боя меньше', 'select', 'dn_timeUntilDef'), new Setting('Свободных мест больше', 'select', 'dn_playersEnrolled'), new Setting('Всего дорожек', 'select', 'dn_totalRows'), new Setting('Слито процентов', 'select', 'dn_percLost'), new Setting('Незакрытые заявки', 'select', 'dn_uncloosed') ] var output = '<tr>'; for (var i = 0; i < settings.length; i++){ output += '<td align="center">' + settings[i].header + '</td><td style="width: 2%;"> </td>'; } output += '</tr><tr>'; for (i = 0; i < settings.length; i++){ if (settings[i].inputType != 'select') output += '<td align="center"><input type="' + settings[i].inputType + '" class="' + settings[i].inputClass + '"></td>'; else output += '<td align="center"><select class="' + settings[i].inputClass + '"></td>'; if (i != settings.length - 1) output += '<td style="width: 2%;"> </td>'; } return output + '</tr><tr><td colspan="9"><hr></td></tr>'; } function reduceRow(){ var curRows = parseInt(GM_getValue(_gmVars.settingRows, _defaultSettingRows)); if (curRows > 1) curRows--; GM_setValue(_gmVars.settingRows, curRows); drawSettingsBox(1); _settings.importAgain(); } function addRow(){ var curRows = parseInt(GM_getValue(_gmVars.settingRows, _defaultSettingRows)); if (curRows < 10) curRows++; GM_setValue(_gmVars.settingRows, curRows); drawSettingsBox(1); _settings.importAgain(); } function setDefaults(e){ var selectedDefauls = e.target.value; var rows, settings; if (selectedDefauls == '0') return; else if (selectedDefauls == '1'){ rows = _defaultSettingRows; settings = _defaultSettings; } else { rows = _defaultSettingRows2; settings = _defaultSettings2; } GM_setValue(_gmVars.settingRows, rows); GM_setValue('dn_settings', settings); drawSettingsBox(1); _settings = new ScriptSettings('dn_settings', 'dn_settingsForm'); setTimeout( function (){ GM_setValue('dn_settings', settings) }, 300); // Затычка бага, найти баг в будущем. } function fetchValuesToSettings(){ for(var i = 0; i < document.getElementsByClassName('dn_timeUntilDef').length; i++){ var el = document.getElementsByClassName('dn_timeUntilDef')[i]; el.id = el.className + i; for (var j = 1; j <= 15; j++){ var newEl = document.createElement('option'); newEl.value = j; newEl.innerHTML = j + ' мин.'; el.appendChild(newEl); } var el = document.getElementsByClassName('dn_playersEnrolled')[i]; el.id = el.className + i; for (var j = 0; j <= 20; j++){ var newEl = document.createElement('option'); newEl.value = j; newEl.innerHTML = j; el.appendChild(newEl); } var el = document.getElementsByClassName('dn_totalRows')[i]; el.id = el.className + i; var newEl = document.createElement('option'); newEl.value = 0; newEl.innerHTML = 'Неважно'; el.appendChild(newEl); for (var j = 3; j <= 6; j++){ if (j == 6) j++ var newEl = document.createElement('option'); newEl.value = j; newEl.innerHTML = j; el.appendChild(newEl); } var el = document.getElementsByClassName('dn_percLost')[i]; el.id = el.className + i; for (var j = 0; j <= 50; j += 15){ var newEl = document.createElement('option'); newEl.value = j; if(j == 0) newEl.innerHTML = 'Неважно'; else newEl.innerHTML = 'больше ' + j + '%'; el.appendChild(newEl); } var el = document.getElementsByClassName('dn_uncloosed')[i]; el.id = el.className + i; var newEl = document.createElement('option'); newEl.value = 0; newEl.innerHTML = 'Неважно'; el.appendChild(newEl); var newEl = document.createElement('option'); newEl.value = 1; newEl.innerHTML = 'Да'; el.appendChild(newEl); } var el = document.getElementById('dn_notify_interval'); for (var j = 0; j <= 15; j++){ var newEl = document.createElement('option'); newEl.value = j * 1000 * 60; if(j == 0) newEl.innerHTML = 'Не уведомлять'; else newEl.innerHTML = j + ' мин'; el.appendChild(newEl); } } function ScriptSettings(settingsKey, formId){ function save(){ GM_setValue(_settingsKey, JSON.stringify(_settings)); } function load(){ var stringSettings = GM_getValue(_settingsKey); if (!stringSettings) importFromDocument(); else _settings = JSON.parse(stringSettings); } function apply(){ try{ var element; for(var setting in _settings){ element = document.getElementById(setting); if(element.type == 'checkbox') element.checked = _settings[setting]; else if (element.type == 'radio') element.selected = _settings[setting]; else element.value = _settings[setting]; } document.getElementById(_formId).onchange = function(){_self.changed()}; } catch (e) { try{ document.getElementById(_formId).onchange = function(){_self.changed()}; } catch (ee){ // Page without settings } } } function importFromDocument(){ try{ var element, value, formElements = document.getElementById(_formId).elements; for(var i = 0; i < formElements.length; i++){ element = formElements[i]; if(element.id != null && element.id != '' && element.type != 'button') { if (element.type == 'checkbox') value = element.checked; else if (element.type == 'radio') value = element.selected; else value = element.value; _settings[element.id] = value; } } } catch ( e ) { // not set on page _settings = JSON.parse(_defaultSettings); } save(); } function enableGMvars() { if (!this.GM_getValue || typeof this.GM_getValue != 'function') { if (typeof(Storage) === "undefined") console.log( 'Local storage must be enabled to use scriptSettings.' ); else { 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]; } } } } this.changed = function(){ var element, value; for(var setting in _settings){ element = document.getElementById(setting); if(element.type == 'checkbox') value = element.checked; else if (element.type == 'radio') value = element.selected; else value = element.value; _settings[setting] = this.validateValue(element.type, element.id, value); if(element.type == 'checkbox') element.checked = _settings[setting]; else if (element.type == 'radio') element.selected = _settings[setting]; else element.value = _settings[setting]; } save(); this.onchange(); } this.importAgain = function(){ apply(); this.forget(); _settings = {}; load(); } this.validateValue = function(elementType, elementId, elementValue){return elementValue}; this.onchange = function(){}; this.getSetting = function(setting){ if(_settings[setting] != null) return _settings[setting]; throw {message: 'undefined setting requested: ' + setting}; } this.forget = function(){ GM_deleteValue(_settingsKey); } var _self = this; var _settings = {}; var _settingsKey = settingsKey; var _formId = formId; enableGMvars(); load(); apply(); } try{ if (document.location.href.indexOf('mapwars.php') != -1){ addInterface(); } var _settings = new ScriptSettings('dn_settings', 'dn_settingsForm'); main(); } catch (e) { console.log(e); }