python-rucaptcha 5.3.1__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.
Files changed (53) hide show
  1. {python-rucaptcha-5.3.1 → python-rucaptcha-6.0}/PKG-INFO +19 -7
  2. python-rucaptcha-6.0/python_rucaptcha/__version__.py +1 -0
  3. python-rucaptcha-6.0/python_rucaptcha/amazon_waf.py +114 -0
  4. python-rucaptcha-6.0/python_rucaptcha/audio_captcha.py +161 -0
  5. python-rucaptcha-6.0/python_rucaptcha/capy_puzzle.py +138 -0
  6. python-rucaptcha-6.0/python_rucaptcha/control.py +174 -0
  7. python-rucaptcha-6.0/python_rucaptcha/core/base.py +239 -0
  8. {python-rucaptcha-5.3.1 → python-rucaptcha-6.0}/python_rucaptcha/core/config.py +1 -1
  9. python-rucaptcha-6.0/python_rucaptcha/core/enums.py +111 -0
  10. python-rucaptcha-6.0/python_rucaptcha/core/result_handler.py +65 -0
  11. python-rucaptcha-6.0/python_rucaptcha/core/serializer.py +76 -0
  12. python-rucaptcha-6.0/python_rucaptcha/fun_captcha.py +103 -0
  13. python-rucaptcha-6.0/python_rucaptcha/gee_test.py +224 -0
  14. python-rucaptcha-6.0/python_rucaptcha/hcaptcha.py +111 -0
  15. python-rucaptcha-6.0/python_rucaptcha/image_captcha.py +249 -0
  16. {python-rucaptcha-5.3.1 → python-rucaptcha-6.0}/python_rucaptcha/key_captcha.py +14 -38
  17. python-rucaptcha-6.0/python_rucaptcha/lemin_captcha.py +112 -0
  18. python-rucaptcha-6.0/python_rucaptcha/re_captcha.py +172 -0
  19. python-rucaptcha-6.0/python_rucaptcha/rotate_captcha.py +196 -0
  20. python-rucaptcha-6.0/python_rucaptcha/text_captcha.py +119 -0
  21. python-rucaptcha-6.0/python_rucaptcha/turnstile.py +111 -0
  22. {python-rucaptcha-5.3.1 → python-rucaptcha-6.0}/python_rucaptcha.egg-info/PKG-INFO +19 -7
  23. {python-rucaptcha-5.3.1 → python-rucaptcha-6.0}/python_rucaptcha.egg-info/SOURCES.txt +1 -4
  24. python-rucaptcha-6.0/python_rucaptcha.egg-info/requires.txt +4 -0
  25. {python-rucaptcha-5.3.1 → python-rucaptcha-6.0}/setup.py +2 -3
  26. python-rucaptcha-5.3.1/python_rucaptcha/SocketAPI.py +0 -104
  27. python-rucaptcha-5.3.1/python_rucaptcha/TikTokCaptcha.py +0 -59
  28. python-rucaptcha-5.3.1/python_rucaptcha/__version__.py +0 -1
  29. python-rucaptcha-5.3.1/python_rucaptcha/amazon_waf.py +0 -123
  30. python-rucaptcha-5.3.1/python_rucaptcha/audio_captcha.py +0 -230
  31. python-rucaptcha-5.3.1/python_rucaptcha/capy_puzzle.py +0 -185
  32. python-rucaptcha-5.3.1/python_rucaptcha/control.py +0 -404
  33. python-rucaptcha-5.3.1/python_rucaptcha/core/base.py +0 -191
  34. python-rucaptcha-5.3.1/python_rucaptcha/core/enums.py +0 -112
  35. python-rucaptcha-5.3.1/python_rucaptcha/core/result_handler.py +0 -92
  36. python-rucaptcha-5.3.1/python_rucaptcha/core/serializer.py +0 -171
  37. python-rucaptcha-5.3.1/python_rucaptcha/fun_captcha.py +0 -99
  38. python-rucaptcha-5.3.1/python_rucaptcha/gee_test.py +0 -255
  39. python-rucaptcha-5.3.1/python_rucaptcha/hcaptcha.py +0 -143
  40. python-rucaptcha-5.3.1/python_rucaptcha/image_captcha.py +0 -294
  41. python-rucaptcha-5.3.1/python_rucaptcha/lemin_cropped_captcha.py +0 -136
  42. python-rucaptcha-5.3.1/python_rucaptcha/re_captcha.py +0 -175
  43. python-rucaptcha-5.3.1/python_rucaptcha/rotate_captcha.py +0 -196
  44. python-rucaptcha-5.3.1/python_rucaptcha/text_captcha.py +0 -103
  45. python-rucaptcha-5.3.1/python_rucaptcha/turnstile.py +0 -107
  46. python-rucaptcha-5.3.1/python_rucaptcha/yandex_smart_captcha.py +0 -127
  47. python-rucaptcha-5.3.1/python_rucaptcha.egg-info/requires.txt +0 -4
  48. {python-rucaptcha-5.3.1 → python-rucaptcha-6.0}/python_rucaptcha/__init__.py +0 -0
  49. {python-rucaptcha-5.3.1 → python-rucaptcha-6.0}/python_rucaptcha/core/__init__.py +0 -0
  50. {python-rucaptcha-5.3.1 → python-rucaptcha-6.0}/python_rucaptcha.egg-info/dependency_links.txt +0 -0
  51. {python-rucaptcha-5.3.1 → python-rucaptcha-6.0}/python_rucaptcha.egg-info/not-zip-safe +0 -0
  52. {python-rucaptcha-5.3.1 → python-rucaptcha-6.0}/python_rucaptcha.egg-info/top_level.txt +0 -0
  53. {python-rucaptcha-5.3.1 → 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: 5.3.1
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.7.0
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
- ![](https://github.com/AndreiDrang/python-rucaptcha/blob/master/files/RuCaptcha.png)
62
+ ![](files/RuCaptchaHigh.png)
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
  [![PyPI version](https://badge.fury.io/py/python-rucaptcha.svg)](https://badge.fury.io/py/python-rucaptcha)
62
72
  [![Python versions](https://img.shields.io/pypi/pyversions/python-rucaptcha.svg?logo=python&logoColor=FBE072)](https://badge.fury.io/py/python-rucaptcha)
63
- [![Downloads](https://pepy.tech/badge/python-rucaptcha/month)](https://pepy.tech/project/python-rucaptcha)
73
+ [![Downloads](https://static.pepy.tech/badge/python-rucaptcha/month)](https://pepy.tech/project/python-rucaptcha)
64
74
 
65
75
  [![Maintainability](https://api.codeclimate.com/v1/badges/aec93bb04a277cf0dde9/maintainability)](https://codeclimate.com/github/AndreiDrang/python-rucaptcha/maintainability)
66
76
  [![Codacy Badge](https://app.codacy.com/project/badge/Grade/b4087362bd024b088b358b3e10e7a62f)](https://www.codacy.com/gh/AndreiDrang/python-rucaptcha/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=AndreiDrang/python-rucaptcha&amp;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
+ )