// ==UserScript==
// @name Time Hooker (V57.0 - External Final Guard)
// @namespace https://tampermonkey.net/
// @version 57.0
// @description External and final destination links now always stay manual, while verified intermediate steps, honest two-step learning, and guarded VPlink automation remain fast.
// @author rehan & Pankaj034
// @match *://*/*
// @match file:///*
// @run-at document-start
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// @connect raw.githubusercontent.com
// @connect githubusercontent.com
// @connect github.io
// @license GPL-3.0-or-later
// @homepageURL https://greasyfork.org/en/scripts/569833
// @supportURL https://greasyfork.org/en/scripts/569833/feedback
// @updateURL https://raw.githubusercontent.com/subscriptions-dot/time-hooker-tools/main/userscripts/time-hooker.user.js
// @downloadURL https://raw.githubusercontent.com/subscriptions-dot/time-hooker-tools/main/userscripts/time-hooker.user.js
// @icon https://www.google.com/s2/favicons?sz=64&domain=greasyfork.org
// ==/UserScript==
(function() {
'use strict';
const STORAGE_KEY = "th_v19_global_settings";
// --- REMOTE RULES SYNC (stable, optional) ---
// One hosted JSON adds/updates site rules for every device with NO re-publish.
// Change this URL to your own raw JSON (and add a matching @connect host above).
// If the URL is unreachable, the script silently keeps using cached + built-in rules โ it never blocks the page.
const REMOTE_RULES_URL = "https://raw.githubusercontent.com/subscriptions-dot/time-hooker-tools/main/rules/time-hooker-rules.json";
const REMOTE_CACHE_KEY = "th_remote_rules_cache";
const REMOTE_TS_KEY = "th_remote_rules_ts";
const REMOTE_REFRESH_MS = 86400000; // refresh at most once per day
window.addEventListener('TH_SAVE_GLOBAL', function(e) {
try {
GM_setValue(STORAGE_KEY, JSON.stringify(e.detail || {}));
} catch(e) {}
});
let savedData = GM_getValue(STORAGE_KEY);
let remoteRulesCached = null;
try { remoteRulesCached = GM_getValue(REMOTE_CACHE_KEY) || null; } catch(e) { remoteRulesCached = null; }
const mainPageLogic = function(savedStr, remoteStr) {
const isIframe = window.top !== window.self;
const DEFAULTS = { enabled: false, skipTimers: true, speed: 15, aggroBypass: true, smartVerifyFlow: false, waitUntilTimerMoves: false, safeCountdownMode: true, videoSpeed: true, autoClick: false, autoFlowSkip: false, universalFlow: false, antiAdblock: true, highlight: true, pinMode: true, topOffset: 0, menuLeft: '', menuTop: '', menuExpanded: true };
const PROFILE_KEYS = ['enabled', 'skipTimers', 'speed', 'aggroBypass', 'smartVerifyFlow', 'waitUntilTimerMoves', 'safeCountdownMode', 'videoSpeed', 'autoClick', 'autoFlowSkip', 'universalFlow', 'antiAdblock', 'highlight', 'pinMode', 'topOffset'];
const SITE_KEY = (location.hostname || (location.protocol === 'file:' ? 'local-file' : location.host) || 'unknown-site').toLowerCase();
const BUILTIN_SITE_PROFILES = {
'sb1.schemepro.org': { enabled: true, skipTimers: true, speed: 15, aggroBypass: false, videoSpeed: false, autoClick: false, autoFlowSkip: true, antiAdblock: true, highlight: true, pinMode: true, topOffset: 0 },
'sb2.schemepro.org': { enabled: true, skipTimers: true, speed: 15, aggroBypass: false, videoSpeed: false, autoClick: false, autoFlowSkip: true, antiAdblock: true, highlight: true, pinMode: true, topOffset: 0 },
'lksfy.com': { enabled: true, skipTimers: true, speed: 15, aggroBypass: false, smartVerifyFlow: false, waitUntilTimerMoves: false, videoSpeed: false, autoClick: false, autoFlowSkip: false, antiAdblock: true, highlight: true, pinMode: true, topOffset: 0 },
'darkguruji.com': { enabled: true, skipTimers: true, speed: 15, aggroBypass: false, smartVerifyFlow: false, waitUntilTimerMoves: false, safeCountdownMode: true, videoSpeed: false, autoClick: false, autoFlowSkip: true, antiAdblock: true, highlight: true, pinMode: true, topOffset: 0 },
'startuplearners.com': { enabled: true, skipTimers: true, speed: 15, aggroBypass: false, smartVerifyFlow: false, waitUntilTimerMoves: false, safeCountdownMode: true, videoSpeed: false, autoClick: false, autoFlowSkip: true, antiAdblock: true, highlight: true, pinMode: true, topOffset: 0 },
'privatejobbeta.com': { enabled: true, skipTimers: true, speed: 15, aggroBypass: false, smartVerifyFlow: false, waitUntilTimerMoves: false, safeCountdownMode: true, videoSpeed: false, autoClick: false, autoFlowSkip: true, antiAdblock: true, highlight: true, pinMode: true, topOffset: 0 },
'rempo.xyz': { enabled: true, skipTimers: true, speed: 15, aggroBypass: false, smartVerifyFlow: false, waitUntilTimerMoves: false, safeCountdownMode: true, videoSpeed: false, autoClick: false, autoFlowSkip: true, antiAdblock: true, highlight: true, pinMode: true, topOffset: 0 },
'genas.xyz': { enabled: true, skipTimers: true, speed: 15, aggroBypass: false, smartVerifyFlow: false, waitUntilTimerMoves: false, safeCountdownMode: true, videoSpeed: false, autoClick: false, autoFlowSkip: true, antiAdblock: true, highlight: true, pinMode: true, topOffset: 0 },
'vplink.in': { enabled: true, skipTimers: true, speed: 15, aggroBypass: false, smartVerifyFlow: false, waitUntilTimerMoves: false, safeCountdownMode: true, videoSpeed: false, autoClick: false, autoFlowSkip: true, antiAdblock: true, highlight: true, pinMode: true, topOffset: 0 },
'vacancymode.in': { enabled: true, skipTimers: true, speed: 15, aggroBypass: false, smartVerifyFlow: false, waitUntilTimerMoves: false, safeCountdownMode: true, videoSpeed: false, autoClick: false, autoFlowSkip: true, universalFlow: true, antiAdblock: true, highlight: true, pinMode: true, topOffset: 0 }
};
// Applied to sites the script has learned on its own (or that the user added via "Add This Site").
// Universal pattern detection stays on so unknown-but-similar pages keep working safely.
const LEARNED_PROFILE = { enabled: true, skipTimers: true, speed: 15, aggroBypass: true, smartVerifyFlow: false, waitUntilTimerMoves: false, safeCountdownMode: true, videoSpeed: false, autoClick: false, autoFlowSkip: true, universalFlow: true, antiAdblock: true, highlight: true, pinMode: true, topOffset: 0 };
// Remote rules: validated, sanitised per-site flags fetched from the hosted JSON (cached in GM storage).
// Only known PROFILE_KEYS are copied and type-coerced, so a malformed remote file can never break the engine.
let REMOTE_PROFILES = {};
(function() {
try {
const r = remoteStr ? (typeof remoteStr === 'string' ? JSON.parse(remoteStr) : remoteStr) : null;
if (r && typeof r === 'object' && r.sites && typeof r.sites === 'object') {
Object.keys(r.sites).forEach(function(host) {
const raw = r.sites[host];
if (!raw || typeof raw !== 'object') return;
const clean = {};
PROFILE_KEYS.forEach(function(k) {
if (!Object.prototype.hasOwnProperty.call(raw, k)) return;
if (k === 'speed' || k === 'topOffset') { const n = parseInt(raw[k], 10); if (Number.isFinite(n)) clean[k] = n; }
else clean[k] = !!raw[k];
});
const key = String(host || '').toLowerCase().trim();
if (key && Object.keys(clean).length) REMOTE_PROFILES[key] = clean;
});
}
} catch(e) { REMOTE_PROFILES = {}; }
})();
function sanitizeRecipes(raw) {
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return {};
const clean = {};
const safeNumber = (value, max) => {
const number = Number(value);
return Number.isFinite(number) ? Math.max(0, Math.min(max, number)) : 0;
};
Object.keys(raw).slice(0, 160).forEach(function(key) {
const item = raw[key];
if (!item || typeof item !== 'object' || Array.isArray(item)) return;
const step = item.step;
if (!step || typeof step !== 'object' || Array.isArray(step)) return;
const host = String(item.host || '').toLowerCase().slice(0, 180);
const shape = String(item.shape || '').slice(0, 240);
if (!host || !shape) return;
clean[String(key).slice(0, 460)] = {
host,
shape,
step: {
id: String(step.id || '').slice(0, 120),
text: String(step.text || '').slice(0, 120),
tag: String(step.tag || '').slice(0, 24),
role: String(step.role || '').slice(0, 40),
selector: String(step.selector || '').slice(0, 260),
hrefSig: String(step.hrefSig || '').slice(0, 320),
kind: step.kind === 'navigate' ? 'navigate' : 'click'
},
hits: safeNumber(item.hits, 999),
fails: safeNumber(item.fails, 999),
confirmations: safeNumber(item.confirmations, 999),
consecutiveFails: safeNumber(item.consecutiveFails, 20),
updatedAt: safeNumber(item.updatedAt, Number.MAX_SAFE_INTEGER),
lastFailAt: safeNumber(item.lastFailAt, Number.MAX_SAFE_INTEGER)
};
});
return clean;
}
function normalizeStore(saved) {
let parsed = {};
if (saved) {
try { parsed = (typeof saved === 'string') ? JSON.parse(saved) : saved; } catch(e) { parsed = {}; }
}
if (parsed && typeof parsed === 'object' && (parsed.global || parsed.profiles)) {
return {
global: Object.assign({}, DEFAULTS, parsed.global || {}),
profiles: (parsed.profiles && typeof parsed.profiles === 'object') ? parsed.profiles : {},
disabledBuiltins: (parsed.disabledBuiltins && typeof parsed.disabledBuiltins === 'object') ? parsed.disabledBuiltins : {},
macros: (parsed.macros && typeof parsed.macros === 'object') ? parsed.macros : {},
learnedSites: (parsed.learnedSites && typeof parsed.learnedSites === 'object') ? parsed.learnedSites : {},
siteTricks: (parsed.siteTricks && typeof parsed.siteTricks === 'object') ? parsed.siteTricks : {},
recipes: sanitizeRecipes(parsed.recipes)
};
}
return { global: Object.assign({}, DEFAULTS, parsed || {}), profiles: {}, disabledBuiltins: {}, macros: {}, learnedSites: {}, siteTricks: {}, recipes: {} };
}
function pickProfile(s) {
const p = {};
PROFILE_KEYS.forEach(k => { p[k] = s[k]; });
return p;
}
let store = normalizeStore(savedStr);
function isLearnedSite() { return !!(store.learnedSites && store.learnedSites[SITE_KEY]); }
let activeProfile = !!(store.profiles && store.profiles[SITE_KEY]);
let builtinSuggest = !activeProfile && !!BUILTIN_SITE_PROFILES[SITE_KEY] && !(store.disabledBuiltins && store.disabledBuiltins[SITE_KEY]);
let remoteSuggest = !activeProfile && !builtinSuggest && !!REMOTE_PROFILES[SITE_KEY] && !(store.disabledBuiltins && store.disabledBuiltins[SITE_KEY]);
let learnedSuggest = !activeProfile && !builtinSuggest && !remoteSuggest && isLearnedSite() && !(store.disabledBuiltins && store.disabledBuiltins[SITE_KEY]);
let suggestedProfile = builtinSuggest || remoteSuggest || learnedSuggest;
const suggestedData = builtinSuggest ? BUILTIN_SITE_PROFILES[SITE_KEY] : (remoteSuggest ? Object.assign({}, LEARNED_PROFILE, REMOTE_PROFILES[SITE_KEY]) : (learnedSuggest ? LEARNED_PROFILE : {}));
let S = Object.assign({}, DEFAULTS, store.global, suggestedProfile ? suggestedData : {}, activeProfile ? store.profiles[SITE_KEY] : {});
if (activeProfile && store.profiles[SITE_KEY] && !Object.prototype.hasOwnProperty.call(store.profiles[SITE_KEY], 'autoFlowSkip') && BUILTIN_SITE_PROFILES[SITE_KEY]) {
S.autoFlowSkip = !!BUILTIN_SITE_PROFILES[SITE_KEY].autoFlowSkip;
}
S.smartVerifyFlow = false;
S.waitUntilTimerMoves = false;
function saveStore() {
window.dispatchEvent(new CustomEvent('TH_SAVE_GLOBAL', { detail: JSON.parse(JSON.stringify(store)) }));
}
let recipesDirty = false;
let recipeSaveTimer = null;
function flushRecipeStore() {
if (!recipesDirty) return;
recipesDirty = false;
if (recipeSaveTimer) {
(window.th_nativeClearTimeout || clearTimeout)(recipeSaveTimer);
recipeSaveTimer = null;
}
saveStore();
}
function markRecipesDirty() {
recipesDirty = true;
if (recipeSaveTimer) return;
recipeSaveTimer = (window.th_nativeSetTimeout || setTimeout)(flushRecipeStore, 10000);
}
window.addEventListener('pagehide', flushRecipeStore);
function saveGlobalFromS() {
store.global = Object.assign({}, store.global, S);
saveStore();
}
function saveUiState() {
store.global = Object.assign({}, store.global, {
menuLeft: S.menuLeft,
menuTop: S.menuTop,
menuExpanded: S.menuExpanded
});
saveStore();
}
function refreshLiveFlags(s) {
window.th_masterEnabled = !!s.enabled;
window.th_skipTimersWanted = !!s.skipTimers;
window.th_smart_gate_armed = true;
window.th_gate_boost_armed = true;
window.th_skipTimersEnabled = !!s.skipTimers;
}
function setS(s) {
refreshLiveFlags(s);
if (suggestedProfile || activeProfile) saveSiteProfile();
else if (!activeProfile) saveGlobalFromS();
}
function saveSiteProfile() {
store.profiles = store.profiles || {};
store.profiles[SITE_KEY] = pickProfile(S);
if (store.disabledBuiltins && store.disabledBuiltins[SITE_KEY]) delete store.disabledBuiltins[SITE_KEY];
activeProfile = true;
suggestedProfile = false;
saveStore();
}
function useGlobalProfile() {
if (store.profiles && store.profiles[SITE_KEY]) delete store.profiles[SITE_KEY];
store.disabledBuiltins = store.disabledBuiltins || {};
store.disabledBuiltins[SITE_KEY] = true;
activeProfile = false;
suggestedProfile = false;
S = Object.assign(S, DEFAULTS, store.global);
refreshLiveFlags(S);
saveStore();
}
function isLearnableSite() {
return !!SITE_KEY && SITE_KEY !== 'unknown-site' && SITE_KEY !== 'local-file' && !BUILTIN_SITE_PROFILES[SITE_KEY];
}
function learnedSiteCount() {
return store.learnedSites ? Object.keys(store.learnedSites).length : 0;
}
function learnCurrentSite(reason) {
if (!isLearnableSite()) return false;
store.learnedSites = store.learnedSites || {};
const existing = store.learnedSites[SITE_KEY];
store.learnedSites[SITE_KEY] = {
reason: reason || (existing && existing.reason) || 'auto',
hits: ((existing && existing.hits) || 0) + 1,
ts: Math.floor(Date.now())
};
if (store.disabledBuiltins && store.disabledBuiltins[SITE_KEY]) delete store.disabledBuiltins[SITE_KEY];
saveStore();
return true;
}
function forgetCurrentSite() {
let changed = false;
if (store.learnedSites && store.learnedSites[SITE_KEY]) { delete store.learnedSites[SITE_KEY]; changed = true; }
if (store.profiles && store.profiles[SITE_KEY]) { delete store.profiles[SITE_KEY]; changed = true; activeProfile = false; }
store.disabledBuiltins = store.disabledBuiltins || {};
store.disabledBuiltins[SITE_KEY] = true;
suggestedProfile = false;
S = Object.assign(S, DEFAULTS, store.global);
refreshLiveFlags(S);
saveStore();
return changed;
}
// Manual "Add This Site": save a strong per-site profile AND remember it for the learned list.
function addSiteProfileManually() {
if (!isLearnableSite() && !BUILTIN_SITE_PROFILES[SITE_KEY]) return false;
S = Object.assign(S, LEARNED_PROFILE);
learnCurrentSite('manual');
saveSiteProfile();
refreshLiveFlags(S);
return true;
}
// Auto-learn during runtime: called when universal/flow logic confidently advances an unknown page.
let th_autoLearnArmed = !activeProfile && !builtinSuggest;
function autoLearnIfNew(reason) {
if (!th_autoLearnArmed || !isLearnableSite()) return;
if (store.learnedSites && store.learnedSites[SITE_KEY]) { th_autoLearnArmed = false; return; }
if (learnCurrentSite(reason || 'auto')) th_autoLearnArmed = false;
}
// Per-site trick learning: remember whether this site needed FORCE (stuck) or flowed normally as a TIMER,
// so next visit can act faster (lower the stuck threshold on known force-sites).
function getSiteTrick() {
return (store.siteTricks && store.siteTricks[SITE_KEY]) || '';
}
function recordSiteTrick(trick) {
if (!SITE_KEY || SITE_KEY === 'unknown-site' || SITE_KEY === 'local-file') return;
store.siteTricks = store.siteTricks || {};
if (store.siteTricks[SITE_KEY] === trick) return;
store.siteTricks[SITE_KEY] = trick;
saveStore();
}
function getStuckThreshold() {
return getSiteTrick() === 'force' ? 3 : 8;
}
window.isProActive = false;
window.proEngineInitialized = false;
window.th_masterEnabled = !!S.enabled;
window.th_skipTimersWanted = !!S.skipTimers;
window.th_smart_gate_armed = true;
window.th_gate_boost_armed = true;
window.th_skipTimersEnabled = !!S.skipTimers;
window.th_flowManualMode = false;
window.th_timer_last_value = null;
window.th_timer_observed_value = null;
window.th_timer_moving_since = 0;
window.th_gate_clicked = false;
window.th_gate_status = 'Macro: idle';
window.th_auto_executed = false; // ๐ฅ Global Lock for current target
window.th_auto_target_key = '';
window.th_verify_aggro_until = 0;
// --- ENGINE 1: V8.0 (Fast Engine) ---
function hookLogic(initialSpeed, S_enabled, S_skipTimers, S_smartFlow, S_waitUntilMoving, S_aggro, S_video) {
window.pankajSpeed = initialSpeed;
window.th_masterEnabled = !!S_enabled;
window.th_skipTimersWanted = !!S_skipTimers;
window.th_smart_gate_armed = true;
window.th_gate_boost_armed = true;
window.th_skipTimersEnabled = !!S_skipTimers;
const makeNative = (func, name) => { try { func.toString = () => `function ${name}() { [native code] }`; } catch(e){} };
const isCloudflare = () => Array.from(document.querySelectorAll('*')).some(el => {
if (!el || !el.textContent || el.textContent.length > 500) return false;
const t = el.textContent.toLowerCase(); return t.includes("checking") || t.includes("cloudflare");
});
const origSetInterval = window.setInterval;
const origSetTimeout = window.setTimeout;
const origDateNow = Date.now;
window.th_nativeSetTimeout = origSetTimeout;
let timeAppDate = origDateNow(); let lastTickDate = origDateNow();
const isSafeCountdownPage = () => {
try {
if (window.th_safeCountdownDetected) return true;
const hasTpGate = !!(document.getElementById('tpForm') && document.getElementById('tp98') && document.getElementById('tp-time'));
const hasDarkGurujiGate = !!(document.getElementById('tp-time') && (document.getElementById('tp-snp2') || document.getElementById('tp-generate') || document.getElementById('tp-wait1')));
const hasStartupGate = !!((document.getElementById('ce-time') || document.getElementById('link1s-time') || document.getElementById('countdown')) && (document.getElementById('btn6') || document.getElementById('btn7') || document.getElementById('startCountdownBtn') || document.getElementById('cross-snp2')));
const hasVpLinkGate = location.hostname === 'vplink.in' && !!(document.getElementById('get-link') || document.getElementById('gt-link') || document.getElementById('go-link'));
if (hasTpGate || hasDarkGurujiGate || hasStartupGate || hasVpLinkGate) return true;
const body = (document.body && document.body.innerText || '').toLowerCase();
return /\bplease\s+wait\s+\d{1,3}\s*seconds?\b/.test(body) && !!document.querySelector('form[name="tp"], #tpForm, #tp98, #tp-snp2, #tp-generate, #btn6, #btn7, #startCountdownBtn, #cross-snp2');
} catch(e) { return false; }
};
const getSpeedToUse = (kind) => {
if (window.th_captcha_present) return 1;
if (!(window.th_masterEnabled && window.th_skipTimersEnabled && !window.isProActive && !isCloudflare())) return 1;
if (window.th_flowManualMode && isSafeCountdownPage()) return 1;
if (kind === 'date' && isSafeCountdownPage()) return 1;
return window.pankajSpeed;
};
window.setTimeout = function(cb, delay, ...args) {
let speedToUse = getSpeedToUse('timeout');
return origSetTimeout(cb, delay / speedToUse, ...args);
};
window.setInterval = function(cb, interval, ...args) {
let speedToUse = getSpeedToUse('interval');
return origSetInterval(cb, interval / speedToUse, ...args);
};
Date.now = function() {
let now = origDateNow(); let delta = now - lastTickDate; lastTickDate = now;
let speedToUse = getSpeedToUse('date');
timeAppDate += (delta * speedToUse); return Math.floor(timeAppDate);
};
// Hook performance.now() with the SAME speed factor as Date.now, so requestAnimationFrame / perf-based
// countdowns also fast-forward, and Date.now vs performance.now stay consistent (avoids tamper detection).
try {
const perf = window.performance;
const origPerfNow = (perf && typeof perf.now === 'function') ? perf.now.bind(perf) : null;
if (origPerfNow) {
let timeAppPerf = origPerfNow(); let lastTickPerf = origPerfNow();
perf.now = function() {
let now = origPerfNow(); let delta = now - lastTickPerf; lastTickPerf = now;
let speedToUse = getSpeedToUse('date');
timeAppPerf += (delta * speedToUse); return timeAppPerf;
};
makeNative(perf.now, 'now');
}
} catch(e) {}
makeNative(window.setTimeout, 'setTimeout'); makeNative(window.setInterval, 'setInterval'); makeNative(Date.now, 'now');
}
try {
const script = document.createElement('script');
script.textContent = `(${hookLogic.toString()})(${S.speed}, ${S.enabled}, ${S.skipTimers}, ${S.smartVerifyFlow}, ${S.waitUntilTimerMoves}, ${S.aggroBypass}, ${S.videoSpeed});`;
(document.head || document.documentElement).appendChild(script);
script.remove();
} catch (e) { hookLogic(S.speed, S.enabled, S.skipTimers, S.smartVerifyFlow, S.waitUntilTimerMoves, S.aggroBypass, S.videoSpeed); }
// --- PRO ENGINE LIVE INJECTION ---
function initProEngine(initialSpeed) {
window.isDOMLoaded = true; window.isDOMRendered = true;
~function (global) {
var helper = function (eHookContext, timerContext, util) {
return {
applyUI: function () {},
applyGlobalAction: function (timer) {
global.setPankajProSpeed = function(speedMultiplier) { if (timer) timer.change(speedMultiplier > 0 ? 1 / speedMultiplier : 1); };
},
applyHooking: function () {
var _this = this;
eHookContext.hookReplace(window, 'setInterval', function (s) { return _this.getHookedTimerFunction('interval', s); });
eHookContext.hookReplace(window, 'setTimeout', function (s) { return _this.getHookedTimerFunction('timeout', s) });
eHookContext.hookBefore(window, 'clearInterval', function (m, a) { _this.redirectNewestId(a); });
eHookContext.hookBefore(window, 'clearTimeout', function (m, a) { _this.redirectNewestId(a); });
eHookContext.hookClass(window, 'Date', this.getHookedDateConstructor(), '_innerDate', ['now']);
timerContext._mDate = window.Date;
},
getHookedDateConstructor: function () { return function() { Object.defineProperty(this, '_innerDate', { value: new timerContext._Date(arguments.length ? arguments[0] : timerContext._Date.now()), writable: false }); }; },
getHookedTimerFunction: function (t, o) { return function() { arguments[1] *= timerContext._percentage; return o.apply(window, arguments); }; },
redirectNewestId: function (a) {}, registerShortcutKeys: function (t) {}, percentageChangeHandler: function (p) {}, hookShadowRoot: function () {}, hookDefine: function () {}, hookDefineDetails: function (t, k, o) { return [t, k, o]; }, suppressEvent: function (e, n) {}, changePlaybackRate: function (e, r) {}
}
};
var generate = function () { return function (u) { var ehc = this; var th = { _intervalIds: {}, _timeoutIds: {}, _auoUniqueId: 1, __percentage: 1.0/initialSpeed, _setInterval: window['setInterval'], _clearInterval: window['clearInterval'], _clearTimeout: window['clearTimeout'], _setTimeout: window['setTimeout'], _Date: window['Date'], __lastDatetime: new Date().getTime(), __lastMDatetime: new Date().getTime(), init: function () { var tc = this; var h = helper(ehc, tc, u); h.applyHooking(); Object.defineProperty(tc, '_percentage', { get: function () { return tc.__percentage; }, set: function (p) { tc.__percentage = p; return p; } }); h.applyGlobalAction(tc); }, change: function (p) { this._percentage = p; } }; th.init(); return th; } };
if (global.eHook) { global.eHook.plugins({ name: 'timer', mount: generate() }); }
else {
var s = document.createElement('script'); s.src = "https://greasyfork.org/scripts/372672-everything-hook/code/Everything-Hook.js";
s.onload = function() { global.eHook.plugins({ name: 'timer', mount: generate() }); };
document.documentElement.appendChild(s);
}
}(window);
window.proEngineInitialized = true;
}
// --- PANKAJ UI ---
function createFloatingMenu() {
if (document.getElementById("th-panel-root")) return;
const container = document.createElement("div"); container.id = "th-panel-root";
let pos = (S.menuLeft && S.menuTop) ? `left: ${S.menuLeft}; top: ${S.menuTop};` : `right: 20px; top: 20px;`;
container.style.cssText = `position: fixed; z-index: 2147483647; user-select: none; touch-action: none; ${pos}`;
document.body.appendChild(container);
const shadow = container.attachShadow({ mode: 'open' });
const panel = document.createElement("div");
panel.style.cssText = "width: 270px; background: rgba(15,15,20,0.95); border: 1px solid rgba(255,255,255,0.1); border-radius: 12px; color: white; font-family: 'Segoe UI', sans-serif; padding: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.6); backdrop-filter: blur(8px); font-size: 13px;";
panel.innerHTML = `
`;
shadow.appendChild(panel);
const $ = (id) => shadow.getElementById(id);
$("th-toggle-btn").onclick = () => { let h = $("th-content").style.display === "none"; $("th-content").style.display = h ? "flex" : "none"; $("th-toggle-btn").textContent = h ? "โ" : "+"; S.menuExpanded = h; saveUiState(); };
const paintMaster = () => {
const b = $("th-master-btn");
b.textContent = S.enabled ? "SCRIPT ON" : "SCRIPT OFF";
b.style.background = S.enabled ? "linear-gradient(90deg,#00c781,#00a8ff)" : "linear-gradient(90deg,#444,#222)";
};
const paintProfile = () => {
const status = $("th-profile-status");
if (status) status.textContent = `Profile: ${activeProfile ? 'this site' : (suggestedProfile ? (builtinSuggest ? 'built-in' : (remoteSuggest ? 'remote' : 'learned')) : 'global')} ยท ${SITE_KEY}`;
const lc = $("th-learned-count");
if (lc) lc.textContent = "Learned sites: " + learnedSiteCount();
const useGlobal = $("th-use-global");
if (useGlobal) useGlobal.style.opacity = activeProfile ? "1" : "0.55";
};
$("th-master-btn").onclick = () => {
S.enabled = !S.enabled;
if (!S.enabled) {
window.isProActive = false;
if (window.setPankajProSpeed) window.setPankajProSpeed(0);
document.querySelectorAll('video, audio').forEach(m => { try { m.playbackRate = 1; } catch(e) {} });
const proxy = document.getElementById("th-proxy-btn");
if (proxy) proxy.style.display = "none";
}
setS(S);
paintMaster();
paintProfile();
};
const saveSiteBtn = $("th-save-site");
if (saveSiteBtn) saveSiteBtn.onclick = () => {
saveSiteProfile();
paintProfile();
};
const useGlobalBtn = $("th-use-global");
if (useGlobalBtn) useGlobalBtn.onclick = () => {
useGlobalProfile();
refreshControls();
paintMaster();
paintProfile();
};
const addSiteBtn = $("th-add-site");
if (addSiteBtn) addSiteBtn.onclick = () => {
if (addSiteProfileManually()) {
refreshControls();
paintMaster();
paintProfile();
window.th_gate_status = "Saved this site โ";
} else {
window.th_gate_status = "Cannot add this page";
}
};
const forgetBtn = $("th-forget-site");
if (forgetBtn) forgetBtn.onclick = () => {
forgetCurrentSite();
refreshControls();
paintMaster();
paintProfile();
window.th_gate_status = "Forgot this site";
};
const forceBtn = $("th-force-skip");
if (forceBtn) forceBtn.onclick = () => {
try {
if (!S.enabled) { S.enabled = true; setS(S); paintMaster(); }
window.th_gate_status = "Force skipโฆ";
// 1) zero out any standalone visible countdown number (0-180)
Array.from(document.querySelectorAll('span,div,b,strong,p,h1,h2,h3,td,#tp-time,#ce-time,#link1s-time,#timer,#countdown')).slice(0, 500).forEach(el => {
if (isOwnUi(el) || el.children.length !== 0) return;
const t = (el.textContent || '').trim();
if (/^\d{1,3}$/.test(t) && parseInt(t, 10) <= 180) { try { el.textContent = '0'; } catch(e){} }
});
// 2) finish a recognised gate (reveals/zeros its own elements)
const st = getSafeCountdownState();
if (st && st.detected) finishSafeCountdown(st);
// 3) reveal + click the best continue/get-link target; keep final/Telegram links manual
const target = getFlowReadyTarget() || findBestActionTarget();
if (target) {
revealFlowElement(target);
if (isFinalVplinkTarget(target) || isTelegramHref(target.href || '')) {
if (S.highlight) target.style.setProperty('outline', '4px solid #00ffcc', 'important');
window.th_gate_status = "Final link ready โ tap it";
} else {
simulateClick(target);
window.th_gate_status = "Force: clicked " + (getTargetLabel(target) || '').slice(0, 22);
}
} else {
// No clickable target โ scan the page code for a hidden next-URL and go there.
const scannedNext = (getDeepScanAutoTarget() || (scanPageForNextUrl()[0] || ''));
if (scannedNext) { window.th_gate_status = "Force: next link โ"; location.href = scannedNext; }
else window.th_gate_status = "Force: no target found";
}
} catch(e) { window.th_gate_status = "Force skip error"; }
};
let isD = false, sx, sy, ix, iy;
const getPoint = (e) => {
const t = e.touches && e.touches[0];
return { x: t ? t.clientX : e.clientX, y: t ? t.clientY : e.clientY };
};
const startDrag = (e) => {
if (e.target.tagName === 'BUTTON' || e.target.tagName === 'INPUT') return;
const p = getPoint(e);
isD = true; sx = p.x; sy = p.y; ix = container.offsetLeft; iy = container.offsetTop; container.style.right = 'auto';
if (e.cancelable) e.preventDefault();
};
const moveDrag = (e) => {
if (!isD) return;
const p = getPoint(e);
container.style.left = (ix + (p.x - sx)) + 'px';
container.style.top = (iy + (p.y - sy)) + 'px';
if (e.cancelable) e.preventDefault();
};
const endDrag = () => { if(isD){ isD=false; S.menuLeft=container.style.left; S.menuTop=container.style.top; saveUiState(); } };
$("th-header").addEventListener("mousedown", startDrag);
$("th-header").addEventListener("touchstart", startDrag, { passive: false });
document.addEventListener("mousemove", moveDrag);
document.addEventListener("touchmove", moveDrag, { passive: false });
document.addEventListener("mouseup", endDrag);
document.addEventListener("touchend", endDrag);
const bind = (id, key) => { $(id).onchange = (e) => { S[key] = e.target.checked; setS(S); if (key === 'aggroBypass' && S[key]) window.th_live_aggro_request = Date.now(); }; };
bind("t-skip", "skipTimers"); bind("t-aggro", "aggroBypass"); bind("t-video", "videoSpeed"); bind("t-antiad", "antiAdblock"); bind("t-flow", "autoFlowSkip"); bind("t-universal", "universalFlow"); bind("t-highlight", "highlight"); bind("t-pin", "pinMode");
$("t-speed").oninput = (e) => { S.speed = e.target.value; setS(S); window.pankajSpeed = parseFloat(S.speed); const lab = $("t-speed-label"); if (lab) lab.textContent = S.speed + "x"; if (window.isProActive && window.setPankajProSpeed) window.setPankajProSpeed(parseFloat(S.speed)); };
$("t-pos").oninput = (e) => { S.topOffset = e.target.value; setS(S); };
shadow.querySelectorAll('.pro-btn').forEach(btn => {
btn.onclick = (e) => {
let v = parseInt(e.target.getAttribute('data-val'));
if (!S.enabled && v !== 0) { S.enabled = true; setS(S); paintMaster(); }
if (v === 0) { window.isProActive = false; if(window.setPankajProSpeed) window.setPankajProSpeed(0); }
else { window.isProActive = true; if(!window.proEngineInitialized) initProEngine(v); else if(window.setPankajProSpeed) window.setPankajProSpeed(v); }
};
});
function refreshControls() {
$("t-skip").checked = !!S.skipTimers;
$("t-aggro").checked = !!S.aggroBypass;
$("t-video").checked = !!S.videoSpeed;
$("t-antiad").checked = !!S.antiAdblock;
$("t-flow").checked = !!S.autoFlowSkip;
$("t-universal").checked = !!S.universalFlow;
$("t-highlight").checked = !!S.highlight;
$("t-pin").checked = !!S.pinMode;
$("t-speed").value = S.speed;
const lab = $("t-speed-label"); if (lab) lab.textContent = S.speed + "x";
$("t-pos").value = S.topOffset;
window.pankajSpeed = parseFloat(S.speed);
}
paintProfile();
setInterval(() => {
const status = $("th-gate-status");
if (status) {
const brain = window.th_page_brain;
const idle = !window.th_gate_status || window.th_gate_status === 'Macro: idle';
status.textContent = idle && brain ? ('BRAIN: ' + brain.state + ' โ ' + brain.reason) : (window.th_gate_status || 'BRAIN: observing page');
status.title = brain ? (brain.state + ': ' + brain.reason + (brain.target ? (' โ ' + brain.target) : '')) : '';
}
}, 1000);
}
if (!isIframe) {
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", createFloatingMenu); else createFloatingMenu();
// Self-healing panel: shortlink/timer pages often rebuild or wipe the DOM, which removes the menu.
// Re-inject it instantly (MutationObserver) and via a periodic safety net, and keep it on top.
const ensurePanel = () => {
try {
if (!document.body) return;
const root = document.getElementById("th-panel-root");
if (!root || !document.documentElement.contains(root)) { createFloatingMenu(); return; }
if (root.style.zIndex !== "2147483647") root.style.zIndex = "2147483647";
} catch(e) {}
};
try {
let pending = false;
const mo = new MutationObserver(() => {
if (pending) return;
pending = true;
(window.th_nativeSetTimeout || setTimeout)(() => { pending = false; ensurePanel(); }, 150);
});
const startObserver = () => { try { mo.observe(document.documentElement, { childList: true, subtree: true }); } catch(e) {} };
if (document.documentElement) startObserver(); else document.addEventListener("DOMContentLoaded", startObserver);
} catch(e) {}
setInterval(ensurePanel, 1500);
}
// --- CLICKER LOGIC ---
function simulateClick(el) {
if (!el) return;
['pointerdown','mousedown','mouseup','pointerup'].forEach(ev => el.dispatchEvent(new PointerEvent(ev, { bubbles: true, cancelable: true, view: window })));
el.click();
}
function isAutoFlowHost() {
return /(^|\.)((vplink\.in)|(vacancymode\.in)|(darkguruji\.com)|(startuplearners\.com)|(privatejobbeta\.com)|(rempo\.xyz)|(genas\.xyz))$/i.test(location.hostname);
}
function shouldAutoFlow() {
// Auto Click Target was merged into Auto Flow Skip โ one toggle now drives both.
return !!(S.enabled && (S.autoClick || S.autoFlowSkip));
}
function shouldSkipFlow() {
return !!(S.enabled && S.autoFlowSkip);
}
function isTelegramHref(href) {
return /^https?:\/\/(t\.me|telegram\.me)\//i.test(href || '');
}
function isFinalVplinkTarget(el) {
if (!el || location.hostname !== 'vplink.in') return false;
const href = el.href || (el.closest && el.closest('a') && el.closest('a').href) || '';
return !!(/^(get-link|gt-link)$/i.test(el.id || '') || isTelegramHref(href));
}
function isFinalActionTarget(el) {
if (!el) return false;
const href = el.href || (el.closest && el.closest('a') && el.closest('a').href) || '';
if (isFinalVplinkTarget(el) || isTelegramHref(href)) return true;
return !!(href && isFinalUniversalUrl(href));
}
function clickFlowTarget(el, manualFinal) {
if (!el) return;
const href = el.href || (el.closest && el.closest('a') && el.closest('a').href) || '';
if (isFinalActionTarget(el) && !manualFinal) {
window.th_gate_status = 'Final link ready: manual click';
return;
}
if ((isTelegramHref(href) && manualFinal) || (location.hostname === 'vplink.in' && /get-?link|gt-link/i.test(el.id || '') && href)) {
location.href = href;
return;
}
simulateClick(el);
}
function clickIntermediateFlowTarget(el) {
if (!el) return false;
const href = el.href || (el.closest && el.closest('a') && el.closest('a').href) || '';
if (isFinalActionTarget(el)) {
window.th_gate_status = 'Final link ready: manual click';
return false;
}
clickFlowTarget(el, false);
return true;
}
function getTargetKey(el) {
if (!el) return '';
const text = (el.innerText || el.value || el.textContent || '').toLowerCase().trim().slice(0, 80);
const href = el.href || el.action || '';
return [el.tagName, el.id || '', el.className || '', href, text].join('|');
}
const INVALID_TARGET_TEXT = ['click on ads', 'please wait', 'generating', 'wait', 'seconds', 'scroll down link is ready', 'join telegram channel', 'join whatsapp channel'];
const VALID_TARGET_TEXT = ['human veification', 'human verification', 'click to verify', 'click to continue', 'continue', 'get link', 'download link', 'get destination link', 'go to link', 'open link'];
window.th_click_cooldowns = window.th_click_cooldowns || {};
const macroState = { recording: false, playing: false, steps: [], startedAt: 0, lastAt: 0 };
function getSiteMacros() {
store.macros = store.macros || {};
return Array.isArray(store.macros[SITE_KEY]) ? store.macros[SITE_KEY] : [];
}
function setSiteMacros(macros) {
store.macros = store.macros || {};
store.macros[SITE_KEY] = macros;
saveStore();
}
function isTimeHookerUi(el) {
return !!(el && el.closest && el.closest('#th-panel-root, #th-proxy-btn, #th-dns-helper'));
}
function isVisibleMacroTarget(el) {
if (!el || isTimeHookerUi(el)) return false;
const r = el.getBoundingClientRect();
const style = getComputedStyle(el);
return r.width > 0 && r.height > 0 && style.display !== 'none' && style.visibility !== 'hidden' && parseFloat(style.opacity || '1') > 0.05;
}
function getActionText(el) {
return (el && (el.innerText || el.value || el.textContent) || '').replace(/\s+/g, ' ').trim();
}
function getTargetLabel(el) {
const text = getActionText(el);
if (text) return text;
if (el && el.tagName === 'IMG') return (el.alt || el.title || 'image').replace(/\s+/g, ' ').trim();
return el && el.tagName ? el.tagName.toLowerCase() : 'target';
}
function visibleById(id) {
const el = document.getElementById(id);
return el && isVisibleAction(el) && !isDisabledAction(el) ? el : null;
}
function getFlowReadyTarget() {
const priority = [
'get-link',
'gt-link',
'btn7',
'cross-snp2',
'tp98',
'tp-snp2',
'btn6',
'startCountdownBtn'
];
for (const id of priority) {
const el = visibleById(id);
if (!el) continue;
const text = getActionText(el).toLowerCase();
const href = el.href || (el.closest && el.closest('a') && el.closest('a').href) || '';
if (id === 'startCountdownBtn' && !text.includes('verify') && !text.includes('click')) continue;
if ((id === 'get-link' || id === 'gt-link') && !href) continue;
return el;
}
return null;
}
function getSafeCountdownState() {
const form = document.getElementById('tpForm') || document.querySelector('form[name="tp"]');
const btn = getFlowReadyTarget() || document.getElementById('tp98') || document.getElementById('tp-snp2') || document.getElementById('btn6') || document.getElementById('startCountdownBtn') || document.getElementById('cross-snp2') || document.getElementById('btn7');
const timerEl = document.getElementById('tp-time') || document.getElementById('ce-time') || document.getElementById('link1s-time') || document.getElementById('timer');
const bodyText = (document.body && document.body.innerText || '').replace(/\s+/g, ' ').toLowerCase();
const hasTextGate = /\bplease\s+wait\s+\d{1,3}\s*seconds?\b/.test(bodyText);
const hasDarkGurujiGate = !!(timerEl && (document.getElementById('tp-snp2') || document.getElementById('tp-generate') || document.getElementById('tp-wait1')));
const hasStartupGate = !!(timerEl && (document.getElementById('btn6') || document.getElementById('btn7') || document.getElementById('startCountdownBtn') || document.getElementById('cross-snp2') || document.getElementById('countdown')));
const hasVpLinkGate = location.hostname === 'vplink.in' && !!(document.getElementById('get-link') || document.getElementById('gt-link') || document.getElementById('go-link'));
const detected = !!(S.safeCountdownMode && ((form && btn && timerEl) || hasDarkGurujiGate || hasStartupGate || hasVpLinkGate || (hasTextGate && (form || btn))));
if (detected) window.th_safeCountdownDetected = true;
const timerValue = timerEl ? parseInt((timerEl.textContent || '').replace(/[^\d-]/g, ''), 10) : parseVisibleTimerValue(bodyText);
const ready = btn && isVisibleAction(btn) && !isDisabledAction(btn) ? btn : null;
return { detected, form, btn, timerEl, timerValue: Number.isFinite(timerValue) ? timerValue : null, ready };
}
function isSafeCountdownPage() {
return getSafeCountdownState().detected;
}
function exposeSafeCountdownTarget(state) {
if (!state || !state.detected) return;
if (state.ready) {
window.th_gate_status = 'Safe timer ready: ' + getTargetLabel(state.ready).slice(0, 40);
return;
}
window.th_gate_status = state.timerValue !== null ? ('Safe timer: ' + state.timerValue + 's fast') : 'Safe timer: waiting';
}
function revealSafeReadyButton(el) {
if (!el) return false;
const target = (el.closest && el.closest('a')) || el;
[target, el].forEach(node => {
if (!node || !node.style) return;
node.style.setProperty('display', node.tagName === 'A' ? 'inline-block' : 'block', 'important');
node.style.setProperty('visibility', 'visible', 'important');
node.style.setProperty('opacity', '1', 'important');
try { node.removeAttribute('disabled'); node.setAttribute('aria-disabled', 'false'); } catch(e) {}
});
return true;
}
function finishSafeCountdown(state) {
if (!state || !state.detected) return false;
const ready = getFlowReadyTarget();
if (ready && revealSafeReadyButton(ready)) {
window.th_gate_status = 'Aggro: ready button shown';
return true;
}
const candidates = ['tp98', 'tp-snp2', 'btn7', 'cross-snp2', 'btn6', 'get-link', 'gt-link'].map(id => document.getElementById(id)).filter(Boolean);
for (const el of candidates) {
if (revealSafeReadyButton(el)) {
window.th_gate_status = 'Aggro: ' + getTargetLabel(el).slice(0, 36);
return true;
}
}
if (state.timerEl) state.timerEl.textContent = '0';
['tp-wait1', 'countdown', 'link'].forEach(id => { const el = document.getElementById(id); if (el) el.style.setProperty('display', 'none', 'important'); });
['tp-generate'].forEach(id => { const el = document.getElementById(id); if (el) el.style.setProperty('display', 'block', 'important'); });
window.th_gate_status = 'Aggro: timer finished';
return true;
}
function isManualGateTarget(el, text) {
if (!text || !isVisibleAction(el) || isDisabledAction(el)) return false;
if (text.includes('click any image') || text.includes('click any link') || text.includes('click here')) return true;
if (text.includes('click to verify') && text.length <= 120) return true;
return false;
}
function escCss(value) {
if (window.CSS && CSS.escape) return CSS.escape(value);
return String(value).replace(/[^a-zA-Z0-9_-]/g, '\\$&');
}
function cssPath(el) {
if (!el || !el.tagName || el === document.body) return '';
if (el.id && !el.id.includes('th-')) return '#' + escCss(el.id);
const parts = [];
let node = el;
while (node && node.nodeType === 1 && node !== document.body && parts.length < 5) {
let part = node.tagName.toLowerCase();
const cls = (node.className || '').toString().trim().split(/\s+/).filter(Boolean).slice(0, 2);
if (cls.length) part += '.' + cls.map(c => escCss(c)).join('.');
const parent = node.parentElement;
if (parent) {
const same = Array.from(parent.children).filter(x => x.tagName === node.tagName);
if (same.length > 1) part += `:nth-of-type(${same.indexOf(node) + 1})`;
}
parts.unshift(part);
node = parent;
}
return parts.join(' > ');
}
function buildMacroStep(el, delay) {
const rect = el.getBoundingClientRect();
return {
delay: Math.max(0, Math.round(delay)),
text: getActionText(el).slice(0, 120),
tag: (el.tagName || '').toLowerCase(),
role: el.getAttribute && (el.getAttribute('role') || ''),
href: el.href || el.action || '',
id: el.id || '',
className: (el.className || '').toString().slice(0, 160),
selector: cssPath(el),
xPct: Math.round(((rect.left + rect.width / 2) / Math.max(1, window.innerWidth)) * 10000) / 10000,
yPct: Math.round(((rect.top + rect.height / 2) / Math.max(1, window.innerHeight)) * 10000) / 10000,
nearby: ((el.closest && el.closest('article, main, section, div')) ? getActionText(el.closest('article, main, section, div')) : '').slice(0, 180)
};
}
function startMacroRecording() {
macroState.recording = true;
macroState.playing = false;
macroState.steps = [];
macroState.startedAt = Date.now();
macroState.lastAt = macroState.startedAt;
window.th_gate_status = 'Recording step 1';
}
function stopAndSaveMacro() {
if (!macroState.recording) {
window.th_gate_status = 'Macro: not recording';
return;
}
macroState.recording = false;
if (!macroState.steps.length) {
window.th_gate_status = 'Macro: no steps saved';
return;
}
const macros = getSiteMacros();
macros.push({ name: 'Macro ' + new Date().toLocaleTimeString(), createdAt: new Date().toISOString(), steps: macroState.steps.slice() });
setSiteMacros(macros);
window.th_gate_status = 'Macro saved: ' + macroState.steps.length + ' steps';
}
function deleteSelectedMacro(index) {
const macros = getSiteMacros();
if (index < 0 || index >= macros.length) {
window.th_gate_status = 'Macro: nothing to delete';
return;
}
macros.splice(index, 1);
setSiteMacros(macros);
window.th_gate_status = 'Macro deleted';
}
document.addEventListener('click', function(e) {
if (!macroState.recording || macroState.playing || isTimeHookerUi(e.target)) return;
const now = Date.now();
macroState.steps.push(buildMacroStep(e.target, now - macroState.lastAt));
macroState.lastAt = now;
window.th_gate_status = 'Recording step ' + (macroState.steps.length + 1);
}, true);
function scoreMacroCandidate(el, step) {
if (!el || isTimeHookerUi(el) || !isVisibleMacroTarget(el)) return -1;
const text = getActionText(el).toLowerCase();
const stepText = (step.text || '').toLowerCase();
const rect = el.getBoundingClientRect();
const cx = (rect.left + rect.width / 2) / Math.max(1, window.innerWidth);
const cy = (rect.top + rect.height / 2) / Math.max(1, window.innerHeight);
let score = 0;
if (step.id && el.id === step.id) score += 1000;
if (step.href && (el.href || el.action || '') === step.href) score += 800;
if (step.tag && (el.tagName || '').toLowerCase() === step.tag) score += 250;
if (step.role && el.getAttribute && el.getAttribute('role') === step.role) score += 150;
if (stepText && text === stepText) score += 700;
else if (stepText && text.includes(stepText.slice(0, 40))) score += 350;
const dx = Math.abs(cx - (step.xPct || 0.5));
const dy = Math.abs(cy - (step.yPct || 0.5));
score += Math.max(0, 300 - Math.round((dx + dy) * 600));
return score;
}
function findMacroTarget(step) {
if (step.selector) {
try {
const found = document.querySelector(step.selector);
if (found && scoreMacroCandidate(found, step) > 120) return found;
} catch(e) {}
}
const nodes = Array.from(document.querySelectorAll("a, button, input[type='button'], input[type='submit'], [role='button'], [role='link'], img, [onclick]"));
return nodes.map(el => ({ el, score: scoreMacroCandidate(el, step) })).filter(x => x.score > 120).sort((a, b) => b.score - a.score)[0]?.el || null;
}
function sleep(ms) {
return new Promise(resolve => (window.th_nativeSetTimeout || setTimeout)(resolve, ms));
}
async function playSelectedMacro(index, speed) {
const macros = getSiteMacros();
const macro = macros[index];
if (!macro || !Array.isArray(macro.steps) || !macro.steps.length) {
window.th_gate_status = 'Macro: select saved macro';
return;
}
macroState.playing = true;
macroState.recording = false;
const rate = speed > 0 ? speed : 1;
for (let i = 0; i < macro.steps.length; i++) {
const step = macro.steps[i];
const delay = i === 0 ? Math.max(1200, step.delay || 0) : Math.max(150, Math.round((step.delay || 0) / rate));
window.th_gate_status = 'Playing step ' + (i + 1) + '/' + macro.steps.length;
await sleep(delay);
let target = null;
for (let tries = 0; tries < 12 && !target; tries++) {
target = findMacroTarget(step);
if (!target) {
window.th_gate_status = 'Waiting for target ' + (i + 1);
await sleep(500);
}
}
if (!target) {
window.th_gate_status = 'Step failed: target not found';
macroState.playing = false;
return;
}
simulateClick(target);
}
macroState.playing = false;
window.th_gate_status = 'Macro complete';
}
function isVisibleAction(el) {
if (!el || el.id === "th-proxy-btn" || (el.id || '').includes("th-")) return false;
if (el === document.body || el === document.documentElement) return false;
const r = el.getBoundingClientRect();
return r.width > 0 && r.height > 0 && r.width <= window.innerWidth * 1.05 && r.height <= window.innerHeight * 0.9;
}
function isDisabledAction(el) {
return !!(el.disabled || el.hasAttribute('disabled') || el.getAttribute('aria-disabled') === 'true' || (el.className || '').toString().toLowerCase().includes('disabled'));
}
function isAllowedNextTarget(el, text) {
if (text !== 'next') return false;
const host = location.hostname.toLowerCase();
const href = (el && el.href || '').toLowerCase();
return /^(sb1|sb2)\.schemepro\.org$/.test(host) && href.includes('lksfy.com');
}
function isSchemeProHost() {
return /^(sb1|sb2)\.schemepro\.org$/i.test(location.hostname);
}
function getCookieValue(name) {
const m = document.cookie.match(new RegExp('(?:^|;\\s*)' + name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '=([^;]*)'));
return m ? decodeURIComponent(m[1]) : '';
}
function setCookieValue(name, value, maxAgeSeconds) {
document.cookie = name + '=' + encodeURIComponent(value) + '; path=/; max-age=' + String(maxAgeSeconds);
}
function deleteCookieValue(name) {
document.cookie = name + '=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; max-age=0';
}
function parseSchemeProStep() {
if (!isSchemeProHost() || !document.documentElement) return null;
const html = document.documentElement.innerHTML || '';
const bodyText = (document.body && document.body.innerText || '').replace(/\s+/g, ' ');
const stepMatch = bodyText.match(/Step\s*([1-4])\s*\/\s*4/i) || html.match(/Step\s*([1-4])\s*\/\s*4/i);
const targetMatch = html.match(/tagrget_url\s*=\s*["']([^"']+)["']/i) || html.match(/target_url\s*=\s*["']([^"']+)["']/i);
if (!stepMatch || !targetMatch) return null;
let decoded = '';
try { decoded = atob(targetMatch[1]).trim(); } catch(e) { decoded = ''; }
if (!/^https?:\/\//i.test(decoded)) return null;
const step = parseInt(stepMatch[1], 10);
const alias = getCookieValue('alias') || getCookieValue('ref' + (location.pathname.split('/').filter(Boolean)[0] || '')) || '';
return { step, target: decoded, alias };
}
function getSchemeProSkipKey(info) {
return 'th_schemepro_skip_' + location.hostname + '_' + location.pathname + '_' + (info ? info.step + '_' + info.target : '');
}
function rememberSchemeProStep(info) {
try {
const key = 'th_schemepro_trace_' + (info.alias || 'latest');
const trace = JSON.parse(sessionStorage.getItem(key) || '[]');
trace.push({ host: location.hostname, step: info.step, from: location.href, to: info.target, at: Date.now() });
sessionStorage.setItem(key, JSON.stringify(trace.slice(-8)));
} catch(e) {}
}
function maybeSkipSchemeProArticle(proxy) {
if (!S.enabled || !isSchemeProHost()) return false;
const info = parseSchemeProStep();
if (!info) return false;
const skipKey = getSchemeProSkipKey(info);
if (sessionStorage.getItem(skipKey) === '1' || window.th_schemepro_skip_pending) return true;
const current = location.href.replace(/\/$/, '');
const target = info.target.replace(/\/$/, '');
if (current === target) return false;
sessionStorage.setItem(skipKey, '1');
window.th_schemepro_skip_pending = true;
rememberSchemeProStep(info);
if (info.step === 1 || info.step === 3) setCookieValue('user_step', '1', 180);
else deleteCookieValue('user_step');
window.th_gate_status = 'SchemePro: skipping step ' + info.step + '/4';
if (!proxy && S.pinMode && document.body) {
proxy = document.createElement("button"); proxy.id = "th-proxy-btn";
proxy.style.cssText = "position: fixed !important; left: 50% !important; transform: translateX(-50%) !important; z-index: 2147483647; padding: 15px 30px; font-weight: bold; background: linear-gradient(90deg, #5b42f3, #00ddeb); color: white; border-radius: 10px; cursor: pointer;";
document.body.appendChild(proxy);
}
if (S.pinMode && proxy) {
proxy.innerText = 'SKIP STEP ' + info.step + '/4';
proxy.style.top = S.topOffset + 'px';
proxy.style.display = 'block';
}
(window.th_nativeSetTimeout || setTimeout)(() => {
if (S.enabled) location.href = info.target;
}, 350);
return true;
}
function isVplinkChainHost() {
return /(^|\.)((vplink\.in)|(vacancymode\.in)|(darkguruji\.com)|(startuplearners\.com)|(privatejobbeta\.com)|(rempo\.xyz)|(genas\.xyz))$/i.test(location.hostname);
}
function getVplinkAlias() {
const cleanAlias = value => {
const alias = String(value || '').trim();
return /^[A-Za-z0-9_-]{3,80}$/.test(alias) ? alias : '';
};
const params = new URLSearchParams(location.search || '');
const knownParams = ['studiissinsucrnce', 'alias', 'code', 'id', 'slug', 'key'];
for (let i = 0; i < knownParams.length; i++) {
const candidate = cleanAlias(params.get(knownParams[i]));
if (candidate) {
try { sessionStorage.setItem('th_vplink_active_alias_v55', candidate); } catch(e) {}
return candidate;
}
}
const cookieAlias = cleanAlias(getCookieValue('gt_uc_') || getCookieValue('user_in'));
if (cookieAlias) {
try { sessionStorage.setItem('th_vplink_active_alias_v55', cookieAlias); } catch(e) {}
return cookieAlias;
}
const path = cleanAlias(location.pathname.split('/').filter(Boolean).pop() || '');
if (location.hostname === 'vplink.in' && path) {
try { sessionStorage.setItem('th_vplink_active_alias_v55', path); } catch(e) {}
return path;
}
try {
const active = cleanAlias(sessionStorage.getItem('th_vplink_active_alias_v55'));
if (active) return active;
} catch(e) {}
const fallback = [location.hostname, location.pathname].join('|').split('').reduce((hash, ch) => ((hash * 31 + ch.charCodeAt(0)) >>> 0), 2166136261).toString(36);
return 'page-' + fallback;
}
function normalizeFlowUrl(url) {
try {
const u = new URL(url, location.href);
u.hash = '';
return u.href.replace(/\/$/, '');
} catch(e) { return ''; }
}
function isSafeVplinkFlowUrl(url) {
try {
const u = new URL(url, location.href);
return /(^|\.)((vplink\.in)|(vacancymode\.in)|(darkguruji\.com)|(startuplearners\.com)|(privatejobbeta\.com)|(rempo\.xyz)|(genas\.xyz))$/i.test(u.hostname);
} catch(e) { return false; }
}
function getFlowTraceKey() {
return 'th_vplink_flow_v55_' + getVplinkAlias();
}
function getFlowTrace() {
try {
const trace = JSON.parse(sessionStorage.getItem(getFlowTraceKey()) || '[]');
const cutoff = Date.now() - 5 * 60000;
return Array.isArray(trace) ? trace.filter(item => item && Number(item.at || 0) >= cutoff) : [];
} catch(e) { return []; }
}
function countFlowVisits(url) {
const normalized = normalizeFlowUrl(url);
if (!normalized) return 0;
const cutoff = Date.now() - 45000;
return getFlowTrace().filter(item => item && item.to === normalized && Number(item.at || 0) >= cutoff).length;
}
function rememberFlowHop(to, label) {
try {
const trace = getFlowTrace();
trace.push({ from: normalizeFlowUrl(location.href), to: normalizeFlowUrl(to), label: label || '', at: Date.now() });
sessionStorage.setItem(getFlowTraceKey(), JSON.stringify(trace.slice(-14)));
} catch(e) {}
}
const BRAIN_HISTORY_KEY = 'th_page_brain_v54';
function getServerErrorState() {
if (!document.body) return null;
const title = String(document.title || '').toLowerCase();
const text = (document.body.innerText || document.body.textContent || '').replace(/\s+/g, ' ').toLowerCase().slice(0, 2200);
const codeMatch = (title + ' ' + text).match(/(?:^|\D)(429|5[0-2][0-9])(?=\D|$)/);
const allowedCodes = ['429', '500', '502', '503', '504', '520', '521', '522', '523', '524'];
const code = codeMatch && allowedCodes.includes(codeMatch[1]) ? codeMatch[1] : '';
const cloudflareHostError = /bad gateway|web server reported|host error|connection timed out|origin is unreachable|web server is down/.test(text);
if (!code && !cloudflareHostError) return null;
return {
code: code || '5xx',
reason: cloudflareHostError ? 'website host/server unavailable' : 'temporary website server error'
};
}
function getPageBrainState() {
if (!document.body) return { state: 'LOADING', confidence: 1, reason: 'document body pending' };
if (window.th_captcha_present || detectChallenge()) return { state: 'CAPTCHA', confidence: 1, reason: 'human verification detected' };
const serverError = getServerErrorState();
if (serverError) return { state: 'SERVER_ERROR', confidence: 1, reason: serverError.reason, target: serverError.code };
if (getVacancymodeManualGate()) return { state: 'MANUAL_GATE', confidence: 1, reason: 'server confirmation cookie required' };
const redirect = getScriptRedirectTarget();
if (redirect) return { state: 'REDIRECT', confidence: isSafeVplinkFlowUrl(redirect) || isSafeUniversalFlowUrl(redirect) ? 1 : 0.6, reason: 'page-owned redirect found', target: normalizeFlowUrl(redirect) };
const finalTarget = document.querySelector('#get-link, #gt-link, #go-link, a[href^="https://t.me/"], a[href^="https://telegram.me/"]');
if (finalTarget) {
const href = finalTarget.href || (finalTarget.closest && finalTarget.closest('a') && finalTarget.closest('a').href) || '';
return { state: 'FINAL', confidence: 1, reason: 'final or Telegram target detected', target: normalizeFlowUrl(href) };
}
const stepInfo = getStepFlowInfo();
if (stepInfo) return { state: 'STEP', confidence: 0.95, reason: stepInfo.current && stepInfo.total ? ('structured step ' + stepInfo.current + '/' + stepInfo.total) : 'structured verify controls' };
const countdown = getSafeCountdownState();
if (countdown && countdown.detected) return { state: countdown.ready ? 'READY' : 'TIMER', confidence: 0.9, reason: countdown.ready ? 'continue target is ready' : ('countdown' + (countdown.timerValue !== null ? ' ' + countdown.timerValue + 's' : '') + ' detected') };
const bodyText = (document.body.innerText || document.body.textContent || '').replace(/\s+/g, ' ').toLowerCase().slice(0, 5000);
const hasFlowHint = /please\s+wait|count(?:ing)?\s*down|skip\s+timer|click\s+(?:to\s+)?verify|continue|get\s+link|opening\s+link|generating\s+link/.test(bodyText);
const best = shouldRunUniversalFlow() && hasFlowHint ? getBestUniversalAction() : null;
if (best && best.el && best.score >= 90) return { state: 'ACTION', confidence: Math.min(1, best.score / 160), reason: 'high-confidence intermediate action', target: getTargetLabel(best.el).slice(0, 60) };
return { state: 'UNKNOWN', confidence: 0.2, reason: 'no safe flow pattern yet' };
}
function rememberBrainState(brain) {
if (!brain || !brain.state) return;
window.th_page_brain = brain;
try {
const history = JSON.parse(sessionStorage.getItem(BRAIN_HISTORY_KEY) || '[]');
const list = Array.isArray(history) ? history : [];
const last = list[list.length - 1];
const signature = [location.hostname, location.pathname, brain.state, brain.reason].join('|');
if (!last || last.signature !== signature) {
list.push({ signature, state: brain.state, reason: brain.reason, target: brain.target || '', url: normalizeFlowUrl(location.href), at: Date.now() });
sessionStorage.setItem(BRAIN_HISTORY_KEY, JSON.stringify(list.slice(-24)));
}
} catch(e) {}
}
function maybeHandleServerError(proxy) {
const error = getServerErrorState();
if (!error) return false;
clearPendingRecipe();
window.th_navigating = false;
window.th_gate_status = 'SERVER ' + error.code + ': retry later';
rememberBrainState({ state: 'SERVER_ERROR', confidence: 1, reason: error.reason, target: error.code });
proxy = setProxyStatus(proxy, 'SERVER ' + error.code + ': retry page');
if (proxy) {
proxy.onclick = () => { if (S.enabled) location.reload(); };
}
return true;
}
const RECIPE_PENDING_KEY = 'th_recipe_pending_v52';
const RECIPE_IDS = ['btn6', 'btn7', 'tp-snp2', 'tp98', 'cross-snp2', 'startCountdownBtn', 'get-link', 'gt-link', 'go-link', 'tp-time', 'ce-time', 'countdown', 'link1s-time'];
function getRecipeShape() {
if (!document.body || window.th_captcha_present) return '';
const ids = RECIPE_IDS.filter(id => !!document.getElementById(id)).sort();
const text = (document.body.innerText || '').replace(/\s+/g, ' ').toLowerCase().slice(0, 5000);
const step = text.match(/step\s*([0-9]+)\s*\/\s*([0-9]+)/i);
const flags = [
step ? ('step:' + step[1] + '/' + step[2]) : '',
/\bplease\s+wait\s+\d{1,3}\s*seconds?\b/.test(text) ? 'wait' : '',
/click\s+(?:to\s+)?verify|click\s+any\s+(?:image|link)/i.test(text) ? 'verify' : '',
/count(?:ing)?\s*down|skip\s+timer/i.test(text) ? 'countdown' : '',
getScriptRedirectTarget() ? 'script-redirect' : ''
].filter(Boolean);
if (!ids.length && !flags.length) return '';
return ids.join(',') + '|' + flags.join(',');
}
function recipeKey(host, shape) {
return String(host || '').toLowerCase() + '::' + String(shape || '');
}
function hrefSignature(href) {
if (!href) return '';
try {
const u = new URL(href, location.href);
const keys = Array.from(u.searchParams.keys()).sort().slice(0, 12);
return [u.hostname.toLowerCase(), u.pathname.replace(/\/+$/, '') || '/', keys.join(',')].join('|');
} catch(e) { return ''; }
}
function isUnstableRecipeSelector(selector) {
return !selector || selector.includes(':nth-of-type') || /[.#][A-Za-z_-]*[0-9a-f]{7,}/i.test(selector) || /#(?:google_ads|aswift|adsbygoogle|adngin|div-gpt|ad_iframe)/i.test(selector);
}
function isAdLikeRecipeTarget(el) {
if (!el || isTimeHookerUi(el) || isOwnUi(el)) return true;
const meta = [el.id, el.className, el.src || ''].join(' ').toLowerCase();
if (/(^|\W)(google_ads|aswift|adsbygoogle|adngin|div-gpt|ad_iframe|popup|interstitial)(\W|$)/i.test(meta)) return true;
try {
const style = getComputedStyle(el);
const rect = el.getBoundingClientRect();
const fixedish = style.position === 'fixed' || style.position === 'absolute' || style.position === 'sticky';
if (fixedish && rect.width >= window.innerWidth * 0.6 && rect.height >= window.innerHeight * 0.6) return true;
} catch(e) {}
return false;
}
function isLearnableRecipeTarget(el) {
if (!el || !isVisibleMacroTarget(el) || isAdLikeRecipeTarget(el)) return false;
const text = getActionText(el).toLowerCase();
const href = el.href || (el.closest && el.closest('a') && el.closest('a').href) || '';
if (INVALID_TARGET_TEXT.some(k => text.includes(k))) return false;
if (isFinalVplinkTarget(el) || isTelegramHref(href) || (href && isFinalUniversalUrl(href))) return false;
if (/^(get-link|gt-link|go-link)$/i.test(el.id || '')) return false;
if (href) {
try {
const u = new URL(href, location.href);
if (u.hostname !== location.hostname) return false;
} catch(e) { return false; }
}
return true;
}
function buildRecipeStep(el, kind) {
if (!isLearnableRecipeTarget(el)) return null;
const selector = cssPath(el);
const href = el.href || (el.closest && el.closest('a') && el.closest('a').href) || '';
return {
id: String(el.id || '').slice(0, 120),
text: getActionText(el).slice(0, 120),
tag: String((el.tagName || '').toLowerCase()).slice(0, 24),
role: String((el.getAttribute && el.getAttribute('role')) || '').slice(0, 40),
selector: isUnstableRecipeSelector(selector) ? '' : selector.slice(0, 260),
hrefSig: hrefSignature(href),
kind: kind === 'navigate' ? 'navigate' : 'click'
};
}
function pruneRecipes() {
store.recipes = sanitizeRecipes(store.recipes);
const now = Date.now();
Object.keys(store.recipes).forEach(key => {
const item = store.recipes[key];
const tooOld = item.updatedAt && now - item.updatedAt > 45 * 86400000;
const unhealthy = item.consecutiveFails >= 3 || (item.fails > item.hits && item.fails >= 4);
if (tooOld || unhealthy) delete store.recipes[key];
});
const keys = Object.keys(store.recipes).sort((a, b) => (store.recipes[b].updatedAt || 0) - (store.recipes[a].updatedAt || 0));
keys.slice(80).forEach(key => { delete store.recipes[key]; });
}
pruneRecipes();
function readPendingRecipe() {
try {
const pending = JSON.parse(sessionStorage.getItem(RECIPE_PENDING_KEY) || 'null');
return pending && typeof pending === 'object' ? pending : null;
} catch(e) { return null; }
}
function clearPendingRecipe() {
try { sessionStorage.removeItem(RECIPE_PENDING_KEY); } catch(e) {}
}
function stageRecipeAction(el, kind) {
if (window.th_captcha_present || detectChallenge() || readPendingRecipe()) return false;
const shape = getRecipeShape();
const step = shape ? buildRecipeStep(el, kind) : null;
if (!step) return false;
const href = el.href || (el.closest && el.closest('a') && el.closest('a').href) || '';
const targetUrl = href ? normalizeFlowUrl(href) : '';
const stableId = /^(btn6|btn7|tp-snp2|tp98|cross-snp2|startCountdownBtn)$/i.test(step.id || '');
const sameHostTarget = !targetUrl || (() => { try { return new URL(targetUrl).hostname === location.hostname; } catch(e) { return false; } })();
const brain = getPageBrainState();
const pending = {
id: Math.random().toString(36).slice(2) + Date.now().toString(36),
host: SITE_KEY,
shape,
key: recipeKey(SITE_KEY, shape),
step,
fromUrl: normalizeFlowUrl(location.href),
targetUrl,
traceLen: getFlowTrace().length,
hadAutoRedirect: !!getScriptRedirectTarget() || !!document.querySelector('meta[http-equiv="refresh" i]'),
strongEvidence: !!(stableId && sameHostTarget && ['STEP', 'READY', 'TIMER', 'ACTION'].includes(brain.state)),
brainState: brain.state,
ts: Date.now()
};
try {
sessionStorage.setItem(RECIPE_PENDING_KEY, JSON.stringify(pending));
el.dataset.thRecipeFired = pending.id;
return true;
} catch(e) { return false; }
}
function failRecipe(key) {
const item = store.recipes && store.recipes[key];
if (!item) return;
item.hits = Math.floor(Number(item.hits || 0) / 2);
item.fails = Math.min(999, Number(item.fails || 0) + 1);
item.consecutiveFails = Math.min(20, Number(item.consecutiveFails || 0) + 1);
item.lastFailAt = Date.now();
item.updatedAt = Date.now();
if (item.consecutiveFails >= 3) delete store.recipes[key];
pruneRecipes();
markRecipesDirty();
}
function commitPendingRecipe(pending, strongTransition) {
store.recipes = store.recipes || {};
const existing = store.recipes[pending.key] || {
host: pending.host,
shape: pending.shape,
step: pending.step,
hits: 0,
fails: 0,
confirmations: 0,
consecutiveFails: 0,
updatedAt: 0,
lastFailAt: 0
};
existing.step = pending.step;
const strong = !!(pending.strongEvidence && strongTransition);
existing.hits = Math.min(999, Number(existing.hits || 0) + (strong ? 2 : 1));
existing.confirmations = Math.min(999, Number(existing.confirmations || 0) + 1);
existing.consecutiveFails = 0;
existing.updatedAt = Date.now();
store.recipes[pending.key] = existing;
pruneRecipes();
markRecipesDirty();
}
function evaluatePendingRecipe() {
const pending = readPendingRecipe();
if (!pending) return false;
if (window.th_captcha_present || detectChallenge()) {
clearPendingRecipe();
return false;
}
const age = Date.now() - Number(pending.ts || 0);
const currentUrl = normalizeFlowUrl(location.href);
if (pending.host && pending.host !== SITE_KEY) {
failRecipe(pending.key);
clearPendingRecipe();
window.th_gate_status = 'LEARNING CANCELLED: website changed';
return false;
}
const currentShape = getRecipeShape();
const urlChanged = !!(currentUrl && pending.fromUrl && currentUrl !== pending.fromUrl);
const shapeChanged = !!(currentShape && pending.shape && currentShape !== pending.shape);
const traceAdvanced = getFlowTrace().length > Number(pending.traceLen || 0);
const reachedTarget = !!(pending.targetUrl && currentUrl === pending.targetUrl);
const finalLanding = isFinalUniversalUrl(currentUrl) || /^(get-link|gt-link|go-link)$/i.test((document.activeElement && document.activeElement.id) || '');
if ((urlChanged || shapeChanged) && !pending.hadAutoRedirect && !finalLanding && (reachedTarget || traceAdvanced || shapeChanged)) {
commitPendingRecipe(pending, !!(shapeChanged || reachedTarget));
clearPendingRecipe();
return false;
}
if (age > 8000 && !urlChanged && !shapeChanged) {
failRecipe(pending.key);
clearPendingRecipe();
window.th_gate_status = 'LEARNING FAILED: page did not advance';
return false;
}
if (age > 60000 || (urlChanged && (!reachedTarget || finalLanding))) {
failRecipe(pending.key);
clearPendingRecipe();
window.th_gate_status = 'LEARNING REJECTED: wrong or final route';
return false;
}
return true;
}
function scoreRecipeCandidate(el, step) {
if (!el || !step || !isLearnableRecipeTarget(el)) return -1;
const text = getActionText(el).toLowerCase();
const expected = String(step.text || '').toLowerCase();
const href = el.href || (el.closest && el.closest('a') && el.closest('a').href) || '';
let score = 0;
if (step.id && el.id === step.id) score += 1000;
if (step.hrefSig && hrefSignature(href) === step.hrefSig) score += 900;
if (expected && text === expected) score += 700;
else if (expected && text.includes(expected.slice(0, 40))) score += 300;
if (step.tag && (el.tagName || '').toLowerCase() === step.tag) score += 120;
if (step.role && el.getAttribute && el.getAttribute('role') === step.role) score += 80;
return score;
}
function findRecipeTarget(step) {
const candidates = [];
if (step && step.selector) {
try {
const selected = document.querySelector(step.selector);
if (selected) candidates.push(selected);
} catch(e) {}
}
Array.from(document.querySelectorAll("a, button, input[type='button'], input[type='submit'], [role='button'], [role='link'], [onclick]")).slice(0, 320).forEach(el => {
if (!candidates.includes(el)) candidates.push(el);
});
return candidates.map(el => ({ el, score: scoreRecipeCandidate(el, step) })).filter(item => item.score >= 900).sort((a, b) => b.score - a.score)[0] || null;
}
function recipeIsConfident(recipe) {
const hits = Number(recipe && recipe.hits || 0);
const fails = Number(recipe && recipe.fails || 0);
const confirmations = Number(recipe && recipe.confirmations || 0);
const ratio = hits / Math.max(1, hits + fails);
return (confirmations >= 2 || hits >= 3) && ratio >= 0.8 && fails < 2 && Number(recipe.consecutiveFails || 0) === 0 && Date.now() - Number(recipe.updatedAt || 0) < 30 * 86400000;
}
function getTemplateRecipe(shape) {
if (!shape) return null;
return Object.values(store.recipes || {}).filter(item => item && item.shape === shape && item.host !== SITE_KEY).sort((a, b) => Number(b.hits || 0) - Number(a.hits || 0))[0] || null;
}
function maybeRunLearnedRecipe(proxy) {
if (!shouldRunUniversalFlow() || isVplinkChainHost() || window.th_captcha_present || !document.body) return false;
if (evaluatePendingRecipe()) {
const pending = readPendingRecipe();
const existing = pending && store.recipes && store.recipes[pending.key];
const done = Math.min(1, Number(existing && existing.confirmations || 0));
window.th_gate_status = 'LEARNING ' + done + '/2: verifying page progress';
setProxyStatus(proxy, 'LEARNING ' + done + '/2: verifying');
return true;
}
const shape = getRecipeShape();
if (!shape) return false;
const key = recipeKey(SITE_KEY, shape);
const localRecipe = store.recipes && store.recipes[key];
const recipe = localRecipe || getTemplateRecipe(shape);
if (!recipe) return false;
const found = findRecipeTarget(recipe.step);
if (!found) {
window.th_recipe_misses = window.th_recipe_misses || {};
window.th_recipe_misses[key] = Number(window.th_recipe_misses[key] || 0) + 1;
if (localRecipe && window.th_recipe_misses[key] >= 12) {
failRecipe(key);
window.th_recipe_misses[key] = 0;
}
return false;
}
window.th_recipe_misses = window.th_recipe_misses || {};
window.th_recipe_misses[key] = 0;
revealFlowElement(found.el);
const href = found.el.href || (found.el.closest && found.el.closest('a') && found.el.closest('a').href) || '';
if (!localRecipe || !recipeIsConfident(localRecipe)) {
const confirmations = Number(localRecipe && localRecipe.confirmations || 0);
const label = localRecipe ? ('LEARNING ' + Math.min(1, confirmations) + '/2: tap Continue') : 'LEARNED TEMPLATE: tap once';
return setUniversalManual(proxy, label, found.el);
}
if (href) {
if (!isSafeUniversalFlowUrl(href) || isFinalUniversalUrl(href)) return setUniversalManual(proxy, 'FINAL LINK: manual', found.el);
return navigateUniversalUrl(href, 'LEARNED: continue', proxy, found.el);
}
if (window.th_recipe_clicking) return true;
window.th_recipe_clicking = true;
stageRecipeAction(found.el, 'click');
window.th_gate_status = 'LEARNED: verified click';
setProxyStatus(proxy, 'LEARNED: verified click');
(window.th_nativeSetTimeout || setTimeout)(() => {
try { clickIntermediateFlowTarget(found.el); }
finally { window.th_recipe_clicking = false; }
}, 180);
return true;
}
function setProxyStatus(proxy, text) {
if (!S.pinMode || !document.body) return proxy;
if (!proxy) {
proxy = document.createElement("button"); proxy.id = "th-proxy-btn";
proxy.style.cssText = "position: fixed !important; left: 50% !important; transform: translateX(-50%) !important; z-index: 2147483647; padding: 15px 30px; font-weight: bold; background: linear-gradient(90deg, #ff0055, #ffaa00); color: white; border-radius: 10px; cursor: pointer;";
document.body.appendChild(proxy);
}
proxy.innerText = text;
proxy.style.top = S.topOffset + 'px';
proxy.style.display = 'block';
return proxy;
}
function navigateFlowUrl(url, label, proxy) {
const target = normalizeFlowUrl(url);
if (!target || !isSafeVplinkFlowUrl(target)) return false;
if (countFlowVisits(target) >= 3) {
window.th_gate_status = 'FLOW LOOP: manual';
rememberBrainState({ state: 'LOOP', confidence: 1, reason: 'same guarded route attempted three times', target });
setProxyStatus(proxy, 'FLOW LOOP: manual');
return true;
}
window.th_gate_status = label || 'FLOW: next';
setProxyStatus(proxy, label || 'FLOW: next');
// Fast auto-walk + anti-crash guard: only one navigation may be scheduled at a time.
if (window.th_navigating) return true;
window.th_navigating = true;
const navStartedAt = Date.now();
window.th_navigating_since = navStartedAt;
(window.th_nativeSetTimeout || setTimeout)(() => {
if (window.th_navigating && window.th_navigating_since === navStartedAt) window.th_navigating = false;
}, 4000);
rememberFlowHop(target, label);
(window.th_nativeSetTimeout || setTimeout)(() => {
if (shouldSkipFlow()) location.href = target; else window.th_navigating = false;
}, 150);
return true;
}
function getScriptRedirectTarget() {
if (!document.documentElement) return '';
const html = document.documentElement.innerHTML || '';
const text = (document.body && document.body.innerText || '').replace(/\s+/g, ' ').toLowerCase();
if (!/(please wait|opening link|generating link|redirect after a delay|redirecting)/i.test(text)) return '';
const m = html.match(/(?:window|document)\.location(?:\.href)?\s*=\s*["']([^"']+)["']/i) || html.match(/document\.location\s*=\s*["']([^"']+)["']/i);
return m ? m[1] : '';
}
function getStepFlowInfo() {
if (!document.body) return null;
const bodyText = (document.body.innerText || '').replace(/\s+/g, ' ');
const stepMatch = bodyText.match(/step\s*([0-9]+)\s*\/\s*([0-9]+)/i);
const btn6 = document.getElementById('btn6');
const btn7 = document.getElementById('btn7');
if (!stepMatch && !btn6 && !btn7) return null;
return { current: stepMatch ? parseInt(stepMatch[1], 10) : 0, total: stepMatch ? parseInt(stepMatch[2], 10) : 0, btn6, btn7 };
}
function revealFlowElement(el) {
if (!el) return false;
[el, (el.closest && el.closest('a'))].forEach(node => {
if (!node || !node.style) return;
node.style.setProperty('display', node.tagName === 'A' ? 'inline-block' : 'block', 'important');
node.style.setProperty('visibility', 'visible', 'important');
node.style.setProperty('opacity', '1', 'important');
try { node.removeAttribute('disabled'); node.setAttribute('aria-disabled', 'false'); } catch(e) {}
});
return true;
}
function prepareStepFlow(info) {
['ce-wait1', 'tp-wait1'].forEach(id => { const el = document.getElementById(id); if (el) el.style.setProperty('display', 'none', 'important'); });
['ce-text', 'tp-generate'].forEach(id => { const el = document.getElementById(id); if (el) el.style.setProperty('display', 'block', 'important'); });
document.querySelectorAll("[id='loading-container'], #continue1").forEach(el => el.style.setProperty('display', 'none', 'important'));
if (info.btn6) revealFlowElement(info.btn6);
if (info.btn7) revealFlowElement(info.btn7);
}
function getVacancymodeManualGate() {
if (!/(^|\.)vacancymode\.in$/i.test(location.hostname) || getCookieValue('adcadg')) return null;
const timer = document.getElementById('tp-time');
const button = document.getElementById('tp-snp2');
const gate = document.getElementById('gcont');
if (!timer || !button || !gate) return null;
const text = (gate.innerText || gate.textContent || '').replace(/\s+/g, ' ').toLowerCase();
if (!/click (?:on )?(?:the )?ads? to continue|click ads wait\s*&?\s*back|support the developer/.test(text)) return null;
return { timer, button, gate };
}
function maybeHandleVacancymodeManualGate(proxy) {
const manualGate = getVacancymodeManualGate();
if (!manualGate) return false;
window.th_skipTimersEnabled = false;
window.th_flowManualMode = true;
window.th_gate_status = 'MANUAL GATE: open ad, wait 15s, return';
recordSiteTrick('manual');
proxy = setProxyStatus(proxy, 'MANUAL GATE: open ad & return');
if (proxy) {
proxy.style.cursor = 'pointer';
proxy.onclick = () => {
try { manualGate.gate.scrollIntoView({ behavior: 'smooth', block: 'center' }); } catch(e) {}
};
}
return true;
}
function maybeRunVplinkChain(proxy) {
if (!shouldSkipFlow() || !isVplinkChainHost()) return false;
if (maybeHandleVacancymodeManualGate(proxy)) return true;
const redirectTarget = getScriptRedirectTarget();
if (redirectTarget && isSafeVplinkFlowUrl(redirectTarget)) {
return navigateFlowUrl(redirectTarget, 'FLOW: redirect', proxy);
}
const stepInfo = getStepFlowInfo();
if (stepInfo) {
prepareStepFlow(stepInfo);
const stepLabel = stepInfo.current && stepInfo.total ? ('FLOW: Step ' + stepInfo.current + '/' + stepInfo.total) : 'FLOW: verify';
setProxyStatus(proxy, stepLabel);
window.th_gate_status = stepLabel;
if (stepInfo.btn6 && !stepInfo.btn6.dataset.thFlowClicked) {
stepInfo.btn6.dataset.thFlowClicked = '1';
(window.th_nativeSetTimeout || setTimeout)(() => {
if (!shouldSkipFlow() || !document.contains(stepInfo.btn6)) return;
try { if (typeof window.nextbtn === 'function') window.nextbtn(); else simulateClick(stepInfo.btn6); } catch(e) { simulateClick(stepInfo.btn6); }
}, 250);
return true;
}
if (stepInfo.btn7) {
const href = stepInfo.btn7.href || '';
if (isTelegramHref(href) || /vplink\.in\/(?:links\/go|go|final)/i.test(href)) {
window.th_gate_status = 'FINAL LINK: manual';
setProxyStatus(proxy, 'FINAL LINK: manual');
return true;
}
return navigateFlowUrl(href, 'FLOW: Continue', proxy);
}
return true;
}
const tpBtn = document.getElementById('tp-snp2');
if (tpBtn && document.getElementById('tp-time')) {
finishSafeCountdown(getSafeCountdownState());
if (tpBtn && (tpBtn.href || (tpBtn.closest && tpBtn.closest('a') && tpBtn.closest('a').href))) {
const href = tpBtn.href || (tpBtn.closest && tpBtn.closest('a') && tpBtn.closest('a').href);
return navigateFlowUrl(href, 'FLOW: timer continue', proxy);
}
window.th_gate_status = 'FLOW: timer ready';
setProxyStatus(proxy, 'FLOW: timer ready');
return true;
}
return false;
}
function shouldRunUniversalFlow() {
return !!(S.enabled && S.autoFlowSkip && S.universalFlow && !isVplinkChainHost());
}
function isSafeUniversalFlowUrl(url) {
try {
const u = new URL(url, location.href);
if (!/^https?:$/i.test(u.protocol)) return false;
if (isTelegramHref(u.href)) return false;
if (u.hostname === location.hostname) return true;
return isSafeVplinkFlowUrl(u.href);
} catch(e) { return false; }
}
function isFinalUniversalUrl(url) {
try {
const u = new URL(url, location.href);
if (isTelegramHref(u.href)) return true;
if (u.hostname !== location.hostname && !isSafeVplinkFlowUrl(u.href)) return true;
return /(?:\/(?:go|final|links\/go)(?:\/|$)|[?&](?:final|destination|target)=)/i.test(u.pathname + u.search);
} catch(e) { return true; }
}
function setUniversalManual(proxy, label, el) {
proxy = setProxyStatus(proxy, label);
window.th_gate_status = label;
if (proxy && el) {
proxy.onclick = () => {
if (!S.enabled || !S.universalFlow) return;
revealFlowElement(el);
stageRecipeAction(el, (el.href || (el.closest && el.closest('a') && el.closest('a').href)) ? 'navigate' : 'click');
clickIntermediateFlowTarget(el);
};
}
return true;
}
function navigateUniversalUrl(url, label, proxy, recipeTarget) {
const target = normalizeFlowUrl(url);
if (!target || !isSafeUniversalFlowUrl(target)) return false;
if (isFinalUniversalUrl(target)) {
window.th_gate_status = 'FINAL LINK: manual';
setProxyStatus(proxy, 'FINAL LINK: manual');
return true;
}
if (countFlowVisits(target) >= 3) {
window.th_gate_status = 'UNIVERSAL LOOP: manual';
rememberBrainState({ state: 'LOOP', confidence: 1, reason: 'same universal route attempted three times', target });
setProxyStatus(proxy, 'UNIVERSAL LOOP: manual');
return true;
}
window.th_gate_status = label || 'UNIVERSAL: next';
setProxyStatus(proxy, label || 'UNIVERSAL: next');
// Fast auto-walk + anti-crash guard: only one navigation may be scheduled at a time.
if (window.th_navigating) return true;
window.th_navigating = true;
const navStartedAt = Date.now();
window.th_navigating_since = navStartedAt;
(window.th_nativeSetTimeout || setTimeout)(() => {
if (window.th_navigating && window.th_navigating_since === navStartedAt) window.th_navigating = false;
}, 4000);
if (recipeTarget) stageRecipeAction(recipeTarget, 'navigate');
rememberFlowHop(target, label);
(window.th_nativeSetTimeout || setTimeout)(() => {
if (shouldRunUniversalFlow()) location.href = target; else window.th_navigating = false;
}, 150);
return true;
}
function getUniversalActionCandidates() {
const selectors = [
'#btn6', '#btn7', '#tp-snp2', '#tp98', '#cross-snp2', '#startCountdownBtn',
'a[href]', 'button', 'input[type="button"]', 'input[type="submit"]'
];
return Array.from(document.querySelectorAll(selectors.join(','))).filter(el => {
if (!el || isOwnUi(el) || isDisabledAction(el)) return false;
const text = getActionText(el).toLowerCase();
const href = el.href || (el.closest && el.closest('a') && el.closest('a').href) || '';
if (INVALID_TARGET_TEXT.some(k => text.includes(k))) return false;
if (isTelegramHref(href)) return true;
if (/^(btn6|btn7|tp-snp2|tp98|cross-snp2|startCountdownBtn)$/i.test(el.id || '')) return true;
return VALID_TARGET_TEXT.some(k => text.includes(k)) || /continue|verify|get\s*link|download\s*link|open\s*link/i.test(text);
});
}
function getBestUniversalAction() {
const candidates = getUniversalActionCandidates();
let best = null;
let bestScore = -1;
candidates.forEach(el => {
revealFlowElement(el);
const text = getActionText(el).toLowerCase();
const href = el.href || (el.closest && el.closest('a') && el.closest('a').href) || '';
let score = 10;
if (/^(btn7|tp-snp2|tp98|cross-snp2)$/i.test(el.id || '')) score += 80;
if (/^(btn6|startCountdownBtn)$/i.test(el.id || '')) score += 65;
if (/get\s*link|download\s*link|open\s*link/.test(text)) score += 50;
if (/continue|verify|click\s*to\s*verify/.test(text)) score += 40;
if (href && isSafeUniversalFlowUrl(href)) score += 25;
if (href && isFinalUniversalUrl(href)) score -= 90;
if (isVisibleAction(el)) score += 10;
if (score > bestScore) { bestScore = score; best = el; }
});
return { el: best, score: bestScore };
}
// Deep page scanner: read the page's own HTML + inline scripts to find a hidden "next" URL even when there is
// no obvious button โ JS location assignments, meta-refresh, data-* attributes, and base64-encoded URLs.
function scanPageForNextUrl() {
const found = [];
try {
const html = (document.documentElement && document.documentElement.innerHTML) || '';
let m;
const re1 = /(?:window\.|document\.)?location(?:\.href)?\s*=\s*["']([^"']{4,})["']/gi;
while ((m = re1.exec(html))) found.push(m[1]);
const re2 = /location\.replace\(\s*["']([^"']{4,})["']\s*\)/gi;
while ((m = re2.exec(html))) found.push(m[1]);
const meta = document.querySelector('meta[http-equiv="refresh" i]');
if (meta) { const mm = (meta.getAttribute('content') || '').match(/url=([^;]+)$/i); if (mm) found.push(mm[1].trim()); }
let b64count = 0;
const re3 = /["']([A-Za-z0-9+/]{24,}={0,2})["']/g;
while ((m = re3.exec(html)) && b64count < 80) { b64count++; try { const d = atob(m[1]).trim(); if (/^https?:\/\/[^\s"'<>]+$/i.test(d)) found.push(d); } catch(e) {} }
document.querySelectorAll('[data-url],[data-href],[data-link]').forEach(el => {
const u = el.getAttribute('data-url') || el.getAttribute('data-href') || el.getAttribute('data-link');
if (u) found.push(u);
});
} catch(e) {}
const here = normalizeFlowUrl(location.href);
const seen = {};
const out = [];
found.forEach(u => {
const n = normalizeFlowUrl(u);
if (!n || !/^https?:/i.test(n) || n === here || seen[n]) return;
seen[n] = 1;
out.push(n);
});
return out;
}
// Pick a SAFE same-host/known-intermediate scanned URL for auto-navigation (final/external/Telegram are excluded).
function getDeepScanAutoTarget() {
const cands = scanPageForNextUrl();
for (let i = 0; i < cands.length; i++) {
if (isFinalUniversalUrl(cands[i])) continue;
if (isSafeUniversalFlowUrl(cands[i]) && countFlowVisits(cands[i]) < 3) return cands[i];
}
return '';
}
function maybeRunUniversalPatternFlow(proxy) {
if (!shouldRunUniversalFlow() || !document.body) return false;
const bodyText = (document.body.innerText || '').replace(/\s+/g, ' ').toLowerCase();
const hasFlowShape = /step\s*[0-9]+\s*\/\s*[0-9]+|you are currently on step|please\s+wait\s+\d{1,3}\s*seconds?|count(?:ing)?\s*down|click\s+(?:to\s+)?verify|click\s+any\s+image|skip\s+timer|get\s+link/i.test(bodyText) || !!(document.getElementById('btn6') || document.getElementById('btn7') || document.getElementById('tp-snp2'));
if (!hasFlowShape) return false;
// This unknown page matches the shortlink/countdown shape while Universal mode is on โ remember it.
autoLearnIfNew('universal');
const redirectTarget = getScriptRedirectTarget();
if (redirectTarget && isSafeUniversalFlowUrl(redirectTarget)) {
return navigateUniversalUrl(redirectTarget, 'UNIVERSAL: redirect', proxy);
}
const stepInfo = getStepFlowInfo();
if (stepInfo) {
prepareStepFlow(stepInfo);
const stepLabel = stepInfo.current && stepInfo.total ? ('UNIVERSAL: Step ' + stepInfo.current + '/' + stepInfo.total) : 'UNIVERSAL: verify';
if (stepInfo.btn6 && !stepInfo.btn6.dataset.thUniversalClicked) {
stepInfo.btn6.dataset.thUniversalClicked = '1';
return setUniversalManual(proxy, 'LEARNING 0/2: tap Continue', stepInfo.btn6);
}
if (stepInfo.btn7) {
const href = stepInfo.btn7.href || '';
if (href && isSafeUniversalFlowUrl(href) && !isFinalUniversalUrl(href)) return navigateUniversalUrl(href, 'UNIVERSAL: Continue', proxy, stepInfo.btn7);
return setUniversalManual(proxy, 'UNIVERSAL: proxy click', stepInfo.btn7);
}
return true;
}
const safeCountdownState = getSafeCountdownState();
if (safeCountdownState.detected) finishSafeCountdown(safeCountdownState);
const found = getBestUniversalAction();
if (!found.el || found.score < 55) {
// No confident button โ read the page code for a hidden next-URL.
const scanned = getDeepScanAutoTarget();
if (scanned) return navigateUniversalUrl(scanned, 'UNIVERSAL: scanned link', proxy);
const all = scanPageForNextUrl();
if (all.length) {
// A next-URL exists but it is external/final โ offer one-tap rather than auto-jumping somewhere unsafe.
const next = all[0];
const p = setProxyStatus(proxy, 'โก๏ธ NEXT PAGE');
window.th_gate_status = 'Next link found โ tap to go';
if (p) p.onclick = () => { if (S.enabled) location.href = next; };
return true;
}
window.th_gate_status = 'LOW CONFIDENCE: manual';
setProxyStatus(proxy, 'LOW CONFIDENCE: manual');
return true;
}
const href = found.el.href || (found.el.closest && found.el.closest('a') && found.el.closest('a').href) || '';
if (href && isSafeUniversalFlowUrl(href) && !isFinalUniversalUrl(href) && found.score >= 90) {
return navigateUniversalUrl(href, 'UNIVERSAL: timer continue', proxy, found.el);
}
return setUniversalManual(proxy, 'UNIVERSAL: proxy click', found.el);
}
function isSmartVerifyTarget(el, text) {
return !!(S.smartVerifyFlow && text.includes('click to verify') && text.length <= 90 && isVisibleAction(el) && !isDisabledAction(el));
}
function hasSmartGateText(text) {
return !!(text && (text.includes('click to verify') || text.includes('click any image') || text.includes('counting down') || text.includes('wait ') || text.includes('scroll down')));
}
function parseVisibleTimerValue(text) {
if (!text) return null;
const values = [];
let m;
const secRe = /\b(-?\d{1,3})\s*(?:seconds?|secs?|s)\b/g;
while ((m = secRe.exec(text))) {
const n = parseInt(m[1], 10);
if (n >= 0 && n <= 180) values.push(n);
}
const mmssRe = /\b([0-5]?\d):([0-5]\d)\b/g;
while ((m = mmssRe.exec(text))) {
const n = parseInt(m[1], 10) * 60 + parseInt(m[2], 10);
if (n >= 0 && n <= 180) values.push(n);
}
return values.length ? Math.min.apply(null, values) : null;
}
function updateTimerMovementState(state) {
const current = state.timerValue;
window.th_timer_observed_value = current;
if (current === null) {
window.th_gate_status = S.waitUntilTimerMoves ? (state.gateVisible ? 'Gate: waiting for timer' : 'Timer: waiting') : 'Timer: normal mode';
return;
}
const last = window.th_timer_last_value;
if (last !== null && current < last) {
window.th_timer_moving_since = Date.now();
window.th_gate_boost_armed = true;
window.th_smart_gate_armed = true;
window.th_gate_status = 'Timer: moving, boost armed';
} else if (!window.th_gate_boost_armed) {
window.th_gate_status = 'Timer: stuck at ' + current + 's';
} else {
window.th_gate_status = 'Timer: boost armed';
}
window.th_timer_last_value = current;
}
function getSmartVerifyState() {
if (!S.smartVerifyFlow && !S.waitUntilTimerMoves) return { verify: null, timerText: '', timerValue: null, gateVisible: false };
const candidates = Array.from(document.querySelectorAll("a, button, input[type='button'], input[type='submit'], [role='button']"));
const verify = candidates.find(el => isSmartVerifyTarget(el, getActionText(el).toLowerCase())) || null;
const bodyText = (document.body && document.body.innerText || '').replace(/\s+/g, ' ').toLowerCase();
const timerMatch = bodyText.match(/\b-?\d+\s*seconds?\b/);
return { verify, timerText: timerMatch ? timerMatch[0] : '', timerValue: parseVisibleTimerValue(bodyText), gateVisible: hasSmartGateText(bodyText) };
}
function armSmartGate(el) {
if (!S.smartVerifyFlow) return;
const key = el ? getTargetKey(el) : 'smart-gate-manual-click';
window.th_smart_gate_armed = true;
window.th_gate_clicked = true;
if (!S.waitUntilTimerMoves) window.th_gate_boost_armed = true;
window.th_skipTimersEnabled = !!(window.th_skipTimersWanted && (!S.waitUntilTimerMoves || window.th_gate_boost_armed));
window.th_verify_aggro_until = Date.now() + 2500;
window.th_gate_status = S.waitUntilTimerMoves ? 'Gate: clicked, watching timer' : 'Gate: clicked, boost armed';
window.th_click_cooldowns[key] = Date.now();
}
document.addEventListener('click', function(e) {
if (!S.smartVerifyFlow || window.th_smart_gate_armed || isOwnUi(e.target)) return;
const tag = (e.target && e.target.tagName || '').toLowerCase();
const text = (document.body && document.body.innerText || '').toLowerCase();
if (tag === 'img' || tag === 'picture' || hasSmartGateText(text)) armSmartGate(e.target);
}, true);
function isValidActionTarget(el) {
if (!isVisibleAction(el) || isDisabledAction(el)) return false;
const t = getActionText(el).toLowerCase();
if (!t) return false;
if (S.safeCountdownMode && el && /^(tp98|tp-snp2|btn6|btn7|cross-snp2|get-link|gt-link|startCountdownBtn)$/.test(el.id || '') && /continue|verify|get link|getting link|click to verify/.test(t)) return true;
if (t === 'next') return isAllowedNextTarget(el, t);
if (isManualGateTarget(el, t)) return true;
if (isSmartVerifyTarget(el, t)) return true;
if (INVALID_TARGET_TEXT.some(k => t.includes(k))) return false;
return VALID_TARGET_TEXT.some(k => t.includes(k));
}
function targetScore(el) {
if (!isValidActionTarget(el)) return -1;
const text = getActionText(el).toLowerCase();
const rect = el.getBoundingClientRect();
let score = rect.top + window.scrollY;
if (S.safeCountdownMode && /^(get-link|gt-link)$/.test(el.id || '')) score += 3800;
else if (S.safeCountdownMode && /^(btn7|cross-snp2)$/.test(el.id || '')) score += 3600;
else if (S.safeCountdownMode && /^(tp98|tp-snp2|btn6|startCountdownBtn)$/.test(el.id || '')) score += 3000;
else if (isAllowedNextTarget(el, text)) score += 2400;
else if (isManualGateTarget(el, text)) score += 2350;
else if (isSmartVerifyTarget(el, text)) score += 2300;
else if (text.includes('click to continue')) score += 2200;
else if (text === 'continue') score += 1800;
else if (text.includes('human veification') || text.includes('human verification')) score += 1500;
else if (text.includes('get link') || text.includes('download link')) score += 1200;
if (el.tagName === 'BUTTON' || el.getAttribute('role') === 'button') score += 300;
if (el.querySelector && el.querySelector('button')) score += 250;
if (el.closest && el.closest('nav, header, aside, [role="navigation"], [role="complementary"]')) score -= 1200;
return score;
}
function findBestActionTarget() {
const nodes = Array.from(document.querySelectorAll("a, button, input[type='button'], input[type='submit'], [role='button'], [role='link'], [onclick]"));
const best = nodes.map(el => ({ el, score: targetScore(el) })).filter(x => x.score >= 0).sort((a, b) => b.score - a.score)[0]?.el || null;
if (best) return best;
const bodyText = (document.body && document.body.innerText || '').toLowerCase();
if (!bodyText.includes('click any image')) return null;
return findFirstVisibleContentImage();
}
function findFirstVisibleContentImage() {
const imgs = Array.from(document.querySelectorAll('article img, main img, .inside-article img, .entry-content img, img'));
return imgs.find(img => {
if (!isVisibleAction(img) || isOwnUi(img)) return false;
const rect = img.getBoundingClientRect();
const src = (img.currentSrc || img.src || '').toLowerCase();
if (rect.width < 80 || rect.height < 60) return false;
if (/logo|icon|avatar|spinner|loader|adsbygoogle|doubleclick|googlesyndication/.test(src)) return false;
return true;
}) || null;
}
function getLinkShortifyState() {
if (!/lksfy\.com$/i.test(location.hostname)) return null;
const bodyText = (document.body && document.body.innerText || '').toLowerCase();
if (!bodyText.includes('your link is almost ready')) return null;
const hasTurnstile = !!document.querySelector('.cf-turnstile, iframe[src*="challenges.cloudflare.com"], [data-sitekey]');
const tokenEl = document.querySelector('input[name="cf-turnstile-response"], textarea[name="cf-turnstile-response"]');
const turnstileToken = tokenEl && (tokenEl.value || '').trim();
const needsTurnstile = !!(hasTurnstile && !turnstileToken);
const waiting = Array.from(document.querySelectorAll('a, button')).find(el => getActionText(el).toLowerCase().includes('please wait'));
const ready = needsTurnstile ? null : Array.from(document.querySelectorAll('a, button')).find(el => {
const text = getActionText(el).toLowerCase();
const href = el.href || '';
if (!isVisibleAction(el) || isDisabledAction(el)) return false;
if (INVALID_TARGET_TEXT.some(k => text.includes(k)) || text.includes('linkshortify')) return false;
if (href && href !== 'javascript: void(0)' && !href.endsWith('#') && !href.includes('linkshortify.com') && !href.includes('/pages/')) return true;
return ['get link', 'go to link', 'open link', 'get destination link'].some(k => text.includes(k));
});
return { waiting, ready, needsTurnstile };
}
function nudgeLinkShortifyTimer(proxy) {
if (window.th_lksfy_nudged) return;
window.th_lksfy_nudged = true;
try {
document.dispatchEvent(new Event('DOMContentLoaded', { bubbles: true }));
window.dispatchEvent(new Event('load'));
window.dispatchEvent(new Event('focus'));
} catch(e) {}
if (proxy) {
proxy.innerText = 'โฑ FINAL TIMER...';
proxy.style.top = S.topOffset + 'px';
proxy.style.display = 'block';
}
}
// Detect a captcha / Cloudflare / human-verification challenge that needs a real human.
// When present, Time Hooker fully pauses: no timer speed-up, no skip, no auto-click.
function detectChallenge() {
try {
const bodyText = (document.body && document.body.innerText || '');
if (bodyText.length < 2500) {
const t = bodyText.toLowerCase();
if (/just a moment|checking your browser|verify you are human|verifying you are human|needs to review the security of your connection|enable javascript and cookies to continue|attention required/i.test(t)) return true;
}
const widgets = document.querySelectorAll('.cf-turnstile, iframe[src*="challenges.cloudflare.com"], .g-recaptcha, iframe[src*="recaptcha/api2"], iframe[src*="google.com/recaptcha"], iframe[src*="hcaptcha.com"], .h-captcha, #cf-challenge-running, #challenge-form');
for (let i = 0; i < widgets.length; i++) {
const w = widgets[i];
if (isOwnUi(w)) continue;
const r = w.getBoundingClientRect();
const st = getComputedStyle(w);
if (r.width > 40 && r.height > 40 && st.display !== 'none' && st.visibility !== 'hidden' && parseFloat(st.opacity || '1') > 0.1) return true;
}
return false;
} catch(e) { return false; }
}
function getDnsBlockMessage() {
const host = location.hostname.toLowerCase();
const bodyText = (document.body && document.body.innerText || '').toLowerCase();
const blockedHost = host.includes('whalebone.io') || host.includes('dns.google') || host.includes('familyshield') || host.includes('block');
const blockedText = bodyText.includes('detected threats') || bodyText.includes('malware') || bodyText.includes('considers to be harmful') || bodyText.includes('security warning');
if (!blockedHost && !blockedText) return '';
return 'DNS/security block detected. Userscript cannot toggle DNS. Turn off Private DNS/security DNS in browser/device settings, then reload.';
}
function showDnsBlockHelper(message) {
if (!message || !document.body || document.getElementById('th-dns-helper')) return;
const helper = document.createElement('div');
helper.id = 'th-dns-helper';
helper.textContent = message;
helper.style.cssText = 'position:fixed;left:12px;right:12px;bottom:14px;z-index:2147483647;background:rgba(15,15,20,0.96);color:#fff;border:1px solid rgba(255,255,255,0.18);border-radius:10px;padding:12px 14px;font:600 13px/1.45 system-ui,-apple-system,Segoe UI,sans-serif;box-shadow:0 8px 26px rgba(0,0,0,0.35);';
document.body.appendChild(helper);
}
function isOwnUi(el) {
return !!(el && el.closest && el.closest('#th-panel-root, #th-proxy-btn, #th-dns-helper'));
}
function isVisibleBox(el) {
const rect = el.getBoundingClientRect();
const style = getComputedStyle(el);
return rect.width > 0 && rect.height > 0 && style.display !== 'none' && style.visibility !== 'hidden' && parseFloat(style.opacity || '1') > 0.05;
}
// Don't hide a container that holds the real flow (timer/continue/get-link) or our own UI.
function hasFlowInside(el) {
try {
if (el.querySelector && el.querySelector('#th-panel-root, #th-proxy-btn, #th-dns-helper, #get-link, #gt-link, #btn6, #btn7, #tp-snp2, #tp98, #startCountdownBtn, #cross-snp2, #tp-time, #countdown, #ce-time, #link1s-time')) return true;
const t = (el.innerText || '').toLowerCase();
if (t && t.length < 400 && /continue|get\s*link|download\s*link|click to (verify|continue)|go to link|open link/.test(t)) return true;
} catch(e) {}
return false;
}
function cleanupAdsAndPopups() {
if (!document.body) return;
// Undo scroll-locks that overlays add to the page.
document.documentElement.style.setProperty('overflow', 'auto', 'important');
document.body.style.setProperty('overflow', 'auto', 'important');
try { if (getComputedStyle(document.body).position === 'fixed') document.body.style.setProperty('position', 'static', 'important'); } catch(e) {}
['modal-open', 'no-scroll', 'noscroll', 'overflow-hidden', 'stop-scrolling', 'sweet-alert-open', 'fc-html-overlay-active'].forEach(c => { try { document.body.classList.remove(c); document.documentElement.classList.remove(c); } catch(e) {} });
const closeTexts = ['close ad', 'close ads', 'close', 'ร', 'x', 'โ', 'skip ad', 'skip'];
Array.from(document.querySelectorAll('button, a, [role="button"], span, div')).slice(0, 400).forEach(el => {
if (isOwnUi(el) || el.dataset.thClosed === '1' || !isVisibleBox(el)) return;
const text = getActionText(el).toLowerCase();
if (!closeTexts.includes(text) && !text.startsWith('close ad') && !text.startsWith('skip ad')) return;
const rect = el.getBoundingClientRect();
if (rect.width > window.innerWidth * 0.8 || rect.height > window.innerHeight * 0.25) return;
el.dataset.thClosed = '1';
try { simulateClick(el); } catch(e) {}
});
Array.from(document.querySelectorAll('iframe, ins, [class*="adsbygoogle"], [id*="google_ads"], [id^="aswift"], [id^="ad_iframe"], [id*="popup"], [class*="popup"], [class*="modal"], [class*="overlay"], [class*="backdrop"], [class*="interstitial"], [aria-modal="true"]')).slice(0, 320).forEach(el => {
if (isOwnUi(el) || !isVisibleBox(el) || hasFlowInside(el)) return;
const meta = [el.id, el.className, el.src || ''].join(' ').toLowerCase();
const style = getComputedStyle(el);
const z = parseInt(style.zIndex || '0', 10) || 0;
const rect = el.getBoundingClientRect();
const fixedish = style.position === 'fixed' || style.position === 'absolute' || style.position === 'sticky';
const isAdFrame = el.tagName === 'IFRAME' && /(doubleclick|googlesyndication|adservice|adnxs|taboola|outbrain|data527|adv\.so|adsterra|popads|propeller|hilltopads|monetag|onclickads|popcash)/i.test(meta);
const isAdSlot = el.tagName === 'INS' || /(^|\W)(ad|ads|advert|adsbygoogle|popup|overlay|backdrop|interstitial|modal)(\W|$)/i.test(meta);
const coversScreen = fixedish && rect.width >= window.innerWidth * 0.6 && rect.height >= window.innerHeight * 0.6;
const isBlockingLayer = fixedish && z >= 100 && (rect.width > window.innerWidth * 0.45 || rect.height > window.innerHeight * 0.22);
if (isAdFrame || isAdSlot || isBlockingLayer || coversScreen) el.style.setProperty('display', 'none', 'important');
});
}
setInterval(function() {
if (isIframe) return;
let proxy = document.getElementById("th-proxy-btn");
const dnsBlockMessage = getDnsBlockMessage();
if (dnsBlockMessage) {
showDnsBlockHelper(dnsBlockMessage);
if (proxy) proxy.style.display = "none";
return;
}
if (!S.enabled) {
if (proxy) proxy.style.display = "none";
return;
}
if (maybeHandleServerError(proxy)) return;
// ๐ CAPTCHA / CLOUDFLARE GUARD: if a human-verification challenge is on the page, fully pause โ
// no timer speed-up (flag read by the timer engine), no skip, no auto-click. Just show "SOLVE CAPTCHA".
if (detectChallenge()) {
window.th_captcha_present = true;
clearPendingRecipe();
window.th_gate_status = 'Captcha/Cloudflare โ paused, solve it';
rememberBrainState({ state: 'CAPTCHA', confidence: 1, reason: 'human verification detected' });
recordSiteTrick('manual');
if (S.pinMode) {
if (!proxy) {
proxy = document.createElement("button"); proxy.id = "th-proxy-btn";
proxy.style.cssText = "position: fixed !important; left: 50% !important; transform: translateX(-50%) !important; z-index: 2147483647; padding: 15px 30px; font-weight: bold; background: linear-gradient(90deg, #d7263d, #f46036); color: white; border-radius: 10px; cursor: default;";
document.body.appendChild(proxy);
}
proxy.innerText = '๐ SOLVE CAPTCHA';
proxy.style.top = S.topOffset + 'px';
proxy.style.display = 'block';
proxy.onclick = null;
}
return;
}
window.th_captcha_present = false;
rememberBrainState(getPageBrainState());
if (maybeSkipSchemeProArticle(proxy)) return;
if (maybeRunVplinkChain(proxy)) return;
try { if (maybeRunLearnedRecipe(proxy)) return; } catch(e) { window.th_gate_status = 'LEARNED: safe fallback'; }
if (maybeRunUniversalPatternFlow(proxy)) return;
window.th_skipTimersEnabled = !!S.skipTimers;
const safeCountdownState = getSafeCountdownState();
window.th_flowManualMode = !!(safeCountdownState.detected && isAutoFlowHost() && !S.autoClick);
exposeSafeCountdownTarget(safeCountdownState);
if (safeCountdownState.detected && S.aggroBypass && window.th_live_aggro_request && Date.now() - window.th_live_aggro_request < 4000) {
finishSafeCountdown(safeCountdownState);
window.th_live_aggro_request = 0;
}
const effectiveAggroBypass = !!(S.aggroBypass && !safeCountdownState.detected);
if (effectiveAggroBypass) {
window.isClicked = true; window.adClicked = true;
if (typeof window.count !== "undefined") window.count = 0; if (typeof window.timer !== "undefined") window.timer = 0;
}
if (S.antiAdblock) cleanupAdsAndPopups();
if (S.videoSpeed) {
document.querySelectorAll('video, audio').forEach(m => { if(m.playbackRate != S.speed) m.playbackRate = (S.speed > 16 ? 16 : S.speed); });
}
const linkShortifyState = getLinkShortifyState();
if (linkShortifyState) {
if (!proxy && S.pinMode) {
proxy = document.createElement("button"); proxy.id = "th-proxy-btn";
proxy.style.cssText = "position: fixed !important; left: 50% !important; transform: translateX(-50%) !important; z-index: 2147483647; padding: 15px 30px; font-weight: bold; background: linear-gradient(90deg, #5b42f3, #00ddeb); color: white; border-radius: 10px; cursor: pointer;";
document.body.appendChild(proxy);
}
if (linkShortifyState.ready) {
if (S.highlight) linkShortifyState.ready.style.setProperty('outline', '4px solid #00ffcc', 'important');
if (S.pinMode && proxy && !String(proxy.innerText || '').includes("WAITING")) {
proxy.innerText = "CLICK: " + getTargetLabel(linkShortifyState.ready).slice(0, 32);
proxy.style.top = S.topOffset + 'px'; proxy.style.display = "block";
proxy.onclick = () => { proxy.innerText = "โณ WAITING..."; clickFlowTarget(linkShortifyState.ready); };
}
return;
}
if (linkShortifyState.needsTurnstile) {
if (linkShortifyState.waiting && S.pinMode && proxy) nudgeLinkShortifyTimer(proxy);
if (S.pinMode && proxy) {
proxy.innerText = 'SOLVE TURNSTILE';
proxy.style.top = S.topOffset + 'px';
proxy.style.display = 'block';
proxy.onclick = null;
}
window.th_gate_status = 'Final page: Turnstile required';
return;
}
if (linkShortifyState.waiting && S.pinMode && proxy) nudgeLinkShortifyTimer(proxy);
if (linkShortifyState.waiting) return;
}
if (safeCountdownState.detected) {
// Stuck-timer auto-recovery: if the visible countdown value has not changed for several loop ticks
// (e.g. an ad callback never fired, or it is a server/perf timer we cannot speed), force the gate to finish.
if (safeCountdownState.timerValue !== null && safeCountdownState.timerValue > 0) {
if (window.th_stuck_val === safeCountdownState.timerValue) window.th_stuck_count = (window.th_stuck_count || 0) + 1;
else { window.th_stuck_val = safeCountdownState.timerValue; window.th_stuck_count = 0; }
if ((window.th_stuck_count || 0) >= getStuckThreshold()) {
finishSafeCountdown(safeCountdownState);
recordSiteTrick('force');
window.th_gate_status = 'Timer stuck โ forced finish';
window.th_stuck_count = 0;
}
} else {
window.th_stuck_count = 0;
}
if (!proxy && S.pinMode) {
proxy = document.createElement("button"); proxy.id = "th-proxy-btn";
proxy.style.cssText = "position: fixed !important; left: 50% !important; transform: translateX(-50%) !important; z-index: 2147483647; padding: 15px 30px; font-weight: bold; background: linear-gradient(90deg, rgb(255, 0, 85), rgb(255, 170, 0)); color: white; border-radius: 10px; cursor: pointer;";
document.body.appendChild(proxy);
}
if (safeCountdownState.ready) {
recordSiteTrick('timer');
if (S.highlight) safeCountdownState.ready.style.setProperty('outline', '4px solid #00ffcc', 'important');
if (S.pinMode && proxy && !String(proxy.innerText || '').includes("WAITING")) {
proxy.innerText = "CLICK: " + getTargetLabel(safeCountdownState.ready).slice(0, 32);
proxy.style.top = S.topOffset + 'px'; proxy.style.display = "block";
proxy.onclick = () => { proxy.innerText = "WAITING..."; clickFlowTarget(safeCountdownState.ready, true); };
}
if (isFinalActionTarget(safeCountdownState.ready)) {
window.th_gate_status = 'Final link ready: manual click';
} else if (shouldAutoFlow()) {
const key = getTargetKey(safeCountdownState.ready);
const last = window.th_click_cooldowns[key] || 0;
if (Date.now() - last > 12000) {
window.th_click_cooldowns[key] = Date.now();
setTimeout(() => {
if (S.enabled && shouldAutoFlow() && document.contains(safeCountdownState.ready) && isVisibleAction(safeCountdownState.ready) && !isDisabledAction(safeCountdownState.ready)) clickFlowTarget(safeCountdownState.ready);
}, 450);
}
}
return;
}
if (S.pinMode && proxy && !String(proxy.innerText || '').includes("WAITING")) {
proxy.innerText = safeCountdownState.timerValue !== null ? ("FAST TIMER: " + safeCountdownState.timerValue + "s") : "FAST TIMER...";
proxy.style.top = S.topOffset + 'px'; proxy.style.display = "block";
}
return;
}
const best = findBestActionTarget();
if (!best) {
if (proxy && !String(proxy.innerText || '').includes("WAITING")) proxy.style.display = "none";
return;
}
const finalAction = isFinalActionTarget(best);
const targetKey = getTargetKey(best);
if (targetKey && targetKey !== window.th_auto_target_key) {
window.th_auto_target_key = targetKey;
window.th_auto_executed = false;
}
if (S.highlight) best.style.setProperty('outline', '4px solid #00ffcc', 'important');
if (S.pinMode) {
if (!proxy) {
proxy = document.createElement("button"); proxy.id = "th-proxy-btn";
proxy.style.cssText = "position: fixed !important; left: 50% !important; transform: translateX(-50%) !important; z-index: 2147483647; padding: 15px 30px; font-weight: bold; background: linear-gradient(90deg, #ff0055, #ffaa00); color: white; border-radius: 10px; cursor: pointer;";
document.body.appendChild(proxy);
}
if (!String(proxy.innerText || '').includes("WAITING") && !String(proxy.innerText || '').includes("AUTO-CLICKING")) {
proxy.innerText = (finalAction ? "FINAL LINK: " : "CLICK: ") + getTargetLabel(best).slice(0, 32);
}
proxy.style.top = S.topOffset + 'px'; proxy.style.display = "block";
proxy.onclick = () => { proxy.innerText = "โณ WAITING..."; if (isSmartVerifyTarget(best, getActionText(best).toLowerCase())) armSmartGate(best); clickFlowTarget(best, true); setTimeout(() => { proxy.innerText = "CLICK: " + getTargetLabel(best).slice(0, 32); }, 3000); };
}
// ๐ฅ FIXED AUTO-CLICK: target-level lock plus delayed safety checks
if (finalAction) {
window.th_gate_status = 'Final link ready: manual click';
return;
}
if (shouldAutoFlow() && !window.th_auto_executed && best.dataset.thDone !== "1") {
const t = getActionText(best).toLowerCase();
if (isValidActionTarget(best)) {
const cooldownKey = getTargetKey(best);
if (window.th_click_cooldowns[cooldownKey] && Date.now() - window.th_click_cooldowns[cooldownKey] < 8000) return;
best.dataset.thDone = "1"; // Lock element
window.th_auto_executed = true; // Lock page
setTimeout(() => {
const latestText = getActionText(best).toLowerCase();
if (!S.enabled || !shouldAutoFlow() || !document.contains(best) || !isValidActionTarget(best) || INVALID_TARGET_TEXT.some(k => latestText.includes(k))) return;
if(proxy) proxy.innerText = "โณ AUTO-CLICKING...";
window.th_click_cooldowns[cooldownKey] = Date.now();
if (isSmartVerifyTarget(best, latestText)) armSmartGate(best);
clickFlowTarget(best);
setTimeout(() => { if(proxy) proxy.innerText = "CLICK: " + getTargetLabel(best).slice(0, 32); }, 3000);
}, 1000);
}
}
}, 1500);
};
const scriptEl = document.createElement('script');
scriptEl.textContent = `(${mainPageLogic.toString()})(${JSON.stringify(savedData || null)}, ${JSON.stringify(remoteRulesCached || null)});`;
(document.head || document.documentElement).appendChild(scriptEl);
scriptEl.remove();
// Background, throttled remote-rules refresh. Runs in the userscript sandbox (GM_xmlhttpRequest only exists here),
// fully guarded, size-limited and validated. Never blocks the page; only updates the cache for the NEXT load.
try {
const lastTs = parseInt(GM_getValue(REMOTE_TS_KEY) || '0', 10) || 0;
if (REMOTE_RULES_URL && (Date.now() - lastTs > REMOTE_REFRESH_MS) && typeof GM_xmlhttpRequest === 'function') {
GM_xmlhttpRequest({
method: 'GET',
url: REMOTE_RULES_URL,
timeout: 15000,
onload: function(res) {
try {
if (res && res.status >= 200 && res.status < 300 && typeof res.responseText === 'string' && res.responseText.length < 200000) {
const parsed = JSON.parse(res.responseText);
if (parsed && typeof parsed === 'object' && parsed.sites && typeof parsed.sites === 'object') {
GM_setValue(REMOTE_CACHE_KEY, JSON.stringify(parsed));
}
}
} catch(e) {}
try { GM_setValue(REMOTE_TS_KEY, String(Date.now())); } catch(e) {}
},
onerror: function() { try { GM_setValue(REMOTE_TS_KEY, String(Date.now())); } catch(e) {} },
ontimeout: function() { try { GM_setValue(REMOTE_TS_KEY, String(Date.now())); } catch(e) {} }
});
}
} catch(e) {}
})();