mirror of
https://github.com/yeongpin/cursor-free-vip.git
synced 2025-08-02 20:47:35 +08:00
fix & optimize
This commit is contained in:
parent
887239d80c
commit
1cc93ffc22
@ -1,5 +0,0 @@
|
|||||||
fr.nf
|
|
||||||
yopmail.com
|
|
||||||
1s.fr
|
|
||||||
xl.cx
|
|
||||||
fr.cr
|
|
48
browser.py
48
browser.py
@ -32,11 +32,6 @@ class BrowserManager:
|
|||||||
extension_block_path = self.get_extension_block()
|
extension_block_path = self.get_extension_block()
|
||||||
co.add_extension(extension_block_path)
|
co.add_extension(extension_block_path)
|
||||||
co.set_argument("--allow-extensions-in-incognito")
|
co.set_argument("--allow-extensions-in-incognito")
|
||||||
|
|
||||||
extension_recaptcha_path = self.get_extension_recaptcha()
|
|
||||||
co.add_extension(extension_recaptcha_path)
|
|
||||||
co.set_argument("--allow-extensions-in-incognito")
|
|
||||||
|
|
||||||
except FileNotFoundError as e:
|
except FileNotFoundError as e:
|
||||||
logging.warning(f"警告: {e}")
|
logging.warning(f"警告: {e}")
|
||||||
|
|
||||||
@ -47,35 +42,6 @@ class BrowserManager:
|
|||||||
|
|
||||||
# 基本设置
|
# 基本设置
|
||||||
co.set_pref("credentials_enable_service", False)
|
co.set_pref("credentials_enable_service", False)
|
||||||
co.set_pref("profile.password_manager_enabled", False)
|
|
||||||
|
|
||||||
# 禁用自动化标志
|
|
||||||
co.set_pref("useAutomationExtension", False)
|
|
||||||
co.set_pref("excludeSwitches", ["enable-automation"])
|
|
||||||
|
|
||||||
# WebGL 和 GPU 设置
|
|
||||||
co.set_pref("webgl.disabled", False)
|
|
||||||
co.set_pref("webgl.enable_webgl2", True)
|
|
||||||
|
|
||||||
# 设置语言和地区
|
|
||||||
co.set_pref("intl.accept_languages", "en-US,en")
|
|
||||||
|
|
||||||
# 基本命令行参数
|
|
||||||
co.set_argument("--disable-blink-features=AutomationControlled")
|
|
||||||
co.set_argument("--hide-crash-restore-bubble")
|
|
||||||
co.set_argument("--no-first-run")
|
|
||||||
co.set_argument("--no-default-browser-check")
|
|
||||||
co.set_argument("--disable-popup-blocking")
|
|
||||||
|
|
||||||
# 性能和稳定性参数
|
|
||||||
co.set_argument("--disable-dev-shm-usage")
|
|
||||||
co.set_argument("--disable-gpu")
|
|
||||||
co.set_argument("--no-sandbox")
|
|
||||||
co.set_argument("--ignore-certificate-errors")
|
|
||||||
|
|
||||||
# WebGL 相关参数
|
|
||||||
co.set_argument("--use-gl=swiftshader")
|
|
||||||
co.set_argument("--enable-webgl")
|
|
||||||
|
|
||||||
# 随机端口
|
# 随机端口
|
||||||
co.auto_port()
|
co.auto_port()
|
||||||
@ -87,7 +53,6 @@ class BrowserManager:
|
|||||||
elif sys.platform == "win32": # Windows
|
elif sys.platform == "win32": # Windows
|
||||||
co.set_argument("--disable-software-rasterizer")
|
co.set_argument("--disable-software-rasterizer")
|
||||||
|
|
||||||
|
|
||||||
# 设置窗口大小
|
# 设置窗口大小
|
||||||
window_width = random.randint(1024, 1920)
|
window_width = random.randint(1024, 1920)
|
||||||
window_height = random.randint(768, 1080)
|
window_height = random.randint(768, 1080)
|
||||||
@ -121,19 +86,6 @@ class BrowserManager:
|
|||||||
|
|
||||||
return extension_path
|
return extension_path
|
||||||
|
|
||||||
def get_extension_recaptcha(self):
|
|
||||||
"""获取插件路径"""
|
|
||||||
root_dir = os.getcwd()
|
|
||||||
extension_path = os.path.join(root_dir, "recaptchaPatch")
|
|
||||||
|
|
||||||
if hasattr(sys, "_MEIPASS"):
|
|
||||||
extension_path = os.path.join(sys._MEIPASS, "recaptchaPatch")
|
|
||||||
|
|
||||||
if not os.path.exists(extension_path):
|
|
||||||
raise FileNotFoundError(f"插件不存在: {extension_path}")
|
|
||||||
|
|
||||||
return extension_path
|
|
||||||
|
|
||||||
def quit(self):
|
def quit(self):
|
||||||
"""关闭浏览器"""
|
"""关闭浏览器"""
|
||||||
if self.browser:
|
if self.browser:
|
||||||
|
@ -24,7 +24,6 @@ a = Analysis(
|
|||||||
binaries=[],
|
binaries=[],
|
||||||
datas=[
|
datas=[
|
||||||
('turnstilePatch', 'turnstilePatch'),
|
('turnstilePatch', 'turnstilePatch'),
|
||||||
('recaptchaPatch', 'recaptchaPatch'),
|
|
||||||
('uBlock0.chromium', 'uBlock0.chromium'),
|
('uBlock0.chromium', 'uBlock0.chromium'),
|
||||||
('locales', 'locales'),
|
('locales', 'locales'),
|
||||||
('cursor_auth.py', '.'),
|
('cursor_auth.py', '.'),
|
||||||
@ -32,8 +31,7 @@ a = Analysis(
|
|||||||
('cursor_register.py', '.'),
|
('cursor_register.py', '.'),
|
||||||
('browser.py', '.'),
|
('browser.py', '.'),
|
||||||
('control.py', '.'),
|
('control.py', '.'),
|
||||||
('.env', '.'),
|
('.env', '.')
|
||||||
('blacklist.txt', '.')
|
|
||||||
],
|
],
|
||||||
hiddenimports=[
|
hiddenimports=[
|
||||||
'cursor_auth',
|
'cursor_auth',
|
||||||
|
164
control.py
164
control.py
@ -59,96 +59,6 @@ class BrowserControl:
|
|||||||
"""获取当前标签页"""
|
"""获取当前标签页"""
|
||||||
return self.browser
|
return self.browser
|
||||||
|
|
||||||
def generate_new_email(self):
|
|
||||||
"""点击新的按钮生成新邮箱"""
|
|
||||||
try:
|
|
||||||
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.generate_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}{EMOJI['SUCCESS']} {self.translator.get('control.generate_email_success')}{Style.RESET_ALL}")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.generate_email_failed')}{Style.RESET_ALL}")
|
|
||||||
return False
|
|
||||||
except Exception as e:
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.browser_error', error=str(e))}{Style.RESET_ALL}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def select_email_domain(self, domain_index=None):
|
|
||||||
"""选择邮箱域名,如果不指定index则随机选择"""
|
|
||||||
try:
|
|
||||||
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.select_email_domain')}...{Style.RESET_ALL}")
|
|
||||||
|
|
||||||
# 读取黑名单域名
|
|
||||||
blacklist = []
|
|
||||||
try:
|
|
||||||
with open('blacklist.txt', 'r', encoding='utf-8') as f:
|
|
||||||
blacklist = [line.strip().lower() for line in f if line.strip()]
|
|
||||||
except FileNotFoundError:
|
|
||||||
# 如果文件不存在,创建一个包含已知黑名单域名的文件
|
|
||||||
with open('blacklist.txt', 'w', encoding='utf-8') as f:
|
|
||||||
f.write("fr.nf\nyopmail.com\n1s.fr\nfr.cr")
|
|
||||||
blacklist = ["fr.nf", "yopmail.com", "1s.fr", "fr.cr"]
|
|
||||||
|
|
||||||
# 找到下拉框
|
|
||||||
select_element = self.browser.ele('xpath://select[@id="seldom"]')
|
|
||||||
if select_element:
|
|
||||||
# 获取所有选项
|
|
||||||
all_options = []
|
|
||||||
new_options = self.browser.eles('xpath://select[@id="seldom"]/optgroup[@label="-- 新的 --"]/option')
|
|
||||||
other_options = self.browser.eles('xpath://select[@id="seldom"]/optgroup[@label="-- 其他 --"]/option')
|
|
||||||
all_options.extend(new_options)
|
|
||||||
all_options.extend(other_options)
|
|
||||||
|
|
||||||
if all_options:
|
|
||||||
max_attempts = 5
|
|
||||||
attempt = 0
|
|
||||||
|
|
||||||
while attempt < max_attempts:
|
|
||||||
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.lower()
|
|
||||||
|
|
||||||
# 检查域名是否在黑名单中
|
|
||||||
is_blacklisted = False
|
|
||||||
for blocked_domain in blacklist:
|
|
||||||
if blocked_domain in selected_domain:
|
|
||||||
print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('control.blocked_domain', domain=blocked_domain)}{Style.RESET_ALL}")
|
|
||||||
domain_index = None
|
|
||||||
attempt += 1
|
|
||||||
is_blacklisted = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if is_blacklisted:
|
|
||||||
continue
|
|
||||||
|
|
||||||
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.select_email_domain')}: {selected_domain}{Style.RESET_ALL}")
|
|
||||||
|
|
||||||
# 点击选择
|
|
||||||
all_options[domain_index].click()
|
|
||||||
time.sleep(1)
|
|
||||||
print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.select_email_domain_success')}{Style.RESET_ALL}")
|
|
||||||
return True
|
|
||||||
|
|
||||||
attempt += 1
|
|
||||||
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} 无法找到可用的域名{Style.RESET_ALL}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_available_domain_options', count=len(all_options))}{Style.RESET_ALL}")
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_domain_select_box')}{Style.RESET_ALL}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.select_email_domain_failed', error=str(e))}{Style.RESET_ALL}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def wait_for_page_load(self, seconds=2):
|
def wait_for_page_load(self, seconds=2):
|
||||||
"""等待页面加载"""
|
"""等待页面加载"""
|
||||||
time.sleep(seconds)
|
time.sleep(seconds)
|
||||||
@ -164,80 +74,6 @@ class BrowserControl:
|
|||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.browser_error', error=str(e))}{Style.RESET_ALL}")
|
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.browser_error', error=str(e))}{Style.RESET_ALL}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def copy_and_get_email(self):
|
|
||||||
"""获取邮箱地址"""
|
|
||||||
try:
|
|
||||||
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.generate_email')}...{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}{EMOJI['MAIL']} {self.translator.get('control.get_email_name')}: {email_name}{Style.RESET_ALL}")
|
|
||||||
else:
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_email_name_failed')}{Style.RESET_ALL}")
|
|
||||||
return None
|
|
||||||
except Exception as e:
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_email_name_failed', error=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}{EMOJI['MAIL']} {self.translator.get('control.get_email_address')}: {full_email}{Style.RESET_ALL}")
|
|
||||||
return full_email
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_email_address_failed', error=str(e))}{Style.RESET_ALL}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def view_mailbox(self):
|
|
||||||
"""点击查看邮箱按钮"""
|
|
||||||
try:
|
|
||||||
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.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}{EMOJI['SUCCESS']} {self.translator.get('control.enter_mailbox_success')}{Style.RESET_ALL}")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_view_mailbox_button')}{Style.RESET_ALL}")
|
|
||||||
return False
|
|
||||||
except Exception as e:
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.enter_mailbox_failed', error=str(e))}{Style.RESET_ALL}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def refresh_mailbox(self):
|
|
||||||
"""刷新邮箱获取最新信息"""
|
|
||||||
try:
|
|
||||||
print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.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}{EMOJI['SUCCESS']} {self.translator.get('control.refresh_mailbox_success')}{Style.RESET_ALL}")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_refresh_button')}{Style.RESET_ALL}")
|
|
||||||
return False
|
|
||||||
except Exception as e:
|
|
||||||
print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.refresh_mailbox_failed', error=str(e))}{Style.RESET_ALL}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def get_verification_code(self):
|
def get_verification_code(self):
|
||||||
"""从邮件中获取验证码"""
|
"""从邮件中获取验证码"""
|
||||||
try:
|
try:
|
||||||
|
@ -100,12 +100,11 @@ def setup_driver(translator=None):
|
|||||||
|
|
||||||
# 使用无痕模式
|
# 使用无痕模式
|
||||||
co.set_argument("--incognito")
|
co.set_argument("--incognito")
|
||||||
co.set_argument("--headless=new")
|
|
||||||
|
|
||||||
# 设置随机端口
|
# 设置随机端口
|
||||||
co.auto_port()
|
co.auto_port()
|
||||||
|
|
||||||
# 使用有头模式
|
# 使用有头模式(一定要设置为False,模擬人類操作)
|
||||||
co.headless(False)
|
co.headless(False)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
{
|
|
||||||
"manifest_version": 3,
|
|
||||||
"name": "Recaptcha Blocker",
|
|
||||||
"version": "1.0",
|
|
||||||
"description": "Blocks reCAPTCHA from loading",
|
|
||||||
"content_scripts": [
|
|
||||||
{
|
|
||||||
"matches": ["*://yopmail.com/zh/wm*"],
|
|
||||||
"js": ["script.js"],
|
|
||||||
"run_at": "document_start",
|
|
||||||
"all_frames": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"permissions": [
|
|
||||||
"webNavigation",
|
|
||||||
"activeTab"
|
|
||||||
],
|
|
||||||
"host_permissions": [
|
|
||||||
"*://yopmail.com/*",
|
|
||||||
"*://*.google.com/*"
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,123 +0,0 @@
|
|||||||
// Debug logging function
|
|
||||||
function log(message) {
|
|
||||||
console.log(`[reCAPTCHA Bypass] ${new Date().toISOString()}: ${message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to get element by selector
|
|
||||||
function qSelector(selector) {
|
|
||||||
return document.querySelector(selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constants
|
|
||||||
const MAX_ATTEMPTS = 1;
|
|
||||||
const SELECTORS = {
|
|
||||||
CHECK_BOX: ".recaptcha-checkbox-border",
|
|
||||||
AUDIO_BUTTON: "#recaptcha-audio-button",
|
|
||||||
PLAY_BUTTON: ".rc-audiochallenge-play-button .rc-button-default",
|
|
||||||
AUDIO_SOURCE: "#audio-source",
|
|
||||||
IMAGE_SELECT: "#rc-imageselect",
|
|
||||||
RESPONSE_FIELD: ".rc-audiochallenge-response-field",
|
|
||||||
AUDIO_ERROR_MESSAGE: ".rc-audiochallenge-error-message",
|
|
||||||
AUDIO_RESPONSE: "#audio-response",
|
|
||||||
RELOAD_BUTTON: "#recaptcha-reload-button",
|
|
||||||
RECAPTCHA_STATUS: "#recaptcha-accessible-status",
|
|
||||||
DOSCAPTCHA: ".rc-doscaptcha-body",
|
|
||||||
VERIFY_BUTTON: "#recaptcha-verify-button"
|
|
||||||
};
|
|
||||||
|
|
||||||
// Function to check if element is hidden
|
|
||||||
function isHidden(el) {
|
|
||||||
return (el.offsetParent === null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to handle the bypass process
|
|
||||||
async function bypassRecaptcha() {
|
|
||||||
try {
|
|
||||||
log('Starting bypass process...');
|
|
||||||
log('Waiting 3 seconds before starting...');
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
||||||
|
|
||||||
let solved = false;
|
|
||||||
let checkBoxClicked = false;
|
|
||||||
let requestCount = 0;
|
|
||||||
|
|
||||||
const recaptchaInitialStatus = qSelector(SELECTORS.RECAPTCHA_STATUS) ?
|
|
||||||
qSelector(SELECTORS.RECAPTCHA_STATUS).innerText : "";
|
|
||||||
|
|
||||||
log('Initial reCAPTCHA status: ' + recaptchaInitialStatus);
|
|
||||||
|
|
||||||
// Main bypass logic
|
|
||||||
try {
|
|
||||||
if (!checkBoxClicked && qSelector(SELECTORS.CHECK_BOX) &&
|
|
||||||
!isHidden(qSelector(SELECTORS.CHECK_BOX))) {
|
|
||||||
log('Clicking checkbox...');
|
|
||||||
qSelector(SELECTORS.CHECK_BOX).click();
|
|
||||||
checkBoxClicked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the captcha is solved
|
|
||||||
if (qSelector(SELECTORS.RECAPTCHA_STATUS) &&
|
|
||||||
(qSelector(SELECTORS.RECAPTCHA_STATUS).innerText != recaptchaInitialStatus)) {
|
|
||||||
solved = true;
|
|
||||||
log('SOLVED!');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestCount > MAX_ATTEMPTS) {
|
|
||||||
log('Attempted Max Retries. Stopping the solver');
|
|
||||||
solved = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop solving when Automated queries message is shown
|
|
||||||
if (qSelector(SELECTORS.DOSCAPTCHA) &&
|
|
||||||
qSelector(SELECTORS.DOSCAPTCHA).innerText.length > 0) {
|
|
||||||
log('Automated Queries Detected');
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
log(`Error in main bypass logic: ${err.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
log('Bypass process completed');
|
|
||||||
|
|
||||||
// If not solved, retry after delay
|
|
||||||
if (!solved && requestCount < MAX_ATTEMPTS) {
|
|
||||||
requestCount++;
|
|
||||||
log(`Retrying... Attempt ${requestCount} of ${MAX_ATTEMPTS}`);
|
|
||||||
setTimeout(bypassRecaptcha, 2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
log(`Bypass failed: ${e.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a MutationObserver to watch for reCAPTCHA elements
|
|
||||||
log('Setting up MutationObserver...');
|
|
||||||
const observer = new MutationObserver((mutations) => {
|
|
||||||
mutations.forEach((mutation) => {
|
|
||||||
mutation.addedNodes.forEach((node) => {
|
|
||||||
if (node.nodeType === 1 && // Element node
|
|
||||||
((node.tagName === 'SCRIPT' && node.src && node.src.includes('recaptcha')) ||
|
|
||||||
(node.tagName === 'IFRAME' && node.src && node.src.includes('recaptcha')))) {
|
|
||||||
log(`Detected new reCAPTCHA element: ${node.tagName} - ${node.src}`);
|
|
||||||
bypassRecaptcha();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Start observing
|
|
||||||
observer.observe(document, {
|
|
||||||
childList: true,
|
|
||||||
subtree: true
|
|
||||||
});
|
|
||||||
log('MutationObserver started');
|
|
||||||
|
|
||||||
// Run on page load
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
log('Document still loading, waiting for DOMContentLoaded');
|
|
||||||
document.addEventListener('DOMContentLoaded', bypassRecaptcha);
|
|
||||||
} else {
|
|
||||||
log('Document already loaded, starting bypass process');
|
|
||||||
bypassRecaptcha();
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user