python-rucaptcha 5.3__tar.gz → 6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python-rucaptcha-5.3 → python-rucaptcha-6.0}/PKG-INFO +19 -7
- python-rucaptcha-6.0/python_rucaptcha/__version__.py +1 -0
- python-rucaptcha-6.0/python_rucaptcha/amazon_waf.py +114 -0
- python-rucaptcha-6.0/python_rucaptcha/audio_captcha.py +161 -0
- python-rucaptcha-6.0/python_rucaptcha/capy_puzzle.py +138 -0
- python-rucaptcha-6.0/python_rucaptcha/control.py +174 -0
- python-rucaptcha-6.0/python_rucaptcha/core/base.py +239 -0
- {python-rucaptcha-5.3 → python-rucaptcha-6.0}/python_rucaptcha/core/config.py +1 -1
- python-rucaptcha-6.0/python_rucaptcha/core/enums.py +111 -0
- python-rucaptcha-6.0/python_rucaptcha/core/result_handler.py +65 -0
- python-rucaptcha-6.0/python_rucaptcha/core/serializer.py +76 -0
- python-rucaptcha-6.0/python_rucaptcha/fun_captcha.py +103 -0
- python-rucaptcha-6.0/python_rucaptcha/gee_test.py +224 -0
- python-rucaptcha-6.0/python_rucaptcha/hcaptcha.py +111 -0
- python-rucaptcha-6.0/python_rucaptcha/image_captcha.py +249 -0
- {python-rucaptcha-5.3 → python-rucaptcha-6.0}/python_rucaptcha/key_captcha.py +14 -38
- python-rucaptcha-6.0/python_rucaptcha/lemin_captcha.py +112 -0
- python-rucaptcha-6.0/python_rucaptcha/re_captcha.py +172 -0
- python-rucaptcha-6.0/python_rucaptcha/rotate_captcha.py +196 -0
- python-rucaptcha-6.0/python_rucaptcha/text_captcha.py +119 -0
- python-rucaptcha-6.0/python_rucaptcha/turnstile.py +111 -0
- {python-rucaptcha-5.3 → python-rucaptcha-6.0}/python_rucaptcha.egg-info/PKG-INFO +19 -7
- {python-rucaptcha-5.3 → python-rucaptcha-6.0}/python_rucaptcha.egg-info/SOURCES.txt +1 -4
- python-rucaptcha-6.0/python_rucaptcha.egg-info/requires.txt +4 -0
- {python-rucaptcha-5.3 → python-rucaptcha-6.0}/setup.py +2 -3
- python-rucaptcha-5.3/python_rucaptcha/SocketAPI.py +0 -104
- python-rucaptcha-5.3/python_rucaptcha/TikTokCaptcha.py +0 -59
- python-rucaptcha-5.3/python_rucaptcha/__version__.py +0 -1
- python-rucaptcha-5.3/python_rucaptcha/amazon_waf.py +0 -123
- python-rucaptcha-5.3/python_rucaptcha/audio_captcha.py +0 -208
- python-rucaptcha-5.3/python_rucaptcha/capy_puzzle.py +0 -185
- python-rucaptcha-5.3/python_rucaptcha/control.py +0 -404
- python-rucaptcha-5.3/python_rucaptcha/core/base.py +0 -191
- python-rucaptcha-5.3/python_rucaptcha/core/enums.py +0 -112
- python-rucaptcha-5.3/python_rucaptcha/core/result_handler.py +0 -92
- python-rucaptcha-5.3/python_rucaptcha/core/serializer.py +0 -171
- python-rucaptcha-5.3/python_rucaptcha/fun_captcha.py +0 -99
- python-rucaptcha-5.3/python_rucaptcha/gee_test.py +0 -255
- python-rucaptcha-5.3/python_rucaptcha/hcaptcha.py +0 -143
- python-rucaptcha-5.3/python_rucaptcha/image_captcha.py +0 -273
- python-rucaptcha-5.3/python_rucaptcha/lemin_cropped_captcha.py +0 -136
- python-rucaptcha-5.3/python_rucaptcha/re_captcha.py +0 -175
- python-rucaptcha-5.3/python_rucaptcha/rotate_captcha.py +0 -173
- python-rucaptcha-5.3/python_rucaptcha/text_captcha.py +0 -103
- python-rucaptcha-5.3/python_rucaptcha/turnstile.py +0 -107
- python-rucaptcha-5.3/python_rucaptcha/yandex_smart_captcha.py +0 -127
- python-rucaptcha-5.3/python_rucaptcha.egg-info/requires.txt +0 -4
- {python-rucaptcha-5.3 → python-rucaptcha-6.0}/python_rucaptcha/__init__.py +0 -0
- {python-rucaptcha-5.3 → python-rucaptcha-6.0}/python_rucaptcha/core/__init__.py +0 -0
- {python-rucaptcha-5.3 → python-rucaptcha-6.0}/python_rucaptcha.egg-info/dependency_links.txt +0 -0
- {python-rucaptcha-5.3 → python-rucaptcha-6.0}/python_rucaptcha.egg-info/not-zip-safe +0 -0
- {python-rucaptcha-5.3 → python-rucaptcha-6.0}/python_rucaptcha.egg-info/top_level.txt +0 -0
- {python-rucaptcha-5.3 → python-rucaptcha-6.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-rucaptcha
|
|
3
|
-
Version:
|
|
3
|
+
Version: 6.0
|
|
4
4
|
Summary: Python 3.7+ RuCaptcha library with AIO module.
|
|
5
5
|
Home-page: https://andreidrang.github.io/python-rucaptcha/
|
|
6
6
|
Author: AndreiDrang, redV0ID
|
|
@@ -39,28 +39,38 @@ Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
|
|
|
39
39
|
Classifier: Programming Language :: Python
|
|
40
40
|
Classifier: Programming Language :: Python :: 3
|
|
41
41
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
42
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
43
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
44
42
|
Classifier: Programming Language :: Python :: 3.9
|
|
45
43
|
Classifier: Programming Language :: Python :: 3.10
|
|
46
44
|
Classifier: Programming Language :: Python :: 3.11
|
|
45
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
47
46
|
Classifier: Development Status :: 5 - Production/Stable
|
|
48
47
|
Classifier: Framework :: AsyncIO
|
|
49
48
|
Classifier: Operating System :: Unix
|
|
50
49
|
Classifier: Operating System :: Microsoft :: Windows
|
|
51
50
|
Classifier: Operating System :: MacOS
|
|
52
|
-
Requires-Python: >=3.
|
|
51
|
+
Requires-Python: >=3.9.0
|
|
53
52
|
Description-Content-Type: text/markdown
|
|
53
|
+
Requires-Dist: requests>=2.28.0
|
|
54
|
+
Requires-Dist: aiohttp>=3.9.0
|
|
55
|
+
Requires-Dist: msgspec==0.18.*
|
|
56
|
+
Requires-Dist: tenacity==8.2.*
|
|
54
57
|
|
|
55
58
|
|
|
56
59
|
# python-rucaptcha
|
|
57
60
|
|
|
58
61
|
|
|
59
|
-

|
|
63
|
+
|
|
64
|
+
<a href="https://dashboard.capsolver.com/passport/register?inviteCode=kQTn-tG07Jb1">
|
|
65
|
+
<img src="https://cdn.discordapp.com/attachments/1105172394655625306/1105180101802471575/20221207-160749.gif" alt="Capsolver's Banner">
|
|
66
|
+
</a>
|
|
67
|
+
<br>
|
|
68
|
+
At the lowest price on the market, you may receive a variety of solutions, including reCAPTCHA V2, reCAPTCHA V3, hCaptcha, hCaptcha Click, FunCaptcha, picture-to-text, and more. With this service, 0.1s is the slowest speed ever measured.
|
|
69
|
+
<hr>
|
|
60
70
|
|
|
61
71
|
[](https://badge.fury.io/py/python-rucaptcha)
|
|
62
72
|
[](https://badge.fury.io/py/python-rucaptcha)
|
|
63
|
-
[](https://pepy.tech/project/python-rucaptcha)
|
|
73
|
+
[](https://pepy.tech/project/python-rucaptcha)
|
|
64
74
|
|
|
65
75
|
[](https://codeclimate.com/github/AndreiDrang/python-rucaptcha/maintainability)
|
|
66
76
|
[](https://www.codacy.com/gh/AndreiDrang/python-rucaptcha/dashboard?utm_source=github.com&utm_medium=referral&utm_content=AndreiDrang/python-rucaptcha&utm_campaign=Badge_Grade)
|
|
@@ -111,12 +121,14 @@ Is described in the [documentation-website](https://andreidrang.github.io/python
|
|
|
111
121
|
|
|
112
122
|
### Changelog
|
|
113
123
|
|
|
124
|
+
For full changelog info check - [Releases page](https://github.com/AndreiDrang/python-rucaptcha/releases).
|
|
125
|
+
|
|
126
|
+
- v.6.0 - Library refactoring. Stop using `pydantic`, start using `msgspec`. Move to API v2. Drop Python 3.8 support. More details at [Releases page](https://github.com/AndreiDrang/python-rucaptcha/releases).
|
|
114
127
|
- v.5.3 - Added support for [Death By Captcha](https://www.deathbycaptcha.com?refid=1237267242) and other services by changing `service_type` and `url_request` \ `url_response` parameters.
|
|
115
128
|
- v.5.2 - Added Audio captcha method.
|
|
116
129
|
- v.5.1 - Check [releases page](https://github.com/AndreiDrang/python-rucaptcha/releases).
|
|
117
130
|
- v.5.0 - Added AmazonWAF captcha method.
|
|
118
131
|
- v.4.2 - Added [Yandex Smart Captcha](https://rucaptcha.com/api-rucaptcha#yandex).
|
|
119
|
-
- v.4.0 - Rework classes and methods. Adding `TikTok` captcha. Adding inheritance and serializers. The `Callback server` is deprecated.
|
|
120
132
|
|
|
121
133
|
### Get API Key to work with the library
|
|
122
134
|
1. On the page - https://rucaptcha.com/enterpage
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "6.0"
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
|
|
3
|
+
from .core.base import BaseCaptcha
|
|
4
|
+
from .core.enums import AmazonWAFCaptchaEnm
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class AmazonWAF(BaseCaptcha):
|
|
8
|
+
def __init__(
|
|
9
|
+
self,
|
|
10
|
+
websiteURL: str,
|
|
11
|
+
websiteKey: str,
|
|
12
|
+
iv: str,
|
|
13
|
+
context: str,
|
|
14
|
+
method: Union[str, AmazonWAFCaptchaEnm] = AmazonWAFCaptchaEnm.AmazonTaskProxyless,
|
|
15
|
+
*args,
|
|
16
|
+
**kwargs,
|
|
17
|
+
):
|
|
18
|
+
"""
|
|
19
|
+
The class is used to work with Amazon WAF
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
rucaptcha_key: User API key
|
|
23
|
+
websiteURL: Full URL of the captcha page
|
|
24
|
+
websiteKey: Key value from the page
|
|
25
|
+
iv: Value iv from the page
|
|
26
|
+
context: Value of context from page
|
|
27
|
+
method: Captcha type
|
|
28
|
+
|
|
29
|
+
Examples:
|
|
30
|
+
>>> AmazonWAF(rucaptcha_key="aa9011f31111181111168611f1151122",
|
|
31
|
+
... websiteURL="https://page-with-waf.com/",
|
|
32
|
+
... websiteKey="some-site-key",
|
|
33
|
+
... iv="some-iv-value",
|
|
34
|
+
... context="some-context-value").captcha_handler()
|
|
35
|
+
{
|
|
36
|
+
"errorId":0,
|
|
37
|
+
"status":"ready",
|
|
38
|
+
"solution":{
|
|
39
|
+
"captcha_voucher":"eyJ0eXAiO...oQjTnJlBvAW4",
|
|
40
|
+
"existing_token":"f8ab5749-f916-...5D8yAA39JtKVbw="
|
|
41
|
+
},
|
|
42
|
+
"cost":"0.00145",
|
|
43
|
+
"ip":"1.2.3.4",
|
|
44
|
+
"createTime":1692863536,
|
|
45
|
+
"endTime":1692863556,
|
|
46
|
+
"solveCount":0,
|
|
47
|
+
"taskId": 73243152973,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
>>> AmazonWAF(rucaptcha_key="aa9011f31111181111168611f1151122",
|
|
51
|
+
... websiteURL="https://page-with-waf.com/",
|
|
52
|
+
... websiteKey="some-site-key",
|
|
53
|
+
... iv="some-iv-value",
|
|
54
|
+
... context="some-context-value").aio_captcha_handler()
|
|
55
|
+
{
|
|
56
|
+
"errorId":0,
|
|
57
|
+
"status":"ready",
|
|
58
|
+
"solution":{
|
|
59
|
+
"captcha_voucher":"eyJ0eXAiO...oQjTnJlBvAW4",
|
|
60
|
+
"existing_token":"f8ab5749-f916-...5D8yAA39JtKVbw="
|
|
61
|
+
},
|
|
62
|
+
"cost":"0.00145",
|
|
63
|
+
"ip":"1.2.3.4",
|
|
64
|
+
"createTime":1692863536,
|
|
65
|
+
"endTime":1692863556,
|
|
66
|
+
"solveCount":0,
|
|
67
|
+
"taskId": 73243152973,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Dict with full server response
|
|
72
|
+
|
|
73
|
+
Notes:
|
|
74
|
+
https://rucaptcha.com/api-docs/amazon-aws-waf-captcha
|
|
75
|
+
"""
|
|
76
|
+
super().__init__(method=method, *args, **kwargs)
|
|
77
|
+
|
|
78
|
+
# check user params
|
|
79
|
+
if method not in AmazonWAFCaptchaEnm.list_values():
|
|
80
|
+
raise ValueError(f"Invalid method parameter set, available - {AmazonWAFCaptchaEnm.list_values()}")
|
|
81
|
+
# insert `gt` param to payload
|
|
82
|
+
self.create_task_payload["task"].update(
|
|
83
|
+
{
|
|
84
|
+
"websiteURL": websiteURL,
|
|
85
|
+
"websiteKey": websiteKey,
|
|
86
|
+
"iv": iv,
|
|
87
|
+
"context": context,
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
def captcha_handler(self, **kwargs) -> dict:
|
|
92
|
+
"""
|
|
93
|
+
Synchronous method for captcha solving
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
Dict with full server response
|
|
97
|
+
|
|
98
|
+
Notes:
|
|
99
|
+
Check class docstirng for more info
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
return self._processing_response(**kwargs)
|
|
103
|
+
|
|
104
|
+
async def aio_captcha_handler(self) -> dict:
|
|
105
|
+
"""
|
|
106
|
+
Asynchronous method for captcha solving
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Dict with full server response
|
|
110
|
+
|
|
111
|
+
Notes:
|
|
112
|
+
Check class docstirng for more info
|
|
113
|
+
"""
|
|
114
|
+
return await self._aio_processing_response()
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from typing import Union, Optional
|
|
3
|
+
|
|
4
|
+
from .core.base import BaseCaptcha
|
|
5
|
+
from .core.enums import SaveFormatsEnm, AudioCaptchaEnm
|
|
6
|
+
from .core.serializer import GetTaskResultResponseSer
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AudioCaptcha(BaseCaptcha):
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
save_format: Union[str, SaveFormatsEnm] = SaveFormatsEnm.TEMP,
|
|
13
|
+
audio_clearing: bool = True,
|
|
14
|
+
audio_path: str = "PythonRuCaptchaAudio",
|
|
15
|
+
lang: str = "en",
|
|
16
|
+
*args,
|
|
17
|
+
**kwargs,
|
|
18
|
+
):
|
|
19
|
+
"""
|
|
20
|
+
The class is used to work with Text Captcha.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
rucaptcha_key: User API key
|
|
24
|
+
save_format: The format in which the file will be saved, or as a temporary file - 'temp',
|
|
25
|
+
or as a regular file to a folder created by the library - 'const'.
|
|
26
|
+
audio_clearing: True - delete file after solution, False - don't delete file after solution
|
|
27
|
+
audio_path: Folder to save captcha audio
|
|
28
|
+
lang: Captcha audio lang: `en`, `fr`, `de`, `el`, `pt`, `ru`
|
|
29
|
+
|
|
30
|
+
Examples:
|
|
31
|
+
>>> AudioCaptcha(rucaptcha_key="aa9011f31111181111168611f1151122",
|
|
32
|
+
... lang='en'
|
|
33
|
+
... ).captcha_handler(captcha_file='examples/mediacaptcha_audio/recaptcha_55914.mp3')
|
|
34
|
+
{
|
|
35
|
+
'captchaSolve': 'five five nine one four',
|
|
36
|
+
'taskId': 73243152973,
|
|
37
|
+
'error': False,
|
|
38
|
+
'errorBody': None
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
>>> with open("src/examples/mediacaptcha_audio/recaptcha_55914.mp3", "rb") as f:
|
|
42
|
+
... file_data = f.read()
|
|
43
|
+
>>> AudioCaptcha(rucaptcha_key="aa9011f31111181111168611f1151122"
|
|
44
|
+
... ).captcha_handler(captcha_base64=file_data)
|
|
45
|
+
{
|
|
46
|
+
'captchaSolve': 'five five nine one four',
|
|
47
|
+
'taskId': 73243152973,
|
|
48
|
+
'error': False,
|
|
49
|
+
'errorBody': None
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
>>> await AudioCaptcha(rucaptcha_key="aa9011f31111181111168611f1151122",
|
|
53
|
+
... lang='en'
|
|
54
|
+
... ).aio_captcha_handler(captcha_file='examples/mediacaptcha_audio/recaptcha_55914.mp3')
|
|
55
|
+
{
|
|
56
|
+
'captchaSolve': 'five five nine one four',
|
|
57
|
+
'taskId': 73243152973,
|
|
58
|
+
'error': False,
|
|
59
|
+
'errorBody': None
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
>>> with open("src/examples/mediacaptcha_audio/recaptcha_55914.mp3", "rb") as f:
|
|
63
|
+
... file_data = f.read()
|
|
64
|
+
>>> await AudioCaptcha(rucaptcha_key="aa9011f31111181111168611f1151122"
|
|
65
|
+
... ).aio_captcha_handler(captcha_base64=file_data)
|
|
66
|
+
{
|
|
67
|
+
'captchaSolve': 'five five nine one four',
|
|
68
|
+
'taskId': 73243152973,
|
|
69
|
+
'error': False,
|
|
70
|
+
'errorBody': None
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Dict with full server response
|
|
75
|
+
|
|
76
|
+
Notes:
|
|
77
|
+
https://rucaptcha.com/api-docs/audio
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
super().__init__(method=AudioCaptchaEnm.AudioTask.value, *args, **kwargs)
|
|
81
|
+
self.save_format = save_format
|
|
82
|
+
self.audio_clearing = audio_clearing
|
|
83
|
+
self.audio_path = audio_path
|
|
84
|
+
self.result = GetTaskResultResponseSer()
|
|
85
|
+
|
|
86
|
+
self.create_task_payload["task"].update({"lang": lang})
|
|
87
|
+
|
|
88
|
+
def captcha_handler(
|
|
89
|
+
self,
|
|
90
|
+
captcha_link: Optional[str] = None,
|
|
91
|
+
captcha_file: Optional[str] = None,
|
|
92
|
+
captcha_base64: Optional[bytes] = None,
|
|
93
|
+
**kwargs,
|
|
94
|
+
) -> dict:
|
|
95
|
+
"""
|
|
96
|
+
Synchronous method for captcha solving
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
captcha_link: Captcha file URL
|
|
100
|
+
captcha_file: Captcha file path
|
|
101
|
+
captcha_base64: Captcha file BASE64 info
|
|
102
|
+
kwargs: additional params for `requests` library
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
Dict with full server response
|
|
106
|
+
|
|
107
|
+
Notes:
|
|
108
|
+
Check class docstirng for more info
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
self._body_file_processing(
|
|
112
|
+
save_format=self.save_format,
|
|
113
|
+
file_path=self.audio_path,
|
|
114
|
+
file_extension="mp3",
|
|
115
|
+
captcha_link=captcha_link,
|
|
116
|
+
captcha_file=captcha_file,
|
|
117
|
+
captcha_base64=captcha_base64,
|
|
118
|
+
**kwargs,
|
|
119
|
+
)
|
|
120
|
+
if not self.result.errorId:
|
|
121
|
+
return self._processing_response(**kwargs)
|
|
122
|
+
return self.result.to_dict()
|
|
123
|
+
|
|
124
|
+
async def aio_captcha_handler(
|
|
125
|
+
self,
|
|
126
|
+
captcha_link: Optional[str] = None,
|
|
127
|
+
captcha_file: Optional[str] = None,
|
|
128
|
+
captcha_base64: Optional[bytes] = None,
|
|
129
|
+
**kwargs,
|
|
130
|
+
) -> dict:
|
|
131
|
+
"""
|
|
132
|
+
Asynchronous method for captcha solving
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
captcha_link: Captcha file URL
|
|
136
|
+
captcha_file: Captcha file path
|
|
137
|
+
captcha_base64: Captcha file BASE64
|
|
138
|
+
kwargs: additional params for `aiohttp` library
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
Dict with full server response
|
|
142
|
+
|
|
143
|
+
Notes:
|
|
144
|
+
Check class docstirng for more info
|
|
145
|
+
"""
|
|
146
|
+
await self._aio_body_file_processing(
|
|
147
|
+
save_format=self.save_format,
|
|
148
|
+
file_path=self.audio_path,
|
|
149
|
+
file_extension="mp3",
|
|
150
|
+
captcha_link=captcha_link,
|
|
151
|
+
captcha_file=captcha_file,
|
|
152
|
+
captcha_base64=captcha_base64,
|
|
153
|
+
**kwargs,
|
|
154
|
+
)
|
|
155
|
+
if not self.result.errorId:
|
|
156
|
+
return await self._aio_processing_response()
|
|
157
|
+
return self.result.to_dict()
|
|
158
|
+
|
|
159
|
+
def __del__(self):
|
|
160
|
+
if self.save_format == SaveFormatsEnm.CONST.value and self.audio_clearing:
|
|
161
|
+
shutil.rmtree(self.audio_path)
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
|
|
3
|
+
from .core.base import BaseCaptcha
|
|
4
|
+
from .core.enums import CapyPuzzleEnm
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CapyPuzzle(BaseCaptcha):
|
|
8
|
+
def __init__(
|
|
9
|
+
self,
|
|
10
|
+
websiteURL: str,
|
|
11
|
+
websiteKey: str,
|
|
12
|
+
method: Union[str, CapyPuzzleEnm] = CapyPuzzleEnm.CapyTaskProxyless,
|
|
13
|
+
*args,
|
|
14
|
+
**kwargs,
|
|
15
|
+
):
|
|
16
|
+
"""
|
|
17
|
+
The class is used to work with CapyPuzzle.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
rucaptcha_key: User API key
|
|
21
|
+
websiteURL: Full URL of the captcha page
|
|
22
|
+
websiteKey: The value of the `captchakey` parameter you found in the code of the page
|
|
23
|
+
method: Captcha type
|
|
24
|
+
|
|
25
|
+
Examples:
|
|
26
|
+
>>> CapyPuzzle(rucaptcha_key="aa9011f31111181111168611f1151122",
|
|
27
|
+
... websiteKey="PUZZLE_Cme4hZLjuZRMYC3uh14C52D3uNms5w",
|
|
28
|
+
... websiteURL="https://www.capy.me/account/register/",
|
|
29
|
+
... method=CapyPuzzleEnm.CapyTaskProxyless.value,
|
|
30
|
+
... api_server="https://jp.api.capy.me/",
|
|
31
|
+
... version="puzzle",
|
|
32
|
+
... ).captcha_handler()
|
|
33
|
+
{
|
|
34
|
+
"errorId":0,
|
|
35
|
+
"status":"ready",
|
|
36
|
+
"solution":{
|
|
37
|
+
"captchakey":"PUZZLE_Abc1dEFghIJKLM2no34P56q7rStu8v",
|
|
38
|
+
"challengekey":"qHAPtn68KTnXFM8VQ3mtYRtmy3cSKuHJ",
|
|
39
|
+
"answer":"0xax8ex0xax84x0xkx7qx0xux7gx0xx42x0x3ox42x0x3ox4cx",
|
|
40
|
+
"respKey":""
|
|
41
|
+
},
|
|
42
|
+
"cost":"0.00299",
|
|
43
|
+
"ip":"1.2.3.4",
|
|
44
|
+
"createTime":1692863536,
|
|
45
|
+
"endTime":1692863556,
|
|
46
|
+
"solveCount":1,
|
|
47
|
+
"taskId":75190409731
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
>>> CapyPuzzle(rucaptcha_key="aa9011f31111181111168611f1151122",
|
|
51
|
+
... websiteKey="PUZZLE_Cme4hZLjuZRMYC3uh14C52D3uNms5w",
|
|
52
|
+
... websiteURL="https://www.capy.me/account/register/",
|
|
53
|
+
... method=CapyPuzzleEnm.CapyTaskProxyless.value,
|
|
54
|
+
... api_server="https://jp.api.capy.me/",
|
|
55
|
+
... version="avatar",
|
|
56
|
+
... ).captcha_handler()
|
|
57
|
+
{
|
|
58
|
+
"errorId":0,
|
|
59
|
+
"status":"ready",
|
|
60
|
+
"solution":{
|
|
61
|
+
"captchakey":"PUZZLE_Abc1dEFghIJKLM2no34P56q7rStu8v",
|
|
62
|
+
"challengekey":"qHAPtn68KTnXFM8VQ3mtYRtmy3cSKuHJ",
|
|
63
|
+
"answer":"0xax8ex0xax84x0xkx7qx0xux7gx0xx42x0x3ox42x0x3ox4cx",
|
|
64
|
+
"respKey":""
|
|
65
|
+
},
|
|
66
|
+
"cost":"0.00299",
|
|
67
|
+
"ip":"1.2.3.4",
|
|
68
|
+
"createTime":1692863536,
|
|
69
|
+
"endTime":1692863556,
|
|
70
|
+
"solveCount":1,
|
|
71
|
+
"taskId":75190409731
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
>>> CapyPuzzle(rucaptcha_key="aa9011f31111181111168611f1151122",
|
|
75
|
+
... websiteKey="PUZZLE_Cme4hZLjuZRMYC3uh14C52D3uNms5w",
|
|
76
|
+
... websiteURL="https://www.capy.me/account/register/",
|
|
77
|
+
... method="CapyTaskProxyless",
|
|
78
|
+
... api_server="https://jp.api.capy.me/",
|
|
79
|
+
... version="puzzle",
|
|
80
|
+
... ).captcha_handler()
|
|
81
|
+
{
|
|
82
|
+
"errorId":0,
|
|
83
|
+
"status":"ready",
|
|
84
|
+
"solution":{
|
|
85
|
+
"captchakey":"PUZZLE_Abc1dEFghIJKLM2no34P56q7rStu8v",
|
|
86
|
+
"challengekey":"qHAPtn68KTnXFM8VQ3mtYRtmy3cSKuHJ",
|
|
87
|
+
"answer":"0xax8ex0xax84x0xkx7qx0xux7gx0xx42x0x3ox42x0x3ox4cx",
|
|
88
|
+
"respKey":""
|
|
89
|
+
},
|
|
90
|
+
"cost":"0.00299",
|
|
91
|
+
"ip":"1.2.3.4",
|
|
92
|
+
"createTime":1692863536,
|
|
93
|
+
"endTime":1692863556,
|
|
94
|
+
"solveCount":1,
|
|
95
|
+
"taskId":75190409731
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Dict with full server response
|
|
100
|
+
|
|
101
|
+
Notes:
|
|
102
|
+
https://rucaptcha.com/api-docs/capy-puzzle-captcha
|
|
103
|
+
"""
|
|
104
|
+
super().__init__(method=method, *args, **kwargs)
|
|
105
|
+
|
|
106
|
+
self.create_task_payload["task"].update({"websiteURL": websiteURL, "websiteKey": websiteKey})
|
|
107
|
+
|
|
108
|
+
# check user params
|
|
109
|
+
if method not in CapyPuzzleEnm.list_values():
|
|
110
|
+
raise ValueError(f"Invalid method parameter set, available - {CapyPuzzleEnm.list_values()}")
|
|
111
|
+
|
|
112
|
+
def captcha_handler(self, **kwargs) -> dict:
|
|
113
|
+
"""
|
|
114
|
+
Sync solving method
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
kwargs: additional params for `requests` library
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
Dict with full server response
|
|
121
|
+
|
|
122
|
+
Notes:
|
|
123
|
+
Check class docstirng for more info
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
return self._processing_response(**kwargs)
|
|
127
|
+
|
|
128
|
+
async def aio_captcha_handler(self) -> dict:
|
|
129
|
+
"""
|
|
130
|
+
Async solving method
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
Dict with full server response
|
|
134
|
+
|
|
135
|
+
Notes:
|
|
136
|
+
Check class docstirng for more info
|
|
137
|
+
"""
|
|
138
|
+
return await self._aio_processing_response()
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
from .core.base import BaseCaptcha
|
|
2
|
+
from .core.enums import ControlEnm
|
|
3
|
+
from .core.result_handler import get_sync_result, get_async_result
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Control(BaseCaptcha):
|
|
7
|
+
def __init__(
|
|
8
|
+
self,
|
|
9
|
+
*args,
|
|
10
|
+
**kwargs,
|
|
11
|
+
):
|
|
12
|
+
"""
|
|
13
|
+
The class is used to work with RuCaptcha control methods.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
action: Control action type
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
>>> Control(rucaptcha_key="aa9.....").getBalance()
|
|
20
|
+
{
|
|
21
|
+
'balance': 1593.4479
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
>>> await Control(rucaptcha_key="aa9.....").aio_getBalance()
|
|
25
|
+
{
|
|
26
|
+
'balance': 1593.4479
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
>>> Control(rucaptcha_key="aa9.....").reportCorrect(id=75188571838)
|
|
30
|
+
{
|
|
31
|
+
'errorId': 0,
|
|
32
|
+
'status': 'success'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
>>> await Control(rucaptcha_key="aa9.....").aio_reportCorrect(id=75188571838)
|
|
36
|
+
{
|
|
37
|
+
'errorId': 0,
|
|
38
|
+
'status': 'success'
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
>>> Control(rucaptcha_key="aa9.....").reportIncorrect(id=75188571838)
|
|
42
|
+
{
|
|
43
|
+
'errorId': 0,
|
|
44
|
+
'status': 'success'
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
>>> await Control(rucaptcha_key="aa9.....").aio_reportIncorrect(id=75188571838)
|
|
48
|
+
{
|
|
49
|
+
'errorId': 0,
|
|
50
|
+
'status': 'success'
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
Dict with full server response
|
|
55
|
+
|
|
56
|
+
Notes:
|
|
57
|
+
https://rucaptcha.com/api-docs/get-balance
|
|
58
|
+
https://rucaptcha.com/api-docs/report-correct
|
|
59
|
+
https://rucaptcha.com/api-docs/report-incorrect
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
super().__init__(method=ControlEnm.control, *args, **kwargs)
|
|
63
|
+
|
|
64
|
+
def reportCorrect(self, id: int) -> dict:
|
|
65
|
+
"""
|
|
66
|
+
reportCorrect method
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
id: Captcha task ID
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Dict with full server response
|
|
73
|
+
|
|
74
|
+
Notes:
|
|
75
|
+
https://2captcha.com/api-docs/report-correct
|
|
76
|
+
"""
|
|
77
|
+
self.get_task_payload.taskId = id
|
|
78
|
+
return get_sync_result(
|
|
79
|
+
get_payload=self.get_task_payload,
|
|
80
|
+
sleep_time=self.params.sleep_time,
|
|
81
|
+
url_response=f"https://api.{self.params.service_type}.com/reportCorrect",
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
async def aio_reportCorrect(self, id: int) -> dict:
|
|
85
|
+
"""
|
|
86
|
+
Captcha results report
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
id: Captcha task ID
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Dict with full server response
|
|
93
|
+
|
|
94
|
+
Notes:
|
|
95
|
+
https://2captcha.com/api-docs/report-correct
|
|
96
|
+
"""
|
|
97
|
+
self.get_task_payload.taskId = id
|
|
98
|
+
return await get_async_result(
|
|
99
|
+
get_payload=self.get_task_payload,
|
|
100
|
+
sleep_time=self.params.sleep_time,
|
|
101
|
+
url_response=f"https://api.{self.params.service_type}.com/reportCorrect",
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
def reportIncorrect(self, id: int) -> dict:
|
|
105
|
+
"""
|
|
106
|
+
reportCorrect method
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
id: Captcha task ID
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
Dict with full server response
|
|
113
|
+
|
|
114
|
+
Notes:
|
|
115
|
+
https://2captcha.com/api-docs/report-incorrect
|
|
116
|
+
"""
|
|
117
|
+
self.get_task_payload.taskId = id
|
|
118
|
+
return get_sync_result(
|
|
119
|
+
get_payload=self.get_task_payload,
|
|
120
|
+
sleep_time=self.params.sleep_time,
|
|
121
|
+
url_response=f"https://api.{self.params.service_type}.com/reportIncorrect",
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
async def aio_reportIncorrect(self, id: int) -> dict:
|
|
125
|
+
"""
|
|
126
|
+
Captcha results report
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
id: Captcha task ID
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
Dict with full server response
|
|
133
|
+
|
|
134
|
+
Notes:
|
|
135
|
+
https://2captcha.com/api-docs/report-incorrect
|
|
136
|
+
"""
|
|
137
|
+
self.get_task_payload.taskId = id
|
|
138
|
+
return await get_async_result(
|
|
139
|
+
get_payload=self.get_task_payload,
|
|
140
|
+
sleep_time=self.params.sleep_time,
|
|
141
|
+
url_response=f"https://api.{self.params.service_type}.com/reportIncorrect",
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
def getBalance(self) -> dict:
|
|
145
|
+
"""
|
|
146
|
+
GetBalance method
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
Dict with full server response
|
|
150
|
+
|
|
151
|
+
Notes:
|
|
152
|
+
Check class docstirng for more info
|
|
153
|
+
"""
|
|
154
|
+
return get_sync_result(
|
|
155
|
+
get_payload=self.get_task_payload,
|
|
156
|
+
sleep_time=self.params.sleep_time,
|
|
157
|
+
url_response=f"https://api.{self.params.service_type}.com/getBalance",
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
async def aio_getBalance(self) -> dict:
|
|
161
|
+
"""
|
|
162
|
+
Async GetBalance method
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
Dict with full server response
|
|
166
|
+
|
|
167
|
+
Notes:
|
|
168
|
+
Check class docstirng for more info
|
|
169
|
+
"""
|
|
170
|
+
return get_sync_result(
|
|
171
|
+
get_payload=self.get_task_payload,
|
|
172
|
+
sleep_time=self.params.sleep_time,
|
|
173
|
+
url_response=f"https://api.{self.params.service_type}.com/getBalance",
|
|
174
|
+
)
|