diff --git a/config.py b/config.py index beb6c2f..69d7dbc 100644 --- a/config.py +++ b/config.py @@ -2,7 +2,7 @@ import os import sys import configparser from colorama import Fore, Style -from utils import get_user_documents_path, get_default_chrome_path, get_linux_cursor_path +from utils import get_user_documents_path, get_linux_cursor_path, get_default_driver_path, get_default_browser_path import shutil import datetime @@ -29,8 +29,19 @@ def setup_config(translator=None): # Default configuration default_config = { + 'Browser': { + 'default_browser': 'chrome', + 'chrome_path': get_default_browser_path('chrome'), + 'edge_path': get_default_browser_path('edge'), + 'firefox_path': get_default_browser_path('firefox'), + 'brave_path': get_default_browser_path('brave'), + 'chrome_driver_path': get_default_driver_path('chrome'), + 'edge_driver_path': get_default_driver_path('edge'), + 'firefox_driver_path': get_default_driver_path('firefox'), + 'brave_driver_path': get_default_driver_path('brave') + }, 'Chrome': { - 'chromepath': get_default_chrome_path() + 'chromepath': get_default_browser_path('chrome') }, 'Turnstile': { 'handle_turnstile_time': '2', diff --git a/locales/en.json b/locales/en.json index da3bb7d..9f37b44 100644 --- a/locales/en.json +++ b/locales/en.json @@ -199,7 +199,15 @@ "setting_on_password": "Setting Password", "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." + "max_retries_reached": "Maximum retry attempts reached. Registration failed.", + "browser_path_invalid": "{browser} path is invalid, using default path", + "using_browser": "Using {browser} browser: {path}", + "using_browser_profile": "Using {browser} profile from: {user_data_dir}", + "make_sure_browser_is_properly_installed": "Make sure {browser} is properly installed", + "try_install_browser": "Try installing the browser with your package manager", + "tracking_processes": "Tracking {count} {browser} processes", + "no_new_processes_detected": "No new {browser} processes detected to track", + "could_not_track_processes": "Could not track {browser} processes: {error}" }, "auth": { "title": "Cursor Auth Manager", @@ -623,19 +631,26 @@ "warning_could_not_kill_existing_browser_processes": "Warning: Could not kill existing browser processes: {error}", "browser_failed_to_start": "Browser failed to start: {error}", "browser_failed": "Browser failed to start: {error}", - "browser_failed_to_start_fallback": "Browser failed to start: {error}" + "browser_failed_to_start_fallback": "Browser failed to start: {error}", + "user_data_dir_not_found": "{browser} user data directory not found at {path}, will try Chrome instead", + "error_getting_user_data_directory": "Error getting user data directory: {error}", + "warning_browser_close": "Warning: This will close all running {browser} processes", + "killing_browser_processes": "Killing {browser} processes...", + "profile_selection_error": "Error during profile selection: {error}", + "using_configured_browser_path": "Using configured {browser} path: {path}", + "browser_not_found_trying_chrome": "Could not find {browser}, trying Chrome instead", + "found_chrome_at": "Found Chrome at: {path}" }, - "chrome_profile": { - "title": "Chrome Profile Selection", - "select_profile": "Select a Chrome profile to use:", - "profile_list": "Available profiles:", - "default_profile": "Default Profile", + "browser_profile": { + "title": "Browser Profile Selection", + "select_profile": "Select {browser} profile to use:", + "profile_list": "Available {browser} profiles:", + "default_profile": "Default profile", "profile": "Profile {number}", - "no_profiles": "No Chrome profiles found", - "error_loading": "Error loading Chrome profiles: {error}", + "no_profiles": "No {browser} profiles found", + "error_loading": "Error loading {browser} profiles: {error}", "profile_selected": "Selected profile: {profile}", - "invalid_selection": "Invalid selection. Please try again", - "warning_chrome_close": "Warning: This will close all running Chrome processes" + "invalid_selection": "Invalid selection. Please try again." }, "account_delete": { "title": "Cursor Google Account Deletion Tool", diff --git a/locales/zh_cn.json b/locales/zh_cn.json index 4767999..196be99 100644 --- a/locales/zh_cn.json +++ b/locales/zh_cn.json @@ -197,7 +197,15 @@ "password_submitted": "密码已提交", "total_usage": "总使用量: {usage}", "setting_on_password": "设置密码", - "getting_code": "获取验证码,将在60秒内尝试..." + "getting_code": "获取验证码,将在60秒内尝试...", + "browser_path_invalid": "{browser} 路径无效,使用默认路径", + "using_browser": "正在使用 {browser} 浏览器: {path}", + "using_browser_profile": "使用 {browser} 配置文件: {user_data_dir}", + "make_sure_browser_is_properly_installed": "确保 {browser} 已正确安装", + "try_install_browser": "尝试使用包管理器安装浏览器", + "tracking_processes": "正在跟踪 {count} 个 {browser} 进程", + "no_new_processes_detected": "未检测到新的 {browser} 进程", + "could_not_track_processes": "无法跟踪 {browser} 进程: {error}" }, "auth": { "title": "Cursor 认证管理器", @@ -601,19 +609,26 @@ "warning_could_not_kill_existing_browser_processes": "警告: 无法杀死现有浏览器进程: {error}", "browser_failed_to_start": "浏览器启动失败: {error}", "browser_failed": "浏览器启动失败: {error}", - "browser_failed_to_start_fallback": "浏览器启动失败: {error}" + "browser_failed_to_start_fallback": "浏览器启动失败: {error}", + "user_data_dir_not_found": "{browser} 用户数据目录未找到:{path},将尝试使用 Chrome", + "error_getting_user_data_directory": "获取用户数据目录出错:{error}", + "warning_browser_close": "警告:这将关闭所有正在运行的 {browser} 进程", + "killing_browser_processes": "正在关闭 {browser} 进程...", + "profile_selection_error": "配置文件选择过程中出错: {error}", + "using_configured_browser_path": "使用配置的 {browser} 路径: {path}", + "browser_not_found_trying_chrome": "未找到 {browser},尝试使用 Chrome 代替", + "found_chrome_at": "找到 Chrome: {path}" }, - "chrome_profile": { - "title": "Chrome配置文件选择", - "select_profile": "选择要使用的Chrome配置文件:", - "profile_list": "可用配置文件:", + "browser_profile": { + "title": "浏览器配置文件选择", + "select_profile": "选择要使用的{browser}配置文件:", + "profile_list": "可用{browser}配置文件:", "default_profile": "默认配置文件", "profile": "配置文件 {number}", - "no_profiles": "未找到Chrome配置文件", - "error_loading": "加载Chrome配置文件时出错:{error}", + "no_profiles": "未找到{browser}配置文件", + "error_loading": "加载{browser}配置文件时出错:{error}", "profile_selected": "已选择配置文件:{profile}", - "invalid_selection": "选择无效。请重试", - "warning_chrome_close": "警告:这将关闭所有正在运行的Chrome进程" + "invalid_selection": "选择无效。请重试" }, "account_delete": { "title": "Cursor Google 账号删除工具", @@ -678,7 +693,7 @@ "title": "Cursor 版本绕过工具", "description": "此工具修改 Cursor 的 product.json 以绕过版本限制", "menu_option": "绕过 Cursor 版本检查" - }, + }, "auth_check": { "checking_authorization": "检查授权...", "token_source": "从数据库获取 token 或手动输入?(d/m, 默认: d)", diff --git a/new_signup.py b/new_signup.py index b67fefa..906b007 100644 --- a/new_signup.py +++ b/new_signup.py @@ -8,6 +8,7 @@ import configparser from pathlib import Path import sys from config import get_config +from utils import get_default_browser_path as utils_get_default_browser_path # Add global variable at the beginning of the file _translator = None @@ -112,29 +113,6 @@ def fill_signup_form(page, first_name, last_name, email, config, translator=None print(f"Error filling form: {e}") return False -def get_default_chrome_path(): - """Get default Chrome path""" - if sys.platform == "win32": - paths = [ - os.path.join(os.environ.get('PROGRAMFILES', ''), 'Google/Chrome/Application/chrome.exe'), - os.path.join(os.environ.get('PROGRAMFILES(X86)', ''), 'Google/Chrome/Application/chrome.exe'), - os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Google/Chrome/Application/chrome.exe') - ] - elif sys.platform == "darwin": - paths = [ - "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" - ] - else: # Linux - paths = [ - "/usr/bin/google-chrome", - "/usr/bin/google-chrome-stable" - ] - - for path in paths: - if os.path.exists(path): - return path - return "" - def get_user_documents_path(): """Get user Documents folder path""" if sys.platform == "win32": @@ -186,25 +164,32 @@ def setup_driver(translator=None): # Get config config = get_config(translator) - # Get Chrome path - chrome_path = config.get('Chrome', 'chromepath', fallback=get_default_chrome_path()) + # Get browser type and path + browser_type = config.get('Browser', 'default_browser', fallback='chrome') + browser_path = config.get('Browser', f'{browser_type}_path', fallback=utils_get_default_browser_path(browser_type)) - if not chrome_path or not os.path.exists(chrome_path): + if not browser_path or not os.path.exists(browser_path): if translator: - print(f"{Fore.YELLOW}⚠️ {translator.get('register.chrome_path_invalid') if translator else 'Chrome路径无效,使用默认路径'}{Style.RESET_ALL}") - chrome_path = get_default_chrome_path() + print(f"{Fore.YELLOW}⚠️ {browser_type} {translator.get('register.browser_path_invalid')}{Style.RESET_ALL}") + browser_path = utils_get_default_browser_path(browser_type) + + # For backward compatibility, also check Chrome path + if browser_type == 'chrome': + chrome_path = config.get('Chrome', 'chromepath', fallback=None) + if chrome_path and os.path.exists(chrome_path): + browser_path = chrome_path # Set browser options co = ChromiumOptions() - # Set Chrome path - co.set_browser_path(chrome_path) + # Set browser path + co.set_browser_path(browser_path) # Use incognito mode co.set_argument("--incognito") if sys.platform == "linux": - # Set random port + # Set Linux specific options co.set_argument("--no-sandbox") # Set random port @@ -213,6 +198,10 @@ def setup_driver(translator=None): # Use headless mode (must be set to False, simulate human operation) co.headless(False) + # Log browser info + if translator: + print(f"{Fore.CYAN}🌐 {translator.get('register.using_browser')}: {browser_type} {browser_path}{Style.RESET_ALL}") + try: # Load extension extension_path = os.path.join(os.getcwd(), "turnstilePatch") @@ -234,30 +223,38 @@ def setup_driver(translator=None): before_pids = [] try: import psutil - before_pids = [p.pid for p in psutil.process_iter() if 'chrome' in p.name().lower()] + browser_process_names = { + 'chrome': ['chrome', 'chromium'], + 'edge': ['msedge', 'edge'], + 'firefox': ['firefox'], + 'brave': ['brave', 'brave-browser'] + } + process_names = browser_process_names.get(browser_type, ['chrome']) + before_pids = [p.pid for p in psutil.process_iter() if any(name in p.name().lower() for name in process_names)] except: pass # Launch browser page = ChromiumPage(co) - # Wait a moment for Chrome to fully launch + # Wait a moment for browser to fully launch time.sleep(1) - # Record Chrome processes after launching and find new ones + # Record browser processes after launching and find new ones try: import psutil - after_pids = [p.pid for p in psutil.process_iter() if 'chrome' in p.name().lower()] - # Find new Chrome processes + process_names = browser_process_names.get(browser_type, ['chrome']) + after_pids = [p.pid for p in psutil.process_iter() if any(name in p.name().lower() for name in process_names)] + # Find new browser processes new_pids = [pid for pid in after_pids if pid not in before_pids] _chrome_process_ids.extend(new_pids) if _chrome_process_ids: - print(f"Tracking {len(_chrome_process_ids)} Chrome processes") + print(f"{translator.get('register.tracking_processes', count=len(_chrome_process_ids), browser=browser_type)}") else: - print(f"{Fore.YELLOW}Warning: No new Chrome processes detected to track{Style.RESET_ALL}") + print(f"{Fore.YELLOW}Warning: {translator.get('register.no_new_processes_detected', browser=browser_type)}{Style.RESET_ALL}") except Exception as e: - print(f"Warning: Could not track Chrome processes: {e}") + print(f"{translator.get('register.could_not_track_processes', browser=browser_type, error=str(e))}") return config, page diff --git a/new_tempemail.py b/new_tempemail.py index 178f24f..dff765d 100644 --- a/new_tempemail.py +++ b/new_tempemail.py @@ -6,7 +6,8 @@ from colorama import Fore, Style, init import requests import random import string -from utils import get_random_wait_time +from config import get_config +from utils import get_random_wait_time, get_default_browser_path as utils_get_default_browser_path # Initialize colorama init() @@ -104,9 +105,34 @@ class NewTempEmail: else: print(f"{Fore.CYAN}ℹ️ 正在启动浏览器...{Style.RESET_ALL}") + # 获取配置 + config = get_config(self.translator) + + # 获取浏览器类型和路径 + browser_type = config.get('Browser', 'default_browser', fallback='chrome') + browser_path = config.get('Browser', f'{browser_type}_path', fallback=utils_get_default_browser_path(browser_type)) + + if not browser_path or not os.path.exists(browser_path): + if self.translator: + print(f"{Fore.YELLOW}⚠️ {self.translator.get('email.browser_path_invalid', browser=browser_type) if self.translator else f'{browser_type} 路径无效,使用默认路径'}{Style.RESET_ALL}") + browser_path = utils_get_default_browser_path(browser_type) + + # 为了向后兼容,也检查 Chrome 路径 + if browser_type == 'chrome': + chrome_path = config.get('Chrome', 'chromepath', fallback=None) + if chrome_path and os.path.exists(chrome_path): + browser_path = chrome_path + # 创建浏览器选项 co = ChromiumOptions() + # 设置浏览器路径 + co.set_browser_path(browser_path) + + # 记录浏览器信息 + if self.translator: + print(f"{Fore.CYAN}🌐 {self.translator.get('email.using_browser', browser=browser_type, path=browser_path) if self.translator else f'使用 {browser_type} 浏览器: {browser_path}'}{Style.RESET_ALL}") + # Only use headless for non-OAuth operations if not hasattr(self, 'auth_type') or self.auth_type != 'oauth': co.set_argument("--headless=new") @@ -122,22 +148,43 @@ class NewTempEmail: co.set_argument("--disable-dev-shm-usage") co.set_argument("--disable-gpu") - # If running as root, try to use actual user's Chrome profile + # If running as root, try to use actual user's browser profile if os.geteuid() == 0: sudo_user = os.environ.get('SUDO_USER') if sudo_user: actual_home = f"/home/{sudo_user}" - user_data_dir = os.path.join(actual_home, ".config", "google-chrome") + + # 根据浏览器类型选择配置文件夹 + profile_dirs = { + 'chrome': os.path.join(actual_home, ".config", "google-chrome"), + 'brave': os.path.join(actual_home, ".config", "BraveSoftware", "Brave-Browser"), + 'edge': os.path.join(actual_home, ".config", "microsoft-edge"), + 'firefox': os.path.join(actual_home, ".mozilla", "firefox") + } + + user_data_dir = profile_dirs.get(browser_type, profile_dirs['chrome']) + if os.path.exists(user_data_dir): - print(f"{Fore.CYAN}ℹ️ {self.translator.get('email.using_chrome_profile', user_data_dir=user_data_dir) if self.translator else f'Using Chrome profile from: {user_data_dir}'}{Style.RESET_ALL}") + print(f"{Fore.CYAN}ℹ️ {self.translator.get('email.using_browser_profile', browser=browser_type, user_data_dir=user_data_dir) if self.translator else f'Using {browser_type} profile from: {user_data_dir}'}{Style.RESET_ALL}") co.set_argument(f"--user-data-dir={user_data_dir}") co.auto_port() # 自动设置端口 + # 根据浏览器类型设置扩展参数 + extension_args = { + 'chrome': "--allow-extensions-in-incognito", + 'brave': "--allow-extensions-in-brave-incognito", # Brave 可能使用不同的参数 + 'edge': "--allow-extensions-in-incognito", + 'firefox': None # Firefox 可能使用不同的方式加载扩展 + } + + extension_arg = extension_args.get(browser_type, "--allow-extensions-in-incognito") + # 加载 uBlock 插件 try: extension_path = self.get_extension_block() - co.set_argument("--allow-extensions-in-incognito") + if extension_arg: # 如果有扩展参数 + co.set_argument(extension_arg) co.add_extension(extension_path) except Exception as e: if self.translator: @@ -154,8 +201,17 @@ class NewTempEmail: print(f"{Fore.RED}❌ 启动浏览器失败: {str(e)}{Style.RESET_ALL}") if sys.platform == "linux": - print(f"{Fore.YELLOW}ℹ️ {self.translator.get('email.make_sure_chrome_chromium_is_properly_installed') if self.translator else 'Make sure Chrome/Chromium is properly installed'}{Style.RESET_ALL}") - print(f"{Fore.YELLOW}ℹ️ {self.translator.get('email.try_install_chromium') if self.translator else 'Try: sudo apt install chromium-browser'}{Style.RESET_ALL}") + browser_install_suggestions = { + 'chrome': "sudo apt install chromium-browser 或 sudo apt install google-chrome-stable", + 'brave': "sudo apt install brave-browser", + 'edge': "sudo apt install microsoft-edge-stable", + 'firefox': "sudo apt install firefox" + } + + suggestion = browser_install_suggestions.get(browser_type, browser_install_suggestions['chrome']) + + print(f"{Fore.YELLOW}ℹ️ {self.translator.get('email.make_sure_browser_is_properly_installed', browser=browser_type) if self.translator else f'Make sure {browser_type} is properly installed'}{Style.RESET_ALL}") + print(f"{Fore.YELLOW}ℹ️ {self.translator.get('email.try_install_browser') if self.translator else f'Try: {suggestion}'}{Style.RESET_ALL}") return False def create_email(self): diff --git a/oauth_auth.py b/oauth_auth.py index da97634..5d757ba 100644 --- a/oauth_auth.py +++ b/oauth_auth.py @@ -7,7 +7,7 @@ import sys import json from DrissionPage import ChromiumPage, ChromiumOptions from cursor_auth import CursorAuth -from utils import get_random_wait_time, get_default_chrome_path +from utils import get_random_wait_time, get_default_browser_path from config import get_config import platform @@ -63,41 +63,100 @@ class OAuthHandler: return [] def _select_profile(self): - """Select a Chrome profile to use""" + """Allow user to select a browser profile to use""" try: - # Get available profiles - profiles = self._get_available_profiles(self._get_user_data_directory()) - if not profiles: - print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('chrome_profile.no_profiles') if self.translator else 'No Chrome profiles found'}{Style.RESET_ALL}") - return False - - # Display available profiles - print(f"\n{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('chrome_profile.select_profile') if self.translator else 'Select a Chrome profile to use:'}{Style.RESET_ALL}") - print(f"{Fore.CYAN}{self.translator.get('chrome_profile.profile_list') if self.translator else 'Available profiles:'}{Style.RESET_ALL}") - print(f"{Fore.CYAN}0. {self.translator.get('menu.exit') if self.translator else 'Exit'}{Style.RESET_ALL}") - for i, (dir_name, display_name) in enumerate(profiles, 1): - print(f"{Fore.CYAN}{i}. {display_name} ({dir_name}){Style.RESET_ALL}") - - # Get user selection - while True: - try: - choice = int(input(f"\n{Fore.CYAN}{self.translator.get('menu.input_choice', choices=f'0-{len(profiles)}') if self.translator else f'Please enter your choice (0-{len(profiles)}): '}{Style.RESET_ALL}")) - if choice == 0: # Add quit - print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('menu.exiting') if self.translator else 'Exiting profile selection...'}{Style.RESET_ALL}") - return False - elif 1 <= choice <= len(profiles): - self.selected_profile = profiles[choice - 1][0] - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('chrome_profile.profile_selected', profile=self.selected_profile) if self.translator else f'Selected profile: {self.selected_profile}'}{Style.RESET_ALL}") - return True + # 从配置中获取浏览器类型 + config = get_config(self.translator) + browser_type = config.get('Browser', 'default_browser', fallback='chrome') + browser_type_display = browser_type.capitalize() + + if self.translator: + # 动态使用浏览器类型 + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('browser_profile.select_profile', browser=browser_type_display)}{Style.RESET_ALL}") + print(f"{Fore.CYAN}{self.translator.get('browser_profile.profile_list', browser=browser_type_display)}{Style.RESET_ALL}") + else: + print(f"{Fore.CYAN}{EMOJI['INFO']} Select {browser_type_display} profile to use:{Style.RESET_ALL}") + print(f"Available {browser_type_display} profiles:") + + # Get the user data directory for the browser type + user_data_dir = self._get_user_data_directory() + + # Load available profiles from the selected browser type + try: + local_state_file = os.path.join(user_data_dir, "Local State") + if os.path.exists(local_state_file): + with open(local_state_file, 'r', encoding='utf-8') as f: + state_data = json.load(f) + profiles_data = state_data.get('profile', {}).get('info_cache', {}) + + # Create a list of available profiles + profiles = [] + for profile_id, profile_info in profiles_data.items(): + name = profile_info.get('name', profile_id) + # Mark the default profile + if profile_id.lower() == 'default': + name = f"{name} (Default)" + profiles.append((profile_id, name)) + + # Sort profiles by name + profiles.sort(key=lambda x: x[1]) + + # Show available profiles + if self.translator: + print(f"{Fore.CYAN}0. {self.translator.get('menu.exit')}{Style.RESET_ALL}") else: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('chrome_profile.invalid_selection') if self.translator else 'Invalid selection. Please try again.'}{Style.RESET_ALL}") - except ValueError: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('chrome_profile.invalid_selection') if self.translator else 'Invalid selection. Please try again.'}{Style.RESET_ALL}") + print(f"{Fore.CYAN}0. Exit{Style.RESET_ALL}") + + for i, (profile_id, name) in enumerate(profiles, 1): + print(f"{Fore.CYAN}{i}. {name}{Style.RESET_ALL}") + + # Get user's choice + max_choice = len(profiles) + choice_str = input(f"\n{Fore.CYAN}{self.translator.get('menu.input_choice', choices=f'0-{max_choice}') if self.translator else f'Please enter your choice (0-{max_choice})'}{Style.RESET_ALL}") + + try: + choice = int(choice_str) + if choice == 0: + return False + elif 1 <= choice <= max_choice: + selected_profile = profiles[choice-1][0] + self.selected_profile = selected_profile + + if self.translator: + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('browser_profile.profile_selected', profile=selected_profile)}{Style.RESET_ALL}") + else: + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} Selected profile: {selected_profile}{Style.RESET_ALL}") + return True + else: + if self.translator: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('browser_profile.invalid_selection')}{Style.RESET_ALL}") + else: + print(f"{Fore.RED}{EMOJI['ERROR']} Invalid selection. Please try again.{Style.RESET_ALL}") + return self._select_profile() + except ValueError: + if self.translator: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('browser_profile.invalid_selection')}{Style.RESET_ALL}") + else: + print(f"{Fore.RED}{EMOJI['ERROR']} Invalid selection. Please try again.{Style.RESET_ALL}") + return self._select_profile() + else: + # No Local State file, use Default profile + print(f"{Fore.YELLOW}{EMOJI['WARNING']} {self.translator.get('browser_profile.no_profiles', browser=browser_type_display) if self.translator else f'No {browser_type_display} profiles found'}{Style.RESET_ALL}") + self.selected_profile = "Default" + return True + + except Exception as e: + # Error loading profiles, use Default profile + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('browser_profile.error_loading', error=str(e), browser=browser_type_display) if self.translator else f'Error loading {browser_type_display} profiles: {str(e)}'}{Style.RESET_ALL}") + self.selected_profile = "Default" + return True except Exception as e: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('chrome_profile.error_loading', error=str(e)) if self.translator else f'Error loading Chrome profiles: {e}'}{Style.RESET_ALL}") - return False - + # General error, use Default profile + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.profile_selection_error', error=str(e)) if self.translator else f'Error during profile selection: {str(e)}'}{Style.RESET_ALL}") + self.selected_profile = "Default" + return True + def setup_browser(self): """Setup browser for OAuth flow using selected profile""" try: @@ -107,11 +166,15 @@ class OAuthHandler: platform_name = platform.system().lower() print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.detected_platform', platform=platform_name) if self.translator else f'Detected platform: {platform_name}'}{Style.RESET_ALL}") + # 从配置中获取浏览器类型 + config = get_config(self.translator) + browser_type = config.get('Browser', 'default_browser', fallback='chrome') + # Get browser paths and user data directory user_data_dir = self._get_user_data_directory() - chrome_path = self._get_browser_path() + browser_path = self._get_browser_path() - if not chrome_path: + if not browser_path: raise Exception(f"{self.translator.get('oauth.no_compatible_browser_found') if self.translator else 'No compatible browser found. Please install Google Chrome or Chromium.'}\n{self.translator.get('oauth.supported_browsers', platform=platform_name)}\n" + "- Windows: Google Chrome, Chromium\n" + "- macOS: Google Chrome, Chromium\n" + @@ -119,8 +182,14 @@ class OAuthHandler: print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.found_browser_data_directory', path=user_data_dir) if self.translator else f'Found browser data directory: {user_data_dir}'}{Style.RESET_ALL}") - # Show warning about closing Chrome first - print(f"\n{Fore.YELLOW}{EMOJI['WARNING']} {self.translator.get('chrome_profile.warning_chrome_close') if self.translator else 'Warning: This will close all running Chrome processes'}{Style.RESET_ALL}") + # Show warning about closing browser first - 使用动态提示 + if self.translator: + warning_msg = self.translator.get('oauth.warning_browser_close', browser=browser_type) + else: + warning_msg = f'Warning: This will close all running {browser_type} processes' + + print(f"\n{Fore.YELLOW}{EMOJI['WARNING']} {warning_msg}{Style.RESET_ALL}") + choice = input(f"{Fore.YELLOW} {self.translator.get('menu.continue_prompt', choices='y/N')} {Style.RESET_ALL}").lower() if choice != 'y': print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('menu.operation_cancelled_by_user') if self.translator else 'Operation cancelled by user'}{Style.RESET_ALL}") @@ -135,9 +204,9 @@ class OAuthHandler: return False # Configure browser options - co = self._configure_browser_options(chrome_path, user_data_dir, self.selected_profile) + co = self._configure_browser_options(browser_path, user_data_dir, self.selected_profile) - print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.starting_browser', path=chrome_path) if self.translator else f'Starting browser at: {chrome_path}'}{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.starting_browser', path=browser_path) if self.translator else f'Starting browser at: {browser_path}'}{Style.RESET_ALL}") self.browser = ChromiumPage(co) # Verify browser launched successfully @@ -158,14 +227,56 @@ class OAuthHandler: return False def _kill_browser_processes(self): - """Kill existing browser processes based on platform""" + """Kill existing browser processes based on platform and browser type""" try: + # 从配置中获取浏览器类型 + config = get_config(self.translator) + browser_type = config.get('Browser', 'default_browser', fallback='chrome') + browser_type = browser_type.lower() + + # 根据浏览器类型和平台定义要关闭的进程 + browser_processes = { + 'chrome': { + 'win': ['chrome.exe', 'chromium.exe'], + 'linux': ['chrome', 'chromium', 'chromium-browser'], + 'mac': ['Chrome', 'Chromium'] + }, + 'brave': { + 'win': ['brave.exe'], + 'linux': ['brave', 'brave-browser'], + 'mac': ['Brave Browser'] + }, + 'edge': { + 'win': ['msedge.exe'], + 'linux': ['msedge'], + 'mac': ['Microsoft Edge'] + }, + 'firefox': { + 'win': ['firefox.exe'], + 'linux': ['firefox'], + 'mac': ['Firefox'] + } + } + + # 获取平台类型 + if os.name == 'nt': + platform_type = 'win' + elif sys.platform == 'darwin': + platform_type = 'mac' + else: + platform_type = 'linux' + + # 获取要关闭的进程列表 + processes = browser_processes.get(browser_type, browser_processes['chrome']).get(platform_type, []) + + if self.translator: + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.killing_browser_processes', browser=browser_type) if self.translator else f'Killing {browser_type} processes...'}{Style.RESET_ALL}") + + # 根据平台关闭进程 if os.name == 'nt': # Windows - processes = ['chrome.exe', 'chromium.exe'] for proc in processes: os.system(f'taskkill /f /im {proc} >nul 2>&1') else: # Linux/Mac - processes = ['chrome', 'chromium', 'chromium-browser'] for proc in processes: os.system(f'pkill -f {proc} >/dev/null 2>&1') @@ -174,95 +285,169 @@ class OAuthHandler: print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('oauth.warning_could_not_kill_existing_browser_processes', error=str(e)) if self.translator else f'Warning: Could not kill existing browser processes: {e}'}{Style.RESET_ALL}") def _get_user_data_directory(self): - """Get the appropriate user data directory based on platform""" + """Get the default user data directory based on browser type and platform""" try: + # 从配置中获取浏览器类型 + config = get_config(self.translator) + browser_type = config.get('Browser', 'default_browser', fallback='chrome') + browser_type = browser_type.lower() + + # 根据操作系统和浏览器类型获取用户数据目录 if os.name == 'nt': # Windows - possible_paths = [ - os.path.expandvars(r'%LOCALAPPDATA%\Google\Chrome\User Data'), - os.path.expandvars(r'%LOCALAPPDATA%\Chromium\User Data') - ] + user_data_dirs = { + 'chrome': os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Google', 'Chrome', 'User Data'), + 'brave': os.path.join(os.environ.get('LOCALAPPDATA', ''), 'BraveSoftware', 'Brave-Browser', 'User Data'), + 'edge': os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Microsoft', 'Edge', 'User Data'), + 'firefox': os.path.join(os.environ.get('APPDATA', ''), 'Mozilla', 'Firefox', 'Profiles') + } elif sys.platform == 'darwin': # macOS - possible_paths = [ - os.path.expanduser('~/Library/Application Support/Google/Chrome'), - os.path.expanduser('~/Library/Application Support/Chromium') - ] + user_data_dirs = { + 'chrome': os.path.expanduser('~/Library/Application Support/Google/Chrome'), + 'brave': os.path.expanduser('~/Library/Application Support/BraveSoftware/Brave-Browser'), + 'edge': os.path.expanduser('~/Library/Application Support/Microsoft Edge'), + 'firefox': os.path.expanduser('~/Library/Application Support/Firefox/Profiles') + } else: # Linux - possible_paths = [ - os.path.expanduser('~/.config/google-chrome'), - os.path.expanduser('~/.config/chromium'), - '/usr/bin/google-chrome', - '/usr/bin/chromium-browser' - ] + user_data_dirs = { + 'chrome': os.path.expanduser('~/.config/google-chrome'), + 'brave': os.path.expanduser('~/.config/BraveSoftware/Brave-Browser'), + 'edge': os.path.expanduser('~/.config/microsoft-edge'), + 'firefox': os.path.expanduser('~/.mozilla/firefox') + } - # Try each possible path - for path in possible_paths: - if os.path.exists(path): - return path + # 获取选定浏览器的用户数据目录,如果找不到则使用 Chrome 的 + user_data_dir = user_data_dirs.get(browser_type, user_data_dirs['chrome']) - # Create temporary profile if no existing profile found - temp_profile = os.path.join(os.path.expanduser('~'), '.cursor_temp_profile') - print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('oauth.creating_temporary_profile', path=temp_profile) if self.translator else f'Creating temporary profile at: {temp_profile}'}{Style.RESET_ALL}") - os.makedirs(temp_profile, exist_ok=True) - return temp_profile + if os.path.exists(user_data_dir): + return user_data_dir + else: + print(f"{Fore.YELLOW}{EMOJI['WARNING']} {self.translator.get('oauth.user_data_dir_not_found', browser=browser_type, path=user_data_dir) if self.translator else f'{browser_type} user data directory not found at {user_data_dir}, will try Chrome instead'}{Style.RESET_ALL}") + return user_data_dirs['chrome'] # 回退到 Chrome 目录 except Exception as e: print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.error_getting_user_data_directory', error=str(e)) if self.translator else f'Error getting user data directory: {e}'}{Style.RESET_ALL}") - raise + # 在出错时提供一个默认目录 + if os.name == 'nt': + return os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Google', 'Chrome', 'User Data') + elif sys.platform == 'darwin': + return os.path.expanduser('~/Library/Application Support/Google/Chrome') + else: + return os.path.expanduser('~/.config/google-chrome') def _get_browser_path(self): - """Get the browser executable path based on platform""" + """Get appropriate browser path based on platform and selected browser type""" try: - # Try default path first - chrome_path = get_default_chrome_path() - if chrome_path and os.path.exists(chrome_path): - return chrome_path + # 从配置中获取浏览器类型 + config = get_config(self.translator) + browser_type = config.get('Browser', 'default_browser', fallback='chrome') + browser_type = browser_type.lower() + + # 首先检查配置中是否有明确指定的浏览器路径 + browser_path = config.get('Browser', f'{browser_type}_path', fallback=None) + if browser_path and os.path.exists(browser_path): + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('oauth.using_configured_browser_path', browser=browser_type, path=browser_path) if self.translator else f'Using configured {browser_type} path: {browser_path}'}{Style.RESET_ALL}") + return browser_path + + # 尝试获取默认路径 + browser_path = get_default_browser_path(browser_type) + if browser_path and os.path.exists(browser_path): + return browser_path print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('oauth.searching_for_alternative_browser_installations') if self.translator else 'Searching for alternative browser installations...'}{Style.RESET_ALL}") - # Platform-specific paths + # 如果未找到配置中指定的浏览器,则尝试查找其他兼容浏览器 if os.name == 'nt': # Windows - alt_paths = [ - r'C:\Program Files\Google\Chrome\Application\chrome.exe', - r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe', - r'C:\Program Files\Chromium\Application\chrome.exe', - os.path.expandvars(r'%ProgramFiles%\Google\Chrome\Application\chrome.exe'), - os.path.expandvars(r'%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe') - ] + possible_paths = [] + if browser_type == 'brave': + possible_paths = [ + os.path.join(os.environ.get('PROGRAMFILES', ''), 'BraveSoftware', 'Brave-Browser', 'Application', 'brave.exe'), + os.path.join(os.environ.get('PROGRAMFILES(X86)', ''), 'BraveSoftware', 'Brave-Browser', 'Application', 'brave.exe'), + os.path.join(os.environ.get('LOCALAPPDATA', ''), 'BraveSoftware', 'Brave-Browser', 'Application', 'brave.exe') + ] + elif browser_type == 'edge': + possible_paths = [ + os.path.join(os.environ.get('PROGRAMFILES', ''), 'Microsoft', 'Edge', 'Application', 'msedge.exe'), + os.path.join(os.environ.get('PROGRAMFILES(X86)', ''), 'Microsoft', 'Edge', 'Application', 'msedge.exe') + ] + elif browser_type == 'firefox': + possible_paths = [ + os.path.join(os.environ.get('PROGRAMFILES', ''), 'Mozilla Firefox', 'firefox.exe'), + os.path.join(os.environ.get('PROGRAMFILES(X86)', ''), 'Mozilla Firefox', 'firefox.exe') + ] + else: # 默认为 Chrome + possible_paths = [ + os.path.join(os.environ.get('PROGRAMFILES', ''), 'Google', 'Chrome', 'Application', 'chrome.exe'), + os.path.join(os.environ.get('PROGRAMFILES(X86)', ''), 'Google', 'Chrome', 'Application', 'chrome.exe'), + os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Google', 'Chrome', 'Application', 'chrome.exe') + ] + elif sys.platform == 'darwin': # macOS - alt_paths = [ - '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', - '/Applications/Chromium.app/Contents/MacOS/Chromium', - '~/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', - '~/Applications/Chromium.app/Contents/MacOS/Chromium' - ] + possible_paths = [] + if browser_type == 'brave': + possible_paths = ['/Applications/Brave Browser.app/Contents/MacOS/Brave Browser'] + elif browser_type == 'edge': + possible_paths = ['/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge'] + elif browser_type == 'firefox': + possible_paths = ['/Applications/Firefox.app/Contents/MacOS/firefox'] + else: # 默认为 Chrome + possible_paths = ['/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'] + else: # Linux - alt_paths = [ - '/usr/bin/google-chrome', - '/usr/bin/chromium-browser', - '/usr/bin/chromium', - '/snap/bin/chromium', - '/usr/local/bin/chrome', - '/usr/local/bin/chromium' - ] + possible_paths = [] + if browser_type == 'brave': + possible_paths = ['/usr/bin/brave-browser', '/usr/bin/brave'] + elif browser_type == 'edge': + possible_paths = ['/usr/bin/microsoft-edge'] + elif browser_type == 'firefox': + possible_paths = ['/usr/bin/firefox'] + else: # 默认为 Chrome + possible_paths = ['/usr/bin/google-chrome', '/usr/bin/google-chrome-stable', '/usr/bin/chromium', '/usr/bin/chromium-browser'] + + # 检查每个可能的路径 + for path in possible_paths: + if os.path.exists(path): + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('oauth.found_browser_at', path=path) if self.translator else f'Found browser at: {path}'}{Style.RESET_ALL}") + return path - # Try each alternative path - for path in alt_paths: - expanded_path = os.path.expanduser(path) - if os.path.exists(expanded_path): - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('oauth.found_browser_at', path=expanded_path) if self.translator else f'Found browser at: {expanded_path}'}{Style.RESET_ALL}") - return expanded_path + # 如果找不到指定浏览器,则尝试使用Chrome + if browser_type != 'chrome': + print(f"{Fore.YELLOW}{EMOJI['WARNING']} {self.translator.get('oauth.browser_not_found_trying_chrome', browser=browser_type) if self.translator else f'Could not find {browser_type}, trying Chrome instead'}{Style.RESET_ALL}") + return self._get_chrome_path() return None except Exception as e: print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.error_finding_browser_path', error=str(e)) if self.translator else f'Error finding browser path: {e}'}{Style.RESET_ALL}") return None + + def _get_chrome_path(self): + """Fallback method to get Chrome path""" + try: + if os.name == 'nt': # Windows + possible_paths = [ + os.path.join(os.environ.get('PROGRAMFILES', ''), 'Google', 'Chrome', 'Application', 'chrome.exe'), + os.path.join(os.environ.get('PROGRAMFILES(X86)', ''), 'Google', 'Chrome', 'Application', 'chrome.exe'), + os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Google', 'Chrome', 'Application', 'chrome.exe') + ] + elif sys.platform == 'darwin': # macOS + possible_paths = ['/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'] + else: # Linux + possible_paths = ['/usr/bin/google-chrome', '/usr/bin/google-chrome-stable', '/usr/bin/chromium', '/usr/bin/chromium-browser'] + + for path in possible_paths: + if os.path.exists(path): + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('oauth.found_chrome_at', path=path) if self.translator else f'Found Chrome at: {path}'}{Style.RESET_ALL}") + return path + return None + except Exception as e: + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.error_finding_chrome_path', error=str(e)) if self.translator else f'Error finding Chrome path: {e}'}{Style.RESET_ALL}") + return None - def _configure_browser_options(self, chrome_path, user_data_dir, active_profile): + def _configure_browser_options(self, browser_path, user_data_dir, active_profile): """Configure browser options based on platform""" try: co = ChromiumOptions() - co.set_paths(browser_path=chrome_path, user_data_path=user_data_dir) + co.set_paths(browser_path=browser_path, user_data_path=user_data_dir) co.set_argument(f'--profile-directory={active_profile}') # Basic options @@ -420,7 +605,6 @@ class OAuthHandler: if check_usage_limits(usage_text): print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('oauth.account_has_reached_maximum_usage', deleting='deleting') if self.translator else 'Account has reached maximum usage, deleting...'}{Style.RESET_ALL}") - if self._delete_current_account(): print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.starting_new_authentication_process') if self.translator else 'Starting new authentication process...'}{Style.RESET_ALL}") if self.auth_type == "google": @@ -632,7 +816,6 @@ class OAuthHandler: if check_usage_limits(usage_text): print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('oauth.account_has_reached_maximum_usage', deleting='deleting') if self.translator else 'Account has reached maximum usage, deleting...'}{Style.RESET_ALL}") - if self._delete_current_account(): print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.starting_new_authentication_process') if self.translator else 'Starting new authentication process...'}{Style.RESET_ALL}") if self.auth_type == "google": @@ -691,19 +874,18 @@ class OAuthHandler: except: return False - if check_usage_limits(usage_text): - print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('oauth.account_has_reached_maximum_usage', deleting='deleting') if self.translator else 'Account has reached maximum usage, deleting...'}{Style.RESET_ALL}") - - if self._delete_current_account(): - print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.starting_new_authentication_process') if self.translator else 'Starting new authentication process...'}{Style.RESET_ALL}") - if self.auth_type == "google": - return self.handle_google_auth() - else: - return self.handle_github_auth() + if check_usage_limits(usage_text): + print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('oauth.account_has_reached_maximum_usage', deleting='deleting') if self.translator else 'Account has reached maximum usage, deleting...'}{Style.RESET_ALL}") + if self._delete_current_account(): + print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.starting_new_authentication_process') if self.translator else 'Starting new authentication process...'}{Style.RESET_ALL}") + if self.auth_type == "google": + return self.handle_google_auth() else: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.failed_to_delete_expired_account') if self.translator else 'Failed to delete expired account'}{Style.RESET_ALL}") + return self.handle_github_auth() else: - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('oauth.account_is_still_valid', usage=usage_text) if self.translator else f'Account is still valid (Usage: {usage_text})'}{Style.RESET_ALL}") + print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.failed_to_delete_expired_account') if self.translator else 'Failed to delete expired account'}{Style.RESET_ALL}") + else: + print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('oauth.account_is_still_valid', usage=usage_text) if self.translator else f'Account is still valid (Usage: {usage_text})'}{Style.RESET_ALL}") except Exception as e: print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('oauth.could_not_check_usage_count', error=str(e)) if self.translator else f'Could not check usage count: {str(e)}'}{Style.RESET_ALL}") diff --git a/utils.py b/utils.py index 5b3873e..fd823cb 100644 --- a/utils.py +++ b/utils.py @@ -9,24 +9,129 @@ def get_user_documents_path(): return os.path.expanduser("~\\Documents") else: return os.path.expanduser("~/Documents") - -def get_default_chrome_path(): - """Get default Chrome path""" - if sys.platform == "win32": - # Trying to find chrome in PATH - try: - import shutil - chrome_in_path = shutil.which("chrome") - if chrome_in_path: - return chrome_in_path - except: - pass - # Going to default path - return r"C:\Program Files\Google\Chrome\Application\chrome.exe" - elif sys.platform == "darwin": - return "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" + +def get_default_driver_path(browser_type='chrome'): + """Get default driver path based on browser type""" + browser_type = browser_type.lower() + if browser_type == 'chrome': + return get_default_chrome_driver_path() + elif browser_type == 'edge': + return get_default_edge_driver_path() + elif browser_type == 'firefox': + return get_default_firefox_driver_path() + elif browser_type == 'brave': + # Brave 使用 Chrome 的 driver + return get_default_chrome_driver_path() else: - return "/usr/bin/google-chrome" + # Default to Chrome if browser type is unknown + return get_default_chrome_driver_path() + +def get_default_chrome_driver_path(): + """Get default Chrome driver path""" + if sys.platform == "win32": + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "drivers", "chromedriver.exe") + elif sys.platform == "darwin": + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "drivers", "chromedriver") + else: + return "/usr/local/bin/chromedriver" + +def get_default_edge_driver_path(): + """Get default Edge driver path""" + if sys.platform == "win32": + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "drivers", "msedgedriver.exe") + elif sys.platform == "darwin": + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "drivers", "msedgedriver") + else: + return "/usr/local/bin/msedgedriver" + +def get_default_firefox_driver_path(): + """Get default Firefox driver path""" + if sys.platform == "win32": + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "drivers", "geckodriver.exe") + elif sys.platform == "darwin": + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "drivers", "geckodriver") + else: + return "/usr/local/bin/geckodriver" + +def get_default_brave_driver_path(): + """Get default Brave driver path (uses Chrome driver)""" + # Brave 浏览器基于 Chromium,所以使用相同的 chromedriver + return get_default_chrome_driver_path() + +def get_default_browser_path(browser_type='chrome'): + """Get default browser executable path""" + browser_type = browser_type.lower() + + if sys.platform == "win32": + if browser_type == 'chrome': + # 尝试在 PATH 中找到 Chrome + try: + import shutil + chrome_in_path = shutil.which("chrome") + if chrome_in_path: + return chrome_in_path + except: + pass + # 使用默认路径 + return r"C:\Program Files\Google\Chrome\Application\chrome.exe" + elif browser_type == 'edge': + return r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" + elif browser_type == 'firefox': + return r"C:\Program Files\Mozilla Firefox\firefox.exe" + elif browser_type == 'brave': + # Brave 浏览器的默认安装路径 + paths = [ + os.path.join(os.environ.get('PROGRAMFILES', ''), 'BraveSoftware/Brave-Browser/Application/brave.exe'), + os.path.join(os.environ.get('PROGRAMFILES(X86)', ''), 'BraveSoftware/Brave-Browser/Application/brave.exe'), + os.path.join(os.environ.get('LOCALAPPDATA', ''), 'BraveSoftware/Brave-Browser/Application/brave.exe') + ] + for path in paths: + if os.path.exists(path): + return path + return paths[0] # 返回第一个路径,即使它不存在 + + elif sys.platform == "darwin": + if browser_type == 'chrome': + return "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" + elif browser_type == 'edge': + return "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge" + elif browser_type == 'firefox': + return "/Applications/Firefox.app/Contents/MacOS/firefox" + elif browser_type == 'brave': + return "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser" + + else: # Linux + if browser_type == 'chrome': + # 尝试多种可能的名称 + chrome_names = ["google-chrome", "chrome", "chromium", "chromium-browser"] + for name in chrome_names: + try: + import shutil + path = shutil.which(name) + if path: + return path + except: + pass + return "/usr/bin/google-chrome" + elif browser_type == 'edge': + return "/usr/bin/microsoft-edge" + elif browser_type == 'firefox': + return "/usr/bin/firefox" + elif browser_type == 'brave': + # 尝试常见的 Brave 路径 + brave_names = ["brave", "brave-browser"] + for name in brave_names: + try: + import shutil + path = shutil.which(name) + if path: + return path + except: + pass + return "/usr/bin/brave-browser" + + # 如果找不到指定的浏览器类型,则返回 Chrome 的路径 + return get_default_browser_path('chrome') def get_linux_cursor_path(): """Get Linux Cursor path"""