from __future__ import absolute_import import re import requests try: import polling except ImportError: raise ImportError( "Please install the python module 'polling' via pip or download it from " "https://github.com/justiniso/polling/" ) from ..exceptions import ( reCaptchaServiceUnavailable, reCaptchaAPIError, reCaptchaTimeout, reCaptchaParameter, reCaptchaBadJobID ) from . import reCaptcha class captchaSolver(reCaptcha): def __init__(self): super(captchaSolver, self).__init__('9kw') self.host = 'https://www.9kw.eu/index.cgi' self.maxtimeout = 180 self.session = requests.Session() # ------------------------------------------------------------------------------- # @staticmethod def checkErrorStatus(response): if response.status_code in [500, 502]: raise reCaptchaServiceUnavailable( f'9kw: Server Side Error {response.status_code}' ) error_codes = { 1: 'No API Key available.', 2: 'No API key found.', 3: 'No active API key found.', 4: 'API Key has been disabled by the operator. ', 5: 'No user found.', 6: 'No data found.', 7: 'Found No ID.', 8: 'found No captcha.', 9: 'No image found.', 10: 'Image size not allowed.', 11: 'credit is not sufficient.', 12: 'what was done.', 13: 'No answer contain.', 14: 'Captcha already been answered.', 15: 'Captcha to quickly filed.', 16: 'JD check active.', 17: 'Unknown problem.', 18: 'Found No ID.', 19: 'Incorrect answer.', 20: 'Do not timely filed (Incorrect UserID).', 21: 'Link not allowed.', 22: 'Prohibited submit.', 23: 'Entering prohibited.', 24: 'Too little credit.', 25: 'No entry found.', 26: 'No Conditions accepted.', 27: 'No coupon code found in the database.', 28: 'Already unused voucher code.', 29: 'maxTimeout under 60 seconds.', 30: 'User not found.', 31: 'An account is not yet 24 hours in system.', 32: 'An account does not have the full rights.', 33: 'Plugin needed a update.', 34: 'No HTTPS allowed.', 35: 'No HTTP allowed.', 36: 'Source not allowed.', 37: 'Transfer denied.', 38: 'Incorrect answer without space', 39: 'Incorrect answer with space', 40: 'Incorrect answer with not only numbers', 41: 'Incorrect answer with not only A-Z, a-z', 42: 'Incorrect answer with not only 0-9, A-Z, a-z', 43: 'Incorrect answer with not only [0-9,- ]', 44: 'Incorrect answer with not only [0-9A-Za-z,- ]', 45: 'Incorrect answer with not only coordinates', 46: 'Incorrect answer with not only multiple coordinates', 47: 'Incorrect answer with not only data', 48: 'Incorrect answer with not only rotate number', 49: 'Incorrect answer with not only text', 50: 'Incorrect answer with not only text and too short', 51: 'Incorrect answer with not enough chars', 52: 'Incorrect answer with too many chars', 53: 'Incorrect answer without no or yes', 54: 'Assignment was not found.' } if response.text.startswith('{'): if response.json().get('error'): raise reCaptchaAPIError(error_codes.get(int(response.json().get('error')))) else: error_code = int(re.search(r'^00(?P\d+)', response.text).groupdict().get('error_code', 0)) if error_code: raise reCaptchaAPIError(error_codes.get(error_code)) # ------------------------------------------------------------------------------- # def requestJob(self, jobID): if not jobID: raise reCaptchaBadJobID( "9kw: Error bad job id to request reCaptcha against." ) def _checkRequest(response): if response.ok and response.json().get('answer') != 'NO DATA': return response self.checkErrorStatus(response) return None response = polling.poll( lambda: self.session.get( self.host, params={ 'apikey': self.api_key, 'action': 'usercaptchacorrectdata', 'id': jobID, 'info': 1, 'json': 1 } ), check_success=_checkRequest, step=10, timeout=(self.maxtimeout + 10) ) if response: return response.json().get('answer') else: raise reCaptchaTimeout("9kw: Error failed to solve reCaptcha.") # ------------------------------------------------------------------------------- # def requestSolve(self, captchaType, url, siteKey): def _checkRequest(response): if response.ok and response.text.startswith('{') and response.json().get('captchaid'): return response self.checkErrorStatus(response) return None captchaMap = { 'reCaptcha': 'recaptchav2', 'hCaptcha': 'hcaptcha' } response = polling.poll( lambda: self.session.post( self.host, data={ 'apikey': self.api_key, 'action': 'usercaptchaupload', 'interactive': 1, 'file-upload-01': siteKey, 'oldsource': captchaMap[captchaType], 'pageurl': url, 'maxtimeout': self.maxtimeout, 'json': 1 }, allow_redirects=False ), check_success=_checkRequest, step=5, timeout=(self.maxtimeout + 10) ) if response: return response.json().get('captchaid') else: raise reCaptchaBadJobID('9kw: Error no valid job id was returned.') # ------------------------------------------------------------------------------- # def getCaptchaAnswer(self, captchaType, url, siteKey, reCaptchaParams): jobID = None if not reCaptchaParams.get('api_key'): raise reCaptchaParameter("9kw: Missing api_key parameter.") self.api_key = reCaptchaParams.get('api_key') if reCaptchaParams.get('maxtimeout'): self.maxtimeout = reCaptchaParams.get('maxtimeout') if reCaptchaParams.get('proxy'): self.session.proxies = reCaptchaParams.get('proxies') try: jobID = self.requestSolve(captchaType, url, siteKey) return self.requestJob(jobID) except polling.TimeoutException: raise reCaptchaTimeout( f"9kw: reCaptcha solve took to long to execute 'captchaid' {jobID}, aborting." ) # ------------------------------------------------------------------------------- # captchaSolver()