mirror of
https://github.com/yeongpin/cursor-free-vip.git
synced 2025-08-02 20:47:35 +08:00
Merge pull request #339 from Nigel1992/fix/human-verification-retry
fix: add retry logic for human verification failures
This commit is contained in:
commit
b5d50ac15a
@ -172,7 +172,9 @@
|
|||||||
"password_submitted": "Password Submitted",
|
"password_submitted": "Password Submitted",
|
||||||
"total_usage": "Total Usage: {usage}",
|
"total_usage": "Total Usage: {usage}",
|
||||||
"setting_on_password": "Setting Password",
|
"setting_on_password": "Setting Password",
|
||||||
"getting_code": "Getting Verification Code, Will Try in 60s"
|
"getting_code": "Getting Verification Code, Will Try in 60s",
|
||||||
|
"human_verify_error": "Can't verify the user is human. Retrying...",
|
||||||
|
"max_retries_reached": "Maximum retry attempts reached. Registration failed."
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"title": "Cursor Auth Manager",
|
"title": "Cursor Auth Manager",
|
||||||
|
316
new_signup.py
316
new_signup.py
@ -39,7 +39,7 @@ def signal_handler(signum, frame):
|
|||||||
os._exit(0)
|
os._exit(0)
|
||||||
|
|
||||||
def simulate_human_input(page, url, config, translator=None):
|
def simulate_human_input(page, url, config, translator=None):
|
||||||
"""Visit URL"""
|
"""Visit URL with human-like behavior"""
|
||||||
if translator:
|
if translator:
|
||||||
print(f"{Fore.CYAN}🚀 {translator.get('register.visiting_url')}: {url}{Style.RESET_ALL}")
|
print(f"{Fore.CYAN}🚀 {translator.get('register.visiting_url')}: {url}{Style.RESET_ALL}")
|
||||||
|
|
||||||
@ -47,53 +47,194 @@ def simulate_human_input(page, url, config, translator=None):
|
|||||||
page.get('about:blank')
|
page.get('about:blank')
|
||||||
time.sleep(get_random_wait_time(config, 'page_load_wait'))
|
time.sleep(get_random_wait_time(config, 'page_load_wait'))
|
||||||
|
|
||||||
|
# Add random mouse movements before visiting target page
|
||||||
|
try:
|
||||||
|
page.run_js("""
|
||||||
|
function simulateMouseMovement() {
|
||||||
|
const points = [];
|
||||||
|
const numPoints = Math.floor(Math.random() * 10) + 5;
|
||||||
|
for (let i = 0; i < numPoints; i++) {
|
||||||
|
points.push({
|
||||||
|
x: Math.random() * window.innerWidth,
|
||||||
|
y: Math.random() * window.innerHeight
|
||||||
|
});
|
||||||
|
}
|
||||||
|
points.forEach((point, i) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const event = new MouseEvent('mousemove', {
|
||||||
|
view: window,
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
clientX: point.x,
|
||||||
|
clientY: point.y
|
||||||
|
});
|
||||||
|
document.dispatchEvent(event);
|
||||||
|
}, i * (Math.random() * 200 + 50));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
simulateMouseMovement();
|
||||||
|
""")
|
||||||
|
except:
|
||||||
|
pass # Ignore if JavaScript execution fails
|
||||||
|
|
||||||
# Visit target page
|
# Visit target page
|
||||||
page.get(url)
|
page.get(url)
|
||||||
time.sleep(get_random_wait_time(config, 'page_load_wait'))
|
time.sleep(get_random_wait_time(config, 'page_load_wait'))
|
||||||
|
|
||||||
|
# Add some random scrolling
|
||||||
|
try:
|
||||||
|
page.run_js("""
|
||||||
|
function simulateHumanScroll() {
|
||||||
|
const maxScroll = Math.max(
|
||||||
|
document.body.scrollHeight,
|
||||||
|
document.documentElement.scrollHeight,
|
||||||
|
document.body.offsetHeight,
|
||||||
|
document.documentElement.offsetHeight,
|
||||||
|
document.body.clientHeight,
|
||||||
|
document.documentElement.clientHeight
|
||||||
|
);
|
||||||
|
const scrollPoints = [];
|
||||||
|
const numPoints = Math.floor(Math.random() * 3) + 2;
|
||||||
|
for (let i = 0; i < numPoints; i++) {
|
||||||
|
scrollPoints.push(Math.floor(Math.random() * maxScroll));
|
||||||
|
}
|
||||||
|
scrollPoints.sort((a, b) => a - b);
|
||||||
|
scrollPoints.forEach((point, i) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
window.scrollTo({
|
||||||
|
top: point,
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
}, i * (Math.random() * 1000 + 500));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
simulateHumanScroll();
|
||||||
|
""")
|
||||||
|
except:
|
||||||
|
pass # Ignore if JavaScript execution fails
|
||||||
|
|
||||||
|
def simulate_human_typing(element, text, config):
|
||||||
|
"""Simulate human-like typing with random delays between keystrokes"""
|
||||||
|
for char in text:
|
||||||
|
element.input(char)
|
||||||
|
# Random delay between keystrokes (30-100ms)
|
||||||
|
time.sleep(random.uniform(0.03, 0.1))
|
||||||
|
time.sleep(get_random_wait_time(config, 'input_wait'))
|
||||||
|
|
||||||
def fill_signup_form(page, first_name, last_name, email, config, translator=None):
|
def fill_signup_form(page, first_name, last_name, email, config, translator=None):
|
||||||
"""Fill signup form"""
|
"""Fill signup form with human-like behavior"""
|
||||||
try:
|
max_retries = 5
|
||||||
if translator:
|
retry_count = 0
|
||||||
print(f"{Fore.CYAN}📧 {translator.get('register.filling_form')}{Style.RESET_ALL}")
|
|
||||||
else:
|
while retry_count < max_retries:
|
||||||
print("\n正在填写注册表单...")
|
try:
|
||||||
|
if translator:
|
||||||
# Fill first name
|
print(f"{Fore.CYAN}📧 {translator.get('register.filling_form')} (Attempt {retry_count + 1}/{max_retries}){Style.RESET_ALL}")
|
||||||
first_name_input = page.ele("@name=first_name")
|
else:
|
||||||
if first_name_input:
|
print(f"\n正在填写注册表单... (Attempt {retry_count + 1}/{max_retries})")
|
||||||
first_name_input.input(first_name)
|
|
||||||
time.sleep(get_random_wait_time(config, 'input_wait'))
|
|
||||||
|
|
||||||
# Fill last name
|
|
||||||
last_name_input = page.ele("@name=last_name")
|
|
||||||
if last_name_input:
|
|
||||||
last_name_input.input(last_name)
|
|
||||||
time.sleep(get_random_wait_time(config, 'input_wait'))
|
|
||||||
|
|
||||||
# Fill email
|
|
||||||
email_input = page.ele("@name=email")
|
|
||||||
if email_input:
|
|
||||||
email_input.input(email)
|
|
||||||
time.sleep(get_random_wait_time(config, 'input_wait'))
|
|
||||||
|
|
||||||
# Click submit button
|
|
||||||
submit_button = page.ele("@type=submit")
|
|
||||||
if submit_button:
|
|
||||||
submit_button.click()
|
|
||||||
time.sleep(get_random_wait_time(config, 'submit_wait'))
|
|
||||||
|
|
||||||
|
# Add random initial delay
|
||||||
|
time.sleep(random.uniform(0.5, 1.5))
|
||||||
|
|
||||||
|
# Fill first name with human-like typing
|
||||||
|
first_name_input = page.ele("@name=first_name")
|
||||||
|
if first_name_input:
|
||||||
|
simulate_human_typing(first_name_input, first_name, config)
|
||||||
|
# Add random pause between fields
|
||||||
|
time.sleep(random.uniform(0.3, 0.8))
|
||||||
|
|
||||||
|
# Fill last name with human-like typing
|
||||||
|
last_name_input = page.ele("@name=last_name")
|
||||||
|
if last_name_input:
|
||||||
|
simulate_human_typing(last_name_input, last_name, config)
|
||||||
|
# Add random pause between fields
|
||||||
|
time.sleep(random.uniform(0.3, 0.8))
|
||||||
|
|
||||||
|
# Fill email with human-like typing
|
||||||
|
email_input = page.ele("@name=email")
|
||||||
|
if email_input:
|
||||||
|
simulate_human_typing(email_input, email, config)
|
||||||
|
# Add random pause before submitting
|
||||||
|
time.sleep(random.uniform(0.5, 1.2))
|
||||||
|
|
||||||
|
# Move mouse to submit button with human-like movement
|
||||||
|
submit_button = page.ele("@type=submit")
|
||||||
|
if submit_button:
|
||||||
|
try:
|
||||||
|
# Simulate mouse movement to button
|
||||||
|
page.run_js("""
|
||||||
|
function moveToButton(button) {
|
||||||
|
const rect = button.getBoundingClientRect();
|
||||||
|
const centerX = rect.left + rect.width / 2;
|
||||||
|
const centerY = rect.top + rect.height / 2;
|
||||||
|
|
||||||
|
// Create a curved path to the button
|
||||||
|
const startX = Math.random() * window.innerWidth;
|
||||||
|
const startY = Math.random() * window.innerHeight;
|
||||||
|
const controlX = (startX + centerX) / 2 + (Math.random() - 0.5) * 100;
|
||||||
|
const controlY = (startY + centerY) / 2 + (Math.random() - 0.5) * 100;
|
||||||
|
|
||||||
|
const steps = 20;
|
||||||
|
for (let i = 0; i <= steps; i++) {
|
||||||
|
const t = i / steps;
|
||||||
|
const x = Math.pow(1-t, 2) * startX + 2 * (1-t) * t * controlX + Math.pow(t, 2) * centerX;
|
||||||
|
const y = Math.pow(1-t, 2) * startY + 2 * (1-t) * t * controlY + Math.pow(t, 2) * centerY;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const event = new MouseEvent('mousemove', {
|
||||||
|
view: window,
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
clientX: x,
|
||||||
|
clientY: y
|
||||||
|
});
|
||||||
|
document.dispatchEvent(event);
|
||||||
|
}, i * (Math.random() * 20 + 10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
moveToButton(document.querySelector('button[type="submit"]'));
|
||||||
|
""")
|
||||||
|
time.sleep(random.uniform(0.3, 0.6))
|
||||||
|
except:
|
||||||
|
pass # Ignore if JavaScript execution fails
|
||||||
|
|
||||||
|
submit_button.click()
|
||||||
|
time.sleep(get_random_wait_time(config, 'submit_wait'))
|
||||||
|
|
||||||
|
# Check for human verification error
|
||||||
|
error_message = page.ele("text:Can't verify the user is human")
|
||||||
|
if error_message:
|
||||||
|
if translator:
|
||||||
|
print(f"{Fore.YELLOW}⚠️ {translator.get('register.human_verify_error')} (Attempt {retry_count + 1}/{max_retries}){Style.RESET_ALL}")
|
||||||
|
else:
|
||||||
|
print(f"Can't verify the user is human. Retrying... (Attempt {retry_count + 1}/{max_retries})")
|
||||||
|
retry_count += 1
|
||||||
|
# Add longer random delay between retries
|
||||||
|
time.sleep(random.uniform(2, 4))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if translator:
|
||||||
|
print(f"{Fore.GREEN}✅ {translator.get('register.form_success')}{Style.RESET_ALL}")
|
||||||
|
else:
|
||||||
|
print("Form filled successfully")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if translator:
|
||||||
|
print(f"{Fore.RED}❌ {translator.get('register.form_error', error=str(e))}{Style.RESET_ALL}")
|
||||||
|
else:
|
||||||
|
print(f"Error filling form: {e}")
|
||||||
|
retry_count += 1
|
||||||
|
if retry_count < max_retries:
|
||||||
|
time.sleep(get_random_wait_time(config, 'verification_retry_wait'))
|
||||||
|
continue
|
||||||
|
return False
|
||||||
|
|
||||||
|
if retry_count >= max_retries:
|
||||||
if translator:
|
if translator:
|
||||||
print(f"{Fore.GREEN}✅ {translator.get('register.form_success')}{Style.RESET_ALL}")
|
print(f"{Fore.RED}❌ {translator.get('register.max_retries_reached')}{Style.RESET_ALL}")
|
||||||
else:
|
else:
|
||||||
print("Form filled successfully")
|
print("Maximum retry attempts reached. Registration failed.")
|
||||||
return True
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
if translator:
|
|
||||||
print(f"{Fore.RED}❌ {translator.get('register.form_error', error=str(e))}{Style.RESET_ALL}")
|
|
||||||
else:
|
|
||||||
print(f"Error filling form: {e}")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_default_chrome_path():
|
def get_default_chrome_path():
|
||||||
@ -163,7 +304,7 @@ def get_random_wait_time(config, timing_type='page_load_wait'):
|
|||||||
return random.uniform(0.1, 0.8) # Return default value when error
|
return random.uniform(0.1, 0.8) # Return default value when error
|
||||||
|
|
||||||
def setup_driver(translator=None):
|
def setup_driver(translator=None):
|
||||||
"""Setup browser driver"""
|
"""Setup browser driver with randomized fingerprint"""
|
||||||
try:
|
try:
|
||||||
# Get config
|
# Get config
|
||||||
config = get_config(translator)
|
config = get_config(translator)
|
||||||
@ -185,10 +326,42 @@ def setup_driver(translator=None):
|
|||||||
# Use incognito mode
|
# Use incognito mode
|
||||||
co.set_argument("--incognito")
|
co.set_argument("--incognito")
|
||||||
|
|
||||||
# Set random port
|
# Randomize browser fingerprint
|
||||||
co.set_argument("--no-sandbox")
|
# Random screen resolution
|
||||||
|
resolutions = [
|
||||||
|
"1920,1080", "1366,768", "1536,864", "1440,900",
|
||||||
|
"1280,720", "1600,900", "1024,768", "1680,1050"
|
||||||
|
]
|
||||||
|
window_size = random.choice(resolutions)
|
||||||
|
co.set_argument(f"--window-size={window_size}")
|
||||||
|
|
||||||
|
# Random user agent
|
||||||
|
user_agents = [
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.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",
|
||||||
|
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
||||||
|
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
||||||
|
]
|
||||||
|
co.set_argument(f"--user-agent={random.choice(user_agents)}")
|
||||||
|
|
||||||
|
# Random color depth
|
||||||
|
color_depths = ["24", "30", "48"]
|
||||||
|
co.set_argument(f"--color-depth={random.choice(color_depths)}")
|
||||||
|
|
||||||
|
# Additional fingerprint randomization
|
||||||
|
co.set_argument("--disable-blink-features=AutomationControlled") # Hide automation
|
||||||
|
co.set_argument("--disable-features=IsolateOrigins,site-per-process")
|
||||||
|
|
||||||
|
# Random platform
|
||||||
|
platforms = ["Win32", "Win64", "MacIntel", "Linux x86_64"]
|
||||||
|
co.set_argument(f"--platform={random.choice(platforms)}")
|
||||||
|
|
||||||
|
# Random language
|
||||||
|
languages = ["en-US", "en-GB", "fr-FR", "de-DE", "es-ES", "it-IT"]
|
||||||
|
co.set_argument(f"--lang={random.choice(languages)}")
|
||||||
|
|
||||||
# Set random port
|
# Set random port
|
||||||
|
co.set_argument("--no-sandbox")
|
||||||
co.auto_port()
|
co.auto_port()
|
||||||
|
|
||||||
# Use headless mode (must be set to False, simulate human operation)
|
# Use headless mode (must be set to False, simulate human operation)
|
||||||
@ -212,6 +385,63 @@ def setup_driver(translator=None):
|
|||||||
print("Starting browser...")
|
print("Starting browser...")
|
||||||
|
|
||||||
page = ChromiumPage(co)
|
page = ChromiumPage(co)
|
||||||
|
|
||||||
|
# Additional JavaScript-based fingerprint randomization
|
||||||
|
try:
|
||||||
|
page.run_js("""
|
||||||
|
// Override navigator properties
|
||||||
|
const originalNavigator = window.navigator;
|
||||||
|
const navigatorProxy = new Proxy(originalNavigator, {
|
||||||
|
get: function(target, key) {
|
||||||
|
switch (key) {
|
||||||
|
case 'webdriver':
|
||||||
|
return undefined;
|
||||||
|
case 'plugins':
|
||||||
|
return [
|
||||||
|
{ name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer' },
|
||||||
|
{ name: 'Chrome PDF Viewer', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai' },
|
||||||
|
{ name: 'Native Client', filename: 'internal-nacl-plugin' }
|
||||||
|
];
|
||||||
|
case 'languages':
|
||||||
|
return ['en-US', 'en'];
|
||||||
|
default:
|
||||||
|
return target[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Override permissions
|
||||||
|
const originalPermissions = window.Permissions;
|
||||||
|
window.Permissions = new Proxy(originalPermissions, {
|
||||||
|
get: function(target, key) {
|
||||||
|
if (key === 'prototype') {
|
||||||
|
return {
|
||||||
|
query: async () => ({ state: 'prompt' })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return target[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Random canvas fingerprint
|
||||||
|
const originalGetContext = HTMLCanvasElement.prototype.getContext;
|
||||||
|
HTMLCanvasElement.prototype.getContext = function() {
|
||||||
|
const context = originalGetContext.apply(this, arguments);
|
||||||
|
if (context && arguments[0] === '2d') {
|
||||||
|
const originalFillText = context.fillText;
|
||||||
|
context.fillText = function() {
|
||||||
|
const noise = Math.random() * 0.1;
|
||||||
|
context.rotate(noise);
|
||||||
|
originalFillText.apply(this, arguments);
|
||||||
|
context.rotate(-noise);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
except:
|
||||||
|
pass # Ignore if JavaScript execution fails
|
||||||
|
|
||||||
return config, page
|
return config, page
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user