Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ __pycache__/
dist/
build/
env/
venv/
capmonstercloudclient.egg-info/
38 changes: 21 additions & 17 deletions capmonstercloud_client/CapMonsterCloudClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
_instance_config = (
((RecaptchaV2Request,), getRecaptchaV2Timeouts),
((RecaptchaV2EnterpriseRequest,), getRecaptchaV2EnterpriseTimeouts),
((RecaptchaV3ProxylessRequest), getRecaptchaV3Timeouts),
((RecaptchaV3EnterpriseRequest), getRecaptchaV3Timeouts),
((ImageToTextRequest), getImage2TextTimeouts),
((RecaptchaV3ProxylessRequest,), getRecaptchaV3Timeouts),
((RecaptchaV3EnterpriseRequest,), getRecaptchaV3Timeouts),
((ImageToTextRequest,), getImage2TextTimeouts),
((FuncaptchaRequest,), getFuncaptchaTimeouts),
((HcaptchaRequest,), getHcaptchaTimeouts),
((GeetestRequest,), getGeetestTimeouts),
Expand All @@ -31,12 +31,15 @@
((AmazonWafRequest,), getAmazonWafTimeouts),
((BinanceTaskRequest,), getBinanceTimeouts),
((ImpervaCustomTaskRequest,), getImpervaTimeouts),
((RecognitionComplexImageTaskRequest), getCITTimeouts),
((MTCaptchaRequest), getImage2TextTimeouts),
((YidunRequest), getYidunTimeouts),
((TemuCustomTaskRequest), getTemuTimeouts),
((ProsopoTaskRequest), getProsopoTimeouts),
((AltchaCustomTaskRequest), getAltchaTimeouts),
((RecognitionComplexImageTaskRequest,), getCITTimeouts),
((MTCaptchaRequest,), getImage2TextTimeouts),
((YidunRequest,), getYidunTimeouts),
((TemuCustomTaskRequest,), getTemuTimeouts),
((ProsopoTaskRequest,), getProsopoTimeouts),
((AltchaCustomTaskRequest,), getAltchaTimeouts),
((CastleCustomTaskRequest,), getCastleTimeouts),
((TspdCustomTaskRequest,), getTspdTimeouts),
((HuntCustomTaskRequest,), getHuntTimeouts),
)


Expand Down Expand Up @@ -100,7 +103,10 @@ async def solve_captcha(self, request: Union[
YidunRequest,
TemuCustomTaskRequest,
ProsopoTaskRequest,
AltchaCustomTaskRequest],
AltchaCustomTaskRequest,
CastleCustomTaskRequest,
TspdCustomTaskRequest,
HuntCustomTaskRequest],
) -> Dict[str, str]:
'''
Non-blocking method for captcha solving.
Expand Down Expand Up @@ -148,6 +154,7 @@ async def _solve(self, request: Union[
raise GetTaskError(f'[{getTaskResponse.get("errorCode")}] ' \
f'{getTaskResponse.get("errorDescription")}.')
timer = RequestController(timeout=timeouts.timeout)
timer.run()
await asyncio.sleep(timeouts.firstRequestDelay)
result = CaptchaResult()
while not timer.cancel:
Expand All @@ -165,13 +172,10 @@ async def _solve(self, request: Union[
elif getResultResponse.get('status') == 'ready':
timer.stop()
result.solution = getResultResponse.get('solution')
break

if result != None:
return result.solution
else:
raise TimeoutError('Failed to get a solution within the maximum ' \
f'response waiting interval: {timeouts.timeout:0.1f} sec.')
return result.solution

raise TimeoutError('Failed to get a solution within the maximum ' \
f'response waiting interval: {timeouts.timeout:0.1f} sec.')


async def _getTaskResult(self, task_id: str) -> Dict[str, Union[int, str, None]]:
Expand Down
9 changes: 9 additions & 0 deletions capmonstercloud_client/GetResultTimeouts.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ def getImpervaTimeouts() -> GetResultTimeouts:
def getAltchaTimeouts() -> GetResultTimeouts:
return GetResultTimeouts(1, 0, 1, 50)

def getCastleTimeouts() -> GetResultTimeouts:
return GetResultTimeouts(1, 0, 1, 60)

def getTspdTimeouts() -> GetResultTimeouts:
return GetResultTimeouts(1, 0, 1, 60)

def getHuntTimeouts() -> GetResultTimeouts:
return GetResultTimeouts(1, 0, 1, 60)

def getCITTimeouts() -> GetResultTimeouts:
return GetResultTimeouts(0.35, 0, 0.2, 10)

Expand Down
42 changes: 42 additions & 0 deletions capmonstercloud_client/requests/CastleCustomTaskRequest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from typing import Dict, Union
from pydantic import Field, validator

from .CustomTaskRequestBase import CustomTaskRequestBase

class CastleCustomTaskRequest(CustomTaskRequestBase):
captchaClass: str = Field(default='Castle')
websiteKey: str = Field()
metadata: Dict[str, Union[str, int]]

@validator('metadata')
def validate_metadata(cls, value):
if value.get('wUrl') is None:
raise TypeError(f'Expect that wUrl will be defined.')
Comment thread
grk717 marked this conversation as resolved.
Outdated
else:
if not isinstance(value.get('wUrl'), str):
raise TypeError(f'Expect that wUrl will be str.')
if value.get('swUrl') is None:
raise TypeError(f'Expect that swUrl will be defined.')
else:
if not isinstance(value.get('swUrl'), str):
raise TypeError(f'Expect that swUrl will be str.')
if value.get('count') is not None and not isinstance(value.get('count'), int):
raise TypeError(f'Expect that count will be int.')
return value

def getTaskDict(self) -> Dict[str, Union[str, int, bool]]:
task = {}
task['type'] = self.type
task['class'] = self.captchaClass
task['websiteURL'] = self.websiteUrl
task['websiteKey'] = self.websiteKey
task['metadata'] = self.metadata
if self.proxy:
task['proxyType'] = self.proxy.proxyType
task['proxyAddress'] = self.proxy.proxyAddress
task['proxyPort'] = self.proxy.proxyPort
task['proxyLogin'] = self.proxy.proxyLogin
task['proxyPassword'] = self.proxy.proxyPassword
if self.userAgent is not None:
task['userAgent'] = self.userAgent
return task
28 changes: 16 additions & 12 deletions capmonstercloud_client/requests/DataDomeCustomTaskRequest.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
from typing import Dict, Union
from pydantic import Field, validator
from pydantic import Field, validator, model_validator
from .CustomTaskRequestBase import CustomTaskRequestBase

class DataDomeCustomTaskRequest(CustomTaskRequestBase):
captchaClass: str = Field(default='DataDome')
metadata : Dict[str, str]

@validator('metadata')
def validate_metadata(cls, value):
if value.get('datadomeCookie') is None:
raise TypeError(f'Expect that datadomeCookie will be defined.')
if value.get('datadomeVersion') is not None and not isinstance(value.get('datadomeVersion'), str):
raise TypeError(f'Expected datadomeVersion to be str')
if value.get('captchaUrl') and value.get('htmlPageBase64'):
raise TypeError(f'Expected only one of [captchaUrl, htmlPageBase64]')
elif value.get('captchaUrl'):
Expand All @@ -18,22 +20,24 @@ def validate_metadata(cls, value):
return {i: value[i] for i in value if i != 'captchaUrl'}
else:
raise TypeError(f'Expected one of [captchaUrl, htmlPageBase64]')
if value.get('datadomeVersion') and not isinstance(value.get('datadomeVersion'), str):
raise TypeError(f'Expected datadomeVersion to be str')


@model_validator(mode='before')
def validate_datadome_proxy(cls, values):
proxy = values.get('proxy')
if proxy is None:
raise RuntimeError(f'You are required to use your own proxies.')
return values

def getTaskDict(self) -> Dict[str, Union[str, int, bool]]:
task = {}
task['type'] = self.type
task['class'] = self.captchaClass
task['websiteURL'] = self.websiteUrl
if self.proxy:
task['proxyType'] = self.proxy.proxyType
task['proxyAddress'] = self.proxy.proxyAddress
task['proxyPort'] = self.proxy.proxyPort
task['proxyLogin'] = self.proxy.proxyLogin
task['proxyPassword'] = self.proxy.proxyPassword
task['domains'] = self.domains
task['proxyType'] = self.proxy.proxyType
task['proxyAddress'] = self.proxy.proxyAddress
task['proxyPort'] = self.proxy.proxyPort
task['proxyLogin'] = self.proxy.proxyLogin
task['proxyPassword'] = self.proxy.proxyPassword
task['metadata'] = self.metadata
if self.userAgent is not None:
task['userAgent'] = self.userAgent
Expand Down
41 changes: 41 additions & 0 deletions capmonstercloud_client/requests/HuntCustomTaskRequest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from typing import Dict, Union
from pydantic import Field, validator, model_validator

from .CustomTaskRequestBase import CustomTaskRequestBase

class HuntCustomTaskRequest(CustomTaskRequestBase):
captchaClass: str = Field(default='HUNT')
metadata: Dict[str, str]

@validator('metadata')
def validate_metadata(cls, value):
if value.get('apiGetLib') is None:
raise TypeError(f'Expect that apiGetLib will be defined.')
else:
if not isinstance(value.get('apiGetLib'), str):
raise TypeError(f'Expect that apiGetLib will be str.')
if value.get('data') is not None and not isinstance(value.get('data'), str):
raise TypeError(f'Expect that data will be str.')
return value

@model_validator(mode='before')
def validate_hunt_proxy(cls, values):
proxy = values.get('proxy')
if proxy is None:
raise RuntimeError(f'You are required to use your own proxies.')
return values

def getTaskDict(self) -> Dict[str, Union[str, int, bool]]:
task = {}
task['type'] = self.type
task['class'] = self.captchaClass
task['websiteURL'] = self.websiteUrl
task['metadata'] = self.metadata
task['proxyType'] = self.proxy.proxyType
task['proxyAddress'] = self.proxy.proxyAddress
task['proxyPort'] = self.proxy.proxyPort
task['proxyLogin'] = self.proxy.proxyLogin
task['proxyPassword'] = self.proxy.proxyPassword
if self.userAgent is not None:
task['userAgent'] = self.userAgent
return task
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ class RecaptchaV2EnterpriseRequest(BaseRequestWithProxy):
enterprisePayload: Optional[str] = Field(default=None)
apiDomain: Optional[str] = Field(default=None)
pageAction: Optional[str] = Field(default=None)

userAgent: Optional[str] = Field(default=None)
cookies: Optional[str] = Field(default=None)

def getTaskDict(self) -> Dict[str, Union[str, int]]:
task = {}
task['type'] = self.type
Expand All @@ -28,4 +30,8 @@ def getTaskDict(self) -> Dict[str, Union[str, int]]:
task['apiDomain'] = self.apiDomain
if self.pageAction is not None:
task['pageAction'] = self.pageAction
if self.userAgent is not None:
task['userAgent'] = self.userAgent
if self.cookies is not None:
task['cookies'] = self.cookies
return task
8 changes: 6 additions & 2 deletions capmonstercloud_client/requests/RecaptchaV2Request.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ class RecaptchaV2Request(BaseRequestWithProxy):
dataSValue: Optional[str] = Field(default=None)
userAgent: Optional[str] = Field(default=None)
cookies: Optional[str] = Field(default=None)
isInvisible: Optional[bool] = Field(default=None)

def getTaskDict(self) -> Dict[str, Union[str, int]]:
def getTaskDict(self) -> Dict[str, Union[str, int, bool]]:
task = {}
task['type'] = self.type
task['websiteURL'] = self.websiteUrl
Expand All @@ -26,12 +27,15 @@ def getTaskDict(self) -> Dict[str, Union[str, int]]:

if self.dataSValue is not None:
task['recaptchaDataSValue'] = self.dataSValue

if self.userAgent is not None:
task['userAgent'] = self.userAgent

if self.cookies is not None:
task['cookies'] = self.cookies

if self.isInvisible is not None:
task['isInvisible'] = self.isInvisible

return task

Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ class RecaptchaV3ProxylessRequest(BaseRequest):
websiteUrl: str
websiteKey: str
type: str = Field(default='RecaptchaV3TaskProxyless')
min_score: Optional[float] = Field(default=None)
minScore: Optional[float] = Field(default=None)
pageAction: Optional[str] = Field(default=None)

@validator('min_score')
@validator('minScore')
def validate_min_score(cls, value):
if value is not None:
if not 0.1 <= value <= 0.9:
Expand All @@ -23,8 +23,8 @@ def getTaskDict(self) -> Dict[str, Union[str, float]]:
task['type'] = self.type
task['websiteURL'] = self.websiteUrl
task['websiteKey'] = self.websiteKey
if self.min_score is not None:
task['minScore'] = self.min_score
if self.minScore is not None:
task['minScore'] = self.minScore
if self.pageAction is not None:
task['pageAction'] = self.pageAction
return task
16 changes: 14 additions & 2 deletions capmonstercloud_client/requests/TenDiCustomTaskRequest.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
from typing import Dict, Union
from pydantic import Field
from typing import Dict, Optional, Union
from pydantic import Field, validator

from .CustomTaskRequestBase import CustomTaskRequestBase

class TenDiCustomTaskRequest(CustomTaskRequestBase):
captchaClass: str = Field(default='TenDI')
websiteKey: str = Field()
metadata: Optional[Dict[str, str]] = Field(default=None)

@validator('metadata')
def validate_metadata(cls, value):
if value is not None:
if not set(value.keys()).issubset(set(["captchaUrl"])):
raise TypeError(f'Allowed keys for metadata are "captchaUrl"')
if value.get('captchaUrl') is not None and not isinstance(value.get('captchaUrl'), str):
raise TypeError(f'Expect that captchaUrl will be str.')
return value

def getTaskDict(self) -> Dict[str, Union[str, int, bool]]:
task = {}
Expand All @@ -21,4 +31,6 @@ def getTaskDict(self) -> Dict[str, Union[str, int, bool]]:
task['proxyPassword'] = self.proxy.proxyPassword
if self.userAgent is not None:
task['userAgent'] = self.userAgent
if self.metadata is not None:
task['metadata'] = self.metadata
return task
44 changes: 44 additions & 0 deletions capmonstercloud_client/requests/TspdCustomTaskRequest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from typing import Dict, Union
from pydantic import Field, validator, model_validator

from .CustomTaskRequestBase import CustomTaskRequestBase

class TspdCustomTaskRequest(CustomTaskRequestBase):
captchaClass: str = Field(default='tspd')
userAgent: str = Field()
metadata: Dict[str, str]

@validator('metadata')
def validate_metadata(cls, value):
if value.get('tspdCookie') is None:
raise TypeError(f'Expect that tspdCookie will be defined.')
else:
if not isinstance(value.get('tspdCookie'), str):
raise TypeError(f'Expect that tspdCookie will be str.')
if value.get('htmlPageBase64') is None:
raise TypeError(f'Expect that htmlPageBase64 will be defined.')
else:
if not isinstance(value.get('htmlPageBase64'), str):
raise TypeError(f'Expect that htmlPageBase64 will be str.')
return value

@model_validator(mode='before')
def validate_tspd_proxy(cls, values):
proxy = values.get('proxy')
if proxy is None:
raise RuntimeError(f'You are required to use your own proxies.')
return values

def getTaskDict(self) -> Dict[str, Union[str, int, bool]]:
task = {}
task['type'] = self.type
task['class'] = self.captchaClass
task['websiteURL'] = self.websiteUrl
task['metadata'] = self.metadata
task['userAgent'] = self.userAgent
task['proxyType'] = self.proxy.proxyType
task['proxyAddress'] = self.proxy.proxyAddress
task['proxyPort'] = self.proxy.proxyPort
task['proxyLogin'] = self.proxy.proxyLogin
task['proxyPassword'] = self.proxy.proxyPassword
return task
Loading