diff --git a/channels.json b/channels.json deleted file mode 100644 index 983d9865..00000000 --- a/channels.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "altadefinizione01": "https://www.altadefinizione01.tel", - "altadefinizione01_link": "https://altadefinizione01.cam", - "altadefinizioneclick": "https://altadefinizione.style", - "animeforce": "https://ww1.animeforce.org", - "animeleggendari": "https://animepertutti.com", - "animesaturn": "https://animesaturn.com", - "animestream": "https://www.animeworld.it", - "animesubita": "http://www.animesubita.org", - "animetubeita": "http://www.animetubeita.com", - "animeunity": "https://www.animeunity.it", - "animeworld": "https://www.animeworld.cc", - "casacinema": "https://www.casacinema.biz", - "casacinemaInfo": "https://casacinema.kim", - "cb01anime": "https://www.cineblog01.ink", - "cinetecadibologna": "http://cinestore.cinetecadibologna.it", - "dreamsub": "https://dreamsub.stream", - "dsda": "https://www.dsda.press/", - "fastsubita": "https://fastsubita.com", - "filmgratis": "https://www.filmaltadefinizione.org", - "filmigratis": "https://filmigratis.org", - "filmpertutti": "https://www.filmpertutti.casa", - "filmsenzalimiticc": "https://www.filmsenzalimiti.monster", - "filmstreaming01": "https://filmstreaming01.com", - "guardarefilm": "https://www.guardarefilm.red", - "guardaserie_stream": "https://guardaserie.store", - "guardaserieclick": "https://www.guardaserie.media", - "ilgeniodellostreaming": "https://ilgeniodellostreaming.si", - "italiaserie": "https://italiaserie.org", - "mondoserietv": "https://mondoserietv.com", - "netfreex": "https://www.netfreex.pro", - "piratestreaming": "https://www.piratestreaming.gratis", - "polpotv": "https://polpo.tv", - "pufimovies": "https://pufimovies.com", - "raiplay": "https://www.raiplay.it", - "seriehd": "https://www.seriehd.watch", - "serietvonline": "https://serietvonline.icu", - "serietvsubita": "http://serietvsubita.xyz", - "serietvu": "https://www.serietvu.link", - "streamingaltadefinizione": "https://www.popcornstream.best", - "streamtime": "https://t.me/s/StreamTime", - "tantifilm": "https://www.tantifilm.eu", - "toonitalia": "https://toonitalia.org", - "vedohd": "https://vedohd.uno", - "vvvvid": "https://www.vvvvid.it" -} \ No newline at end of file diff --git a/core/httptools.py b/core/httptools.py index 89813eb9..163bc8d8 100755 --- a/core/httptools.py +++ b/core/httptools.py @@ -255,7 +255,8 @@ def downloadpage(url, **opt): domain = urlparse.urlparse(url).netloc CF = False if domain in ['www.guardaserie.media', 'casacinema.space', 'wstream.video', 'akvideo.stream', 'backin.net', - 'dreamsub.stream', 'altadefinizione-nuovo.link', 'ilgeniodellostreaming.si', 'www.piratestreaming.gratis']: + 'dreamsub.stream', 'altadefinizione-nuovo.link', 'ilgeniodellostreaming.si', 'www.piratestreaming.gratis', + 'altadefinizione.style']: from lib import cloudscraper session = cloudscraper.create_scraper() CF = True diff --git a/core/servertools.py b/core/servertools.py index 3720fba9..c343a286 100644 --- a/core/servertools.py +++ b/core/servertools.py @@ -775,7 +775,7 @@ def check_video_link(item, timeout=3): except: server_module = None logger.info("[check_video_link] No se puede importar el servidor! %s" % server) - return NK + return item, NK if hasattr(server_module, 'test_video_exists'): ant_timeout = httptools.HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT diff --git a/lib/cloudscraper/__init__.py b/lib/cloudscraper/__init__.py index f4e584e5..1b57f325 100644 --- a/lib/cloudscraper/__init__.py +++ b/lib/cloudscraper/__init__.py @@ -1,4 +1,6 @@ +# https://github.com/VeNoMouS/cloudscraper/tree/master import logging +import os import re import sys import ssl @@ -9,6 +11,14 @@ try: except ImportError: import copy_reg as copyreg +try: + from HTMLParser import HTMLParser +except ImportError: + if sys.version_info >= (3, 4): + import html + else: + from html.parser import HTMLParser + from copy import deepcopy from time import sleep from collections import OrderedDict @@ -31,13 +41,17 @@ except ImportError: pass try: - from urlparse import urlparse + from urlparse import urlparse, urljoin except ImportError: - from urllib.parse import urlparse + from urllib.parse import urlparse, urljoin + +# Add exceptions path +sys.path.append(os.path.join(os.path.dirname(__file__), 'exceptions')) +import cloudflare_exceptions # noqa: E402 # ------------------------------------------------------------------------------- # -__version__ = '1.2.19' +__version__ = '1.2.24' # ------------------------------------------------------------------------------- # @@ -91,6 +105,7 @@ class CloudScraper(Session): 'allow_brotli', True if 'brotli' in sys.modules.keys() else False ) + self.user_agent = User_Agent( allow_brotli=self.allow_brotli, browser=kwargs.pop('browser', None) @@ -107,13 +122,16 @@ class CloudScraper(Session): # Set a random User-Agent if no custom User-Agent has been set # ------------------------------------------------------------------------------- # self.headers = self.user_agent.headers + if not self.cipherSuite: + self.cipherSuite = self.user_agent.cipherSuite + + if isinstance(self.cipherSuite, list): + self.cipherSuite = ':'.join(self.cipherSuite) self.mount( 'https://', CipherSuiteAdapter( - cipherSuite=':'.join(self.user_agent.cipherSuite) - if not self.cipherSuite else ':'.join(self.cipherSuite) - if isinstance(self.cipherSuite, list) else self.cipherSuite + cipherSuite=self.cipherSuite ) ) @@ -138,6 +156,20 @@ class CloudScraper(Session): except ValueError as e: print("Debug Error: {}".format(getattr(e, 'message', e))) + # ------------------------------------------------------------------------------- # + # Unescape / decode html entities + # ------------------------------------------------------------------------------- # + + @staticmethod + def unescape(html_text): + if sys.version_info >= (3, 0): + if sys.version_info >= (3, 4): + return html.unescape(html_text) + + return HTMLParser().unescape(html_text) + + return HTMLParser().unescape(html_text) + # ------------------------------------------------------------------------------- # # Decode Brotli on older versions of urllib3 manually # ------------------------------------------------------------------------------- # @@ -186,7 +218,7 @@ class CloudScraper(Session): sys.tracebacklimit = 0 _ = self._solveDepthCnt self._solveDepthCnt = 0 - raise RuntimeError( + raise cloudflare_exceptions.Cloudflare_Loop_Protection( "!!Loop Protection!! We have tried to solve {} time(s) in a row.".format(_) ) @@ -269,7 +301,7 @@ class CloudScraper(Session): def is_Challenge_Request(self, resp): if self.is_Firewall_Blocked(resp): sys.tracebacklimit = 0 - raise RuntimeError('Cloudflare has blocked this request (Code 1020 Detected).') + raise cloudflare_exceptions.Cloudflare_Block('Cloudflare has blocked this request (Code 1020 Detected).') if self.is_reCaptcha_Challenge(resp) or self.is_IUAM_Challenge(resp): return True @@ -280,17 +312,18 @@ class CloudScraper(Session): # Try to solve cloudflare javascript challenge. # ------------------------------------------------------------------------------- # - @staticmethod - def IUAM_Challenge_Response(body, url, interpreter): + def IUAM_Challenge_Response(self, body, url, interpreter): try: challengeUUID = re.search( r'id="challenge-form" action="(?P\S+)"', body, re.M | re.DOTALL ).groupdict().get('challengeUUID', '') + payload = OrderedDict(re.findall(r'name="(r|jschl_vc|pass)"\svalue="(.*?)"', body)) + except AttributeError: sys.tracebacklimit = 0 - raise RuntimeError( + raise cloudflare_exceptions.Cloudflare_Error_IUAM( "Cloudflare IUAM detected, unfortunately we can't extract the parameters correctly." ) @@ -301,7 +334,7 @@ class CloudScraper(Session): interpreter ).solveChallenge(body, hostParsed.netloc) except Exception as e: - raise RuntimeError( + raise cloudflare_exceptions.Cloudflare_Error_IUAM( 'Unable to parse Cloudflare anti-bots page: {}'.format( getattr(e, 'message', e) ) @@ -311,7 +344,7 @@ class CloudScraper(Session): 'url': '{}://{}{}'.format( hostParsed.scheme, hostParsed.netloc, - challengeUUID + self.unescape(challengeUUID) ), 'data': payload } @@ -320,8 +353,7 @@ class CloudScraper(Session): # Try to solve the reCaptcha challenge via 3rd party. # ------------------------------------------------------------------------------- # - @staticmethod - def reCaptcha_Challenge_Response(provider, provider_params, body, url): + def reCaptcha_Challenge_Response(self, provider, provider_params, body, url): try: payload = re.search( r'(name="r"\svalue="(?P\S+)"|).*?challenge-form" action="(?P\S+)".*?' @@ -330,7 +362,7 @@ class CloudScraper(Session): ).groupdict() except (AttributeError): sys.tracebacklimit = 0 - raise RuntimeError( + raise cloudflare_exceptions.Cloudflare_Error_reCaptcha( "Cloudflare reCaptcha detected, unfortunately we can't extract the parameters correctly." ) @@ -339,7 +371,7 @@ class CloudScraper(Session): 'url': '{}://{}{}'.format( hostParsed.scheme, hostParsed.netloc, - payload.get('challengeUUID', '') + self.unescape(payload.get('challengeUUID', '')) ), 'data': OrderedDict([ ('r', payload.get('r', '')), @@ -377,7 +409,7 @@ class CloudScraper(Session): if not self.recaptcha or not isinstance(self.recaptcha, dict) or not self.recaptcha.get('provider'): sys.tracebacklimit = 0 - raise RuntimeError( + raise cloudflare_exceptions.Cloudflare_reCaptcha_Provider( "Cloudflare reCaptcha detected, unfortunately you haven't loaded an anti reCaptcha provider " "correctly via the 'recaptcha' parameter." ) @@ -413,7 +445,7 @@ class CloudScraper(Session): self.delay = delay except (AttributeError, ValueError): sys.tracebacklimit = 0 - raise RuntimeError("Cloudflare IUAM possibility malformed, issue extracing delay value.") + raise cloudflare_exceptions.Cloudflare_Error_IUAM("Cloudflare IUAM possibility malformed, issue extracing delay value.") sleep(self.delay) @@ -473,34 +505,25 @@ class CloudScraper(Session): return challengeSubmitResponse else: cloudflare_kwargs = deepcopy(kwargs) + cloudflare_kwargs['headers'] = updateAttr( + cloudflare_kwargs, + 'headers', + {'Referer': challengeSubmitResponse.url} + ) if not urlparse(challengeSubmitResponse.headers['Location']).netloc: - cloudflare_kwargs['headers'] = updateAttr( - cloudflare_kwargs, - 'headers', - {'Referer': '{}://{}'.format(urlParsed.scheme, urlParsed.netloc)} - ) - return self.request( - resp.request.method, - '{}://{}{}'.format( - urlParsed.scheme, - urlParsed.netloc, - challengeSubmitResponse.headers['Location'] - ), - **cloudflare_kwargs + redirect_location = urljoin( + challengeSubmitResponse.url, + challengeSubmitResponse.headers['Location'] ) else: - redirectParsed = urlparse(challengeSubmitResponse.headers['Location']) - cloudflare_kwargs['headers'] = updateAttr( - cloudflare_kwargs, - 'headers', - {'Referer': '{}://{}'.format(redirectParsed.scheme, redirectParsed.netloc)} - ) - return self.request( - resp.request.method, - challengeSubmitResponse.headers['Location'], - **cloudflare_kwargs - ) + redirect_location = challengeSubmitResponse.headers['Location'] + + return self.request( + resp.request.method, + redirect_location, + **cloudflare_kwargs + ) # ------------------------------------------------------------------------------- # # We shouldn't be here... @@ -561,7 +584,7 @@ class CloudScraper(Session): break else: sys.tracebacklimit = 0 - raise RuntimeError( + raise cloudflare_exceptions.Cloudflare_Error_IUAM( "Unable to find Cloudflare cookies. Does the site actually " "have Cloudflare IUAM (I'm Under Attack Mode) enabled?" ) diff --git a/lib/cloudscraper/reCaptcha/2captcha.py b/lib/cloudscraper/reCaptcha/2captcha.py index 0a486d3b..8a787d0e 100644 --- a/lib/cloudscraper/reCaptcha/2captcha.py +++ b/lib/cloudscraper/reCaptcha/2captcha.py @@ -1,13 +1,17 @@ from __future__ import absolute_import import requests +import reCaptcha_exceptions try: import polling except ImportError: import sys sys.tracebacklimit = 0 - raise RuntimeError("Please install the python module 'polling' via pip or download it from https://github.com/justiniso/polling/") + raise reCaptcha_exceptions.reCaptcha_Import_Error( + "Please install the python module 'polling' via pip or download it from " + "https://github.com/justiniso/polling/" + ) from . import reCaptcha @@ -24,7 +28,7 @@ class captchaSolver(reCaptcha): @staticmethod def checkErrorStatus(response, request_type): if response.status_code in [500, 502]: - raise RuntimeError('2Captcha: Server Side Error {}'.format(response.status_code)) + raise reCaptcha_exceptions.reCaptcha_Service_Unavailable('2Captcha: Server Side Error {}'.format(response.status_code)) errors = { 'in.php': { @@ -71,16 +75,23 @@ class captchaSolver(reCaptcha): } if response.json().get('status') is False and response.json().get('request') in errors.get(request_type): - raise RuntimeError('{} {}'.format(response.json().get('request'), errors.get(request_type).get(response.json().get('request')))) + raise reCaptcha_exceptions.reCaptcha_Error_From_API( + '{} {}'.format( + response.json().get('request'), + errors.get(request_type).get(response.json().get('request')) + ) + ) # ------------------------------------------------------------------------------- # def reportJob(self, jobID): if not jobID: - raise RuntimeError("2Captcha: Error bad job id to request reCaptcha.") + raise reCaptcha_exceptions.reCaptcha_Bad_Job_ID( + "2Captcha: Error bad job id to request reCaptcha." + ) def _checkRequest(response): - if response.status_code in [200, 303] and response.json().get('status') == 1: + if response.ok and response.json().get('status') == 1: return response self.checkErrorStatus(response, 'res.php') @@ -105,7 +116,9 @@ class captchaSolver(reCaptcha): if response: return True else: - raise RuntimeError("2Captcha: Error - Failed to report bad reCaptcha solve.") + raise reCaptcha_exceptions.reCaptcha_Report_Error( + "2Captcha: Error - Failed to report bad reCaptcha solve." + ) # ------------------------------------------------------------------------------- # @@ -114,7 +127,7 @@ class captchaSolver(reCaptcha): raise RuntimeError("2Captcha: Error bad job id to request reCaptcha.") def _checkRequest(response): - if response.status_code in [200, 303] and response.json().get('status') == 1: + if response.ok and response.json().get('status') == 1: return response self.checkErrorStatus(response, 'res.php') @@ -139,13 +152,15 @@ class captchaSolver(reCaptcha): if response: return response.json().get('request') else: - raise RuntimeError("2Captcha: Error failed to solve reCaptcha.") + raise reCaptcha_exceptions.reCaptcha_Timeout( + "2Captcha: Error failed to solve reCaptcha." + ) # ------------------------------------------------------------------------------- # def requestSolve(self, site_url, site_key): def _checkRequest(response): - if response.status_code in [200, 303] and response.json().get("status") == 1 and response.json().get('request'): + if response.ok and response.json().get("status") == 1 and response.json().get('request'): return response self.checkErrorStatus(response, 'in.php') @@ -173,7 +188,9 @@ class captchaSolver(reCaptcha): if response: return response.json().get('request') else: - raise RuntimeError('2Captcha: Error no job id was returned.') + raise reCaptcha_exceptions.reCaptcha_Bad_Job_ID( + '2Captcha: Error no job id was returned.' + ) # ------------------------------------------------------------------------------- # @@ -181,7 +198,9 @@ class captchaSolver(reCaptcha): jobID = None if not reCaptchaParams.get('api_key'): - raise ValueError("2Captcha: Missing api_key parameter.") + raise reCaptcha_exceptions.reCaptcha_Bad_Parameter( + "2Captcha: Missing api_key parameter." + ) self.api_key = reCaptchaParams.get('api_key') @@ -196,9 +215,13 @@ class captchaSolver(reCaptcha): if jobID: self.reportJob(jobID) except polling.TimeoutException: - raise RuntimeError("2Captcha: reCaptcha solve took to long and also failed reporting the job.") + raise reCaptcha_exceptions.reCaptcha_Timeout( + "2Captcha: reCaptcha solve took to long and also failed reporting the job the job id {}.".format(jobID) + ) - raise RuntimeError("2Captcha: reCaptcha solve took to long to execute, aborting.") + raise reCaptcha_exceptions.reCaptcha_Timeout( + "2Captcha: reCaptcha solve took to long to execute job id {}, aborting.".format(jobID) + ) # ------------------------------------------------------------------------------- # diff --git a/lib/cloudscraper/reCaptcha/anticaptcha.py b/lib/cloudscraper/reCaptcha/anticaptcha.py index d69a9172..15993f86 100644 --- a/lib/cloudscraper/reCaptcha/anticaptcha.py +++ b/lib/cloudscraper/reCaptcha/anticaptcha.py @@ -1,12 +1,16 @@ from __future__ import absolute_import import sys +import reCaptcha_exceptions try: from python_anticaptcha import AnticaptchaClient, NoCaptchaTaskProxylessTask except ImportError: sys.tracebacklimit = 0 - raise RuntimeError("Please install the python module 'python_anticaptcha' via pip or download it from https://github.com/ad-m/python-anticaptcha") + raise reCaptcha_exceptions.reCaptcha_Import_Error( + "Please install the python module 'python_anticaptcha' via pip or download it from " + "https://github.com/ad-m/python-anticaptcha" + ) from . import reCaptcha @@ -16,9 +20,11 @@ class captchaSolver(reCaptcha): def __init__(self): super(captchaSolver, self).__init__('anticaptcha') + # ------------------------------------------------------------------------------- # + def getCaptchaAnswer(self, site_url, site_key, reCaptchaParams): if not reCaptchaParams.get('api_key'): - raise ValueError("reCaptcha provider 'anticaptcha' was not provided an 'api_key' parameter.") + raise reCaptcha_exceptions.reCaptcha_Bad_Parameter("anticaptcha: Missing api_key parameter.") client = AnticaptchaClient(reCaptchaParams.get('api_key')) @@ -29,10 +35,14 @@ class captchaSolver(reCaptcha): if not hasattr(client, 'createTaskSmee'): sys.tracebacklimit = 0 - raise RuntimeError("Please upgrade 'python_anticaptcha' via pip or download it from https://github.com/ad-m/python-anticaptcha") + raise reCaptcha_exceptions.reCaptcha_Import_Error( + "Please upgrade 'python_anticaptcha' via pip or download it from https://github.com/ad-m/python-anticaptcha" + ) job = client.createTaskSmee(task) return job.get_solution_response() +# ------------------------------------------------------------------------------- # + captchaSolver() diff --git a/lib/cloudscraper/reCaptcha/deathbycaptcha.py b/lib/cloudscraper/reCaptcha/deathbycaptcha.py index 530c8739..dc0e4997 100644 --- a/lib/cloudscraper/reCaptcha/deathbycaptcha.py +++ b/lib/cloudscraper/reCaptcha/deathbycaptcha.py @@ -2,13 +2,17 @@ from __future__ import absolute_import import json import requests +import reCaptcha_exceptions try: import polling except ImportError: import sys sys.tracebacklimit = 0 - raise RuntimeError("Please install the python module 'polling' via pip or download it from https://github.com/justiniso/polling/") + raise reCaptcha_exceptions.reCaptcha_Import_Error( + "Please install the python module 'polling' via pip or download it from " + "https://github.com/justiniso/polling/" + ) from . import reCaptcha @@ -20,7 +24,7 @@ class captchaSolver(reCaptcha): self.host = 'http://api.dbcapi.me/api' self.session = requests.Session() - # ------------------------------------------------------------------------------- # + # ------------------------------------------------------------------------------- # @staticmethod def checkErrorStatus(response): @@ -34,21 +38,21 @@ class captchaSolver(reCaptcha): ) if response.status_code in errors: - raise RuntimeError(errors.get(response.status_code)) + raise reCaptcha_exceptions.reCaptcha_Service_Unavailable(errors.get(response.status_code)) - # ------------------------------------------------------------------------------- # + # ------------------------------------------------------------------------------- # def login(self, username, password): self.username = username self.password = password def _checkRequest(response): - if response.status_code == 200: + if response.ok: if response.json().get('is_banned'): - raise RuntimeError('DeathByCaptcha: Your account is banned.') + raise reCaptcha_exceptions.reCaptcha_Account_Error('DeathByCaptcha: Your account is banned.') if response.json().get('balanace') == 0: - raise RuntimeError('DeathByCaptcha: insufficient credits.') + raise reCaptcha_exceptions.reCaptcha_Account_Error('DeathByCaptcha: insufficient credits.') return response @@ -72,11 +76,13 @@ class captchaSolver(reCaptcha): self.debugRequest(response) - # ------------------------------------------------------------------------------- # + # ------------------------------------------------------------------------------- # def reportJob(self, jobID): if not jobID: - raise RuntimeError("DeathByCaptcha: Error bad job id to report failed reCaptcha.") + raise reCaptcha_exceptions.reCaptcha_Bad_Job_ID( + "DeathByCaptcha: Error bad job id to report failed reCaptcha." + ) def _checkRequest(response): if response.status_code == 200: @@ -103,16 +109,20 @@ class captchaSolver(reCaptcha): if response: return True else: - raise RuntimeError("DeathByCaptcha: Error report failed reCaptcha.") + raise reCaptcha_exceptions.reCaptcha_Report_Error( + "DeathByCaptcha: Error report failed reCaptcha." + ) - # ------------------------------------------------------------------------------- # + # ------------------------------------------------------------------------------- # def requestJob(self, jobID): if not jobID: - raise RuntimeError("DeathByCaptcha: Error bad job id to request reCaptcha.") + raise reCaptcha_exceptions.reCaptcha_Bad_Job_ID( + "DeathByCaptcha: Error bad job id to request reCaptcha." + ) def _checkRequest(response): - if response.status_code in [200, 303] and response.json().get('text'): + if response.ok and response.json().get('text'): return response self.checkErrorStatus(response) @@ -132,13 +142,15 @@ class captchaSolver(reCaptcha): if response: return response.json().get('text') else: - raise RuntimeError("DeathByCaptcha: Error failed to solve reCaptcha.") + raise reCaptcha_exceptions.reCaptcha_Timeout( + "DeathByCaptcha: Error failed to solve reCaptcha." + ) - # ------------------------------------------------------------------------------- # + # ------------------------------------------------------------------------------- # def requestSolve(self, site_url, site_key): def _checkRequest(response): - if response.status_code in [200, 303] and response.json().get("is_correct") and response.json().get('captcha'): + if response.ok and response.json().get("is_correct") and response.json().get('captcha'): return response self.checkErrorStatus(response) @@ -168,16 +180,20 @@ class captchaSolver(reCaptcha): if response: return response.json().get('captcha') else: - raise RuntimeError('DeathByCaptcha: Error no job id was returned.') + raise reCaptcha_exceptions.reCaptcha_Bad_Job_ID( + 'DeathByCaptcha: Error no job id was returned.' + ) - # ------------------------------------------------------------------------------- # + # ------------------------------------------------------------------------------- # def getCaptchaAnswer(self, site_url, site_key, reCaptchaParams): jobID = None for param in ['username', 'password']: if not reCaptchaParams.get(param): - raise ValueError("DeathByCaptcha: Missing '{}' parameter.".format(param)) + raise reCaptcha_exceptions.reCaptcha_Bad_Parameter( + "DeathByCaptcha: Missing '{}' parameter.".format(param) + ) setattr(self, param, reCaptchaParams.get(param)) if reCaptchaParams.get('proxy'): @@ -191,9 +207,13 @@ class captchaSolver(reCaptcha): if jobID: self.reportJob(jobID) except polling.TimeoutException: - raise RuntimeError("DeathByCaptcha: reCaptcha solve took to long and also failed reporting the job.") + raise reCaptcha_exceptions.reCaptcha_Timeout( + "DeathByCaptcha: reCaptcha solve took to long and also failed reporting the job id {}.".format(jobID) + ) - raise RuntimeError("DeathByCaptcha: reCaptcha solve took to long to execute, aborting.") + raise reCaptcha_exceptions.reCaptcha_Timeout( + "DeathByCaptcha: reCaptcha solve took to long to execute job id {}, aborting.".format(jobID) + ) # ------------------------------------------------------------------------------- # diff --git a/lib/cloudscraper/user_agent/__init__.py b/lib/cloudscraper/user_agent/__init__.py index ccd3cb4c..df47ca26 100644 --- a/lib/cloudscraper/user_agent/__init__.py +++ b/lib/cloudscraper/user_agent/__init__.py @@ -47,7 +47,7 @@ class User_Agent(): for browser in user_agents: for release in user_agents[browser]['releases']: for platform in ['mobile', 'desktop']: - if re.search(self.custom, ' '.join(user_agents[browser]['releases'][release]['User-Agent'][platform])): + if re.search(re.escape(self.custom), ' '.join(user_agents[browser]['releases'][release]['User-Agent'][platform])): self.browser = browser self.loadHeaders(user_agents, release) self.headers['User-Agent'] = self.custom @@ -74,10 +74,11 @@ class User_Agent(): sys.tracebacklimit = 0 raise RuntimeError("Sorry you can't have mobile and desktop disabled at the same time.") - user_agents = json.load( - open(os.path.join(os.path.dirname(__file__), 'browsers.json'), 'r'), - object_pairs_hook=OrderedDict - ) + with open(os.path.join(os.path.dirname(__file__), 'browsers.json'), 'r') as fp: + user_agents = json.load( + fp, + object_pairs_hook=OrderedDict + ) if self.custom: if not self.tryMatchCustom(user_agents): diff --git a/lib/cloudscraper/user_agent/browsers.json b/lib/cloudscraper/user_agent/browsers.json index d3c610bc..ef6d8591 100644 --- a/lib/cloudscraper/user_agent/browsers.json +++ b/lib/cloudscraper/user_agent/browsers.json @@ -13,9 +13,14 @@ "TLS_CHACHA20_POLY1305_SHA256", "ECDHE-ECDSA-AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256", + "ECDHE-ECDSA-AES256-GCM-SHA384", + "ECDHE-RSA-AES256-GCM-SHA384", "ECDHE-ECDSA-CHACHA20-POLY1305", + "ECDHE-RSA-CHACHA20-POLY1305", + "ECDHE-RSA-AES256-SHA", "AES128-GCM-SHA256", "AES256-GCM-SHA384", + "AES128-SHA", "AES256-SHA" ], "releases": { @@ -12814,10 +12819,15 @@ "ECDHE-ECDSA-AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256", "ECDHE-ECDSA-CHACHA20-POLY1305", + "ECDHE-RSA-CHACHA20-POLY1305", + "ECDHE-ECDSA-AES256-GCM-SHA384", + "ECDHE-RSA-AES256-GCM-SHA384", "ECDHE-ECDSA-AES256-SHA", "ECDHE-ECDSA-AES128-SHA", + "ECDHE-RSA-AES256-SHA", "DHE-RSA-AES128-SHA", "DHE-RSA-AES256-SHA", + "AES128-SHA", "AES256-SHA" ], "releases": {