Refactor registration flow, update config, replace Turnstile patch
- Major refactor of grok_register_ttk.py: improved flow, error handling, logging - Update config.example.json and config.json with new fields - Replace turnstilePatch/content.js with new script.js approach - Update start.sh for better Chromium/Turnstile handling - Remove deprecated turnstilePatch/content.js
This commit is contained in:
1 parent
7a02453601
commit
c87b01967f
7 files changed
+774
-405
No files matched your search
+4
-4
@@ -99,14 +99,14 @@
|
||||
"turnstile_retry_limit": 3,
|
||||
"// turnstile_stuck_timeout": "Turnstile 卡住判定超时(秒)",
|
||||
"turnstile_stuck_timeout": 150,
|
||||
"// turnstile_fast_fail_count": "资料页内连续 getTurnstileToken 失败几次后放弃(服务器建议 4)",
|
||||
"turnstile_fast_fail_count": 4,
|
||||
"// turnstile_fast_fail_count": "资料页内连续 getTurnstileToken 失败几次后放弃(参考 Git-creat7 建议 3)",
|
||||
"turnstile_fast_fail_count": 3,
|
||||
"// turnstile_retry_after_sec": "资料页等待 CF 多久后触发二次复用(秒)",
|
||||
"turnstile_retry_after_sec": 12,
|
||||
"// turnstile_retry_gap_sec": "两次二次复用之间的最小间隔(秒)",
|
||||
"turnstile_retry_gap_sec": 8,
|
||||
"// turnstile_max_rounds": "单次 getTurnstileToken 内 click/poll 轮数",
|
||||
"turnstile_max_rounds": 8,
|
||||
"// turnstile_max_rounds": "单次 getTurnstileToken 内 reset+click 轮数(参考 15-20)",
|
||||
"turnstile_max_rounds": 16,
|
||||
"// sso_timeout_base / sso_timeout_max / sso_progress_extension": "等待 sso cookie 的基础/上限/有进度时延长(秒)",
|
||||
"sso_timeout_base": 240,
|
||||
"sso_timeout_max": 480,
|
||||
|
||||
+9
-6
@@ -10,7 +10,7 @@
|
||||
"proxy": "",
|
||||
"enable_nsfw": true,
|
||||
"register_count": 1,
|
||||
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
|
||||
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36",
|
||||
"grok2api_auto_add_local": false,
|
||||
"grok2api_local_token_file": "",
|
||||
"grok2api_pool_name": "ssoBasic",
|
||||
@@ -46,9 +46,9 @@
|
||||
"mail_poll_interval": 1,
|
||||
"mail_retry_count": 3,
|
||||
"code_form_timeout": 180,
|
||||
"profile_timeout": 50,
|
||||
"profile_timeout": 180,
|
||||
"turnstile_retry_limit": 3,
|
||||
"turnstile_stuck_timeout": 150,
|
||||
"turnstile_stuck_timeout": 180,
|
||||
"sso_timeout_base": 60,
|
||||
"sso_timeout_max": 480,
|
||||
"sso_progress_extension": 120,
|
||||
@@ -98,8 +98,11 @@
|
||||
"gmail_imap_fallback": true,
|
||||
"gmail_imap_fallback_timeout_sec": 45,
|
||||
"gmail_imap_fallback_resend_sec": 10,
|
||||
"turnstile_fast_fail_count": 4,
|
||||
"turnstile_retry_after_sec": 12,
|
||||
"turnstile_fast_fail_count": 3,
|
||||
"turnstile_retry_after_sec": 10,
|
||||
"turnstile_retry_gap_sec": 8,
|
||||
"turnstile_max_rounds": 8
|
||||
"turnstile_max_rounds": 20,
|
||||
"browser_prefer": "chrome",
|
||||
"browser_path": "/usr/bin/google-chrome-stable",
|
||||
"browser_headless": false
|
||||
}
|
||||
+708
-252
File diff suppressed because it is too large.
Load diff
@@ -419,9 +419,31 @@ _resolve_bin() {
|
||||
return 1
|
||||
}
|
||||
|
||||
find_playwright_chromium() {
|
||||
# Playwright Chromium 无 snap AppArmor 限制,ReinerBRO/grok-register 同款优先路径
|
||||
local root cand
|
||||
for root in \
|
||||
"${HOME}/.cache/ms-playwright" \
|
||||
"${LOCALAPPDATA:-}/ms-playwright"; do
|
||||
[ -d "$root" ] || continue
|
||||
# 取最新 chromium-* 目录
|
||||
cand=$(find "$root" -maxdepth 3 -type f \( -path '*/chrome-linux64/chrome' -o -path '*/chrome-linux/chrome' -o -path '*/chrome-win64/chrome.exe' \) 2>/dev/null | sort -r | head -1 || true)
|
||||
if [ -n "$cand" ] && [ -x "$cand" ] || [ -f "$cand" ]; then
|
||||
echo "$cand"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
find_chromium_bin() {
|
||||
local candidate p
|
||||
# 优先 deb/系统包路径,snap 放后面(且不 resolve 成 /usr/bin/snap)
|
||||
# 1) Playwright Chromium(推荐,服务器无 AppArmor/snap 坑)
|
||||
if p="$(find_playwright_chromium 2>/dev/null)"; then
|
||||
echo "$p"
|
||||
return 0
|
||||
fi
|
||||
# 2) deb/系统包路径,snap 放后面(且不 resolve 成 /usr/bin/snap)
|
||||
for candidate in \
|
||||
/usr/bin/chromium \
|
||||
/usr/bin/chromium-browser \
|
||||
@@ -439,7 +461,7 @@ find_chromium_bin() {
|
||||
esac
|
||||
# 必须像 chromium
|
||||
case "$p" in
|
||||
*chromium*|*Chromium*)
|
||||
*chromium*|*Chromium*|*chrome-linux*)
|
||||
echo "$p"
|
||||
return 0
|
||||
;;
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
// Turnstile Patch - minimal only
|
||||
// Full aggressive patches (chrome.runtime delete / permissions / plugins / languages
|
||||
// / iframe postMessage spam) were observed to break xAI signup with:
|
||||
// [permission_denied] HTTP 403
|
||||
// Keep webdriver hide only. Auto-click remains best-effort and local-only.
|
||||
// Note: CF challenge iframes are cross-origin — contentDocument click usually fails;
|
||||
// host-page click + Python CDP shadow path do the real work.
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
if (window.__grokStealthApplied) return;
|
||||
window.__grokStealthApplied = true;
|
||||
|
||||
// 1. Hide navigator.webdriver (instance + prototype when possible)
|
||||
try {
|
||||
Object.defineProperty(navigator, "webdriver", {
|
||||
get: function () {
|
||||
return false;
|
||||
},
|
||||
configurable: true,
|
||||
});
|
||||
} catch (e) {}
|
||||
try {
|
||||
var desc = Object.getOwnPropertyDescriptor(Navigator.prototype, "webdriver");
|
||||
if (!desc || desc.configurable) {
|
||||
Object.defineProperty(Navigator.prototype, "webdriver", {
|
||||
get: function () {
|
||||
return false;
|
||||
},
|
||||
configurable: true,
|
||||
});
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
function firePointer(el) {
|
||||
if (!el) return;
|
||||
try {
|
||||
el.scrollIntoView({ block: "center", inline: "center" });
|
||||
} catch (e) {}
|
||||
var rect;
|
||||
try {
|
||||
rect = el.getBoundingClientRect();
|
||||
} catch (e) {
|
||||
rect = null;
|
||||
}
|
||||
var x = 12;
|
||||
var y = 12;
|
||||
if (rect && rect.width > 0) {
|
||||
x = rect.left + Math.max(6, Math.min(rect.width - 6, rect.width * 0.35));
|
||||
y = rect.top + Math.max(6, Math.min(rect.height - 6, rect.height * 0.5));
|
||||
}
|
||||
var opts = {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
view: window,
|
||||
clientX: x,
|
||||
clientY: y,
|
||||
button: 0,
|
||||
};
|
||||
var types = [
|
||||
"pointerover",
|
||||
"mouseover",
|
||||
"mousemove",
|
||||
"pointerdown",
|
||||
"mousedown",
|
||||
"pointerup",
|
||||
"mouseup",
|
||||
"click",
|
||||
];
|
||||
for (var i = 0; i < types.length; i++) {
|
||||
var t = types[i];
|
||||
try {
|
||||
var Ev = t.indexOf("pointer") === 0 ? PointerEvent : MouseEvent;
|
||||
el.dispatchEvent(new Ev(t, opts));
|
||||
} catch (e) {
|
||||
try {
|
||||
el.dispatchEvent(new MouseEvent(t, opts));
|
||||
} catch (e2) {}
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (typeof el.click === "function") el.click();
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// 2. Best-effort Turnstile interaction (same-origin iframe + host widget)
|
||||
function tryClickTurnstile() {
|
||||
try {
|
||||
var iframes = document.querySelectorAll(
|
||||
'iframe[src*="challenges.cloudflare.com"], iframe[src*="turnstile"]'
|
||||
);
|
||||
for (var i = 0; i < iframes.length; i++) {
|
||||
// Host-side synthetic click (works even when iframe is cross-origin)
|
||||
firePointer(iframes[i]);
|
||||
try {
|
||||
var body = iframes[i].contentDocument || iframes[i].contentWindow.document;
|
||||
if (!body) continue;
|
||||
var checkbox = body.querySelector(
|
||||
'input[type="checkbox"], .mark, label, [role="checkbox"]'
|
||||
);
|
||||
if (checkbox && !checkbox.checked) {
|
||||
firePointer(checkbox);
|
||||
}
|
||||
} catch (e) {
|
||||
// cross-origin: host click above is enough
|
||||
}
|
||||
}
|
||||
var widgets = document.querySelectorAll(
|
||||
"div.cf-turnstile, [data-sitekey], input[name='cf-turnstile-response']"
|
||||
);
|
||||
for (var j = 0; j < widgets.length; j++) {
|
||||
firePointer(widgets[j]);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function startLoop() {
|
||||
var n = 0;
|
||||
var t = setInterval(function () {
|
||||
n++;
|
||||
tryClickTurnstile();
|
||||
// ~90s of best-effort clicks (was 40s)
|
||||
if (n > 180) clearInterval(t);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", startLoop);
|
||||
} else {
|
||||
startLoop();
|
||||
}
|
||||
})();
|
||||
@@ -1,16 +1,12 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "Turnstile Patch",
|
||||
"version": "1.3.0",
|
||||
"description": "Minimal webdriver hide + best-effort host click for Turnstile",
|
||||
"name": "Turnstile Patcher",
|
||||
"version": "2.1",
|
||||
"description": "Patch CDP MouseEvent.screenX/screenY for Turnstile (ReinerBRO / Git-creat7)",
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": [
|
||||
"<all_urls>"
|
||||
],
|
||||
"js": [
|
||||
"content.js"
|
||||
],
|
||||
"js": ["./script.js"],
|
||||
"matches": ["<all_urls>"],
|
||||
"run_at": "document_start",
|
||||
"all_frames": true,
|
||||
"world": "MAIN",
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
function getRandomInt(min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
// CDP Input.dispatchMouseEvent creates MouseEvent where
|
||||
// .screenX/.screenY equal .clientX/.clientY. Cloudflare Turnstile detects
|
||||
// this (Chromium issue 40280325). Patch with realistic screen coords.
|
||||
// Source: ObjectAscended/CDP-bug-MouseEvent-.screenX-.screenY-patcher
|
||||
// Ported from ReinerBRO/grok-register + Git-creat7/grokRegister-cpa.
|
||||
|
||||
// old method wouldn't work on 4k screens
|
||||
let screenX = getRandomInt(800, 1200);
|
||||
let screenY = getRandomInt(400, 600);
|
||||
|
||||
Object.defineProperty(MouseEvent.prototype, "screenX", { value: screenX });
|
||||
Object.defineProperty(MouseEvent.prototype, "screenY", { value: screenY });
|
||||
|
||||
// Best-effort: also cover PointerEvent if present (CF may read either).
|
||||
try {
|
||||
if (typeof PointerEvent !== "undefined" && PointerEvent.prototype) {
|
||||
Object.defineProperty(PointerEvent.prototype, "screenX", { value: screenX });
|
||||
Object.defineProperty(PointerEvent.prototype, "screenY", { value: screenY });
|
||||
}
|
||||
} catch (e) {}
|
||||
Reference in new issue
Block a user