Greasy Fork is available in English.
Hook the wait timers for websites that use them to delay content
当前为
// ==UserScript==
// @name Time Hooker
// @namespace https://tampermonkey.net/
// @version 1.5
// @description Hook the wait timers for websites that use them to delay content
// @author Niteesh
// @match *://*/*
// @grant none
// @license MIT
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
const originalSetInterval = window.setInterval;
const originalSetTimeout = window.setTimeout;
const cloudflareIndicators = [
"Checking your browser", // Common text
"verify your browser", // Additional text
"cloudflare", // May appear in class or ID names
"turnstile" // Cloudflare CAPTCHA widget class
];
function isCloudflareVerificationPresent() {
return [...document.querySelectorAll('*')].some(el => {
const text = el.textContent?.toLowerCase() || "";
const idOrClass = (el.id || "") + " " + (el.className || "");
return cloudflareIndicators.some(indicator =>
text.includes(indicator.toLowerCase()) ||
idOrClass.toLowerCase().includes(indicator.toLowerCase())
);
});
}
function print() {
console.log(...arguments);
}
function clearAllTimers() {
const highestIntervalId = setInterval(() => {}, 0);
for (let i = 0; i <= highestIntervalId; i++) {
clearInterval(i);
}
const highestTimeoutId = setTimeout(() => {}, 0);
for (let i = 0; i <= highestTimeoutId; i++) {
clearTimeout(i);
}
print('Cleared all active timers.');
}
function restoreOriginalTimers() {
window.setInterval = originalSetInterval;
window.setTimeout = originalSetTimeout;
print("Restoring done.");
}
function interceptTimers(val) {
window.setTimeout = function(callback, delay, ...args) {
const newDelay = delay / val;
print(`[Intercepted] setTimeout: ${delay}ms -> ${newDelay}ms`);
return originalSetTimeout(callback, newDelay, ...args);
};
window.setInterval = function(callback, interval, ...args) {
const newInterval = interval / val;
print(`[Intercepted] setInterval: ${interval}ms -> ${newInterval}ms`);
return originalSetInterval(callback, newInterval, ...args);
};
}
interceptTimers(15);
let timerUsed = false;
let potentialTimers;
window.onload = function() {
potentialTimers = [...document.querySelectorAll('*')].filter(el => {
const text = el.textContent.trim().toLowerCase();
const waitRegexes = [
/wait\s+\d+\s+seconds/i,
/please\s+wait/i,
/click\s+on\s+(image|button)/i,
/click\s+and\s+wait\s+\d+/i
];
return waitRegexes.some(regex => regex.test(text));
//return /wait\s+\d+\s+seconds/i.test(text) || /please\s+wait/i.test(text);
});
if (potentialTimers.length > 0) {
print("Potential timers detected:", potentialTimers);
timerUsed = true;
} else {
print("No timers detected.");
restoreOriginalTimers();
if (isCloudflareVerificationPresent()) {
print("Cloudflare verification detected...");
} else {
originalSetTimeout(_ => {
clearAllTimers();
}, 3000);
}
}
if (timerUsed) {
print("Hacking...");
originalSetInterval(() => {
const button = document.querySelector('button:enabled, .clickable');
if (button.textContent.toLowerCase().includes('continue') || button.textContent.toLowerCase().includes('get link')) {
button.click()
}
let clickable = [];
document.addEventListener('DOMContentLoaded', function() {
clickable = [...document.querySelectorAll('*')].find(el =>
(el.textContent.toLowerCase().includes("continue") || el.textContent.toLowerCase().includes("get link")) &&
(el.tagName === 'BUTTON' || el.tagName === 'A') && !el.disabled
);
});
if (clickable) {
print("Clickable element found:", clickable);
if (clickable.tagName === 'BUTTON') {
clickable.click();
} else if (clickable.tagName === 'A') {
print(clickable.href);
if (clickable.href !== window.location.href) {
window.location.replace(clickable.href);
}
}
// else {
// print("just trying to click, do you find the exact button?");
// clickable.click();
// }
} else {
print("No clickable element found.");
}
}, 4000);
// dynamically searching for a button
const observer = new MutationObserver((mutations) => {
mutations.forEach(mutation => {
let button;
document.addEventListener('DOMContentLoaded', function() {
button = [...document.querySelectorAll('*')].find(el =>
(el.textContent.toLowerCase().includes("continue") || el.textContent.toLowerCase().includes("get link")) &&
(el.tagName === 'BUTTON' || el.tagName === 'A') && !el.disabled
);
});
if (button) {
print("Dynamically loaded 'continue' button found:", button);
observer.disconnect(); // Stop observing once found
button.click();
print("clicked");
}
});
});
// Start observing changes in the DOM
observer.observe(document.body, {
childList: true,
subtree: true
});
} else {
}
}
})();