ONPJS

监控proof数量并在3分钟无变化时自动切换按钮状态

  1. // ==UserScript==
  2. // @name ONPJS
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description 监控proof数量并在3分钟无变化时自动切换按钮状态
  6. // @author TinYueUS@gmail.com
  7. // @match https://onprover.orochi.network/*
  8. // @run-at document-start
  9. // @grant GM_xmlhttpRequest
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // @connect onprover.orochi.network
  13. // @connect open.feishu.cn
  14. // ==/UserScript==
  15.  
  16. (function() {
  17. 'use strict';
  18.  
  19. // 添加设备名称配置
  20. const DEVICE_NAME = 'P-1'; // 你可以修改这个设备名称
  21. const FEISHU_WEBHOOK = ''; //飞书 WEBHOOK
  22.  
  23. let lastProofCount = null;
  24. let unchangedCount = 0;
  25. let isProving = true;
  26. let checkInterval = null;
  27. let isHandlingButtonState = false;
  28. let switchAttemptCount = 0; // 记录切换按钮尝试次数
  29. let lastSwitchProofCount = null; // 记录上次切换时的proof数量
  30. let cloudflareCheckInterval = null;
  31. if (FEISHU_WEBHOOK === '') {
  32. return;
  33. }
  34. // 发送飞书通知
  35. async function sendFeishuNotification(message) {
  36. try {
  37. await GM_xmlhttpRequest({
  38. method: 'POST',
  39. url: FEISHU_WEBHOOK,
  40. headers: {
  41. 'Content-Type': 'application/json'
  42. },
  43. data: JSON.stringify({
  44. msg_type: 'text',
  45. content: {
  46. text: `[${DEVICE_NAME}] ${message}`
  47. }
  48. })
  49. });
  50. console.log('飞书通知发送成功');
  51. } catch (error) {
  52. console.error('飞书通知发送失败:', error);
  53. }
  54. }
  55.  
  56. // 检查是否在Cloudflare验证页面
  57. function isCloudflarePage() {
  58. return document.title.includes('Cloudflare') ||
  59. document.querySelector('#challenge-running') !== null ||
  60. document.querySelector('#challenge-stage') !== null;
  61. }
  62.  
  63. // 等待Cloudflare验证完成
  64. function waitForCloudflare() {
  65. return new Promise((resolve) => {
  66. if (!isCloudflarePage()) {
  67. resolve();
  68. return;
  69. }
  70.  
  71. console.log('检测到Cloudflare验证,等待验证完成...');
  72.  
  73. let waitTime = 0;
  74. let notificationSent = false;
  75.  
  76. const checkCloudflare = () => {
  77. if (!isCloudflarePage()) {
  78. console.log('Cloudflare验证已完成');
  79. // 重置通知状态
  80. notificationSent = false;
  81. resolve();
  82. return;
  83. }
  84.  
  85. waitTime += 1;
  86.  
  87. // 当等待时间超过15秒且未发送过通知时发送通知
  88. if (waitTime >= 20 && !notificationSent) {
  89. sendFeishuNotification(`Cloudflare验证时间超过15秒!当前已等待${waitTime}秒`);
  90. notificationSent = true;
  91. }
  92.  
  93. setTimeout(checkCloudflare, 1000);
  94. };
  95.  
  96. checkCloudflare();
  97. });
  98. }
  99.  
  100. // 获取当前proof数量
  101. function getProofCount() {
  102. const proofElement = document.querySelector('p.text-24.font-doto.text-zk-blue-300.font-bold');
  103. if (proofElement) {
  104. return parseInt(proofElement.textContent.trim());
  105. }
  106. return null;
  107. }
  108.  
  109. // 获取当前按钮状态
  110. function getButtonState() {
  111. const buttons = document.querySelectorAll('button');
  112. for (const button of buttons) {
  113. if (button.textContent.includes('prove')) {
  114. return 'prove';
  115. } else if (button.textContent.includes('Stop proving')) {
  116. return 'stop';
  117. }
  118. }
  119. return null;
  120. }
  121.  
  122. // 点击按钮的函数
  123. function clickButton() {
  124. const buttons = document.querySelectorAll('button');
  125. for (const button of buttons) {
  126. if (button.textContent.includes('prove') || button.textContent.includes('Stop proving')) {
  127. console.log('正在点击按钮:', button.textContent.trim());
  128. button.click();
  129. isProving = !isProving;
  130. break;
  131. }
  132. }
  133. }
  134.  
  135. // 检查proof数量是否变化
  136. function checkProofCount() {
  137. const currentCount = getProofCount();
  138.  
  139. if (currentCount === null) {
  140. console.log('无法获取proof数量,等待页面加载...');
  141. return;
  142. }
  143.  
  144. if (lastProofCount === null) {
  145. lastProofCount = currentCount;
  146. console.log('初始化proof数量:', currentCount);
  147. return;
  148. }
  149.  
  150. // 如果proof数量发生变化,重置所有计数器
  151. if (currentCount !== lastProofCount) {
  152. console.log(`Proof数量已变化: ${lastProofCount} -> ${currentCount}`);
  153. unchangedCount = 0;
  154. lastProofCount = currentCount;
  155. switchAttemptCount = 0;
  156. lastSwitchProofCount = null;
  157. return;
  158. }
  159.  
  160. if (currentCount === lastProofCount) {
  161. unchangedCount++;
  162. console.log(`Proof数量未变化: ${currentCount}, 已持续${unchangedCount}次检查`);
  163.  
  164. // 检查是否需要切换按钮状态或刷新页面
  165. if (!isHandlingButtonState) {
  166. const currentState = getButtonState();
  167.  
  168. // 在Stop proving状态下,连续10次未变化时刷新页面
  169. if (currentState === 'stop' && unchangedCount >= 10) {
  170. console.log('Stop proving状态下连续10次proof数量未变化,准备刷新页面');
  171. // 保存当前状态
  172. GM_setValue('lastProofCount', currentCount);
  173. GM_setValue('switchAttemptCount', switchAttemptCount);
  174. // 使用location.reload()进行页面刷新
  175. window.location.reload();
  176. return;
  177. }
  178.  
  179. // 在prove状态下,连续2次未变化时切换到Stop proving
  180. if (currentState === 'prove' && unchangedCount === 2) {
  181. console.log('Proof数量连续两次未变化且按钮为prove状态,准备切换到Stop proving状态');
  182. isHandlingButtonState = true;
  183. handleButtonState();
  184. // 重置unchangedCount
  185. unchangedCount = 0;
  186. }
  187. }
  188. }
  189. }
  190.  
  191. // 等待按钮状态切换
  192. function waitForButtonState(targetState) {
  193. return new Promise((resolve) => {
  194. let attempts = 0;
  195. const maxAttempts = 30; // 最多等待30秒
  196.  
  197. const checkButton = () => {
  198. const currentState = getButtonState();
  199. if (currentState === targetState) {
  200. console.log(`按钮已切换到${targetState}状态`);
  201. resolve(true);
  202. return;
  203. }
  204.  
  205. attempts++;
  206. if (attempts >= maxAttempts) {
  207. console.log(`等待按钮切换到${targetState}状态超时`);
  208. resolve(false);
  209. return;
  210. }
  211.  
  212. setTimeout(checkButton, 1000);
  213. };
  214. checkButton();
  215. });
  216. }
  217.  
  218. // 处理按钮状态切换
  219. async function handleButtonState() {
  220. try {
  221. const currentState = getButtonState();
  222. console.log('当前按钮状态:', currentState);
  223.  
  224. // 记录切换前的proof数量
  225. lastSwitchProofCount = getProofCount();
  226.  
  227. if (currentState === 'prove') {
  228. // 如果当前是prove状态,点击切换到stop状态
  229. console.log('切换到Stop proving状态');
  230. clickButton();
  231. // 等待按钮状态变化
  232. await waitForButtonState('stop');
  233. // 额外等待5秒确保状态稳定
  234. await new Promise(resolve => setTimeout(resolve, 5000));
  235. } else if (currentState === 'stop') {
  236. // 如果当前是stop状态,等待一段时间后点击切换到prove状态
  237. console.log('当前是Stop proving状态,等待5秒后切换到prove状态');
  238. await new Promise(resolve => setTimeout(resolve, 5000));
  239. clickButton();
  240. // 等待按钮状态变化
  241. await waitForButtonState('prove');
  242. // 额外等待5秒确保状态稳定
  243. await new Promise(resolve => setTimeout(resolve, 5000));
  244. }
  245.  
  246. // 重置计数器
  247. unchangedCount = 0;
  248. console.log('按钮状态切换完成,重置计数器');
  249. } finally {
  250. isHandlingButtonState = false;
  251. }
  252. }
  253.  
  254. // 主循环
  255. function mainLoop() {
  256. checkProofCount();
  257. }
  258.  
  259. // 等待页面加载完成
  260. async function waitForPageLoad() {
  261. // 等待Cloudflare验证完成
  262. await waitForCloudflare();
  263.  
  264. return new Promise((resolve) => {
  265. let loadingAttempts = 0;
  266. let notificationSent = false;
  267.  
  268. const checkPage = () => {
  269. const proofElement = document.querySelector('p.text-24.font-doto.text-zk-blue-300.font-bold');
  270. const buttons = document.querySelectorAll('button');
  271.  
  272. if (proofElement && buttons.length > 0) {
  273. console.log('页面加载完成,开始监控');
  274. resolve();
  275. return;
  276. }
  277.  
  278. loadingAttempts++;
  279. console.log(`等待页面加载...${loadingAttempts}次`);
  280.  
  281. // 当等待次数超过15次且未发送过通知时发送通知
  282. if (loadingAttempts >= 15 && !notificationSent) {
  283. sendFeishuNotification(`页面加载时间过长!已尝试加载 ${loadingAttempts} 次`);
  284. notificationSent = true;
  285. }
  286.  
  287. setTimeout(checkPage, 1000);
  288. };
  289. checkPage();
  290. });
  291. }
  292.  
  293. // 启动脚本
  294. async function startScript() {
  295. try {
  296. // 恢复之前保存的状态
  297. const savedProofCount = GM_getValue('lastProofCount');
  298. const savedSwitchAttemptCount = GM_getValue('switchAttemptCount');
  299. if (savedProofCount !== undefined) {
  300. lastProofCount = savedProofCount;
  301. switchAttemptCount = savedSwitchAttemptCount;
  302. console.log('恢复之前的状态:', { lastProofCount, switchAttemptCount });
  303. }
  304.  
  305. await waitForPageLoad();
  306.  
  307. // 清除可能存在的旧定时器
  308. if (checkInterval) {
  309. clearInterval(checkInterval);
  310. }
  311.  
  312. // 设置新的定时器,每10秒执行一次
  313. checkInterval = setInterval(mainLoop, 10 * 1000);
  314.  
  315. // 立即执行一次
  316. mainLoop();
  317.  
  318. console.log('脚本已启动,每10秒检查一次');
  319. } catch (error) {
  320. console.error('脚本启动失败:', error);
  321. }
  322. }
  323.  
  324. // 启动脚本
  325. startScript();
  326. })();