diff --git a/src/flaresolverr_service.py b/src/flaresolverr_service.py index b3a0d2a..395ae65 100644 --- a/src/flaresolverr_service.py +++ b/src/flaresolverr_service.py @@ -13,7 +13,10 @@ from dtos import V1RequestBase, V1ResponseBase, ChallengeResolutionT, ChallengeR HealthResponse, STATUS_OK, STATUS_ERROR import utils - +ACCESS_DENIED_SELECTORS = [ + # Cloudflare + 'div.main-wrapper div.header.section h1 span.code-label span' +] CHALLENGE_SELECTORS = [ # Cloudflare '#cf-challenge-running', '.ray_id', '.attack-box', '#cf-please-wait', '#trk_jschal_js', @@ -62,7 +65,7 @@ def controller_v1_endpoint(req: V1RequestBase) -> V1ResponseBase: res.startTimestamp = start_ts res.endTimestamp = int(time.time() * 1000) res.version = utils.get_flaresolverr_version() - logging.debug(f"Response => POST /v1 body: {utils.object_to_dict(res.solution)}") + logging.debug(f"Response => POST /v1 body: {utils.object_to_dict(res)}") logging.info(f"Response in {(res.endTimestamp - res.startTimestamp) / 1000} s") return res @@ -163,8 +166,17 @@ def _evil_logic(req: V1RequestBase, driver: WebDriver, method: str) -> Challenge if utils.get_config_log_html(): logging.debug(f"Response HTML:\n{driver.page_source}") - # find challenge selectors + # wait for the page html_element = driver.find_element(By.TAG_NAME, "html") + + # find access denied selectors + for selector in ACCESS_DENIED_SELECTORS: + found_elements = driver.find_elements(By.CSS_SELECTOR, selector) + if len(found_elements) > 0: + raise Exception('Cloudflare has blocked this request. ' + 'Probably your IP is banned for this site, check in your web browser.') + + # find challenge selectors challenge_found = False for selector in CHALLENGE_SELECTORS: found_elements = driver.find_elements(By.CSS_SELECTOR, selector) @@ -199,8 +211,10 @@ def _evil_logic(req: V1RequestBase, driver: WebDriver, method: str) -> Challenge logging.debug("Timeout waiting for redirect") logging.info("Challenge solved!") + res.message = "Challenge solved!" else: logging.info("Challenge not detected!") + res.message = "Challenge not detected!" challenge_res = ChallengeResolutionResultT({}) challenge_res.url = driver.current_url diff --git a/src/tests.py b/src/tests.py index 071e4dc..b0347a6 100644 --- a/src/tests.py +++ b/src/tests.py @@ -25,6 +25,7 @@ class TestFlareSolverr(unittest.TestCase): cloudflare_url_2 = "https://idope.se/torrent-list/harry/" ddos_guard_url = "https://anidex.info/" custom_cloudflare_url = "https://www.muziekfabriek.org" + cloudflare_blocked_url = "https://avistaz.to/api/v1/jackett/torrents?in=1&type=0&search=" app = TestApp(flaresolverr.app) @@ -75,7 +76,7 @@ class TestFlareSolverr(unittest.TestCase): body = V1ResponseBase(res.json) self.assertEqual(STATUS_OK, body.status) - self.assertEqual("", body.message) + self.assertEqual("Challenge not detected!", body.message) self.assertGreater(body.startTimestamp, 10000) self.assertGreaterEqual(body.endTimestamp, body.startTimestamp) self.assertEqual(utils.get_flaresolverr_version(), body.version) @@ -97,7 +98,7 @@ class TestFlareSolverr(unittest.TestCase): body = V1ResponseBase(res.json) self.assertEqual(STATUS_OK, body.status) - self.assertEqual("", body.message) + self.assertEqual("Challenge solved!", body.message) self.assertGreater(body.startTimestamp, 10000) self.assertGreaterEqual(body.endTimestamp, body.startTimestamp) self.assertEqual(utils.get_flaresolverr_version(), body.version) @@ -123,7 +124,7 @@ class TestFlareSolverr(unittest.TestCase): body = V1ResponseBase(res.json) self.assertEqual(STATUS_OK, body.status) - self.assertEqual("", body.message) + self.assertEqual("Challenge solved!", body.message) self.assertGreater(body.startTimestamp, 10000) self.assertGreaterEqual(body.endTimestamp, body.startTimestamp) self.assertEqual(utils.get_flaresolverr_version(), body.version) @@ -149,7 +150,7 @@ class TestFlareSolverr(unittest.TestCase): body = V1ResponseBase(res.json) self.assertEqual(STATUS_OK, body.status) - self.assertEqual("", body.message) + self.assertEqual("Challenge solved!", body.message) self.assertGreater(body.startTimestamp, 10000) self.assertGreaterEqual(body.endTimestamp, body.startTimestamp) self.assertEqual(utils.get_flaresolverr_version(), body.version) @@ -175,7 +176,7 @@ class TestFlareSolverr(unittest.TestCase): body = V1ResponseBase(res.json) self.assertEqual(STATUS_OK, body.status) - self.assertEqual("", body.message) + self.assertEqual("Challenge solved!", body.message) self.assertGreater(body.startTimestamp, 10000) self.assertGreaterEqual(body.endTimestamp, body.startTimestamp) self.assertEqual(utils.get_flaresolverr_version(), body.version) @@ -193,7 +194,22 @@ class TestFlareSolverr(unittest.TestCase): self.assertGreater(len(cf_cookie["value"]), 10) # todo: test Cmd 'request.get' should return fail with Cloudflare CAPTCHA - # todo: test Cmd 'request.get' should return fail with Cloudflare Blocked + + def test_v1_endpoint_request_get_cloudflare_blocked(self): + res = self.app.post_json('/v1', { + "cmd": "request.get", + "url": self.cloudflare_blocked_url + }, status=500) + self.assertEqual(res.status_code, 500) + + body = V1ResponseBase(res.json) + self.assertEqual(STATUS_ERROR, body.status) + self.assertEqual("Error: Error solving the challenge. Cloudflare has blocked this request. " + "Probably your IP is banned for this site, check in your web browser.", body.message) + self.assertGreater(body.startTimestamp, 10000) + self.assertGreaterEqual(body.endTimestamp, body.startTimestamp) + self.assertEqual(utils.get_flaresolverr_version(), body.version) + # todo: test Cmd 'request.get' should return OK with 'cookies' param def test_v1_endpoint_request_get_returnOnlyCookies_param(self): @@ -206,7 +222,7 @@ class TestFlareSolverr(unittest.TestCase): body = V1ResponseBase(res.json) self.assertEqual(STATUS_OK, body.status) - self.assertEqual("", body.message) + self.assertEqual("Challenge not detected!", body.message) self.assertGreater(body.startTimestamp, 10000) self.assertGreaterEqual(body.endTimestamp, body.startTimestamp) self.assertEqual(utils.get_flaresolverr_version(), body.version) @@ -260,7 +276,7 @@ class TestFlareSolverr(unittest.TestCase): body = V1ResponseBase(res.json) self.assertEqual(STATUS_OK, body.status) - self.assertEqual("", body.message) + self.assertEqual("Challenge not detected!", body.message) def test_v1_endpoint_request_post_no_cloudflare(self): res = self.app.post_json('/v1', { @@ -272,7 +288,7 @@ class TestFlareSolverr(unittest.TestCase): body = V1ResponseBase(res.json) self.assertEqual(STATUS_OK, body.status) - self.assertEqual("", body.message) + self.assertEqual("Challenge not detected!", body.message) self.assertGreater(body.startTimestamp, 10000) self.assertGreaterEqual(body.endTimestamp, body.startTimestamp) self.assertEqual(utils.get_flaresolverr_version(), body.version) @@ -307,7 +323,7 @@ class TestFlareSolverr(unittest.TestCase): body = V1ResponseBase(res.json) self.assertEqual(STATUS_OK, body.status) - self.assertEqual("", body.message) + self.assertEqual("Challenge solved!", body.message) self.assertGreater(body.startTimestamp, 10000) self.assertGreaterEqual(body.endTimestamp, body.startTimestamp) self.assertEqual(utils.get_flaresolverr_version(), body.version) @@ -346,7 +362,7 @@ class TestFlareSolverr(unittest.TestCase): body = V1ResponseBase(res.json) self.assertEqual(STATUS_OK, body.status) - self.assertEqual("", body.message) + self.assertEqual("Challenge not detected!", body.message) # todo: test Cmd 'sessions.create' should return OK # todo: test Cmd 'sessions.create' should return OK with session diff --git a/src/utils.py b/src/utils.py index 6dddc67..9ba1f7e 100644 --- a/src/utils.py +++ b/src/utils.py @@ -94,4 +94,6 @@ def get_user_agent(driver=None) -> str: def object_to_dict(_object): - return json.loads(json.dumps(_object, default=lambda o: o.__dict__)) + json_dict = json.loads(json.dumps(_object, default=lambda o: o.__dict__)) + # remove hidden fields + return {k: v for k, v in json_dict.items() if not k.startswith('__')}