diff --git a/tests/test_undetected_browser.py b/tests/test_undetected_browser.py new file mode 100644 index 0000000..1d8398b --- /dev/null +++ b/tests/test_undetected_browser.py @@ -0,0 +1,14 @@ +from selenium.webdriver.common.by import By +from yadc.undetected_browser import ManualBusterUndetectedBrowser + + +def test_manual_buster_undetected_browser(tmp_path): + br = ManualBusterUndetectedBrowser( + buster=True, profile_dir=(tmp_path) / "blank-profile" + ) + unique_url = ( + "chrome-extension://mpbjkejclgfgadiemmefgebjfooflfhl/src/options/index.html" + ) + with br as driver: + driver.get(unique_url) + assert "Buster" in driver.page_source diff --git a/yadc/undetected_browser.py b/yadc/undetected_browser.py index 0b23bbe..2d2564d 100644 --- a/yadc/undetected_browser.py +++ b/yadc/undetected_browser.py @@ -1,8 +1,10 @@ """Browser and CaptchaChrome objects based around `undetected_chromedriver`.""" from pathlib import Path -from .browser import CaptchaChromeBase, Browser, TorBrowser, BrowserError -import undetected_chromedriver as us +import undetected_chromedriver as uc +from selenium.webdriver.common.by import By + +from .browser import Browser, BrowserError, CaptchaChromeBase, TorBrowser class UndetectedCaptchaChrome(CaptchaChromeBase, uc.Chrome): @@ -16,7 +18,7 @@ def launch_chrome(self): pass def _connect(self, *args, chrome_options: uc.ChromeOptions = None): - chrome_options = ChromeOptions or uc.ChromeOptions() + chrome_options = chrome_options or uc.ChromeOptions() if self._buster: chrome_options.add_argument(self.buster_arg) @@ -32,7 +34,7 @@ def tor_arg(self): return f'--proxy-server="socks4://localhost:{self.tor_port}"' def _connect(self, *args, chrome_options: uc.ChromeOptions = None): - chrome_options = ChromeOptions or uc.ChromeOptions() + chrome_options = chrome_options or uc.ChromeOptions() chrome_options.add_argument(self.tor_arg) return super()._connect(*args, chrome_options=chrome_options) @@ -41,10 +43,19 @@ class ManualBusterMixin: BUSTER_URL = "https://chrome.google.com/webstore/detail/buster-captcha-solver-for/mpbjkejclgfgadiemmefgebjfooflfhl?hl=en" PROFILE_DIR = "blank-profile" + def __init__(self, *args, profile_dir: Path = None, **kwargs): + buster = kwargs.get("buster", None) + if buster: + del kwargs["buster"] + super().__init__(*args, **kwargs) + if buster: + self._buster = buster + self.profile_dir = profile_dir or self.PROFILE_DIR + def generate_profile(self): """Generate a profile and then install buster manually.""" chrome_options = uc.ChromeOptions() - chrome_options.user_data_dir = "blank-profile" + chrome_options.user_data_dir = self.profile_dir driver = UndetectedCaptchaChrome(options=chrome_options) driver.get(self.BUSTER_URL) driver.find_element(By.XPATH, "//*[text()='I agree']").click() @@ -52,11 +63,13 @@ def generate_profile(self): By.CSS_SELECTOR, ".g-c-R.webstore-test-button-label" ).click() input("Accept installation and press enter: ") + driver.close() del driver def _connect(self, *args, chrome_options: uc.ChromeOptions = None): + chrome_options = chrome_options or uc.ChromeOptions() if self._buster: - profile_dir = Path(self.PROFILE_DIR) + profile_dir = Path(self.profile_dir) if not profile_dir.is_dir(): if profile_dir.exists(): raise BrowserError( @@ -65,7 +78,7 @@ def _connect(self, *args, chrome_options: uc.ChromeOptions = None): self.generate_profile() chrome_options.user_data_dir = self.PROFILE_DIR self._buster = None - return super()._connext(*args, chrome_options=chrome_options) + return super()._connect(*args, chrome_options=chrome_options) class ManualBusterUndetectedBrowser(ManualBusterMixin, UndetectedBrowser):