hwmTime

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

当前为 2023-04-17 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name hwmTime
  3. // @author Tamozhnya1
  4. // @namespace Tamozhnya1
  5. // @description Время с секундами
  6. // @version 4.0
  7. // @encoding utf-8
  8. // @include *heroeswm.ru/*
  9. // @include *lordswm.com/*
  10. // @exclude */rightcol.php*
  11. // @exclude */ch_box.php*
  12. // @exclude */chat*
  13. // @exclude */ticker.html*
  14. // @exclude */frames*
  15. // @exclude */brd.php*
  16. // @grant GM_deleteValue
  17. // @grant GM_getValue
  18. // @grant GM_setValue
  19. // @license MIT
  20. // ==/UserScript==
  21.  
  22. this.GM_getValue = this.GM_getValue || function(key, def) { return localStorage[key] || def; };
  23. this.GM_setValue = this.GM_setValue || function(key, value) { return localStorage[key] = value; };
  24. this.GM_deleteValue = this.GM_deleteValue || function(key) { return delete localStorage[key]; };
  25. let timePanel;
  26. let online;
  27. let serverClientLastRequestedTimeDeltaMilliseconds;
  28. const ClientServerTimeDeltaRequestInterval = 60 * 60 * 1000;
  29.  
  30. main();
  31.  
  32. function main() {
  33. if(document.querySelector("body")) {
  34. let timePanelData = findTimePanel();
  35. if(!timePanelData) {
  36. return;
  37. }
  38. timePanel = timePanelData.TimePanel;
  39. online = timePanelData.Online;
  40. timePanel.addEventListener("click", showSettings, false);
  41. serverClientLastRequestedTimeDeltaMilliseconds = parseInt(GM_getValue("hwmTimeServerClientLastRequestedTimeDeltaMilliseconds", 0));
  42. refreshTimePanel();
  43. requestServerTime(!GM_getValue("hwmTimeServerClientLastRequestedTimeDeltaMilliseconds") || !ValidateEstimatedTimeByPageEnterTime(timePanelData.PageEnterHours, timePanelData.PageEnterMinutes));
  44. }
  45. }
  46. function findTimePanel() {
  47. const isNewInterface = document.querySelector("div.mm_item") ? true : false;
  48. if(isNewInterface) {
  49. const timeTemplate = /(\d+):(\d+)/;
  50. let div1 = document.querySelector("div.sh_extra.sh_extra_right");
  51. let divs = div1.querySelectorAll("div");
  52. for(const div of divs) {
  53. if(/\d+:\d+/.test(div.innerHTML)) {
  54. let timeText = timeTemplate.exec(div.innerText);
  55. console.log([div.innerHTML, div.innerText, timeText]);
  56. let pageEnterHours = parseInt(timeText[1]);
  57. let pageEnterMinutes = parseInt(timeText[2]);
  58. return { TimePanel: div, PageEnterHours: pageEnterHours, PageEnterMinutes: pageEnterMinutes, Online: "" };
  59. }
  60. }
  61. } else {
  62. const timeAndOnlineTemplate = /(\d+):(\d+), \d+ online/;
  63. for(const currentCell of document.getElementsByTagName('td')) {
  64. if(currentCell.innerHTML.indexOf("<td") != -1 || currentCell.innerHTML.search(timeAndOnlineTemplate) == -1) {
  65. continue;
  66. }
  67. online = (/([^,]*)(, \d+ online.*)/.exec(currentCell.innerHTML))[2];
  68. let timeText = timeAndOnlineTemplate.exec(currentCell.innerHTML);
  69. let pageEnterHours = parseInt(timeText[1]);
  70. let pageEnterMinutes = parseInt(timeText[2]);
  71. return { TimePanel: currentCell, PageEnterHours: pageEnterHours, PageEnterMinutes: pageEnterMinutes, Online: online };
  72. }
  73. }
  74. }
  75. function ValidateEstimatedTimeByPageEnterTime(pageEnterHours, pageEnterMinutes) {
  76. const trueTime = getTrueTime();
  77. console.log([pageEnterHours, trueTime.getHours(), pageEnterMinutes, trueTime.getMinutes()]);
  78. if(trueTime.getHours() == pageEnterHours && (trueTime.getMinutes() - pageEnterMinutes) <= 1 && pageEnterMinutes <= trueTime.getMinutes()) {
  79. GM_deleteValue("hwmTimeClientServerTimeDiscrepancyErrorsCount");
  80. return true;
  81. }
  82. if((trueTime.getHours() - pageEnterHours == 1 || pageEnterHours - trueTime.getHours() == 23) && (pageEnterMinutes - trueTime.getMinutes() == 59)) {
  83. GM_deleteValue("hwmTimeClientServerTimeDiscrepancyErrorsCount");
  84. return true;
  85. }
  86. GM_setValue("hwmTimeClientServerTimeDiscrepancyErrorsCount", parseInt(GM_getValue("hwmTimeClientServerTimeDiscrepancyErrorsCount", 0)) + 1);
  87. return false;
  88. }
  89. function requestServerTime(force) {
  90. force = force || false;
  91. if(parseInt(GM_getValue("hwmTimeServerResponseErrorsCount", 0)) >= 4 || parseInt(GM_getValue("hwmTimeClientServerTimeDiscrepancyErrorsCount", 0)) >= 4) {
  92. return;
  93. }
  94. if(force || parseInt(GM_getValue("hwmTimeLastSyncClientTimeMilliseconds", 0)) + ClientServerTimeDeltaRequestInterval < (new Date().getTime())) {
  95. GM_setValue("hwmTimeLastSyncClientTimeMilliseconds", new Date().getTime());
  96. const objXMLHttpReqTime = new XMLHttpRequest();
  97. objXMLHttpReqTime.open('GET', 'time.php?rand=' + (Math.random() * 1000000), true);
  98. objXMLHttpReqTime.onreadystatechange = function() {
  99. handleHttpResponseTime(objXMLHttpReqTime);
  100. }
  101. objXMLHttpReqTime.send(null);
  102. } else {
  103. setTimeout(function() { requestServerTime(); }, ClientServerTimeDeltaRequestInterval);
  104. }
  105. }
  106. function handleHttpResponseTime(obj) {
  107. console.log(obj);
  108. if(obj.readyState == 4 && obj.status == 200) {
  109. let responseParcing = /now (\d+)/.exec(obj.responseText); //obj.responseText: now 1681711364 17-04-23 09:02
  110. if(responseParcing) {
  111. let serverUtcTime = parseInt(responseParcing[1]) * 1000 + parseInt(GM_getValue("hwmTimeAddingIntervalMilliseconds", 0));
  112. serverClientLastRequestedTimeDeltaMilliseconds = new Date().getTime() - serverUtcTime;
  113. GM_setValue("hwmTimeServerClientLastRequestedTimeDeltaMilliseconds", serverClientLastRequestedTimeDeltaMilliseconds);
  114. GM_deleteValue("hwmTimeServerResponseErrorsCount");
  115. refreshTimePanel();
  116. } else {
  117. GM_setValue("hwmTimeServerResponseErrorsCount", parseInt(GM_getValue("hwmTimeServerResponseErrorsCount", 0)) + 1);
  118. setTimeout(function() { requestServerTime(); }, 60 * 1000);
  119. }
  120. }
  121. }
  122. function refreshTimePanel() {
  123. const trueTime = getTrueTime();
  124. timePanel.innerHTML = trueTime.getHours() + ':' + ( (trueTime.getMinutes() < 10) ? '0' : '' ) + trueTime.getMinutes() + ':' + (trueTime.getSeconds() < 10 ? '0' : '') + trueTime.getSeconds() + online;
  125. setTimeout(function() { refreshTimePanel(); }, 1000);
  126. }
  127. function getTrueTime() { return new Date((new Date().getTime()) - serverClientLastRequestedTimeDeltaMilliseconds); }
  128. function showSettings() {
  129. const isEn = document.documentElement.lang == "en";
  130. let settingsBackgroundPanel = document.getElementById('hwmTimeSettingsBackgroundPanel');
  131. let settingsPanel = document.getElementById('hwmTimeSettingsPanel');
  132. if(!settingsBackgroundPanel) {
  133. settingsBackgroundPanel = addElement('div', document.body, { id: 'hwmTimeSettingsBackgroundPanel', style: `position: absolute; display: block; top: 0px; left: 0px; width: 100%; height: ${Math.max(document.documentElement.scrollHeight, document.body.scrollHeight)}px;background: #000000; opacity: 0.5; z-index: 7;` });
  134. settingsPanel = addElement('div', document.body, { id: 'hwmTimeSettingsPanel', style: `position: absolute; display: block; top: ${(window.pageYOffset + 150)}px; left: ${(((document.compatMode == 'CSS1Compat' && document.documentElement ? document.documentElement.clientWidth : document.body.clientWidth) - 650 ) / 2)}px; width: 650px; background: #F6F3EA; z-index: 8;` });
  135. } else {
  136. settingsBackgroundPanel.style.display = "block";
  137. settingsPanel.style.display = "block";
  138. }
  139. settingsPanel.innerHTML = `<div style="border:1px solid #abc;padding:5px;margin:2px;">
  140. <div style="float:right;border:1px solid #abc;width:15px;height:15px;text-align:center;cursor:pointer;" id="hwmTimeCloseSettingsButton" title="Close">x</div>
  141. <table>
  142. <tr>
  143. <td>hwmTimeServerResponseErrorsCount: ${parseInt(GM_getValue("hwmTimeServerResponseErrorsCount", 0))}</td>
  144. </tr>
  145. <tr>
  146. <td>hwmTimeClientServerTimeDiscrepancyErrorsCount: ${parseInt(GM_getValue("hwmTimeClientServerTimeDiscrepancyErrorsCount", 0))}</td>
  147. </tr>
  148. <tr>
  149. <td>hwmTimeServerClientLastRequestedTimeDeltaMilliseconds: ${parseInt(GM_getValue("hwmTimeServerClientLastRequestedTimeDeltaMilliseconds", 0))}</td>
  150. </tr>
  151. <tr>
  152. <td>
  153. ${isEn ? 'Adding' : ustring("Добавлять")}<input id="hwmTimeAddingIntervalInput" type: "number" value="${ GM_getValue("hwmTimeAddingIntervalMilliseconds", 0) }" size="1" maxlength="2" /> ${isEn ? 'Milliseconds to the sync (page load time from the server)' : ustring("милисекунды на синхронизацию (время загрузки страницы с сервера)")}</b>
  154. <input type="submit" id="hwmTimeAddingIntervalSubmit" value="ok">
  155. <br>
  156. <br>
  157. </td>
  158. </tr>
  159. <tr>
  160. <td>
  161. <input type="submit" id="hwmTimeRestartScriptSubmit" value="${isEn ? 'Restart the script' : ustring("Перезапустить скрипт")}" />
  162. </td>
  163. </tr>
  164. </table>
  165. </div>`;
  166.  
  167. settingsBackgroundPanel.addEventListener("click", function() { settingsBackgroundPanel.style.display = "none"; settingsPanel.style.display = "none"; }, false);
  168. document.getElementById("hwmTimeCloseSettingsButton").addEventListener("click", function() { settingsBackgroundPanel.style.display = "none"; settingsPanel.style.display = "none"; }, false);
  169. document.getElementById("hwmTimeAddingIntervalSubmit").addEventListener("click", function() { let addingInterval = parseInt(document.getElementById("hwmTimeAddingIntervalInput").value); if(addingInterval > 0) { GM_setValue("hwmTimeAddingIntervalMilliseconds", addingInterval);} }, false);
  170. document.getElementById("hwmTimeRestartScriptSubmit").addEventListener("click", function() { GM_deleteValue("hwmTimeServerResponseErrorsCount"); GM_deleteValue("hwmTimeClientServerTimeDiscrepancyErrorsCount"); GM_deleteValue("hwmTimeServerClientLastRequestedTimeDeltaMilliseconds"); GM_deleteValue("hwmTimeLastSyncClientTimeMilliseconds"); main(); }, false);
  171. }
  172. function addElement(type, parent, data, style) {
  173. let el = createElement(type, data, style);
  174. if(parent) {
  175. parent.appendChild(el);
  176. }
  177. return el;
  178. }
  179. function createElement(type, data, style) {
  180. let el = document.createElement(type);
  181. if(data) {
  182. for(const key in data) {
  183. if(key == "innerHTML") {
  184. el.innerHTML = data[key];
  185. } else {
  186. el.setAttribute(key, data[key]);
  187. }
  188. }
  189. }
  190. if(style && el.id) {
  191. let styleStr = "";
  192. if(typeof(style) == "string") {
  193. styleStr = style;
  194. } else {
  195. for (let key in style) {
  196. styleStr += key + ": " + style[key] + "; ";
  197. }
  198. }
  199. GM_addStyle("#" + el.id + "{" + styleStr + "}");
  200. }
  201. return el;
  202. }
  203. function uchar(s) {
  204. switch (s[0]) {case "А": return "\u0410"; case "Б": return "\u0411"; case "В": return "\u0412"; case "Г": return "\u0413"; case "Д": return "\u0414"; case "Е": return "\u0415"; case "Ж": return "\u0416"; case "З": return "\u0417"; case "И": return "\u0418"; case "Й": return "\u0419"; case "К": return "\u041a"; case "Л": return "\u041b"; case "М": return "\u041c"; case "Н": return "\u041d"; case "О": return "\u041e"; case "П": return "\u041f"; case "Р": return "\u0420"; case "С": return "\u0421"; case "Т": return "\u0422"; case "У": return "\u0423"; case "Ф": return "\u0424"; case "Х": return "\u0425"; case "Ц": return "\u0426"; case "Ч": return "\u0427"; case "Ш": return "\u0428"; case "Щ": return "\u0429"; case "Ъ": return "\u042a"; case "Ы": return "\u042b"; case "Ь": return "\u042c"; case "Э": return "\u042d"; case "Ю": return "\u042e"; case "Я": return "\u042f"; case "а": return "\u0430"; case "б": return "\u0431"; case "в": return "\u0432"; case "г": return "\u0433"; case "д": return "\u0434"; case "е": return "\u0435"; case "ж": return "\u0436"; case "з": return "\u0437"; case "и": return "\u0438"; case "й": return "\u0439"; case "к": return "\u043a"; case "л": return "\u043b"; case "м": return "\u043c"; case "н": return "\u043d"; case "о": return "\u043e"; case "п": return "\u043f"; case "р": return "\u0440"; case "с": return "\u0441"; case "т": return "\u0442"; case "у": return "\u0443"; case "ф": return "\u0444"; case "х": return "\u0445"; case "ц": return "\u0446"; case "ч": return "\u0447"; case "ш": return "\u0448"; case "щ": return "\u0449"; case "ъ": return "\u044a"; case "ы": return "\u044b"; case "ь": return "\u044c"; case "э": return "\u044d"; case "ю": return "\u044e"; case "я": return "\u044f"; case "Ё": return "\u0401"; case "ё": return "\u0451"; default: return s[0];}}
  205. function ustring(s) {
  206. s = String(s);
  207. let result = "";
  208. for(let i = 0; i < s.length; i++) {
  209. result += uchar(s[i]);
  210. }
  211. return result;
  212. }