Skip to content

Commit

Permalink
Merge pull request #195 from AndreiDrang/master
Browse files Browse the repository at this point in the history
v6.0.3 - DataDome CAPTCHA
  • Loading branch information
AndreiDrang authored Dec 10, 2023
2 parents 21c01a5 + 07d8cbc commit f4bf7a5
Show file tree
Hide file tree
Showing 8 changed files with 266 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
image_captcha,
lemin_captcha,
rotate_captcha,
datadome_captcha,
)
from python_rucaptcha.__version__ import __version__

Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Check our other projects here - `RedPandaDev group <https://red-panda-dev.xyz/bl
modules/image/example.rst
modules/audio/example.rst
modules/cut-captcha/example.rst
modules/datadome-captcha/example.rst
modules/control/example.rst

.. toctree::
Expand Down
12 changes: 12 additions & 0 deletions docs/modules/datadome-captcha/example.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
DataDome
========

To import this module:

.. code-block:: python
from python_rucaptcha.datadome_captcha import DataDomeCaptcha
.. autoclass:: python_rucaptcha.datadome_captcha.DataDomeCaptcha
:members:
4 changes: 4 additions & 0 deletions docs/modules/enum/info.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,7 @@ To import this module:
.. autoclass:: python_rucaptcha.core.enums.CutCaptchaEnm
:members:
:undoc-members:

.. autoclass:: python_rucaptcha.core.enums.DataDomeSliderEnm
:members:
:undoc-members:
2 changes: 1 addition & 1 deletion src/python_rucaptcha/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "6.0.2"
__version__ = "6.0.3"
4 changes: 4 additions & 0 deletions src/python_rucaptcha/core/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,7 @@ class AudioCaptchaEnm(str, MyEnum):
class CutCaptchaEnm(str, MyEnum):
CutCaptchaTask = "CutCaptchaTask"
CutCaptchaTaskProxyless = "CutCaptchaTaskProxyless"


class DataDomeSliderEnm(str, MyEnum):
DataDomeSliderTask = "DataDomeSliderTask"
121 changes: 121 additions & 0 deletions src/python_rucaptcha/datadome_captcha.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
from .core.base import BaseCaptcha
from .core.enums import DataDomeSliderEnm


class DataDomeCaptcha(BaseCaptcha):
def __init__(
self,
websiteURL: str,
captchaUrl: str,
userAgent: str,
proxyType: str,
proxyAddress: str,
proxyPort: str,
*args,
**kwargs,
):
"""
The class is used to work with HCaptcha.
Args:
rucaptcha_key: User API key
websiteURL: Full URL of the captcha page
captchaUrl: The value of the `src` parameter for the `iframe` element containing the captcha on the page.
userAgent: User-Agent of your browser will be used to load the captcha. Use only modern browser's User-Agents
proxyType: Proxy type - `http`, `socks4`, `socks5`
proxyAddress: Proxy IP address or hostname
proxyPort: Proxy port
method: Captcha type
kwargs: Not required params for task creation request
Examples:
>>> DataDomeCaptcha(rucaptcha_key="aa9011f31111181111168611f1151122",
... websiteURL="3ceb8624-1970-4e6b-91d5-70317b70b651",
... captchaUrl="https://rucaptcha.com/demo/hcaptcha",
... userAgent="https://rucaptcha.com/demo/hcaptcha",
... proxyType="socks5",
... proxyAddress="1.2.3.4",
... proxyPort="445",
... ).captcha_handler()
{
"errorId":0,
"status":"ready",
"solution":{
"cookie": "datadome=4ZXwCBlyHx9ktZhSnycMF...; Path=/; Secure; SameSite=Lax"
},
"cost":"0.00299",
"ip":"1.2.3.4",
"createTime":1692863536,
"endTime":1692863556,
"solveCount":1,
"taskId": 73243152973,
}
>>> await DataDomeCaptcha(rucaptcha_key="aa9011f31111181111168611f1151122",
... websiteURL="3ceb8624-1970-4e6b-91d5-70317b70b651",
... captchaUrl="https://rucaptcha.com/demo/hcaptcha",
... userAgent="https://rucaptcha.com/demo/hcaptcha",
... proxyType="socks5",
... proxyAddress="1.2.3.4",
... proxyPort="445",
... ).aio_captcha_handler()
{
"errorId":0,
"status":"ready",
"solution":{
"cookie": "datadome=4ZXwCBlyHx9ktZhSnycMF...; Path=/; Secure; SameSite=Lax"
},
"cost":"0.00299",
"ip":"1.2.3.4",
"createTime":1692863536,
"endTime":1692863556,
"solveCount":1,
"taskId": 73243152973,
}
Returns:
Dict with full server response
Notes:
https://rucaptcha.com/api-docs/datadome-slider-captcha
"""
super().__init__(method=DataDomeSliderEnm.DataDomeSliderTask, *args, **kwargs)

self.create_task_payload["task"].update(
{
"websiteURL": websiteURL,
"captchaUrl": captchaUrl,
"userAgent": userAgent,
"proxyType": proxyType,
"proxyAddress": proxyAddress,
"proxyPort": proxyPort,
}
)

def captcha_handler(self, **kwargs) -> dict:
"""
Sync solving method
Args:
kwargs: Parameters for the `requests` library
Returns:
Dict with full server response
Notes:
Check class docstirng for more info
"""

return self._processing_response(**kwargs)

async def aio_captcha_handler(self) -> dict:
"""
Async solving method
Returns:
Dict with full server response
Notes:
Check class docstirng for more info
"""
return await self._aio_processing_response()
122 changes: 122 additions & 0 deletions tests/test_datadome.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import pytest

from tests.conftest import BaseTest
from python_rucaptcha.core.enums import DataDomeSliderEnm
from python_rucaptcha.datadome_captcha import DataDomeCaptcha


class TestHCaptcha(BaseTest):
websiteURL = "https://www.pokemoncenter.com/"
captchaUrl = "https://geo.captcha-delivery.com/captcha/?initialCid=AHrlqAAAAAMAlk-FmAyNOW8AUyTH_g%3D%3D&hash=5B45875B653A484CC79E57036CE9FC&cid=noJuZstmvINksqOxaXWQogbPBd01y3VaH3r-CZ4eqK4roZuelJMHVhO2rR0IySRieoAivkg74B4UpJ.xj.jVNB6-aLaW.Bwvik7__EncryD6COavwx8RmOqgZ7DK_3v&t=fe&referer=https%3A%2F%2Fwww.pokemoncenter.com%2F&s=9817&e=2b1d5a78107ded0dcdc8317aa879979ed5083a2b3a95b734dbe7871679e1403"
userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
proxyType = "http"
proxyAddress = "1.2.3.4"
proxyPort = "8080"
kwargs_params = {"proxyLogin": "user23", "proxyPassword": "p4$$w0rd"}

def test_methods_exists(self):
assert "captcha_handler" in DataDomeCaptcha.__dict__.keys()
assert "aio_captcha_handler" in DataDomeCaptcha.__dict__.keys()

def test_args(self):
instance = DataDomeCaptcha(
rucaptcha_key=self.RUCAPTCHA_KEY,
websiteURL=self.websiteURL,
captchaUrl=self.captchaUrl,
userAgent=self.userAgent,
proxyType=self.proxyType,
proxyAddress=self.proxyAddress,
proxyPort=self.proxyPort,
)
assert instance.create_task_payload["clientKey"] == self.RUCAPTCHA_KEY
assert instance.create_task_payload["task"]["type"] == DataDomeSliderEnm.DataDomeSliderTask
assert instance.create_task_payload["task"]["websiteURL"] == self.websiteURL
assert instance.create_task_payload["task"]["captchaUrl"] == self.captchaUrl
assert instance.create_task_payload["task"]["userAgent"] == self.userAgent
assert instance.create_task_payload["task"]["proxyType"] == self.proxyType
assert instance.create_task_payload["task"]["proxyAddress"] == self.proxyAddress
assert instance.create_task_payload["task"]["proxyPort"] == self.proxyPort

def test_kwargs(self):
instance = DataDomeCaptcha(
rucaptcha_key=self.RUCAPTCHA_KEY,
websiteURL=self.websiteURL,
captchaUrl=self.captchaUrl,
userAgent=self.userAgent,
proxyType=self.proxyType,
proxyAddress=self.proxyAddress,
proxyPort=self.proxyPort,
**self.kwargs_params,
)
assert set(self.kwargs_params.keys()).issubset(set(instance.create_task_payload["task"].keys()))
assert set(self.kwargs_params.values()).issubset(set(instance.create_task_payload["task"].values()))

"""
Fail tests
"""

def test_no_websiteURL(self):
with pytest.raises(TypeError):
DataDomeCaptcha(
rucaptcha_key=self.RUCAPTCHA_KEY,
captchaUrl=self.captchaUrl,
userAgent=self.userAgent,
proxyType=self.proxyType,
proxyAddress=self.proxyAddress,
proxyPort=self.proxyPort,
)

def test_no_captchaUrl(self):
with pytest.raises(TypeError):
DataDomeCaptcha(
rucaptcha_key=self.RUCAPTCHA_KEY,
websiteURL=self.websiteURL,
userAgent=self.userAgent,
proxyType=self.proxyType,
proxyAddress=self.proxyAddress,
proxyPort=self.proxyPort,
)

def test_no_userAgent(self):
with pytest.raises(TypeError):
DataDomeCaptcha(
rucaptcha_key=self.RUCAPTCHA_KEY,
websiteURL=self.websiteURL,
captchaUrl=self.captchaUrl,
proxyType=self.proxyType,
proxyAddress=self.proxyAddress,
proxyPort=self.proxyPort,
)

def test_no_proxyType(self):
with pytest.raises(TypeError):
DataDomeCaptcha(
rucaptcha_key=self.RUCAPTCHA_KEY,
websiteURL=self.websiteURL,
captchaUrl=self.captchaUrl,
userAgent=self.userAgent,
proxyAddress=self.proxyAddress,
proxyPort=self.proxyPort,
)

def test_no_proxyAddress(self):
with pytest.raises(TypeError):
DataDomeCaptcha(
rucaptcha_key=self.RUCAPTCHA_KEY,
websiteURL=self.websiteURL,
captchaUrl=self.captchaUrl,
userAgent=self.userAgent,
proxyType=self.proxyType,
proxyPort=self.proxyPort,
)

def test_no_proxyPort(self):
with pytest.raises(TypeError):
DataDomeCaptcha(
rucaptcha_key=self.RUCAPTCHA_KEY,
websiteURL=self.websiteURL,
captchaUrl=self.captchaUrl,
userAgent=self.userAgent,
proxyType=self.proxyType,
proxyAddress=self.proxyAddress,
)

0 comments on commit f4bf7a5

Please sign in to comment.