0
0
mirror of https://github.com/yeongpin/cursor-free-vip.git synced 2025-04-29 09:35:50 +00:00
cursor-free-vip/control.py
2025-01-14 18:58:35 +08:00

377 lines
18 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import time
from colorama import Fore, Style
import random
import os
class BrowserControl:
def __init__(self, browser):
self.browser = browser
self.sign_up_url = "https://authenticator.cursor.sh/sign-up"
self.current_tab = None # 当前标签页
self.signup_tab = None # 注册标签页
self.email_tab = None # 邮箱标签页
def create_new_tab(self):
"""创建新标签页"""
try:
# 保存当前标签页
self.current_tab = self.browser
# 创建新的浏览器实例
from browser import BrowserManager
browser_manager = BrowserManager()
new_browser = browser_manager.init_browser()
# 保存新标签页
self.signup_tab = new_browser
print(f"{Fore.GREEN}Create New Tab Success | 成功创建新窗口{Style.RESET_ALL}")
return new_browser
except Exception as e:
print(f"{Fore.RED}Create New Tab Failed | 创建新窗口时发生错误: {str(e)}{Style.RESET_ALL}")
return None
def switch_to_tab(self, browser):
"""切换到指定浏览器窗口"""
try:
self.browser = browser
print(f"{Fore.GREEN}Switch Tab Success | 成功切换窗口{Style.RESET_ALL}")
return True
except Exception as e:
print(f"{Fore.RED}Switch Tab Failed | 切换窗口时发生错误: {str(e)}{Style.RESET_ALL}")
return False
def get_current_tab(self):
"""获取当前标签页"""
return self.browser
def generate_new_email(self):
"""点击新的按钮生成新邮箱"""
try:
print(f"{Fore.CYAN}Click Generate New Email | 点击生成新邮箱...{Style.RESET_ALL}")
new_button = self.browser.ele('xpath://button[contains(@class, "egenbut")]')
if new_button:
new_button.click()
time.sleep(1) # 等待生成
print(f"{Fore.GREEN}Generate New Email | 成功生成新邮箱{Style.RESET_ALL}")
return True
else:
print(f"{Fore.RED}No Generate Button Found | 未找到生成按钮{Style.RESET_ALL}")
return False
except Exception as e:
print(f"{Fore.RED}Generate New Email Failed | 生成新邮箱时发生错误: {str(e)}{Style.RESET_ALL}")
return False
def select_email_domain(self, domain_index=None):
"""选择邮箱域名如果不指定index则随机选择"""
try:
print(f"{Fore.CYAN}Select Email Domain | 选择邮箱域名...{Style.RESET_ALL}")
# 找到下拉框
select_element = self.browser.ele('xpath://select[@id="seldom"]')
if select_element:
# 获取所有选项,包括两个 optgroup 下的所有 option
all_options = []
# 获取 "新的" 组下的选项
new_options = self.browser.eles('xpath://select[@id="seldom"]/optgroup[@label="-- 新的 --"]/option')
all_options.extend(new_options)
# 获取 "其他" 组下的选项
other_options = self.browser.eles('xpath://select[@id="seldom"]/optgroup[@label="-- 其他 --"]/option')
all_options.extend(other_options)
if all_options:
# 如果没有指定索引,随机选择一个
if domain_index is None:
domain_index = random.randint(0, len(all_options) - 1)
if domain_index < len(all_options):
# 获取选中选项的文本
selected_domain = all_options[domain_index].text
print(f"{Fore.CYAN}Select Email Domain | 选择域名: {selected_domain}{Style.RESET_ALL}")
# 点击选择
all_options[domain_index].click()
time.sleep(1)
print(f"{Fore.GREEN}Select Email Domain | 成功选择邮箱域名{Style.RESET_ALL}")
return True
print(f"{Fore.RED}No Available Domain Options | 未找到可用的域名选项,总共有 {len(all_options)} 个选项{Style.RESET_ALL}")
return False
else:
print(f"{Fore.RED}No Domain Select Box Found | 未找到域名选择框{Style.RESET_ALL}")
return False
except Exception as e:
print(f"{Fore.RED}Select Email Domain Failed | 选择邮箱域名时发生错误: {str(e)}{Style.RESET_ALL}")
return False
def wait_for_page_load(self, seconds=2):
"""等待页面加载"""
time.sleep(seconds)
def navigate_to(self, url):
"""导航到指定URL"""
try:
print(f"{Fore.CYAN}Navigate to {url} | 正在访问 {url}...{Style.RESET_ALL}")
self.browser.get(url)
self.wait_for_page_load()
return True
except Exception as e:
print(f"{Fore.RED}Visit {url} Failed | 访问 {url} 时发生错误: {str(e)}{Style.RESET_ALL}")
return False
def copy_and_get_email(self):
"""获取邮箱地址"""
try:
print(f"{Fore.CYAN}Get Email Info | 获取邮箱信息...{Style.RESET_ALL}")
# 等待元素加载
time.sleep(1)
# 获取邮箱名称
try:
email_div = self.browser.ele('xpath://div[@class="segen"]//div[contains(@style, "color: #e5e5e5")]')
if email_div:
email_name = email_div.text.split()[0]
print(f"{Fore.CYAN}Get Email Name | 找到邮箱名称: {email_name}{Style.RESET_ALL}")
else:
print(f"{Fore.RED}Get Email Name Failed | 无法找到邮箱名称元素{Style.RESET_ALL}")
return None
except Exception as e:
print(f"{Fore.RED}Get Email Name Failed | 获取邮箱名称时出错: {str(e)}{Style.RESET_ALL}")
return None
# 直接使用上一步选择的域名
try:
domain = self.browser.ele('xpath://select[@id="seldom"]').value
if not domain: # 如果获取不到value尝试获取选中的选项文本
selected_option = self.browser.ele('xpath://select[@id="seldom"]/option[1]')
domain = selected_option.text if selected_option else "@yopmail.com" # 使用默认域名作为后备
except:
domain = "@yopmail.com" # 如果出错,使用默认域名
# 组合完整邮箱地址
full_email = f"{email_name}{domain}"
print(f"{Fore.GREEN}Get Email Address | 完整邮箱地址: {full_email}{Style.RESET_ALL}")
return full_email
except Exception as e:
print(f"{Fore.RED}Get Email Address Failed | 获取邮箱地址时发生错误: {str(e)}{Style.RESET_ALL}")
return None
def view_mailbox(self):
"""点击查看邮箱按钮"""
try:
print(f"{Fore.CYAN}Enter Mailbox | 正在进入邮箱...{Style.RESET_ALL}")
view_button = self.browser.ele('xpath://button[contains(@class, "egenbut") and contains(.//span, "查看邮箱")]')
if view_button:
view_button.click()
time.sleep(2) # 等待页面加载
print(f"{Fore.GREEN}Successfully Entered Mailbox | 成功进入邮箱{Style.RESET_ALL}")
return True
else:
print(f"{Fore.RED}No View Mailbox Button Found | 未找到查看邮箱按钮{Style.RESET_ALL}")
return False
except Exception as e:
print(f"{Fore.RED}Enter Mailbox Failed | 进入邮箱时发生错误: {str(e)}{Style.RESET_ALL}")
return False
def refresh_mailbox(self):
"""刷新邮箱获取最新信息"""
try:
print(f"{Fore.CYAN}Refresh Mailbox | 正在刷新邮箱...{Style.RESET_ALL}")
refresh_button = self.browser.ele('xpath://button[@id="refresh"]')
if refresh_button:
refresh_button.click()
time.sleep(2) # 等待刷新完成
print(f"{Fore.GREEN}Mailbox Refreshed Successfully | 邮箱刷新成功{Style.RESET_ALL}")
return True
else:
print(f"{Fore.RED}No Refresh Button Found | 未找到刷新按钮{Style.RESET_ALL}")
return False
except Exception as e:
print(f"{Fore.RED}Refresh Mailbox Failed | 刷新邮箱时发生错误: {str(e)}{Style.RESET_ALL}")
return False
def check_and_click_recaptcha(self):
"""检查并点击验证码复选框"""
try:
# 使用环境变量或配置文件中预设的坐标
click_x = int(os.getenv('RECAPTCHA_X', '100')) # 默认值100
click_y = int(os.getenv('RECAPTCHA_Y', '100')) # 默认值100
print(f"{Fore.CYAN}使用预设坐标点击: x={click_x}, y={click_y}{Style.RESET_ALL}")
# 直接点击预设坐标
self.browser.page.mouse.click(click_x, click_y)
print(f"{Fore.GREEN}Clicked reCAPTCHA Position | 已点击 reCAPTCHA 位置{Style.RESET_ALL}")
time.sleep(1)
return True
except Exception as e:
print(f"{Fore.YELLOW}Click reCAPTCHA Failed | 点击 reCAPTCHA 失败: {str(e)}{Style.RESET_ALL}")
return False
def get_verification_code(self):
"""从邮件中获取验证码"""
try:
# 使用新的 XPath 定位验证码
code_div = self.browser.ele('xpath://div[contains(@style, "font-family:-apple-system") and contains(@style, "font-size:28px") and contains(@style, "letter-spacing:2px") and contains(@style, "color:#202020")]')
# 如果找不到,尝试备用选择器
if not code_div:
code_div = self.browser.ele('xpath://div[contains(@style, "font-size:28px") and contains(@style, "letter-spacing:2px") and contains(@style, "line-height:30px")]')
# 如果还找不到,尝试更宽松的选择器
if not code_div:
code_div = self.browser.ele('xpath://div[contains(@style, "font-size:28px") and contains(@style, "letter-spacing:2px")]')
if code_div:
verification_code = code_div.text.strip()
if verification_code.isdigit() and len(verification_code) == 6:
print(f"{Fore.GREEN}Found Verification Code | 找到验证码: {verification_code}{Style.RESET_ALL}")
return verification_code
else:
print(f"{Fore.RED}Verification Code Format Error | 验证码格式不正确: {verification_code}{Style.RESET_ALL}")
return None
else:
print(f"{Fore.YELLOW}No Verification Code Found | 未找到验证码{Style.RESET_ALL}")
return None
except Exception as e:
print(f"{Fore.RED}Get Verification Code Error | 获取验证码时发生错误: {str(e)}{Style.RESET_ALL}")
return None
def fill_verification_code(self, code):
"""填写验证码"""
try:
if not code or len(code) != 6:
print(f"{Fore.RED}Verification Code Format Error | 验证码格式不正确{Style.RESET_ALL}")
return False
print(f"{Fore.CYAN}Fill Verification Code | 正在填写验证码...{Style.RESET_ALL}")
# 记住当前标签页(邮箱页面)
email_tab = self.browser
# 切换回注册页面标签
self.switch_to_tab(self.signup_tab)
time.sleep(1)
# 输入验证码
for digit in code:
self.browser.actions.input(digit)
time.sleep(random.uniform(0.1, 0.3))
print(f"{Fore.GREEN}Verification Code Filled | 验证码填写完成{Style.RESET_ALL}")
# 等待页面加载和登录完成
print(f"{Fore.CYAN}Wait for Login | 等待登录完成...{Style.RESET_ALL}")
time.sleep(5)
# 先访问登录页面确保登录状态
login_url = "https://authenticator.cursor.sh"
self.browser.get(login_url)
time.sleep(3) # 增加等待时间
# 获取cookies第一次尝试
token = self.get_cursor_session_token()
if not token:
print(f"{Fore.YELLOW}Get Token Failed | 首次获取token失败等待后重试...{Style.RESET_ALL}")
time.sleep(3)
token = self.get_cursor_session_token()
if token:
self.save_token_to_file(token)
# 获取到token后再访问设置页面
settings_url = "https://www.cursor.com/settings"
print(f"{Fore.CYAN}Get Account Info | 正在访问设置页面获取账户信息...{Style.RESET_ALL}")
self.browser.get(settings_url)
time.sleep(2)
# 获取账户额度信息
try:
usage_selector = (
"css:div.col-span-2 > div > div > div > div > "
"div:nth-child(1) > div.flex.items-center.justify-between.gap-2 > "
"span.font-mono.text-sm\\/\\[0\\.875rem\\]"
)
usage_ele = self.browser.ele(usage_selector)
if usage_ele:
usage_info = usage_ele.text
total_usage = usage_info.split("/")[-1].strip()
print(f"{Fore.GREEN}Account Usage Limit | 账户可用额度上限: {total_usage}{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}Get Account Usage Failed | 获取账户额度信息失败: {str(e)}{Style.RESET_ALL}")
# 切换回邮箱页面
self.switch_to_tab(email_tab)
return True
except Exception as e:
print(f"{Fore.RED}Fill Verification Code Failed | 填写验证码时发生错误: {str(e)}{Style.RESET_ALL}")
return False
def check_and_click_turnstile(self):
"""检查并点击 Turnstile 验证框"""
try:
# 等待验证框出现
time.sleep(1)
# 查找验证框
verify_checkbox = self.browser.ele('xpath://label[contains(@class, "cb-lb")]//input[@type="checkbox"]')
if verify_checkbox:
print(f"{Fore.CYAN}Find Turnstile Verification Box | 找到 Turnstile 验证框,尝试点击...{Style.RESET_ALL}")
verify_checkbox.click()
time.sleep(2) # 等待验证完成
print(f"{Fore.GREEN}Clicked Turnstile Verification Box | 已点击 Turnstile 验证框{Style.RESET_ALL}")
return True
return False
except Exception as e:
print(f"{Fore.YELLOW}Check and Click Turnstile Failed | 未找到 Turnstile 验证框或点击失败: {str(e)}{Style.RESET_ALL}")
return False
def get_cursor_session_token(self, max_attempts=3, retry_interval=2):
"""获取Cursor会话token"""
print(f"{Fore.CYAN}Get Cursor Session Token | 开始获取cookie...{Style.RESET_ALL}")
attempts = 0
while attempts < max_attempts:
try:
# 直接从浏览器对象获取cookies
all_cookies = self.browser.get_cookies()
# 遍历查找目标cookie
for cookie in all_cookies:
if cookie.get("name") == "WorkosCursorSessionToken":
token = cookie["value"].split("%3A%3A")[1]
print(f"{Fore.GREEN}成功获取CursorSessionToken: {token}{Style.RESET_ALL}")
return token
attempts += 1
if attempts < max_attempts:
print(f"{Fore.YELLOW} Try | 第 {attempts} 次尝试未获取到CursorSessionToken{retry_interval}秒后重试...{Style.RESET_ALL}")
time.sleep(retry_interval)
else:
print(f"{Fore.RED}Reach Max Attempts ({max_attempts}) | 已达到最大尝试次数({max_attempts})获取CursorSessionToken失败{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}获取cookie失败: {str(e)}{Style.RESET_ALL}")
attempts += 1
if attempts < max_attempts:
print(f"{Fore.YELLOW}Will Retry in {retry_interval} seconds | 将在 {retry_interval} 秒后重试...{Style.RESET_ALL}")
time.sleep(retry_interval)
return None
def save_token_to_file(self, token):
"""保存token到文件"""
try:
with open('cursor_tokens.txt', 'a', encoding='utf-8') as f:
f.write(f"Token: {token}\n")
f.write("-" * 50 + "\n")
print(f"{Fore.GREEN}Token Saved to cursor_tokens.txt | Token已保存到 cursor_tokens.txt{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}Save Token Failed | 保存Token时发生错误: {str(e)}{Style.RESET_ALL}")