feat: bot_flag 检测停机、注册间隔与 CLI 参数
注册成功后解析 access_token 的 bot_flag_source,命中则立即停止; 支持 register_interval_sec 与 argparse(count/concurrency/interval/hide-window); 邮箱 local-part 强制 z 起首,并关闭 AutomationControlled 特征。
This commit is contained in:
1 parent
986bc36f04
commit
d0f06ac93c
7 files changed
+193
-22
No files matched your search
@@ -0,0 +1 @@
|
|||||||
|
helenramos281@mail.bblbb.com----N9ee81e6c!a7#VCKDb6V6----eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiMWU1OTMzYWEtMTJiYi00YjU5LTg1ZDktOTRiZmFhNDliYzU2In0.gnekLoMUj2B5DscbjE5hyC9FoLqkYjjXP9X3usyyqDQ
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
zoieroberts1869@mail.bblbb.com----Ndf7a20b2!a7#M3gEsHL-----eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiNjRkOWNjNTMtM2Q0YS00MzNlLThhMTctMTIxYmUyODNmZTU4In0.ra0SYJyU146-eMqSQKcG9J63YDVip_tXOxk0SRXp_54
|
||||||
+3
-3
@@ -27,12 +27,12 @@
|
|||||||
"proxy_check_interval_sec": 300,
|
"proxy_check_interval_sec": 300,
|
||||||
"proxy_source_disable_after": 3,
|
"proxy_source_disable_after": 3,
|
||||||
"enable_nsfw": true,
|
"enable_nsfw": true,
|
||||||
"register_count": 99999,
|
"register_count": 3,
|
||||||
"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/138.0.0.0 Safari/537.36",
|
||||||
"cpa_export_enabled": true,
|
"cpa_export_enabled": true,
|
||||||
"cpa_auth_dir": "./cpa_auths",
|
"cpa_auth_dir": "./cpa_auths",
|
||||||
"cpa_base_url": "https://cli-chat-proxy.grok.com/v1",
|
"cpa_base_url": "https://cli-chat-proxy.grok.com/v1",
|
||||||
"cpa_push_enabled": true,
|
"cpa_push_enabled": false,
|
||||||
"cpa_remote_base": "https://cpa.nopj.cn",
|
"cpa_remote_base": "https://cpa.nopj.cn",
|
||||||
"cpa_remote_secret": "DNznuRVoBhDT2SpSAyWw",
|
"cpa_remote_secret": "DNznuRVoBhDT2SpSAyWw",
|
||||||
"cpa_remote_verify_tls": true,
|
"cpa_remote_verify_tls": true,
|
||||||
@@ -59,4 +59,4 @@
|
|||||||
"gmail_imap_fallback": false,
|
"gmail_imap_fallback": false,
|
||||||
"hide_window": false,
|
"hide_window": false,
|
||||||
"block_media_fonts": false
|
"block_media_fonts": false
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"type": "xai",
|
||||||
|
"auth_kind": "oauth",
|
||||||
|
"access_token": "eyJ0eXAiOiJhdCtqd3QiLCJhbGciOiJFUzI1NiIsImtpZCI6Im9hdXRoMi1wcm9kdWN0aW9uLTIwMjYtMDItMTkifQ.eyJpc3MiOiJodHRwczovL2F1dGgueC5haSIsInN1YiI6Ijc3ZTI4MTVlLTE1MjQtNDM0MS1iYWE4LWM5NGVjZjc3MzAzYSIsImF1ZCI6ImIxYTAwNDkyLTA3M2EtNDdlYS04MTZmLTRjMzI5MjY0YTgyOCIsImV4cCI6MTc4NDEwOTU5MywiaWF0IjoxNzg0MDg3OTkzLCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIG9mZmxpbmVfYWNjZXNzIGdyb2stY2xpOmFjY2VzcyBhcGk6YWNjZXNzIGNvbnZlcnNhdGlvbnM6cmVhZCBjb252ZXJzYXRpb25zOndyaXRlIiwicHJpbmNpcGFsX3R5cGUiOiJVc2VyIiwicHJpbmNpcGFsX2lkIjoiNzdlMjgxNWUtMTUyNC00MzQxLWJhYTgtYzk0ZWNmNzczMDNhIiwiY2xpZW50X2lkIjoiYjFhMDA0OTItMDczYS00N2VhLTgxNmYtNGMzMjkyNjRhODI4IiwianRpIjoiZDQ5YWQyMzEtOGRkNy00Zjk1LWE3ZjAtYWQ2N2VjZTNhYWRmIiwidGVhbV9pZCI6Ijc5OWY1OWM1LTJhZGMtNDllYi1iMTQ3LTVjNTY1NzJjMzE5MCIsInJlZmVycmVyIjoiZ3Jvay1idWlsZCJ9.LHoRB8Ze9wPEIbP1OYllw5cmDvMVLbYh7D2dL2AgQ3YPV0V7zpuw7gzQXYAOxbP7UPeuIQQ97qGOfXgJEW--yA",
|
||||||
|
"refresh_token": "wXTgQRJDSMcyGmC8-krwGpHjkdsDzKHN2KnFwpvtdfnli_jBOqlvDnTSIrl2j90boNMVIO4Dg7UAdgGoTmE7ig",
|
||||||
|
"token_type": "Bearer",
|
||||||
|
"expires_in": 21600,
|
||||||
|
"expired": "2026-07-15T09:59:53Z",
|
||||||
|
"last_refresh": "2026-07-15T03:59:53Z",
|
||||||
|
"email": "helenramos281@mail.bblbb.com",
|
||||||
|
"sub": "77e2815e-1524-4341-baa8-c94ecf77303a",
|
||||||
|
"base_url": "https://cli-chat-proxy.grok.com/v1",
|
||||||
|
"token_endpoint": "https://auth.x.ai/oauth2/token",
|
||||||
|
"redirect_uri": "http://127.0.0.1:56121/callback",
|
||||||
|
"disabled": false,
|
||||||
|
"headers": {
|
||||||
|
"x-grok-client-version": "0.2.93",
|
||||||
|
"x-xai-token-auth": "xai-grok-cli",
|
||||||
|
"x-authenticateresponse": "authenticate-response",
|
||||||
|
"x-grok-client-identifier": "grok-pager",
|
||||||
|
"User-Agent": "grok-pager/0.2.93 grok-shell/0.2.93 (linux; x86_64)"
|
||||||
|
},
|
||||||
|
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6Im9hdXRoMi1wcm9kdWN0aW9uLTIwMjYtMDItMTkifQ.eyJpc3MiOiJodHRwczovL2F1dGgueC5haSIsInN1YiI6Ijc3ZTI4MTVlLTE1MjQtNDM0MS1iYWE4LWM5NGVjZjc3MzAzYSIsImF1ZCI6ImIxYTAwNDkyLTA3M2EtNDdlYS04MTZmLTRjMzI5MjY0YTgyOCIsImV4cCI6MTc4NDEwOTU5MywiaWF0IjoxNzg0MDg3OTkzLCJub25jZSI6IkU3dGRabjVEQmRNZmdNc2tQRF9NelEiLCJnaXZlbl9uYW1lIjoiS2FpIiwiZmFtaWx5X25hbWUiOiJIYW4iLCJlbWFpbCI6ImhlbGVucmFtb3MyODFAbWFpbC5iYmxiYi5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZX0.Ok3MSOzASage-BhrkdDfVvttZYFat-yBmbQbsth0ykj-jRD07iyjw5snRfX8__2A3gkZM_pLdkSUAfgEkFJTjw",
|
||||||
|
"sso": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiMWU1OTMzYWEtMTJiYi00YjU5LTg1ZDktOTRiZmFhNDliYzU2In0.gnekLoMUj2B5DscbjE5hyC9FoLqkYjjXP9X3usyyqDQ",
|
||||||
|
"referrer": "grok-build"
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"type": "xai",
|
||||||
|
"auth_kind": "oauth",
|
||||||
|
"access_token": "eyJ0eXAiOiJhdCtqd3QiLCJhbGciOiJFUzI1NiIsImtpZCI6Im9hdXRoMi1wcm9kdWN0aW9uLTIwMjYtMDItMTkifQ.eyJpc3MiOiJodHRwczovL2F1dGgueC5haSIsInN1YiI6ImJiYzI0ODVlLTcxM2UtNDU4Ny1iZTI3LTZkZTViZWNmZjhkNCIsImF1ZCI6ImIxYTAwNDkyLTA3M2EtNDdlYS04MTZmLTRjMzI5MjY0YTgyOCIsImV4cCI6MTc4NDIxMTcyNywiaWF0IjoxNzg0MTkwMTI3LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIG9mZmxpbmVfYWNjZXNzIGdyb2stY2xpOmFjY2VzcyBhcGk6YWNjZXNzIGNvbnZlcnNhdGlvbnM6cmVhZCBjb252ZXJzYXRpb25zOndyaXRlIiwicHJpbmNpcGFsX3R5cGUiOiJVc2VyIiwicHJpbmNpcGFsX2lkIjoiYmJjMjQ4NWUtNzEzZS00NTg3LWJlMjctNmRlNWJlY2ZmOGQ0IiwiY2xpZW50X2lkIjoiYjFhMDA0OTItMDczYS00N2VhLTgxNmYtNGMzMjkyNjRhODI4IiwianRpIjoiZTQzNjI0ZmMtMDJmNC00MjhmLWFhMmEtNGM5MTAxMDk2MDY3IiwidGVhbV9pZCI6IjkzZGRiMzg3LWMyMDktNDEwZi1iMDJhLTA5NDZhNWM4ODkwNSIsInJlZmVycmVyIjoiZ3Jvay1idWlsZCJ9.DM0FgR-cvN82OkOpza-vvdj6Y7F-DDqcIgALepE3XR_GFKNKlblf6oa6ZGFLg6EkNELsSGNb5bmka_CDx06Mcg",
|
||||||
|
"refresh_token": "YCyRNl-D1-OAzfoVs9sAKPEBBLm5kHJvdI9SEx18W8tZmXKHGcQ9yp_N2q4hNqq_dQH4Emy3EPbV3ikEBBuOAA",
|
||||||
|
"token_type": "Bearer",
|
||||||
|
"expires_in": 21600,
|
||||||
|
"expired": "2026-07-16T14:22:07Z",
|
||||||
|
"last_refresh": "2026-07-16T08:22:07Z",
|
||||||
|
"email": "zoieroberts1869@mail.bblbb.com",
|
||||||
|
"sub": "bbc2485e-713e-4587-be27-6de5becff8d4",
|
||||||
|
"base_url": "https://cli-chat-proxy.grok.com/v1",
|
||||||
|
"token_endpoint": "https://auth.x.ai/oauth2/token",
|
||||||
|
"redirect_uri": "http://127.0.0.1:56121/callback",
|
||||||
|
"disabled": false,
|
||||||
|
"headers": {
|
||||||
|
"x-grok-client-version": "0.2.93",
|
||||||
|
"x-xai-token-auth": "xai-grok-cli",
|
||||||
|
"x-authenticateresponse": "authenticate-response",
|
||||||
|
"x-grok-client-identifier": "grok-pager",
|
||||||
|
"User-Agent": "grok-pager/0.2.93 grok-shell/0.2.93 (linux; x86_64)"
|
||||||
|
},
|
||||||
|
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6Im9hdXRoMi1wcm9kdWN0aW9uLTIwMjYtMDItMTkifQ.eyJpc3MiOiJodHRwczovL2F1dGgueC5haSIsInN1YiI6ImJiYzI0ODVlLTcxM2UtNDU4Ny1iZTI3LTZkZTViZWNmZjhkNCIsImF1ZCI6ImIxYTAwNDkyLTA3M2EtNDdlYS04MTZmLTRjMzI5MjY0YTgyOCIsImV4cCI6MTc4NDIxMTcyNywiaWF0IjoxNzg0MTkwMTI3LCJub25jZSI6Imoxb0JzWUkzR19WUXRseUxWVTBteVEiLCJnaXZlbl9uYW1lIjoiQ2FsZWIiLCJmYW1pbHlfbmFtZSI6IkxpdSIsImVtYWlsIjoiem9pZXJvYmVydHMxODY5QG1haWwuYmJsYmIuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWV9.y38jxu1nWyO0Yzr4lcxVAqVbVc37880Jz0UGlIoQ8P5HWdD1b-hFleiGJmGbqayQ9AhpoKJMcoWrWIYFGMLc2g",
|
||||||
|
"sso": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiNjRkOWNjNTMtM2Q0YS00MzNlLThhMTctMTIxYmUyODNmZTU4In0.ra0SYJyU146-eMqSQKcG9J63YDVip_tXOxk0SRXp_54",
|
||||||
|
"referrer": "grok-build"
|
||||||
|
}
|
||||||
+132
-19
@@ -17,6 +17,7 @@ import random
|
|||||||
import re
|
import re
|
||||||
import string
|
import string
|
||||||
import json
|
import json
|
||||||
|
import base64
|
||||||
|
|
||||||
from DrissionPage import Chromium, ChromiumOptions
|
from DrissionPage import Chromium, ChromiumOptions
|
||||||
from DrissionPage.errors import PageDisconnectedError
|
from DrissionPage.errors import PageDisconnectedError
|
||||||
@@ -586,13 +587,17 @@ def create_browser_options(proxy=None):
|
|||||||
options.set_argument("--disable-background-timer-throttling")
|
options.set_argument("--disable-background-timer-throttling")
|
||||||
options.set_argument("--disable-backgrounding-occluded-windows")
|
options.set_argument("--disable-backgrounding-occluded-windows")
|
||||||
options.set_argument("--disable-renderer-backgrounding")
|
options.set_argument("--disable-renderer-backgrounding")
|
||||||
|
# 反 bot:关闭 Blink AutomationControlled(否则 navigator.webdriver 在 JS 前就暴露)
|
||||||
|
options.set_argument("--disable-blink-features=AutomationControlled")
|
||||||
|
|
||||||
# 固定窗口尺寸,避免 Turnstile iframe 在 0 尺寸窗口里不渲染
|
# 固定窗口尺寸,避免 Turnstile iframe 在 0 尺寸窗口里不渲染
|
||||||
|
# 轻微随机化位置即可,尺寸过大/过小都可能影响验证渲染
|
||||||
options.set_argument("--window-size=1280,900")
|
options.set_argument("--window-size=1280,900")
|
||||||
# 隐藏窗口(可选):仅移出屏幕。注意:部分环境下会让 Turnstile 永远 token=0
|
# 隐藏窗口(可选):仅移出屏幕。注意:部分环境下会让 Turnstile 永远 token=0
|
||||||
if config.get("hide_window", False):
|
if config.get("hide_window", False):
|
||||||
options.set_argument("--window-position=-32000,-32000")
|
options.set_argument("--window-position=-32000,-32000")
|
||||||
else:
|
else:
|
||||||
options.set_argument("--window-position=40,40")
|
options.set_argument(f"--window-position={random.randint(40, 120)},{random.randint(40, 120)}")
|
||||||
|
|
||||||
# 代理:线程绑定(代理池)> 入参 > config.proxy
|
# 代理:线程绑定(代理池)> 入参 > config.proxy
|
||||||
use_proxy = ""
|
use_proxy = ""
|
||||||
@@ -1125,13 +1130,25 @@ _LAST_NAMES = (
|
|||||||
)
|
)
|
||||||
_NAME_SEPARATORS = ("", ".", "_")
|
_NAME_SEPARATORS = ("", ".", "_")
|
||||||
|
|
||||||
|
# z 开头的常见英文名字,用于生成 local-part 全部以 z 起首的邮箱
|
||||||
|
_Z_FIRST_NAMES = (
|
||||||
|
"zachary", "zack", "zackary", "zackery", "zane", "zayn", "zayne", "zavier",
|
||||||
|
"zaid", "zaiden", "zayden", "zaire", "zeke", "zephyr", "zeus", "zion",
|
||||||
|
"ziggy", "zed", "zeb", "zebulon", "zelig", "zeno", "zenon", "zaki",
|
||||||
|
"zoe", "zoey", "zoie", "zoya", "zora", "zara", "zaria", "zariah",
|
||||||
|
"zelda", "zena", "zenia", "zinnia", "ziva", "zola", "zainab", "zaynab",
|
||||||
|
"zahra", "zaida", "zanna", "zara", "zarah", "zaria", "zia", "zula",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def generate_username(length=10):
|
def generate_username(length=10):
|
||||||
"""生成更像正常英文用户的邮箱名:姓名/词根 + 数字结尾。
|
"""生成更像正常英文用户的邮箱名:姓名/词根 + 数字结尾。
|
||||||
|
|
||||||
length 仅作兼容参数(旧调用传 10),实际长度由名字与数字后缀决定,约 8–18。
|
length 仅作兼容参数(旧调用传 10),实际长度由名字与数字后缀决定,约 8–18。
|
||||||
|
强制 local-part 以 'z' 起首(first 从 z 开头姓名池抽取;last+first[0] 风格改为
|
||||||
|
z + last,仍保证首字符为 z)。
|
||||||
"""
|
"""
|
||||||
first = secrets.choice(_FIRST_NAMES)
|
first = secrets.choice(_Z_FIRST_NAMES)
|
||||||
last = secrets.choice(_LAST_NAMES)
|
last = secrets.choice(_LAST_NAMES)
|
||||||
sep = secrets.choice(_NAME_SEPARATORS)
|
sep = secrets.choice(_NAME_SEPARATORS)
|
||||||
# 数字后缀:2–4 位更像真实用户(生日年份、学号尾号等)
|
# 数字后缀:2–4 位更像真实用户(生日年份、学号尾号等)
|
||||||
@@ -1163,8 +1180,8 @@ def generate_username(length=10):
|
|||||||
# first 首字母 + last + digits e.g. jwilson87
|
# first 首字母 + last + digits e.g. jwilson87
|
||||||
base = f"{first[0]}{last}"
|
base = f"{first[0]}{last}"
|
||||||
else:
|
else:
|
||||||
# last + first 首字母 + digits e.g. wilsonj87
|
# z + last + digits e.g. zwilson87(原 last+first[0] 风格改造以保证 z 起首)
|
||||||
base = f"{last}{first[0]}"
|
base = f"z{last}"
|
||||||
|
|
||||||
local = f"{base}{digits}".lower()
|
local = f"{base}{digits}".lower()
|
||||||
# 邮箱 local 只保留 [a-z0-9._],去掉连续分隔符
|
# 邮箱 local 只保留 [a-z0-9._],去掉连续分隔符
|
||||||
@@ -2500,7 +2517,7 @@ def fill_email_and_submit(session, timeout=45, log_callback=None, cancel_callbac
|
|||||||
while time.time() < deadline:
|
while time.time() < deadline:
|
||||||
raise_if_cancelled(cancel_callback)
|
raise_if_cancelled(cancel_callback)
|
||||||
filled = page.run_js(
|
filled = page.run_js(
|
||||||
"""
|
r"""
|
||||||
const email = arguments[0];
|
const email = arguments[0];
|
||||||
function isVisible(node) {
|
function isVisible(node) {
|
||||||
if (!node) return false;
|
if (!node) return false;
|
||||||
@@ -3836,6 +3853,37 @@ def register_one(session, shared, worker_id, slot_no):
|
|||||||
return email
|
return email
|
||||||
|
|
||||||
|
|
||||||
|
def _check_bot_flag(email, cfg=None):
|
||||||
|
"""检查刚注册账号的 access_token 是否带 bot_flag_source。
|
||||||
|
|
||||||
|
返回 (is_bot: bool, detail: str)。
|
||||||
|
"""
|
||||||
|
cfg = cfg or config
|
||||||
|
try:
|
||||||
|
import cpa
|
||||||
|
out_dir = str(cfg.get("cpa_auth_dir", "./cpa_auths"))
|
||||||
|
fname = cpa.credential_file_name(email)
|
||||||
|
path = os.path.join(out_dir, fname)
|
||||||
|
if not os.path.exists(path):
|
||||||
|
return False, f"auth file not found: {path}"
|
||||||
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
at = str(data.get("access_token") or "")
|
||||||
|
if not at:
|
||||||
|
return False, "no access_token"
|
||||||
|
parts = at.split(".")
|
||||||
|
if len(parts) < 2:
|
||||||
|
return False, "invalid JWT"
|
||||||
|
seg = parts[1] + "=" * (-len(parts[1]) % 4)
|
||||||
|
payload = json.loads(base64.urlsafe_b64decode(seg))
|
||||||
|
bot = payload.get("bot_flag_source")
|
||||||
|
if bot == 1:
|
||||||
|
return True, "bot_flag_source=1 → 账号被标记为 bot"
|
||||||
|
return False, f"bot_flag_source={bot} (OK)"
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"check error: {e}"
|
||||||
|
|
||||||
|
|
||||||
def register_worker(worker_id, shared):
|
def register_worker(worker_id, shared):
|
||||||
"""单个并发 worker:自建独立浏览器,循环领取名额并注册。"""
|
"""单个并发 worker:自建独立浏览器,循环领取名额并注册。"""
|
||||||
|
|
||||||
@@ -3878,6 +3926,18 @@ def register_worker(worker_id, shared):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
log(f"[+] 注册成功: {email}(累计成功 {total})")
|
log(f"[+] 注册成功: {email}(累计成功 {total})")
|
||||||
|
|
||||||
|
# ===== 注册后立即检查 bot 标记 =====
|
||||||
|
if config.get("stop_on_bot_flag", True):
|
||||||
|
is_bot, detail = _check_bot_flag(email)
|
||||||
|
if is_bot:
|
||||||
|
log(f"[!] ⛔ 检测到 bot 标记: {detail}")
|
||||||
|
log("[!] 立即停止所有注册(避免继续浪费账号)")
|
||||||
|
shared.stop()
|
||||||
|
raise RegistrationCancelled("检测到 bot_flag,停止注册")
|
||||||
|
else:
|
||||||
|
log(f"[Debug] bot 检查通过: {detail}")
|
||||||
|
|
||||||
break
|
break
|
||||||
except RegistrationCancelled:
|
except RegistrationCancelled:
|
||||||
raise
|
raise
|
||||||
@@ -3928,6 +3988,13 @@ def register_worker(worker_id, shared):
|
|||||||
break
|
break
|
||||||
if shared.should_stop():
|
if shared.should_stop():
|
||||||
break
|
break
|
||||||
|
# 注册间隔:控制注册速率,降低被标记为 bot 的风险
|
||||||
|
interval = float(config.get("register_interval_sec", 0) or 0)
|
||||||
|
if interval > 0:
|
||||||
|
log(f"[*] 等待 {interval:.0f}s 后开始下一个账号(register_interval_sec)")
|
||||||
|
sleep_with_cancel(interval, shared.should_stop)
|
||||||
|
if shared.should_stop():
|
||||||
|
break
|
||||||
# 下一账号:默认轮换出口并重启浏览器
|
# 下一账号:默认轮换出口并重启浏览器
|
||||||
session.restart()
|
session.restart()
|
||||||
except RegistrationCancelled:
|
except RegistrationCancelled:
|
||||||
@@ -3984,11 +4051,55 @@ def run_registration_concurrent(count, concurrency):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
import argparse
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Grok 注册机 - 批量注册 xAI/Grok 账号",
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
epilog="""
|
||||||
|
示例:
|
||||||
|
python grok_register_ttk.py # 交互模式
|
||||||
|
python grok_register_ttk.py --count 10 --concurrency 2 # 注册10个,2并发
|
||||||
|
python grok_register_ttk.py --count 50 --interval 120 # 每2分钟注册1个
|
||||||
|
python grok_register_ttk.py --no-stop-on-bot # 不自动停(调试用)
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
parser.add_argument("--count", type=int, default=None,
|
||||||
|
help="注册数量(默认读取 config.json 或 1)")
|
||||||
|
parser.add_argument("--concurrency", type=int, default=None,
|
||||||
|
help="并发浏览器数(默认交互输入)")
|
||||||
|
parser.add_argument("--interval", type=int, default=None, dest="register_interval_sec",
|
||||||
|
help="注册间隔秒数(如 120=每2分钟1个,0=无间隔)")
|
||||||
|
parser.add_argument("--stop-on-bot", action="store_true", default=None, dest="stop_on_bot_flag",
|
||||||
|
help="检测到 bot_flag 立即停止(默认开启)")
|
||||||
|
parser.add_argument("--no-stop-on-bot", action="store_false", default=None, dest="stop_on_bot_flag",
|
||||||
|
help="不自动停止(调试用)")
|
||||||
|
parser.add_argument("--hide-window", action="store_true", default=None, dest="hide_window",
|
||||||
|
help="隐藏浏览器窗口(移到屏幕外,非 headless)")
|
||||||
|
parser.add_argument("--show-window", action="store_false", default=None, dest="hide_window",
|
||||||
|
help="显示浏览器窗口(默认)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
load_config()
|
load_config()
|
||||||
count = int(config.get("register_count", 1) or 1)
|
count = args.count if args.count is not None else int(config.get("register_count", 1) or 1)
|
||||||
|
|
||||||
|
# 命令行参数覆盖到 config(后续代码统一读 config)
|
||||||
|
if args.register_interval_sec is not None:
|
||||||
|
config["register_interval_sec"] = args.register_interval_sec
|
||||||
|
if args.stop_on_bot_flag is not None:
|
||||||
|
config["stop_on_bot_flag"] = args.stop_on_bot_flag
|
||||||
|
if args.hide_window is not None:
|
||||||
|
config["hide_window"] = args.hide_window
|
||||||
|
# 默认值
|
||||||
|
config.setdefault("register_interval_sec", 0)
|
||||||
|
config.setdefault("stop_on_bot_flag", True)
|
||||||
|
|
||||||
cli_log("[*] 已加载配置")
|
cli_log("[*] 已加载配置")
|
||||||
|
interval = config.get("register_interval_sec", 0)
|
||||||
cli_log(
|
cli_log(
|
||||||
f"[*] 当前邮箱服务商: {config.get('email_provider', 'duckmail')} | 目标注册数: {count}"
|
f"[*] 邮箱: {config.get('email_provider', 'duckmail')} | "
|
||||||
|
f"目标: {count} | 间隔: {'{}s'.format(interval) if interval else '无'} | "
|
||||||
|
f"bot检测: {'开' if config.get('stop_on_bot_flag') else '关'} | "
|
||||||
|
f"窗口: {'隐藏' if config.get('hide_window') else '显示'}"
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
import proxy_pool
|
import proxy_pool
|
||||||
@@ -4005,18 +4116,20 @@ def main():
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
cli_log("[*] CPA 导出: 关闭(仅写 accounts_*.txt)")
|
cli_log("[*] CPA 导出: 关闭(仅写 accounts_*.txt)")
|
||||||
try:
|
|
||||||
raw = input("请输入并发数量(同时开几个浏览器,直接回车=1): ").strip()
|
concurrency = args.concurrency
|
||||||
except (KeyboardInterrupt, EOFError):
|
if concurrency is None:
|
||||||
cli_log("[!] 已取消")
|
try:
|
||||||
return
|
raw = input("请输入并发数量(同时开几个浏览器,直接回车=1): ").strip()
|
||||||
try:
|
except (KeyboardInterrupt, EOFError):
|
||||||
concurrency = int(raw) if raw else 1
|
cli_log("[!] 已取消")
|
||||||
except ValueError:
|
return
|
||||||
cli_log("[!] 并发数量无效,使用 1")
|
try:
|
||||||
concurrency = 1
|
concurrency = int(raw) if raw else 1
|
||||||
if concurrency < 1:
|
except ValueError:
|
||||||
concurrency = 1
|
cli_log("[!] 并发数量无效,使用 1")
|
||||||
|
concurrency = 1
|
||||||
|
concurrency = max(1, min(concurrency, count))
|
||||||
run_registration_concurrent(count, concurrency)
|
run_registration_concurrent(count, concurrency)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -979,3 +979,7 @@ t0rpdza1s0@mail.bblbb.com bblbb:t0rpdza1s0
|
|||||||
w5ayintm8r@mail.bblbb.com bblbb:w5ayintm8r
|
w5ayintm8r@mail.bblbb.com bblbb:w5ayintm8r
|
||||||
2in9y6cab4@mail.bblbb.com bblbb:2in9y6cab4
|
2in9y6cab4@mail.bblbb.com bblbb:2in9y6cab4
|
||||||
5fbu5nq3wj@mail.bblbb.com bblbb:5fbu5nq3wj
|
5fbu5nq3wj@mail.bblbb.com bblbb:5fbu5nq3wj
|
||||||
|
cynthia464@mail.bblbb.com bblbb:cynthia464
|
||||||
|
meganmartinez956@mail.bblbb.com bblbb:meganmartinez956
|
||||||
|
helenramos281@mail.bblbb.com bblbb:helenramos281
|
||||||
|
zoieroberts1869@mail.bblbb.com bblbb:zoieroberts1869
|
||||||
Reference in new issue
Block a user