Spaces:
Paused
Paused
| import time | |
| import json | |
| import logging | |
| import random | |
| import math | |
| from camoufox.sync_api import Camoufox | |
| logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') | |
| logger = logging.getLogger(__name__) | |
| class HumanMouseMovement: | |
| def bezier_curve(start, end, steps=50): | |
| points = [] | |
| control1 = ( | |
| start[0] + random.randint(-100, 100), | |
| start[1] + random.randint(-100, 100) | |
| ) | |
| control2 = ( | |
| end[0] + random.randint(-100, 100), | |
| end[1] + random.randint(-100, 100) | |
| ) | |
| for i in range(steps + 1): | |
| t = i / steps | |
| x = (1-t)**3 * start[0] + 3*(1-t)**2*t * control1[0] + 3*(1-t)*t**2 * control2[0] + t**3 * end[0] | |
| y = (1-t)**3 * start[1] + 3*(1-t)**2*t * control1[1] + 3*(1-t)*t**2 * control2[1] + t**3 * end[1] | |
| shake_x = random.uniform(-2, 2) | |
| shake_y = random.uniform(-2, 2) | |
| points.append((x + shake_x, y + shake_y)) | |
| return points | |
| def add_micro_movements(x, y): | |
| micro_x = x + random.uniform(-1, 1) | |
| micro_y = y + random.uniform(-1, 1) | |
| return micro_x, micro_y | |
| class HCaptchaSolver: | |
| def __init__(self): | |
| self.browser = None | |
| self.page = None | |
| self.context = None | |
| self.mouse_pos = {'x': 0, 'y': 0} | |
| def setup_browser(self): | |
| logger.info("Setting up Camoufox browser...") | |
| try: | |
| self.browser = Camoufox( | |
| headless=True, | |
| humanize=True | |
| ) | |
| self.context = self.browser.new_context( | |
| viewport={'width': 1920, 'height': 1080}, | |
| user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', | |
| locale='en-US', | |
| timezone_id='America/New_York' | |
| ) | |
| self.page = self.context.new_page() | |
| self.page.add_init_script(""" | |
| Object.defineProperty(navigator, 'webdriver', { | |
| get: () => undefined | |
| }); | |
| window.chrome = { | |
| runtime: {}, | |
| }; | |
| Object.defineProperty(navigator, 'plugins', { | |
| get: () => [1, 2, 3, 4, 5], | |
| }); | |
| """) | |
| logger.info("Camoufox browser setup complete") | |
| except Exception as e: | |
| logger.error(f"Browser setup failed: {e}") | |
| raise | |
| def human_mouse_move(self, target_x, target_y): | |
| start = (self.mouse_pos['x'], self.mouse_pos['y']) | |
| end = (target_x, target_y) | |
| points = HumanMouseMovement.bezier_curve(start, end, steps=random.randint(30, 60)) | |
| for x, y in points: | |
| micro_x, micro_y = HumanMouseMovement.add_micro_movements(x, y) | |
| self.page.mouse.move(micro_x, micro_y) | |
| time.sleep(random.uniform(0.001, 0.005)) | |
| self.mouse_pos = {'x': target_x, 'y': target_y} | |
| def human_click(self, selector=None, x=None, y=None): | |
| if selector: | |
| try: | |
| element = self.page.locator(selector) | |
| box = element.bounding_box() | |
| if box: | |
| click_x = box['x'] + box['width'] / 2 + random.uniform(-5, 5) | |
| click_y = box['y'] + box['height'] / 2 + random.uniform(-5, 5) | |
| else: | |
| return False | |
| except: | |
| return False | |
| else: | |
| click_x = x | |
| click_y = y | |
| self.human_mouse_move(click_x, click_y) | |
| time.sleep(random.uniform(0.05, 0.15)) | |
| for _ in range(random.randint(1, 3)): | |
| offset_x = random.uniform(-1, 1) | |
| offset_y = random.uniform(-1, 1) | |
| self.page.mouse.move(click_x + offset_x, click_y + offset_y) | |
| time.sleep(random.uniform(0.01, 0.03)) | |
| self.page.mouse.down() | |
| time.sleep(random.uniform(0.05, 0.12)) | |
| self.page.mouse.up() | |
| time.sleep(random.uniform(0.1, 0.3)) | |
| return True | |
| def open_page(self): | |
| logger.info("Opening bylo.ai...") | |
| self.page.goto("https://bylo.ai/features/sora-2", wait_until="networkidle", timeout=60000) | |
| time.sleep(random.uniform(2, 4)) | |
| def click_login_button(self): | |
| logger.info("Looking for login button...") | |
| try: | |
| self.page.wait_for_selector('button.flex.items-center.gap-3', timeout=10000) | |
| self.human_click('button.flex.items-center.gap-3') | |
| logger.info("Login button clicked") | |
| time.sleep(random.uniform(1.5, 2.5)) | |
| return True | |
| except Exception as e: | |
| logger.error(f"Error clicking login: {e}") | |
| return False | |
| def click_signup(self): | |
| logger.info("Looking for Sign Up...") | |
| try: | |
| self.page.wait_for_selector("text=Sign Up", timeout=10000) | |
| self.human_click("text=Sign Up") | |
| logger.info("Sign Up clicked") | |
| time.sleep(random.uniform(1.5, 2.5)) | |
| return True | |
| except Exception as e: | |
| logger.error(f"Error clicking signup: {e}") | |
| return False | |
| def fill_email(self, email): | |
| logger.info(f"Filling email: {email}") | |
| try: | |
| self.page.wait_for_selector('input[name="email"]', timeout=10000) | |
| email_input = self.page.locator('input[name="email"]') | |
| box = email_input.bounding_box() | |
| if box: | |
| click_x = box['x'] + box['width'] / 2 | |
| click_y = box['y'] + box['height'] / 2 | |
| self.human_mouse_move(click_x, click_y) | |
| self.page.mouse.click(click_x, click_y) | |
| time.sleep(random.uniform(0.3, 0.6)) | |
| for char in email: | |
| self.page.keyboard.type(char) | |
| time.sleep(random.uniform(0.08, 0.25)) | |
| logger.info("Email filled") | |
| time.sleep(random.uniform(0.5, 1)) | |
| return True | |
| except Exception as e: | |
| logger.error(f"Error filling email: {e}") | |
| return False | |
| def click_get_code(self): | |
| logger.info("Clicking Get Code...") | |
| try: | |
| self.page.wait_for_selector("text=Get Code", timeout=10000) | |
| self.human_click("text=Get Code") | |
| logger.info("Get Code clicked") | |
| time.sleep(random.uniform(2, 3)) | |
| return True | |
| except Exception as e: | |
| logger.error(f"Error clicking get code: {e}") | |
| return False | |
| def solve_hcaptcha(self): | |
| logger.info("="*60) | |
| logger.info("Starting hCaptcha solving process...") | |
| logger.info("="*60) | |
| try: | |
| time.sleep(3) | |
| logger.info("Looking for hCaptcha iframe...") | |
| frames = self.page.frames | |
| logger.info(f"Found {len(frames)} frames") | |
| hcaptcha_frame = None | |
| for frame in frames: | |
| try: | |
| frame_url = frame.url | |
| logger.info(f"Frame URL: {frame_url[:100] if frame_url else 'empty'}") | |
| if frame_url and 'hcaptcha.com/captcha' in frame_url: | |
| logger.info("Found hCaptcha checkbox frame!") | |
| hcaptcha_frame = frame | |
| break | |
| except: | |
| continue | |
| if not hcaptcha_frame: | |
| logger.warning("hCaptcha frame not found, waiting...") | |
| for i in range(5): | |
| logger.info(f"Waiting for hCaptcha to load... attempt {i+1}/5") | |
| time.sleep(2) | |
| frames = self.page.frames | |
| for frame in frames: | |
| try: | |
| if frame.url and 'hcaptcha.com/captcha' in frame.url: | |
| hcaptcha_frame = frame | |
| break | |
| except: | |
| continue | |
| if hcaptcha_frame: | |
| break | |
| if hcaptcha_frame: | |
| logger.info("Attempting to click hCaptcha checkbox...") | |
| try: | |
| checkbox = hcaptcha_frame.locator('#checkbox') | |
| checkbox.wait_for(timeout=5000) | |
| box = checkbox.bounding_box() | |
| if box: | |
| click_x = box['x'] + box['width'] / 2 + random.uniform(-3, 3) | |
| click_y = box['y'] + box['height'] / 2 + random.uniform(-3, 3) | |
| self.human_mouse_move(click_x, click_y) | |
| time.sleep(random.uniform(0.5, 1)) | |
| for _ in range(random.randint(2, 4)): | |
| micro_x = click_x + random.uniform(-2, 2) | |
| micro_y = click_y + random.uniform(-2, 2) | |
| self.page.mouse.move(micro_x, micro_y) | |
| time.sleep(random.uniform(0.02, 0.05)) | |
| self.page.mouse.down() | |
| time.sleep(random.uniform(0.08, 0.15)) | |
| self.page.mouse.up() | |
| logger.info("Checkbox clicked!") | |
| time.sleep(random.uniform(2, 4)) | |
| except Exception as e: | |
| logger.error(f"Error clicking checkbox: {e}") | |
| logger.info("Waiting for hCaptcha token...") | |
| for attempt in range(40): | |
| token = self.get_hcaptcha_token() | |
| if token: | |
| return token | |
| time.sleep(1) | |
| if attempt % 5 == 0: | |
| logger.info(f"Still waiting for token... {attempt}s") | |
| logger.warning("Token not found after waiting") | |
| return None | |
| except Exception as e: | |
| logger.error(f"Error solving hCaptcha: {e}") | |
| return None | |
| def get_hcaptcha_token(self): | |
| try: | |
| token = self.page.evaluate(""" | |
| () => { | |
| const elements = [ | |
| document.querySelector('textarea[name="h-captcha-response"]'), | |
| document.querySelector('[data-hcaptcha-response]'), | |
| document.querySelector('input[name="h-captcha-response"]') | |
| ]; | |
| for (let el of elements) { | |
| if (el && el.value && el.value.length > 10) { | |
| return el.value; | |
| } | |
| if (el && el.getAttribute('data-hcaptcha-response')) { | |
| return el.getAttribute('data-hcaptcha-response'); | |
| } | |
| } | |
| return null; | |
| } | |
| """) | |
| if token and len(token) > 10: | |
| logger.info("="*60) | |
| logger.info("TOKEN FOUND!") | |
| logger.info(f"Token: {token[:50]}...") | |
| logger.info(f"Length: {len(token)}") | |
| logger.info("="*60) | |
| return token | |
| except Exception as e: | |
| pass | |
| return None | |
| def run(self, email="herzfnf@gmail.com"): | |
| try: | |
| self.setup_browser() | |
| self.open_page() | |
| if not self.click_login_button(): | |
| raise Exception("Failed to click login button") | |
| if not self.click_signup(): | |
| raise Exception("Failed to click signup") | |
| if not self.fill_email(email): | |
| raise Exception("Failed to fill email") | |
| if not self.click_get_code(): | |
| raise Exception("Failed to click get code") | |
| token = self.solve_hcaptcha() | |
| if token: | |
| logger.info("SUCCESS! Token retrieved") | |
| return { | |
| "success": True, | |
| "token": token, | |
| "email": email | |
| } | |
| else: | |
| logger.warning("Failed to get token") | |
| return { | |
| "success": False, | |
| "message": "Failed to get hCaptcha token" | |
| } | |
| except Exception as e: | |
| logger.error(f"Error: {e}") | |
| return { | |
| "success": False, | |
| "error": str(e) | |
| } | |
| finally: | |
| self.cleanup() | |
| def cleanup(self): | |
| try: | |
| if self.page: | |
| self.page.close() | |
| if self.context: | |
| self.context.close() | |
| if self.browser: | |
| self.browser.close() | |
| logger.info("Browser closed") | |
| except: | |
| pass | |
| if __name__ == "__main__": | |
| solver = HCaptchaSolver() | |
| result = solver.run("herzfnf@gmail.com") | |
| print("\n" + "="*60) | |
| print("FINAL RESULT:") | |
| print(json.dumps(result, indent=2)) | |
| print("="*60) |