mirror of
https://github.com/ddCat-main/cursor-auto-register.git
synced 2025-12-24 13:38:01 +08:00
add:增加配置”是否使用动态ua池“
This commit is contained in:
12
.env.example
12
.env.example
@@ -4,12 +4,17 @@ BROWSER_HEADLESS=True
|
||||
BROWSER_USER_AGENT="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36"
|
||||
# 浏览器代理
|
||||
BROWSER_PROXY=
|
||||
# 是否使用动态ua池
|
||||
DYNAMIC_USERAGENT=False
|
||||
# Windows 浏览器路径
|
||||
#BROWSER_PATH="C:\Users\Administrator\AppData\Local\Google\Chrome\Bin\chrome.exe"
|
||||
|
||||
|
||||
# 多个域名使用逗号分隔
|
||||
EMAIL_DOMAINS=xxx.xxx
|
||||
EMAIL_DOMAINS=xxx.xx
|
||||
|
||||
# 临时邮箱用户名
|
||||
EMAIL_USERNAME=xxxx
|
||||
EMAIL_USERNAME=xxx
|
||||
# 临时邮箱PIN码(如果需要)
|
||||
EMAIL_PIN=
|
||||
|
||||
@@ -33,9 +38,6 @@ API_WORKERS=1
|
||||
# 是否启用UI
|
||||
ENABLE_UI=True
|
||||
|
||||
# Windows 浏览器路径
|
||||
#BROWSER_PATH="C:\Users\Administrator\AppData\Local\Google\Chrome\Bin\chrome.exe"
|
||||
|
||||
# Cursor main.js 主文件路径
|
||||
# windows用户部分安装时是自定义目录安装的,需要修改该配置
|
||||
#CURSOR_PATH="D:\devtools\cursor"
|
||||
5
api.py
5
api.py
@@ -975,6 +975,7 @@ async def use_account_token(id: int):
|
||||
# 添加配置相关模型
|
||||
class ConfigModel(BaseModel):
|
||||
BROWSER_HEADLESS: bool
|
||||
DYNAMIC_USERAGENT: Optional[bool] = False
|
||||
BROWSER_USER_AGENT: str
|
||||
MAX_ACCOUNTS: int
|
||||
EMAIL_DOMAINS: str
|
||||
@@ -999,7 +1000,8 @@ async def get_config():
|
||||
"EMAIL_USERNAME": os.getenv("EMAIL_USERNAME", ""),
|
||||
"EMAIL_PIN": os.getenv("EMAIL_PIN", ""),
|
||||
"BROWSER_PATH": os.getenv("BROWSER_PATH", ""),
|
||||
"CURSOR_PATH": os.getenv("CURSOR_PATH", "")
|
||||
"CURSOR_PATH": os.getenv("CURSOR_PATH", ""),
|
||||
"DYNAMIC_USERAGENT": os.getenv("DYNAMIC_USERAGENT", "False").lower() == "true"
|
||||
}
|
||||
|
||||
return {"success": True, "data": config}
|
||||
@@ -1025,6 +1027,7 @@ async def update_config(config: ConfigModel):
|
||||
# 构建配置字典
|
||||
config_dict = {
|
||||
"BROWSER_HEADLESS": str(config.BROWSER_HEADLESS),
|
||||
"DYNAMIC_USERAGENT": str(config.DYNAMIC_USERAGENT),
|
||||
"BROWSER_USER_AGENT": config.BROWSER_USER_AGENT,
|
||||
"MAX_ACCOUNTS": str(config.MAX_ACCOUNTS),
|
||||
"EMAIL_DOMAINS": config.EMAIL_DOMAINS,
|
||||
|
||||
214
browser_utils.py
214
browser_utils.py
@@ -1,104 +1,143 @@
|
||||
from DrissionPage import ChromiumOptions, Chromium
|
||||
import sys
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from logger import info, warning
|
||||
from logger import info, warning, error
|
||||
from config import (
|
||||
BROWSER_USER_AGENT,
|
||||
BROWSER_PATH,
|
||||
BROWSER_HEADLESS,
|
||||
BROWSER_PROXY,
|
||||
DYNAMIC_USERAGENT
|
||||
)
|
||||
import random
|
||||
import time
|
||||
|
||||
load_dotenv()
|
||||
# 用户代理列表 - 按平台分类
|
||||
USER_AGENTS = {
|
||||
'windows': [
|
||||
# Chrome Windows
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36',
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
|
||||
# Edge Windows
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.76',
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.47',
|
||||
# Firefox Windows
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/118.0',
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/119.0',
|
||||
],
|
||||
'macos': [
|
||||
# Chrome macOS
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36',
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
|
||||
# Safari macOS
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15',
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15',
|
||||
# Firefox macOS
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/118.0',
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/119.0',
|
||||
],
|
||||
'linux': [
|
||||
# Chrome Linux
|
||||
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36',
|
||||
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
|
||||
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
|
||||
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
|
||||
# Firefox Linux
|
||||
'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0',
|
||||
'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/119.0',
|
||||
]
|
||||
}
|
||||
|
||||
def get_random_user_agent():
|
||||
"""根据当前平台获取随机用户代理"""
|
||||
platform = 'windows'
|
||||
if sys.platform == 'darwin':
|
||||
platform = 'macos'
|
||||
elif sys.platform.startswith('linux'):
|
||||
platform = 'linux'
|
||||
|
||||
# 获取当前平台的UA列表
|
||||
ua_list = USER_AGENTS.get(platform, USER_AGENTS['windows'])
|
||||
return random.choice(ua_list)
|
||||
|
||||
class BrowserManager:
|
||||
def __init__(self):
|
||||
self.browser = None
|
||||
|
||||
def init_browser(self):
|
||||
"""初始化浏览器"""
|
||||
co = self._get_browser_options()
|
||||
self.browser = Chromium(co)
|
||||
return self.browser
|
||||
|
||||
def _get_browser_options(self):
|
||||
"""获取浏览器配置"""
|
||||
co = ChromiumOptions()
|
||||
|
||||
# 设置浏览器路径 - 添加这段代码
|
||||
browser_path = os.getenv("BROWSER_PATH")
|
||||
if not browser_path and sys.platform == "win32":
|
||||
# 仅在Windows系统下尝试常见的浏览器路径
|
||||
possible_paths = [
|
||||
r"C:\Program Files\Google\Chrome\Application\chrome.exe",
|
||||
r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe",
|
||||
r"C:\Program Files\Microsoft\Edge\Application\msedge.exe",
|
||||
r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"
|
||||
]
|
||||
for path in possible_paths:
|
||||
if os.path.exists(path):
|
||||
browser_path = path
|
||||
info(f"自动找到浏览器路径: {browser_path}")
|
||||
break
|
||||
|
||||
if not browser_path:
|
||||
info("未找到浏览器路径,请在.env文件中设置BROWSER_PATH环境变量")
|
||||
|
||||
if browser_path:
|
||||
co.set_browser_path(browser_path)
|
||||
|
||||
try:
|
||||
extension_path = self._get_extension_path()
|
||||
co.add_extension(extension_path)
|
||||
except FileNotFoundError as e:
|
||||
info(f"警告: {e}")
|
||||
info("正在初始化浏览器...")
|
||||
co = ChromiumOptions()
|
||||
|
||||
co.set_user_agent(
|
||||
os.getenv(
|
||||
"BROWSER_USER_AGENT",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
|
||||
if BROWSER_PROXY:
|
||||
co.set_proxy(BROWSER_PROXY)
|
||||
|
||||
# 如果配置了特定的浏览器路径,则使用
|
||||
if BROWSER_PATH and os.path.exists(BROWSER_PATH):
|
||||
co.set_browser_path(BROWSER_PATH)
|
||||
info(f"使用自定义浏览器路径: {BROWSER_PATH}")
|
||||
|
||||
try:
|
||||
extension_path = self._get_extension_path()
|
||||
co.add_extension(extension_path)
|
||||
except FileNotFoundError as e:
|
||||
info(f"警告: {e}")
|
||||
|
||||
# 设置User-Agent
|
||||
if DYNAMIC_USERAGENT:
|
||||
# 随机选择一个User-Agent
|
||||
user_agent = get_random_user_agent()
|
||||
info(f"使用动态User-Agent: {user_agent}")
|
||||
co.set_user_agent(user_agent)
|
||||
else:
|
||||
info(f"使用固定User-Agent: {BROWSER_USER_AGENT}")
|
||||
co.set_user_agent(BROWSER_USER_AGENT)
|
||||
|
||||
co.set_pref("credentials_enable_service", False)
|
||||
co.set_argument("--hide-crash-restore-bubble")
|
||||
# 禁用自动化特征(关键参数)
|
||||
co.set_argument("--disable-blink-features=AutomationControlled")
|
||||
co.set_argument("--disable-features=AutomationControlled")
|
||||
co.set_argument("--disable-automation-extension")
|
||||
|
||||
# 随机化指纹参数
|
||||
co.set_pref("webgl.vendor", "NVIDIA Corporation")
|
||||
co.set_pref(
|
||||
"webgl.renderer",
|
||||
"ANGLE (NVIDIA, NVIDIA GeForce RTX 3070 Direct3D11 vs_5_0 ps_5_0)",
|
||||
)
|
||||
)
|
||||
co.set_pref("credentials_enable_service", False)
|
||||
co.set_argument("--hide-crash-restore-bubble")
|
||||
proxy = os.getenv("BROWSER_PROXY")
|
||||
if proxy:
|
||||
co.set_proxy(proxy)
|
||||
co.set_pref("navigator.plugins.length", 5)
|
||||
co.set_pref("navigator.hardwareConcurrency", 8)
|
||||
|
||||
# 禁用自动化特征(关键参数)
|
||||
co.set_argument("--disable-blink-features=AutomationControlled")
|
||||
co.set_argument("--disable-features=AutomationControlled")
|
||||
co.set_argument("--disable-automation-extension")
|
||||
# 覆盖自动化特征(关键)
|
||||
co.set_pref("dom.webdriver.enabled", False)
|
||||
co.set_pref("useAutomationExtension", False)
|
||||
|
||||
# 随机化指纹参数
|
||||
co.set_pref("webgl.vendor", "NVIDIA Corporation")
|
||||
co.set_pref(
|
||||
"webgl.renderer",
|
||||
"ANGLE (NVIDIA, NVIDIA GeForce RTX 3070 Direct3D11 vs_5_0 ps_5_0)",
|
||||
)
|
||||
co.set_pref("navigator.plugins.length", 5)
|
||||
co.set_pref("navigator.hardwareConcurrency", 8)
|
||||
# 设置时区参数
|
||||
co.set_argument("--timezone=Asia/Shanghai")
|
||||
co.set_pref("timezone.override", "Asia/Shanghai")
|
||||
|
||||
# 覆盖自动化特征(关键)
|
||||
co.set_pref("dom.webdriver.enabled", False)
|
||||
co.set_pref("useAutomationExtension", False)
|
||||
# 设置更真实的屏幕参数
|
||||
co.set_pref("screen.width", 1920)
|
||||
co.set_pref("screen.height", 1080)
|
||||
co.set_pref("screen.pixelDepth", 24)
|
||||
co.auto_port()
|
||||
co.headless(BROWSER_HEADLESS) # 生产环境使用无头模式
|
||||
|
||||
# 设置时区参数
|
||||
co.set_argument("--timezone=Asia/Shanghai")
|
||||
co.set_pref("timezone.override", "Asia/Shanghai")
|
||||
|
||||
# 设置更真实的屏幕参数
|
||||
co.set_pref("screen.width", 1920)
|
||||
co.set_pref("screen.height", 1080)
|
||||
co.set_pref("screen.pixelDepth", 24)
|
||||
co.auto_port()
|
||||
co.headless(
|
||||
os.getenv("BROWSER_HEADLESS", "True").lower() == "true"
|
||||
) # 生产环境使用无头模式
|
||||
|
||||
# Mac 系统特殊处理
|
||||
if sys.platform == "darwin" or sys.platform == "linux":
|
||||
co.set_argument("--no-sandbox")
|
||||
co.set_argument("--disable-gpu")
|
||||
|
||||
return co
|
||||
# Mac 系统特殊处理
|
||||
if sys.platform == "darwin" or sys.platform == "linux":
|
||||
co.set_argument("--no-sandbox")
|
||||
co.set_argument("--disable-gpu")
|
||||
|
||||
self.browser = Chromium(co)
|
||||
info("浏览器初始化成功")
|
||||
except Exception as e:
|
||||
error(f"浏览器初始化失败: {str(e)}")
|
||||
return self.browser
|
||||
def _get_extension_path(self):
|
||||
"""获取插件路径"""
|
||||
root_dir = os.getcwd()
|
||||
@@ -113,9 +152,10 @@ class BrowserManager:
|
||||
return extension_path
|
||||
|
||||
def quit(self):
|
||||
"""关闭浏览器"""
|
||||
if self.browser:
|
||||
try:
|
||||
info("正在关闭浏览器...")
|
||||
try:
|
||||
if self.browser:
|
||||
self.browser.quit()
|
||||
except:
|
||||
pass
|
||||
info("浏览器已关闭")
|
||||
except Exception as e:
|
||||
error(f"关闭浏览器出错: {str(e)}")
|
||||
@@ -37,9 +37,15 @@ REGISTRATION_RETRY_INTERVAL = int(os.getenv("REGISTRATION_RETRY_INTERVAL", 5))
|
||||
# 是否以无头模式运行浏览器(不显示界面)
|
||||
BROWSER_HEADLESS = os.getenv("BROWSER_HEADLESS", "true").lower() == "true"
|
||||
# 浏览器可执行文件路径(为空则使用默认路径)
|
||||
BROWSER_EXECUTABLE_PATH = os.getenv("BROWSER_EXECUTABLE_PATH", None)
|
||||
BROWSER_PATH = os.getenv("BROWSER_PATH", None)
|
||||
# 浏览器下载文件保存路径
|
||||
BROWSER_DOWNLOAD_PATH = os.getenv("BROWSER_DOWNLOAD_PATH", None)
|
||||
# 是否使用动态ua池
|
||||
DYNAMIC_USERAGENT = os.getenv("DYNAMIC_USERAGENT", "false").lower() == "true"
|
||||
# 浏览器代理
|
||||
BROWSER_PROXY = os.getenv("BROWSER_PROXY", None)
|
||||
# 浏览器User-Agent
|
||||
BROWSER_USER_AGENT = os.getenv("BROWSER_USER_AGENT", None)
|
||||
|
||||
# ===== Cursor URL配置 =====
|
||||
# Cursor登录页面URL
|
||||
|
||||
36
index.html
36
index.html
@@ -629,6 +629,14 @@
|
||||
<small class="text-muted">用于注册的邮箱域名,多个域名用逗号分隔</small>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="dynamic-useragent" class="form-label">动态User-Agent</label>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="dynamic-useragent" disabled>
|
||||
<label class="form-check-label" for="dynamic-useragent">启用动态User-Agent</label>
|
||||
</div>
|
||||
<small class="text-muted">启用后将从预设的UA列表中随机选择,无需手动配置User-Agent</small>
|
||||
</div>
|
||||
<div class="mb-3" id="useragent-input-container">
|
||||
<label for="browser-useragent" class="form-label">浏览器User-Agent</label>
|
||||
<input type="text" id="browser-useragent" class="form-control" disabled>
|
||||
<small class="text-muted">浏览器模拟的用户代理字符串</small>
|
||||
@@ -1828,6 +1836,11 @@
|
||||
if (data.success) {
|
||||
const config = data.data;
|
||||
$("#browser-headless").val(config.BROWSER_HEADLESS.toString());
|
||||
$("#dynamic-useragent").prop('checked', config.DYNAMIC_USERAGENT || false);
|
||||
|
||||
// 触发动态UA的change事件
|
||||
$("#dynamic-useragent").trigger('change');
|
||||
|
||||
$("#browser-useragent").val(config.BROWSER_USER_AGENT);
|
||||
$("#max-accounts").val(config.MAX_ACCOUNTS);
|
||||
$("#email-domains").val(config.EMAIL_DOMAINS);
|
||||
@@ -1849,9 +1862,12 @@
|
||||
// 保存配置函数
|
||||
function saveConfig() {
|
||||
showLoading();
|
||||
const isDynamicUA = $("#dynamic-useragent").prop('checked');
|
||||
|
||||
const config = {
|
||||
BROWSER_HEADLESS: $("#browser-headless").val() === 'true',
|
||||
BROWSER_USER_AGENT: $("#browser-useragent").val(),
|
||||
DYNAMIC_USERAGENT: isDynamicUA,
|
||||
BROWSER_USER_AGENT: isDynamicUA ? "" : $("#browser-useragent").val(),
|
||||
MAX_ACCOUNTS: parseInt($("#max-accounts").val()),
|
||||
EMAIL_DOMAINS: $("#email-domains").val(),
|
||||
EMAIL_USERNAME: $("#email-username").val(),
|
||||
@@ -1889,6 +1905,10 @@
|
||||
const inputs = $('#config-form select, #config-form input');
|
||||
if (enable) {
|
||||
inputs.prop('disabled', false);
|
||||
// 如果动态UA已启用,保持UA输入框禁用
|
||||
if ($("#dynamic-useragent").prop('checked')) {
|
||||
$("#browser-useragent").prop('disabled', true);
|
||||
}
|
||||
$('#save-config-btn, #cancel-config-btn').show();
|
||||
$('#edit-config-btn').hide();
|
||||
} else {
|
||||
@@ -1897,6 +1917,20 @@
|
||||
$('#edit-config-btn').show();
|
||||
}
|
||||
}
|
||||
|
||||
// 动态User-Agent切换逻辑
|
||||
$("#dynamic-useragent").change(function() {
|
||||
const isDynamicUA = $(this).prop('checked');
|
||||
if (isDynamicUA) {
|
||||
$("#browser-useragent").prop('disabled', true);
|
||||
$("#useragent-input-container").addClass('text-muted');
|
||||
} else {
|
||||
// 只有在编辑模式下才启用输入框
|
||||
const isEditMode = !$("#edit-config-btn").is(":visible");
|
||||
$("#browser-useragent").prop('disabled', !isEditMode);
|
||||
$("#useragent-input-container").removeClass('text-muted');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- 添加删除确认对话框 -->
|
||||
|
||||
Reference in New Issue
Block a user