Time Hooker

Hook the wait timers for websites that use them to delay content

目前为 2024-12-04 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Time Hooker
  3. // @namespace https://tampermonkey.net/
  4. // @version 1.5
  5. // @description Hook the wait timers for websites that use them to delay content
  6. // @author Niteesh
  7. // @match *://*/*
  8. // @grant none
  9. // @license MIT
  10. // @run-at document-start
  11. // ==/UserScript==
  12.  
  13.  
  14. (function() {
  15. 'use strict';
  16. const originalSetInterval = window.setInterval;
  17. const originalSetTimeout = window.setTimeout;
  18. const cloudflareIndicators = [
  19. "Checking your browser", // Common text
  20. "verify your browser", // Additional text
  21. "cloudflare", // May appear in class or ID names
  22. "turnstile" // Cloudflare CAPTCHA widget class
  23. ];
  24. function isCloudflareVerificationPresent() {
  25. return [...document.querySelectorAll('*')].some(el => {
  26. const text = el.textContent?.toLowerCase() || "";
  27. const idOrClass = (el.id || "") + " " + (el.className || "");
  28. return cloudflareIndicators.some(indicator =>
  29. text.includes(indicator.toLowerCase()) ||
  30. idOrClass.toLowerCase().includes(indicator.toLowerCase())
  31. );
  32. });
  33. }
  34. function print() {
  35. console.log(...arguments);
  36. }
  37. function clearAllTimers() {
  38. const highestIntervalId = setInterval(() => {}, 0);
  39. for (let i = 0; i <= highestIntervalId; i++) {
  40. clearInterval(i);
  41. }
  42. const highestTimeoutId = setTimeout(() => {}, 0);
  43. for (let i = 0; i <= highestTimeoutId; i++) {
  44. clearTimeout(i);
  45. }
  46. print('Cleared all active timers.');
  47. }
  48. function restoreOriginalTimers() {
  49. window.setInterval = originalSetInterval;
  50. window.setTimeout = originalSetTimeout;
  51. print("Restoring done.");
  52. }
  53. function interceptTimers(val) {
  54. window.setTimeout = function(callback, delay, ...args) {
  55. const newDelay = delay / val;
  56. print(`[Intercepted] setTimeout: ${delay}ms -> ${newDelay}ms`);
  57. return originalSetTimeout(callback, newDelay, ...args);
  58. };
  59.  
  60. window.setInterval = function(callback, interval, ...args) {
  61. const newInterval = interval / val;
  62. print(`[Intercepted] setInterval: ${interval}ms -> ${newInterval}ms`);
  63. return originalSetInterval(callback, newInterval, ...args);
  64. };
  65. }
  66. interceptTimers(15);
  67. let timerUsed = false;
  68. let potentialTimers;
  69. window.onload = function() {
  70. potentialTimers = [...document.querySelectorAll('*')].filter(el => {
  71. const text = el.textContent.trim().toLowerCase();
  72. const waitRegexes = [
  73. /wait\s+\d+\s+seconds/i,
  74. /please\s+wait/i,
  75. /click\s+on\s+(image|button)/i,
  76. /click\s+and\s+wait\s+\d+/i
  77. ];
  78. return waitRegexes.some(regex => regex.test(text));
  79. //return /wait\s+\d+\s+seconds/i.test(text) || /please\s+wait/i.test(text);
  80. });
  81. if (potentialTimers.length > 0) {
  82. print("Potential timers detected:", potentialTimers);
  83. timerUsed = true;
  84. } else {
  85. print("No timers detected.");
  86. restoreOriginalTimers();
  87. if (isCloudflareVerificationPresent()) {
  88. print("Cloudflare verification detected...");
  89. } else {
  90. originalSetTimeout(_ => {
  91. clearAllTimers();
  92. }, 3000);
  93. }
  94. }
  95. if (timerUsed) {
  96. print("setting up...");
  97. originalSetInterval(() => {
  98. const button = document.querySelector('button:enabled, .clickable');
  99. let clickable = [];
  100. clickable = [...document.querySelectorAll('*')].find(el =>
  101. (el.textContent.toLowerCase().includes("continue") || el.textContent.toLowerCase().includes("get link") || el.textContent.toLowerCase().includes("robot")) &&
  102. (el.tagName === 'BUTTON' || el.tagName === 'A') && !el.disabled
  103. );
  104. if (clickable) {
  105. print("Clickable element found:", clickable);
  106. if (clickable.tagName === 'BUTTON') {
  107. clickable.click();
  108. } else if (clickable.tagName === 'A') {
  109. print(clickable.href);
  110. if (clickable.href !== window.location.href) {
  111. window.location.replace(clickable.href);
  112. }
  113. }
  114. // else {
  115. // print("just trying to click, do you find the exact button?");
  116. // clickable.click();
  117. // }
  118. } else {
  119. print("No clickable element found.");
  120. }
  121. }, 1000);
  122. // dynamically searching for a button
  123. const observer = new MutationObserver((mutations) => {
  124. mutations.forEach(mutation => {
  125. const button = [...document.querySelectorAll('*')].find(el =>
  126. (el.textContent.toLowerCase().includes("continue") || el.textContent.toLowerCase().includes("get link")) &&
  127. (el.tagName === 'BUTTON' || el.tagName === 'A') && !el.disabled
  128. );
  129. if (button) {
  130. print("Dynamically loaded 'continue' button found:", button);
  131. observer.disconnect(); // Stop observing once found
  132. button.click();
  133. print("clicked");
  134. }
  135. });
  136. });
  137. // Start observing changes in the DOM
  138. observer.observe(document.body, {
  139. childList: true,
  140. subtree: true
  141. });
  142. } else {
  143. }
  144. }
  145.  
  146. })();

QingJ © 2025

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