Idleontoolbox Produce Check

Check and notify on https://idleontoolbox.com/dashboard with Telegram support

当前为 2024-02-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Idleontoolbox Produce Check
  3. // @namespace http://tampermonkey.net/
  4. // @version 5.0
  5. // @description Check and notify on https://idleontoolbox.com/dashboard with Telegram support
  6. // @author Tiande
  7. // @match https://idleontoolbox.com/*
  8. // @grant GM_notification
  9. // @grant GM_getValue
  10. // @grant GM_setValue
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. var interval = 5 * 60 * 1000; // check status every 5m
  18. var refreshInterval = 10.1 * 60 * 1000; // auto refresh to Dashboard every 10m
  19.  
  20. // Telegram Bot API Token
  21. var tgbotToken = 'YOUR BOT TOKEN';
  22. // Telegram user ID to send the message to
  23. var tguserId = 'YOUR USER ID';
  24.  
  25. // lable text under player's name
  26. var whichFull = /(is full)/; // (is full|being full|xxx) etc.
  27. // skill to notify
  28. var skill = /(SkillName|Refinery)/; // (Refinery|Cooking|Arena) etc.
  29. // bookcount to check
  30. var bookcount = 3;
  31.  
  32. var notificationPermission = GM_getValue('notificationPermission');
  33. var isFunctionEnabled = true;
  34. var intervalId; // Store interval ID for pausing and resuming
  35.  
  36. // tg send
  37. function tgsendMessage(message) {
  38. var tgurl = 'https://api.telegram.org/bot' + tgbotToken + '/sendMessage';
  39. var tgparams = 'chat_id=' + tguserId + '&text=' + encodeURIComponent(message);
  40.  
  41. var tgxhr = new XMLHttpRequest();
  42. tgxhr.open('POST', tgurl, true);
  43. tgxhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  44. tgxhr.onreadystatechange = function() {
  45. if (tgxhr.readyState == 4 && tgxhr.status == 200) {
  46. console.log('Message sent successfully!');
  47. }
  48. };
  49. tgxhr.onerror = function(error) {
  50. console.error('Error sending message:', error);
  51. };
  52. tgxhr.send(tgparams);
  53. }
  54.  
  55. // autorefresh time
  56. var refreshId;
  57. // refreshPage
  58. function refreshPage() {
  59. // 检查当前页面的URL是否为'https://idleontoolbox.com/dashboard'
  60. if (isFunctionEnabled) {
  61. location.href = 'https://idleontoolbox.com/dashboard'; // 如果是,则刷新页面
  62. } else {
  63. // 如果不是,则等待下一个刷新时间间隔
  64. refreshId = setInterval(refreshPage, refreshInterval);
  65. }
  66. }
  67.  
  68. function toggleRefresh() {
  69. if (isFunctionEnabled) {
  70. intervalId = setInterval(startInterval, interval); // 启动定时器
  71. refreshId = setInterval(refreshPage, refreshInterval);
  72. } else {
  73. clearInterval(intervalId); // 清除定时器
  74. clearInterval(refreshId);
  75. }
  76. }
  77. toggleRefresh(); // 在脚本启动时调用一次,以确保定时器已启动
  78.  
  79. // Preload audio
  80. var audio = new Audio();
  81. audio.src = 'https://github.com/Tiande/IdelonCheck/raw/main/iphonewake.wav';
  82.  
  83.  
  84. // Add CSS styles
  85. var style = document.createElement('style');
  86. style.innerHTML = `
  87. #toggleButtonContainer {
  88. position: fixed;
  89. top: 50%;
  90. left: calc(50% + 100px);
  91. transform: translate(-50%, -50%);
  92. display: flex;
  93. align-items: center;
  94. padding: 5px;
  95. background: green; /* Green color for default enabled state */
  96. color: white;
  97. border-radius: 5px;
  98. font-family: Arial, sans-serif;
  99. font-size: 14px;
  100. box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3);
  101. z-index: 99999;
  102. user-select: none;
  103. cursor: move;
  104. }
  105. #toggleButtonContainer.off {
  106. background: red; /* Red color for disabled state */
  107. }
  108. #toggleButton {
  109. padding: 5px 10px;
  110. border: none;
  111. border-radius: 5px;
  112. background: transparent;
  113. cursor: pointer;
  114. outline: none;
  115. }
  116. .drag-handle {
  117. cursor: move;
  118. }
  119. #produceCheck {
  120. background-color: black;
  121. color: white;
  122. padding: 5px;
  123. border-radius: 5px;
  124. margin-right: 5px;
  125. }
  126. `;
  127. document.head.appendChild(style);
  128.  
  129. createToggleButton(); // Create toggle button on script execution
  130. startInterval(); // Start interval on script execution
  131.  
  132. function createToggleButton() {
  133. var toggleButtonContainer = document.createElement('div');
  134. toggleButtonContainer.id = 'toggleButtonContainer';
  135. toggleButtonContainer.classList.add('drag-handle');
  136. var produceCheck = document.createElement('span');
  137. produceCheck.id = 'produceCheck';
  138. produceCheck.textContent = 'Produce Check: ';
  139. toggleButtonContainer.appendChild(produceCheck);
  140. var toggleButton = document.createElement('button');
  141. toggleButton.id = 'toggleButton';
  142. toggleButton.addEventListener('click', toggleFunction);
  143. toggleButtonContainer.appendChild(toggleButton);
  144. document.body.appendChild(toggleButtonContainer);
  145. updateButtonStyle();
  146. makeDraggable(toggleButtonContainer);
  147. }
  148.  
  149. function updateButtonStyle() {
  150. var toggleButtonContainer = document.getElementById('toggleButtonContainer');
  151. toggleButtonContainer.classList.toggle('off', !isFunctionEnabled);
  152. var toggleButton = document.getElementById('toggleButton');
  153. toggleButton.innerHTML = isFunctionEnabled ? 'ON' : 'OFF';
  154. }
  155.  
  156. function toggleFunction() {
  157. isFunctionEnabled = !isFunctionEnabled;
  158. updateButtonStyle();
  159. toggleRefresh(); // 根据isFunctionEnabled的值启用或暂停定时器
  160. }
  161.  
  162. function startInterval() {
  163. // sth is full
  164. var prepareelements = document.querySelectorAll('img[aria-label]');
  165. var elements = Array.from(prepareelements).filter(function(element) {
  166. return whichFull.test(element.getAttribute('aria-label'));
  167. });
  168.  
  169. if (elements.length > 0) {
  170. var roleNames = [];
  171. elements.forEach(function(element) {
  172. var parentDiv = element.closest('.MuiCardContent-root');
  173. if (parentDiv) {
  174. var roleNameElement = parentDiv.querySelector('.MuiTypography-root.MuiTypography-body1.css-9l3uo3');
  175. if (roleNameElement) {
  176. var roleName = roleNameElement.textContent.trim();
  177. roleNames.push(roleName);
  178. }
  179. }
  180. });
  181.  
  182. if (roleNames.length > 0) {
  183. var message = roleNames.join(' + ') + ' is full!';
  184. showNotification(message);
  185. audio.play();
  186. if (tguserId !== 'your user ID') {
  187. tgsendMessage(message);
  188. }
  189. }
  190. }
  191.  
  192. // skill is ready
  193. var prepareelements = document.querySelectorAll('img[aria-label]');
  194. var elements = Array.from(prepareelements).filter(function(element) {
  195. return skill.test(element.getAttribute('aria-label'));
  196. });
  197.  
  198. if (elements.length > 0) {
  199. var roleNames = [];
  200. elements.forEach(function(element) {
  201. var parentDiv = element.closest('.MuiCardContent-root');
  202. if (parentDiv) {
  203. var roleNameElement = parentDiv.querySelector('.MuiTypography-root.MuiTypography-body1.css-9l3uo3');
  204. if (roleNameElement) {
  205. var roleName = roleNameElement.textContent.trim();
  206. roleNames.push(roleName);
  207. }
  208. }
  209. });
  210.  
  211. if (roleNames.length > 0) {
  212. var message = roleNames.join(' + ') + ' is Skillable!';
  213. showNotification(message);
  214. audio.play();
  215. if (tguserId !== 'your user ID') {
  216. tgsendMessage(message);
  217. }
  218. }
  219. }
  220.  
  221. // 追踪另一组元素
  222. var timeElements = document.querySelectorAll('.MuiTypography-root.MuiTypography-inherit');
  223. timeElements.forEach(function(timeElement) {
  224. var color = getComputedStyle(timeElement).color;
  225. var match = color.match(/^rgb\((\d+), (\d+), (\d+)\)$/);
  226. if (match && match[1] === '249' && match[2] === '29' && match[3] === '29') {
  227. // color 属性值为 rgb(249, 29, 29),视为捕获
  228. var message = 'Some work is done!';
  229. showNotification(message);
  230. audio.play();
  231. if (tguserId !== 'your user ID') {
  232. tgsendMessage(message);
  233. }
  234. }
  235. });
  236.  
  237. // Book count
  238. var bookCountElements = document.querySelectorAll('.MuiCardContent-root h4');
  239. // 遍历每个 <h4> 元素
  240. bookCountElements.forEach(function(element) {
  241. // 获取文本内容
  242. var text = element.textContent.trim();
  243. // 提取数字部分
  244. var count = parseInt(text.match(/\d+/)[0]);
  245. // 如果数字大于等于2,则发送通知
  246. if (count >= bookcount) {
  247. // 发送通知
  248. var message = 'The book count has exceeded the limit!';
  249. showNotification(message);
  250. audio.play();
  251. if (tguserId !== 'your user ID') {
  252. tgsendMessage(message);
  253. }
  254. }
  255. });
  256. }
  257.  
  258. function showNotification(message) {
  259. if (notificationPermission === 'granted') {
  260. GM_notification({
  261. text: message,
  262. title: 'Idleontoolbox Notification',
  263. timeout: 5000,
  264. onclick: function() {
  265. window.focus();
  266. }
  267. });
  268. } else {
  269. window.Notification.requestPermission().then(function(permission) {
  270. if (permission === 'granted') {
  271. GM_notification({
  272. text: message,
  273. title: 'Idleontoolbox Notification',
  274. timeout: 5000,
  275. onclick: function() {
  276. window.focus();
  277. }
  278. });
  279. }
  280. });
  281. }
  282. }
  283.  
  284. function makeDraggable(element) {
  285. let pos1 = 0,
  286. pos2 = 0,
  287. pos3 = 0,
  288. pos4 = 0;
  289.  
  290. element.onmousedown = dragMouseDown;
  291.  
  292. function dragMouseDown(e) {
  293. e = e || window.event;
  294. e.preventDefault();
  295. // get the mouse cursor position at startup:
  296. pos3 = e.clientX;
  297. pos4 = e.clientY;
  298. document.onmouseup = closeDragElement;
  299. // call a function whenever the cursor moves:
  300. document.onmousemove = elementDrag;
  301. }
  302.  
  303. function elementDrag(e) {
  304. e = e || window.event;
  305. e.preventDefault();
  306. // calculate the new cursor position:
  307. pos1 = pos3 - e.clientX;
  308. pos2 = pos4 - e.clientY;
  309. pos3 = e.clientX;
  310. pos4 = e.clientY;
  311. // set the element's new position:
  312. element.style.top = (element.offsetTop - pos2) + "px";
  313. element.style.left = (element.offsetLeft - pos1) + "px";
  314. }
  315.  
  316. function closeDragElement() {
  317. /* stop moving when mouse button is released:*/
  318. document.onmouseup = null;
  319. document.onmousemove = null;
  320. }
  321. }
  322.  
  323. })();