HWM_Def_Notifier

Система уведомлений о защитах

  1. // ==UserScript==
  2. // @name HWM_Def_Notifier
  3. // @namespace Рианти
  4. // @description Система уведомлений о защитах
  5. // @include http://www.heroeswm.ru/*
  6. // @version 1
  7. // @grant GM_getValue
  8. // @grant GM_setValue
  9. // @grant GM_deleteValue
  10. // @grant GM_xmlhttpRequest
  11. // @grant GM_openInTab
  12. // @grant GM_addStyle
  13. // ==/UserScript==
  14.  
  15. // <b><center><font color="red">Вы уже в заявке, ожидайте начала битвы!</font></center></b>
  16. try {
  17. var _notificationSound = 'http://hwm.mcdir.ru/sounds/and-a-happy-new-year-sms.mp3';
  18.  
  19. var _updateInterval = 1000 * 60 * 1;
  20. var _defPage = 'http://www.heroeswm.ru/mapwars.php';
  21. var _defaultSettingRows = 2;
  22. var _defaultSettingRows2 = 4;
  23. 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"}';
  24. 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"}';
  25. var _tabId = Math.random().toString();
  26. var _curCharID = document.querySelector('param[name="FlashVars"]').value.split('|')[3]; // will throw error if run on wrong page, thats ok.
  27. var _gmVars = {
  28. settingRows: 'dn_settingRows',
  29. timeSinceLastNotify: 'dn_timeSinceLastNotify',
  30. timeSinceLastUpdate: 'dn_timeSinceLastUpdate',
  31. lastActiveTab: 'dn_lastActiveTab',
  32. notifyCommand: 'dn_notifyCommand',
  33. bkSign: 'dn_bkSign_' + _curCharID
  34. }
  35.  
  36. var _bkSign = GM_getValue(_gmVars.bkSign, 'null');
  37. if (_bkSign == 'null') _bkSign = prompt('Вас приветствует мастер настройки скрипта уведомления о защитах!\n\nВведите номер и название своего клана. Сначала номер, через пробел название.\nБудьте внимательны, если введете неправильно, скрипт придется переустанавливать.\n\nПравильный ввод выглядит так:', '823 Ginger Tail');
  38. if (_bkSign) GM_setValue(_gmVars.bkSign, _bkSign);
  39. else {
  40. alert ('Настройка не завершена :(');
  41. throw {message: 'HWM_Def_notifier: setup failed'};
  42. }
  43.  
  44. // Последующий сегмент кода отвечает за то, чтоб уведомления исходили только из последней активной вкладки, а не случайной.
  45. if (document.visibilityState == "visible") updateAsActiveTab();
  46.  
  47. document.addEventListener("visibilitychange", function(){
  48. if (document.visibilityState == "visible") updateAsActiveTab();
  49. });
  50. checkForNotifyCommand();
  51. } catch (e) { console.log (e) }
  52.  
  53. function updateAsActiveTab(){
  54. GM_setValue(_gmVars.lastActiveTab, _tabId);
  55. }
  56.  
  57. function checkForNotifyCommand(){
  58. var temp;
  59. if ((temp = GM_getValue(_gmVars.notifyCommand, '0')) != '0'){
  60. if (GM_getValue(_gmVars.lastActiveTab, _tabId) == _tabId){
  61. GM_setValue(_gmVars.notifyCommand, '0');
  62. notify(temp);
  63. } else {
  64. setTimeout(function(){
  65. var temp;
  66. if ((temp = GM_getValue(_gmVars.notifyCommand, '0')) != '0'){
  67. GM_setValue(_gmVars.notifyCommand, '0');
  68. notify(temp);
  69. }
  70. }, 2000);
  71. }
  72. }
  73.  
  74. setTimeout(checkForNotifyCommand, 1000);
  75. }
  76.  
  77. function sendNotifyCommand(message){
  78. GM_setValue(_gmVars.notifyCommand, message);
  79. }
  80. // Конец сегмента. Отслылка уведомлений происходит только посредством вызова функции sendNotifyCommand.
  81.  
  82. function findActiveDefs(doc){
  83. var regexp = /<font color=(?:"red"|red)><b>([\d:]*)<\/b><\/font>(.*?)<br><\/td><\/tr>/g;
  84. var regexp2 = /\d\)/g;
  85. var page = doc.querySelector('body').innerHTML;
  86. var match, activeDefs = [];
  87. var time, playersEnrolled;
  88. var res, count, unclosed;
  89. while (match = regexp.exec(page)){
  90. if (match[2].indexOf(_bkSign) == -1) continue;
  91. time = match[1];
  92. playersEnrolled = match[2].split('pl_info').length - 1;
  93. activeDefs.push({time : time, playersEnrolled : playersEnrolled});
  94. }
  95. for(var i = 0; i < activeDefs.length; i++){
  96. count = 0;
  97. while(res = regexp2.exec(doc.querySelectorAll('td.wb:nth-child(3)')[i].innerHTML)) count++;
  98. activeDefs[i].totalRows = count;
  99. try {
  100. activeDefs[i].curPercLost = parseInt(document.querySelectorAll('td.wb:nth-child(2)')[i].innerHTML.match(/Захвачен врагом на (\d+)/)[1]);
  101. } catch (e) {
  102. activeDefs[i].curPercLost = 0;
  103. }
  104. unclosed = 0;
  105. 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;
  106. activeDefs[i].unclosed = unclosed;
  107. }
  108.  
  109. var temp = activeDefs.reduce(function(o, v, i) { o[i] = v; return o; }, {});
  110.  
  111. return activeDefs;
  112. }
  113.  
  114. function getCurServerTime(doc){
  115. var regexp = /([\d:]+), \d+ online&nbsp;/;
  116. var page = doc.querySelector('body').innerHTML;
  117. var time = page.match(regexp)[1];
  118. return time;
  119. }
  120.  
  121. function minutesDifference(time1, time2){
  122. var t1 = time1.split(':'), t2 = time2.split(':');
  123. if(parseInt(t1[0]) == 0) t1[0] = '24'; if(parseInt(t2[0]) == 0) t2[0] = '24';
  124. var difMin = 60 * (parseInt(t2[0]) - parseInt(t1[0])) + parseInt(t2[1]) - parseInt(t1[1]);
  125. //console.log('minutesDifference', difMin);
  126. return difMin;
  127. }
  128.  
  129. function requestPage (url, onloadHandler){
  130. console.log('loading: ', url);
  131. try{
  132. GM_xmlhttpRequest({
  133. overrideMimeType: 'text/plain; charset=windows-1251',
  134. synchronous: false,
  135. url: url,
  136. method: "GET",
  137. onload: function(response){
  138. onloadHandler(new DOMParser().parseFromString(response.responseText, 'text/html').documentElement);
  139. },
  140. onerror: function(){ requestPage (url, onloadHandler) },
  141. ontimeout: function(){ requestPage (url, onloadHandler) },
  142. timeout: 5000
  143. });
  144. } catch (e) {
  145. console.log(e);
  146. }
  147. }
  148.  
  149. function notifyRules(timeUntil, playersEnrolled, totalRows, percLost, unclosed){
  150. //console.log('notifyRules', timeUntil, playersEnrolled, totalRows, percLost, unclosed);
  151. for (var i = 0; i < parseInt(GM_getValue(_gmVars.settingRows, _defaultSettingRows)); i++)
  152. if ( notifyCase(i, timeUntil, playersEnrolled, totalRows, percLost, unclosed) )
  153. return true;
  154. return false;
  155. }
  156.  
  157. function notifyCase(id, timeUntil, playersEnrolled, totalRows, percLost, unclosed){
  158. var playersEnrolledReq = parseInt(_settings.getSetting('dn_playersEnrolled' + id));
  159. if (_settings.getSetting('dn_rule_modifier') == 'true') playersEnrolledReq = Math.max(0, playersEnrolledReq - 3 * Math.floor(percLost / 15));
  160.  
  161. if(timeUntil > parseInt(_settings.getSetting('dn_timeUntilDef' + id))) return false;
  162. if(totalRows * 3 - playersEnrolled <= playersEnrolledReq) return false;
  163. if(parseInt(_settings.getSetting('dn_totalRows' + id)) != 0 && parseInt(_settings.getSetting('dn_totalRows' + id)) != totalRows) return false;
  164. if(parseInt(_settings.getSetting('dn_percLost' + id)) > percLost) return false;
  165. if(parseInt(_settings.getSetting('dn_uncloosed' + id)) == 1 && unclosed == 1) return false;
  166. return true;
  167. }
  168.  
  169. function notify(message){
  170. //console.log(_settings.getSetting('dn_sound_alert'));
  171. if (_settings.getSetting('dn_sound_alert')) new Audio(_notificationSound).play();
  172. setTimeout(function(){
  173. alert(message);
  174. if(document.location.href.indexOf(_defPage) == -1) GM_openInTab(_defPage);
  175. }, 100);
  176. }
  177.  
  178. function main(){
  179. if (parseInt(_settings.getSetting('dn_notify_interval')) == 0) return;
  180. 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){
  181. requestPage(_defPage, function(doc){
  182. try{
  183. //console.log(doc);
  184. var sTime = getCurServerTime(doc);
  185. //console.log('time:',sTime );
  186. var defs = findActiveDefs(doc);
  187. //console.log('defs:',defs );
  188. for (var i = 0; i < defs.length; i++){
  189. if (notifyRules(minutesDifference(sTime, defs[i].time), defs[i].playersEnrolled, defs[i].totalRows, defs[i].curPercLost, defs[i].unclosed)){
  190. var message = 'Уведомление: защита в ' + defs[i].time;
  191. GM_setValue(_gmVars.timeSinceLastNotify, new Date().getTime());
  192. sendNotifyCommand(message);
  193. break;
  194. }
  195. }
  196. GM_setValue(_gmVars.timeSinceLastUpdate, new Date().getTime());
  197. } catch (e) {
  198. console.log(e);
  199. }
  200. });
  201. GM_setValue(_gmVars.timeSinceLastUpdate, new Date().getTime());
  202. }
  203. 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'))));
  204. //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'))));
  205. }
  206.  
  207. function addInterface(){
  208. GM_addStyle('#settingsInner tr{position: relative; left: 6px;} .copyright td{text-align: right;font: 12px "Times New Roman",Times,serif;color: #000;}');
  209. if (navigator.userAgent.toLowerCase().indexOf('chrome') == -1) GM_addStyle('#settingsInner {border-collapse: collapse;}');
  210. else GM_addStyle('#settingsInner td {top: 21px!important; right: 0px!important;}');
  211. var table = document.querySelector('td[align="center"][width="50%"]').parentElement.parentElement;
  212. var tr = document.createElement('tr');
  213. tr.innerHTML = '<td></td><td align="middle"><span id="dn_settingBoxControl" style="cursor:pointer; color:blue;">Настройки уведомлений</span></td><td></td>';
  214. table.appendChild(tr);
  215. document.getElementById('dn_settingBoxControl').onclick = function(){
  216. var els = document.getElementsByClassName('dn_settingBox');
  217. for(var i = 0; i < els.length; i++){
  218. if(els[i].style.display == 'none') els[i].style.display = '';
  219. else els[i].style.display = 'none';
  220. }
  221. if(els[0].style.display != 'none'){ // Вкл/выкл таймер обновления страницы (взаимодействие со скриптом на странице)
  222. setTimeout("clearTimeout(Timer)", 0);
  223. } else {
  224. setTimeout("Timer=setTimeout('Refresh()', 1000);", 0);
  225. }
  226. }
  227. drawSettingsBox();
  228. }
  229.  
  230. function drawSettingsBox(drawAgain){
  231. var table = document.querySelector('td[align="center"][width="50%"]').parentElement.parentElement;
  232. var t;
  233. if(t = document.getElementsByClassName('dn_settingBox')[0]) table.removeChild(t);
  234.  
  235. var tr = document.createElement('tr');
  236. tr.className = 'dn_settingBox';
  237. if (!drawAgain) tr.style.display = 'none';
  238. var row = settingsRow();
  239. var inputRows = '<tr align="center"><td colspan="9"><i>Уведомлять если</i></td></tr>' + row;
  240. for (var i = 1; i < parseInt(GM_getValue(_gmVars.settingRows, _defaultSettingRows)); i++) inputRows += '<tr align="center"><td colspan="9"><i>или</i></td></tr>' + row;
  241. 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>';
  242. table.appendChild(tr);
  243. fetchValuesToSettings();
  244. document.getElementById('dn_addRule').onclick = addRow;
  245. document.getElementById('dn_reduceRule').onclick = reduceRow;
  246. document.querySelector('select[class="dn_defaults"]').onchange = setDefaults;
  247. }
  248.  
  249. function settingsRow(){
  250. function Setting(header, inputType, inputClass){ this.header = header; this.inputType = inputType; this.inputClass = inputClass; };
  251. var settings = [
  252. new Setting('Времени до боя меньше', 'select', 'dn_timeUntilDef'),
  253. new Setting('Свободных мест больше', 'select', 'dn_playersEnrolled'),
  254. new Setting('Всего дорожек', 'select', 'dn_totalRows'),
  255. new Setting('Слито процентов', 'select', 'dn_percLost'),
  256. new Setting('Незакрытые заявки', 'select', 'dn_uncloosed')
  257. ]
  258. var output = '<tr>';
  259. for (var i = 0; i < settings.length; i++){
  260. output += '<td align="center">' + settings[i].header + '</td><td style="width: 2%;"> </td>';
  261. }
  262. output += '</tr><tr>';
  263. for (i = 0; i < settings.length; i++){
  264. if (settings[i].inputType != 'select') output += '<td align="center"><input type="' + settings[i].inputType + '" class="' + settings[i].inputClass + '"></td>';
  265. else output += '<td align="center"><select class="' + settings[i].inputClass + '"></td>';
  266. if (i != settings.length - 1) output += '<td style="width: 2%;"> </td>';
  267. }
  268. return output + '</tr><tr><td colspan="9"><hr></td></tr>';
  269. }
  270.  
  271. function reduceRow(){
  272. var curRows = parseInt(GM_getValue(_gmVars.settingRows, _defaultSettingRows));
  273. if (curRows > 1) curRows--;
  274. GM_setValue(_gmVars.settingRows, curRows);
  275. drawSettingsBox(1);
  276. _settings.importAgain();
  277. }
  278.  
  279. function addRow(){
  280. var curRows = parseInt(GM_getValue(_gmVars.settingRows, _defaultSettingRows));
  281. if (curRows < 10) curRows++;
  282. GM_setValue(_gmVars.settingRows, curRows);
  283. drawSettingsBox(1);
  284. _settings.importAgain();
  285. }
  286.  
  287. function setDefaults(e){
  288. var selectedDefauls = e.target.value;
  289. var rows, settings;
  290. if (selectedDefauls == '0') return;
  291. else if (selectedDefauls == '1'){
  292. rows = _defaultSettingRows;
  293. settings = _defaultSettings;
  294. } else {
  295. rows = _defaultSettingRows2;
  296. settings = _defaultSettings2;
  297. }
  298. GM_setValue(_gmVars.settingRows, rows);
  299. GM_setValue('dn_settings', settings);
  300. drawSettingsBox(1);
  301. _settings = new ScriptSettings('dn_settings', 'dn_settingsForm');
  302. setTimeout( function (){ GM_setValue('dn_settings', settings) }, 300); // Затычка бага, найти баг в будущем.
  303. }
  304.  
  305. function fetchValuesToSettings(){
  306. for(var i = 0; i < document.getElementsByClassName('dn_timeUntilDef').length; i++){
  307. var el = document.getElementsByClassName('dn_timeUntilDef')[i];
  308. el.id = el.className + i;
  309. for (var j = 1; j <= 15; j++){
  310. var newEl = document.createElement('option');
  311. newEl.value = j;
  312. newEl.innerHTML = j + ' мин.';
  313. el.appendChild(newEl);
  314. }
  315. var el = document.getElementsByClassName('dn_playersEnrolled')[i];
  316. el.id = el.className + i;
  317. for (var j = 0; j <= 20; j++){
  318. var newEl = document.createElement('option');
  319. newEl.value = j;
  320. newEl.innerHTML = j;
  321. el.appendChild(newEl);
  322. }
  323. var el = document.getElementsByClassName('dn_totalRows')[i];
  324. el.id = el.className + i;
  325. var newEl = document.createElement('option');
  326. newEl.value = 0;
  327. newEl.innerHTML = 'Неважно';
  328. el.appendChild(newEl);
  329. for (var j = 3; j <= 6; j++){
  330. if (j == 6) j++
  331. var newEl = document.createElement('option');
  332. newEl.value = j;
  333. newEl.innerHTML = j;
  334. el.appendChild(newEl);
  335. }
  336. var el = document.getElementsByClassName('dn_percLost')[i];
  337. el.id = el.className + i;
  338. for (var j = 0; j <= 50; j += 15){
  339. var newEl = document.createElement('option');
  340. newEl.value = j;
  341. if(j == 0) newEl.innerHTML = 'Неважно';
  342. else newEl.innerHTML = 'больше ' + j + '%';
  343. el.appendChild(newEl);
  344. }
  345. var el = document.getElementsByClassName('dn_uncloosed')[i];
  346. el.id = el.className + i;
  347. var newEl = document.createElement('option');
  348. newEl.value = 0; newEl.innerHTML = 'Неважно';
  349. el.appendChild(newEl);
  350. var newEl = document.createElement('option');
  351. newEl.value = 1; newEl.innerHTML = 'Да';
  352. el.appendChild(newEl);
  353. }
  354. var el = document.getElementById('dn_notify_interval');
  355. for (var j = 0; j <= 15; j++){
  356. var newEl = document.createElement('option');
  357. newEl.value = j * 1000 * 60;
  358. if(j == 0) newEl.innerHTML = 'Не уведомлять';
  359. else newEl.innerHTML = j + ' мин';
  360. el.appendChild(newEl);
  361. }
  362. }
  363.  
  364. function ScriptSettings(settingsKey, formId){
  365. function save(){
  366. GM_setValue(_settingsKey, JSON.stringify(_settings));
  367. }
  368.  
  369. function load(){
  370. var stringSettings = GM_getValue(_settingsKey);
  371. if (!stringSettings) importFromDocument();
  372. else _settings = JSON.parse(stringSettings);
  373. }
  374.  
  375. function apply(){
  376. try{
  377. var element;
  378. for(var setting in _settings){
  379. element = document.getElementById(setting);
  380. if(element.type == 'checkbox') element.checked = _settings[setting];
  381. else if (element.type == 'radio') element.selected = _settings[setting];
  382. else element.value = _settings[setting];
  383. }
  384. document.getElementById(_formId).onchange = function(){_self.changed()};
  385. } catch (e) {
  386. try{
  387. document.getElementById(_formId).onchange = function(){_self.changed()};
  388. } catch (ee){
  389. // Page without settings
  390. }
  391. }
  392. }
  393.  
  394. function importFromDocument(){
  395. try{
  396. var element, value, formElements = document.getElementById(_formId).elements;
  397. for(var i = 0; i < formElements.length; i++){
  398. element = formElements[i];
  399. if(element.id != null && element.id != '' && element.type != 'button') {
  400. if (element.type == 'checkbox') value = element.checked;
  401. else if (element.type == 'radio') value = element.selected;
  402. else value = element.value;
  403. _settings[element.id] = value;
  404. }
  405. }
  406. } catch ( e ) {
  407. // not set on page
  408. _settings = JSON.parse(_defaultSettings);
  409. }
  410. save();
  411. }
  412.  
  413. function enableGMvars() {
  414. if (!this.GM_getValue || typeof this.GM_getValue != 'function') {
  415. if (typeof(Storage) === "undefined") console.log( 'Local storage must be enabled to use scriptSettings.' );
  416. else {
  417. this.GM_getValue = function (key, def) { return localStorage[key] || def; }
  418. this.GM_setValue = function (key, value) { return localStorage[key] = value; }
  419. this.GM_deleteValue = function (key) { return delete localStorage[key]; }
  420. }
  421. }
  422. }
  423.  
  424. this.changed = function(){
  425. var element, value;
  426. for(var setting in _settings){
  427. element = document.getElementById(setting);
  428. if(element.type == 'checkbox') value = element.checked;
  429. else if (element.type == 'radio') value = element.selected;
  430. else value = element.value;
  431. _settings[setting] = this.validateValue(element.type, element.id, value);
  432. if(element.type == 'checkbox') element.checked = _settings[setting];
  433. else if (element.type == 'radio') element.selected = _settings[setting];
  434. else element.value = _settings[setting];
  435. }
  436. save(); this.onchange();
  437. }
  438.  
  439. this.importAgain = function(){
  440. apply(); this.forget(); _settings = {}; load();
  441. }
  442.  
  443. this.validateValue = function(elementType, elementId, elementValue){return elementValue};
  444.  
  445. this.onchange = function(){};
  446.  
  447. this.getSetting = function(setting){
  448. if(_settings[setting] != null) return _settings[setting];
  449. throw {message: 'undefined setting requested: ' + setting};
  450. }
  451.  
  452. this.forget = function(){
  453. GM_deleteValue(_settingsKey);
  454. }
  455.  
  456. var _self = this;
  457. var _settings = {};
  458. var _settingsKey = settingsKey;
  459. var _formId = formId;
  460.  
  461. enableGMvars();
  462. load(); apply();
  463. }
  464.  
  465. try{
  466. if (document.location.href.indexOf('mapwars.php') != -1){
  467. addInterface();
  468. }
  469. var _settings = new ScriptSettings('dn_settings', 'dn_settingsForm');
  470. main();
  471. } catch (e) {
  472. console.log(e);
  473. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址