tweepy-self 1.6.3__py3-none-any.whl → 1.10.0b1__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- {tweepy_self-1.6.3.dist-info → tweepy_self-1.10.0b1.dist-info}/METADATA +16 -9
- tweepy_self-1.10.0b1.dist-info/RECORD +23 -0
- twitter/__init__.py +15 -5
- twitter/_capsolver/__init__.py +0 -0
- twitter/_capsolver/core/__init__.py +0 -0
- twitter/_capsolver/core/base.py +227 -0
- twitter/_capsolver/core/config.py +36 -0
- twitter/_capsolver/core/enum.py +66 -0
- twitter/_capsolver/core/serializer.py +85 -0
- twitter/_capsolver/fun_captcha.py +260 -0
- twitter/account.py +17 -13
- twitter/base/__init__.py +2 -2
- twitter/base/client.py +4 -4
- twitter/client.py +388 -222
- twitter/errors.py +14 -7
- twitter/models.py +126 -50
- twitter/utils/__init__.py +2 -0
- twitter/utils/other.py +13 -0
- tweepy_self-1.6.3.dist-info/RECORD +0 -16
- {tweepy_self-1.6.3.dist-info → tweepy_self-1.10.0b1.dist-info}/WHEEL +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: tweepy-self
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.10.0b1
|
4
4
|
Summary: Twitter (selfbot) for Python!
|
5
5
|
Home-page: https://github.com/alenkimov/tweepy-self
|
6
6
|
Author: Alen
|
@@ -9,15 +9,19 @@ Requires-Python: >=3.11,<4.0
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
10
10
|
Classifier: Programming Language :: Python :: 3.11
|
11
11
|
Classifier: Programming Language :: Python :: 3.12
|
12
|
+
Requires-Dist: aiohttp (>=3.9,<4.0)
|
12
13
|
Requires-Dist: beautifulsoup4 (>=4,<5)
|
13
|
-
Requires-Dist: better-proxy (
|
14
|
-
Requires-Dist: curl_cffi (==0.6.
|
14
|
+
Requires-Dist: better-proxy (>=1.1,<2.0)
|
15
|
+
Requires-Dist: curl_cffi (==0.6.2)
|
16
|
+
Requires-Dist: loguru (>=0.7,<0.8)
|
15
17
|
Requires-Dist: lxml (>=5,<6)
|
16
18
|
Requires-Dist: pydantic (>=1)
|
17
19
|
Requires-Dist: pyotp (>=2,<3)
|
18
|
-
Requires-Dist:
|
20
|
+
Requires-Dist: requests (>=2,<3)
|
21
|
+
Requires-Dist: tenacity (>=8,<9)
|
19
22
|
Requires-Dist: yarl (>=1,<2)
|
20
23
|
Project-URL: Repository, https://github.com/alenkimov/tweepy-self
|
24
|
+
Project-URL: Source, https://github.com/alenkimov/tweepy-self
|
21
25
|
Description-Content-Type: text/markdown
|
22
26
|
|
23
27
|
# Tweepy-self
|
@@ -99,9 +103,10 @@ Automating user accounts is against the Twitter ToS. This library is a proof of
|
|
99
103
|
|
100
104
|
### Примеры работы
|
101
105
|
Запрос информации о пользователе:
|
106
|
+
|
102
107
|
```python
|
103
108
|
# Запрос информации о текущем пользователе:
|
104
|
-
me = await twitter_client.
|
109
|
+
me = await twitter_client.request_user()
|
105
110
|
print(f"[{account.short_auth_token}] {me}")
|
106
111
|
print(f"Аккаунт создан: {me.created_at}")
|
107
112
|
print(f"Following (подписан ты): {me.followings_count}")
|
@@ -109,17 +114,18 @@ print(f"Followers (подписаны на тебя): {me.followers_count}")
|
|
109
114
|
print(f"Прочая информация: {me.raw_data}")
|
110
115
|
|
111
116
|
# Запрос информации об ином пользователе:
|
112
|
-
elonmusk = await twitter.
|
117
|
+
elonmusk = await twitter.request_user("@elonmusk")
|
113
118
|
print(elonmusk)
|
114
119
|
```
|
115
120
|
|
116
121
|
Смена имени пользователя и пароля:
|
122
|
+
|
117
123
|
```python
|
118
124
|
account = twitter.Account("auth_token", password="password")
|
119
125
|
...
|
120
126
|
await twitter_client.change_username("new_username")
|
121
|
-
await twitter_client.
|
122
|
-
print(f"New username: {account.
|
127
|
+
await twitter_client.request_user()
|
128
|
+
print(f"New username: {account.username}")
|
123
129
|
|
124
130
|
await twitter_client.change_password("new_password")
|
125
131
|
print(f"New password: {account.password}")
|
@@ -165,8 +171,9 @@ bind_code = await twitter_client.oauth_2(**bind_data)
|
|
165
171
|
```
|
166
172
|
|
167
173
|
Отправка сообщения:
|
174
|
+
|
168
175
|
```python
|
169
|
-
bro = await twitter_client.
|
176
|
+
bro = await twitter_client.request_user("@username")
|
170
177
|
await twitter_client.send_message(bro.id, "I love you!")
|
171
178
|
```
|
172
179
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
twitter/__init__.py,sha256=-CmcPdm1z-OkG8LkJVe75PwdYKBqBfMpD9WdoXcnGuc,732
|
2
|
+
twitter/_capsolver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
+
twitter/_capsolver/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
+
twitter/_capsolver/core/base.py,sha256=In3qDLgRh1z1UZLaLFgYcDEdnqW3d62PVzgEjU2S4BU,8883
|
5
|
+
twitter/_capsolver/core/config.py,sha256=8_eXT6N2hBheN2uCMNhqk8tLZRJjLDTYLK208fqIkhM,1054
|
6
|
+
twitter/_capsolver/core/enum.py,sha256=ivfAEN6jrg3iaq5C3H7CuRqsvOloX1b8lF8cLa3zaiY,1741
|
7
|
+
twitter/_capsolver/core/serializer.py,sha256=xPEUIPgytuw2wM1ubTY3RMhJGVyp_d3bokPTx0BjF0c,2602
|
8
|
+
twitter/_capsolver/fun_captcha.py,sha256=VVbTmn08cGnvPMGdJmPxaLfAIPxyA68oTSAyEL8RWnU,10974
|
9
|
+
twitter/account.py,sha256=joAB5Zw-Le5E3kOZ-1nb4DPGlTqWYv2Vs6gJ3cwu7is,3175
|
10
|
+
twitter/base/__init__.py,sha256=Q2ko0HeOS5tiBnDVKxxaZYetwRR3YXJ67ujL3oThGd4,141
|
11
|
+
twitter/base/client.py,sha256=J_iL4ZGfwTbZ2gpjtFCbBxNgt7weJ55EeMGzYsLtjf4,500
|
12
|
+
twitter/base/session.py,sha256=JFPS-9Qae1iY3NfNcywxvWWmRDijaU_Rjs3WaQ00iFA,2071
|
13
|
+
twitter/client.py,sha256=CySQ-hTFiPGFKhPBNw4nn_xnO5hdpjmXK90QpSEzRG4,66878
|
14
|
+
twitter/enums.py,sha256=-OH6Ibxarq5qt4E2AhkProVawcEyIf5YG_h_G5xiV9Y,270
|
15
|
+
twitter/errors.py,sha256=oNa0Neos80ZK4-0FBzqgxXonH564qFnoN-kavHalfR4,5274
|
16
|
+
twitter/models.py,sha256=7yObMPUUEwJEbraHzFwmUKd91UhR2-zyfJTm4xIqrSQ,4834
|
17
|
+
twitter/utils/__init__.py,sha256=usxpfcRQ7zxTTgZ-i425tT7hIz73Pwh9FDj4t6O3dYg,663
|
18
|
+
twitter/utils/file.py,sha256=Sz2KEF9DnL04aOP1XabuMYMMF4VR8dJ_KWMEVvQ666Y,1120
|
19
|
+
twitter/utils/html.py,sha256=hVtIRFI2yRAdWEaShFNBG-_ZWxd16og8i8OVDnFy5Hc,1971
|
20
|
+
twitter/utils/other.py,sha256=9RIYF2AMdmNKIwClG3jBP7zlvxZPEgYfuHaIiOhURzM,1061
|
21
|
+
tweepy_self-1.10.0b1.dist-info/METADATA,sha256=FRxYUeZHlrxUB9Jr_nbxlhEkLc1pjO-ik_XiShkwARg,9438
|
22
|
+
tweepy_self-1.10.0b1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
23
|
+
tweepy_self-1.10.0b1.dist-info/RECORD,,
|
twitter/__init__.py
CHANGED
@@ -6,14 +6,23 @@ A basic wrapper for the Twitter user API.
|
|
6
6
|
"""
|
7
7
|
|
8
8
|
from .client import Client
|
9
|
-
from .account import
|
10
|
-
|
9
|
+
from .account import (
|
10
|
+
Account,
|
11
|
+
AccountStatus,
|
12
|
+
load_accounts_from_file,
|
13
|
+
extract_accounts_to_file,
|
14
|
+
)
|
15
|
+
from .models import Tweet, User, Media, Image
|
11
16
|
from . import errors, utils
|
12
17
|
|
13
18
|
__all__ = [
|
14
19
|
"Client",
|
15
20
|
"Account",
|
16
21
|
"AccountStatus",
|
22
|
+
"Tweet",
|
23
|
+
"User",
|
24
|
+
"Media",
|
25
|
+
"Image",
|
17
26
|
"utils",
|
18
27
|
"errors",
|
19
28
|
"load_accounts_from_file",
|
@@ -22,9 +31,10 @@ __all__ = [
|
|
22
31
|
|
23
32
|
|
24
33
|
import warnings
|
34
|
+
|
25
35
|
# HACK: Ignore event loop warnings from curl_cffi
|
26
|
-
warnings.filterwarnings(
|
36
|
+
warnings.filterwarnings("ignore", module="curl_cffi")
|
27
37
|
|
38
|
+
from loguru import logger
|
28
39
|
|
29
|
-
|
30
|
-
config.APP_ID = "6F895B2F-F454-44D1-8FE0-77ACAD3DBDC8"
|
40
|
+
logger.disable("twitter")
|
File without changes
|
File without changes
|
@@ -0,0 +1,227 @@
|
|
1
|
+
import time
|
2
|
+
import asyncio
|
3
|
+
import logging
|
4
|
+
from typing import Any, Dict, Type
|
5
|
+
from urllib import parse
|
6
|
+
|
7
|
+
import aiohttp
|
8
|
+
import requests
|
9
|
+
from pydantic import BaseModel
|
10
|
+
from requests.adapters import HTTPAdapter
|
11
|
+
|
12
|
+
from .enum import ResponseStatusEnm, EndpointPostfixEnm
|
13
|
+
from .config import RETRIES, REQUEST_URL, VALID_STATUS_CODES, attempts_generator
|
14
|
+
from .serializer import (
|
15
|
+
CaptchaOptionsSer,
|
16
|
+
CaptchaResponseSer,
|
17
|
+
RequestCreateTaskSer,
|
18
|
+
RequestGetTaskResultSer,
|
19
|
+
)
|
20
|
+
|
21
|
+
|
22
|
+
class BaseCaptcha:
|
23
|
+
"""
|
24
|
+
Basic Captcha solving class
|
25
|
+
|
26
|
+
Args:
|
27
|
+
api_key: Capsolver API key
|
28
|
+
captcha_type: Captcha type name, like `ReCaptchaV2Task` and etc.
|
29
|
+
sleep_time: The waiting time between requests to get the result of the Captcha
|
30
|
+
request_url: API address for sending requests
|
31
|
+
"""
|
32
|
+
|
33
|
+
def __init__(
|
34
|
+
self,
|
35
|
+
api_key: str,
|
36
|
+
sleep_time: int = 5,
|
37
|
+
request_url: str = REQUEST_URL,
|
38
|
+
**kwargs,
|
39
|
+
):
|
40
|
+
# assign args to validator
|
41
|
+
self.__params = CaptchaOptionsSer(**locals())
|
42
|
+
self.__request_url = request_url
|
43
|
+
|
44
|
+
# prepare session
|
45
|
+
self.__session = requests.Session()
|
46
|
+
self.__session.mount("http://", HTTPAdapter(max_retries=RETRIES))
|
47
|
+
self.__session.mount("https://", HTTPAdapter(max_retries=RETRIES))
|
48
|
+
|
49
|
+
def _prepare_create_task_payload(self, serializer: Type[BaseModel], create_params: Dict[str, Any] = None) -> None:
|
50
|
+
"""
|
51
|
+
Method prepare `createTask` payload
|
52
|
+
|
53
|
+
Args:
|
54
|
+
serializer: Serializer for task creation
|
55
|
+
create_params: Parameters for task creation payload
|
56
|
+
|
57
|
+
Examples:
|
58
|
+
|
59
|
+
>>> self._prepare_create_task_payload(serializer=PostRequestSer, create_params={})
|
60
|
+
|
61
|
+
"""
|
62
|
+
self.task_payload = serializer(clientKey=self.__params.api_key)
|
63
|
+
# added task params to payload
|
64
|
+
self.task_payload.task = {**create_params} if create_params else {}
|
65
|
+
|
66
|
+
def __enter__(self):
|
67
|
+
return self
|
68
|
+
|
69
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
70
|
+
if exc_type:
|
71
|
+
return False
|
72
|
+
return True
|
73
|
+
|
74
|
+
async def __aenter__(self):
|
75
|
+
return self
|
76
|
+
|
77
|
+
async def __aexit__(self, exc_type, exc_value, traceback):
|
78
|
+
if exc_type:
|
79
|
+
return False
|
80
|
+
return True
|
81
|
+
|
82
|
+
"""
|
83
|
+
Sync part
|
84
|
+
"""
|
85
|
+
|
86
|
+
def _processing_captcha(
|
87
|
+
self, create_params: dict, serializer: Type[BaseModel] = RequestCreateTaskSer
|
88
|
+
) -> CaptchaResponseSer:
|
89
|
+
self._prepare_create_task_payload(serializer=serializer, create_params=create_params)
|
90
|
+
self.created_task_data = CaptchaResponseSer(**self._create_task())
|
91
|
+
|
92
|
+
# if task created and ready - return result
|
93
|
+
if self.created_task_data.status == ResponseStatusEnm.Ready.value:
|
94
|
+
return self.created_task_data
|
95
|
+
# if captcha is not ready but task success created - waiting captcha result
|
96
|
+
elif self.created_task_data.errorId == 0:
|
97
|
+
return self._get_result()
|
98
|
+
return self.created_task_data
|
99
|
+
|
100
|
+
def _create_task(self, url_postfix: str = EndpointPostfixEnm.CREATE_TASK.value) -> dict:
|
101
|
+
"""
|
102
|
+
Function send SYNC request to service and wait for result
|
103
|
+
"""
|
104
|
+
try:
|
105
|
+
resp = self.__session.post(
|
106
|
+
parse.urljoin(self.__request_url, url_postfix), json=self.task_payload.dict(exclude_none=True)
|
107
|
+
)
|
108
|
+
if resp.status_code in VALID_STATUS_CODES:
|
109
|
+
return resp.json()
|
110
|
+
else:
|
111
|
+
raise ValueError(resp.raise_for_status())
|
112
|
+
except Exception as error:
|
113
|
+
logging.exception(error)
|
114
|
+
raise
|
115
|
+
|
116
|
+
def _get_result(self, url_postfix: str = EndpointPostfixEnm.GET_TASK_RESULT.value) -> CaptchaResponseSer:
|
117
|
+
"""
|
118
|
+
Method send SYNC request to service and wait for result
|
119
|
+
"""
|
120
|
+
# initial waiting
|
121
|
+
time.sleep(self.__params.sleep_time)
|
122
|
+
|
123
|
+
get_result_payload = RequestGetTaskResultSer(
|
124
|
+
clientKey=self.__params.api_key, taskId=self.created_task_data.taskId
|
125
|
+
)
|
126
|
+
attempts = attempts_generator()
|
127
|
+
for _ in attempts:
|
128
|
+
try:
|
129
|
+
resp = self.__session.post(
|
130
|
+
parse.urljoin(self.__request_url, url_postfix), json=get_result_payload.dict(exclude_none=True)
|
131
|
+
)
|
132
|
+
if resp.status_code in VALID_STATUS_CODES:
|
133
|
+
result_data = CaptchaResponseSer(**resp.json())
|
134
|
+
if result_data.status in (ResponseStatusEnm.Ready, ResponseStatusEnm.Failed):
|
135
|
+
# if captcha ready\failed or have unknown status - return exist data
|
136
|
+
return result_data
|
137
|
+
else:
|
138
|
+
raise ValueError(resp.raise_for_status())
|
139
|
+
except Exception as error:
|
140
|
+
logging.exception(error)
|
141
|
+
raise
|
142
|
+
|
143
|
+
# if captcha just created or in processing now - wait
|
144
|
+
time.sleep(self.__params.sleep_time)
|
145
|
+
# default response if server is silent
|
146
|
+
return CaptchaResponseSer(
|
147
|
+
errorId=1,
|
148
|
+
errorCode="ERROR_CAPTCHA_UNSOLVABLE",
|
149
|
+
errorDescription="Captcha not recognized",
|
150
|
+
taskId=self.created_task_data.taskId,
|
151
|
+
status=ResponseStatusEnm.Failed,
|
152
|
+
)
|
153
|
+
|
154
|
+
"""
|
155
|
+
Async part
|
156
|
+
"""
|
157
|
+
|
158
|
+
async def _aio_processing_captcha(
|
159
|
+
self, create_params: dict, serializer: Type[BaseModel] = RequestCreateTaskSer
|
160
|
+
) -> CaptchaResponseSer:
|
161
|
+
self._prepare_create_task_payload(serializer=serializer, create_params=create_params)
|
162
|
+
self.created_task_data = CaptchaResponseSer(**await self._aio_create_task())
|
163
|
+
|
164
|
+
# if task created and already ready - return result
|
165
|
+
if self.created_task_data.status == ResponseStatusEnm.Ready.value:
|
166
|
+
return self.created_task_data
|
167
|
+
# if captcha is not ready but task success created - waiting captcha result
|
168
|
+
elif self.created_task_data.errorId == 0:
|
169
|
+
return await self._aio_get_result()
|
170
|
+
return self.created_task_data
|
171
|
+
|
172
|
+
async def _aio_create_task(self, url_postfix: str = EndpointPostfixEnm.CREATE_TASK.value) -> dict:
|
173
|
+
"""
|
174
|
+
Function send the ASYNC request to service and wait for result
|
175
|
+
"""
|
176
|
+
async with aiohttp.ClientSession() as session:
|
177
|
+
try:
|
178
|
+
async with session.post(
|
179
|
+
parse.urljoin(self.__request_url, url_postfix), json=self.task_payload.dict(exclude_none=True)
|
180
|
+
) as resp:
|
181
|
+
if resp.status in VALID_STATUS_CODES:
|
182
|
+
return await resp.json()
|
183
|
+
else:
|
184
|
+
raise ValueError(resp.reason)
|
185
|
+
except Exception as error:
|
186
|
+
logging.exception(error)
|
187
|
+
raise
|
188
|
+
|
189
|
+
async def _aio_get_result(self, url_postfix: str = EndpointPostfixEnm.GET_TASK_RESULT.value) -> CaptchaResponseSer:
|
190
|
+
"""
|
191
|
+
Function send the ASYNC request to service and wait for result
|
192
|
+
"""
|
193
|
+
# initial waiting
|
194
|
+
await asyncio.sleep(self.__params.sleep_time)
|
195
|
+
|
196
|
+
get_result_payload = RequestGetTaskResultSer(
|
197
|
+
clientKey=self.__params.api_key, taskId=self.created_task_data.taskId
|
198
|
+
)
|
199
|
+
attempts = attempts_generator()
|
200
|
+
async with aiohttp.ClientSession() as session:
|
201
|
+
for _ in attempts:
|
202
|
+
try:
|
203
|
+
async with session.post(
|
204
|
+
parse.urljoin(self.__request_url, url_postfix), json=get_result_payload.dict(exclude_none=True)
|
205
|
+
) as resp:
|
206
|
+
if resp.status in VALID_STATUS_CODES:
|
207
|
+
result_data = CaptchaResponseSer(**await resp.json())
|
208
|
+
if result_data.status in (ResponseStatusEnm.Ready, ResponseStatusEnm.Failed):
|
209
|
+
# if captcha ready\failed or have unknown status - return exist data
|
210
|
+
return result_data
|
211
|
+
else:
|
212
|
+
raise ValueError(resp.reason)
|
213
|
+
except Exception as error:
|
214
|
+
logging.exception(error)
|
215
|
+
raise
|
216
|
+
|
217
|
+
# if captcha just created or in processing now - wait
|
218
|
+
await asyncio.sleep(self.__params.sleep_time)
|
219
|
+
|
220
|
+
# default response if server is silent
|
221
|
+
return CaptchaResponseSer(
|
222
|
+
errorId=1,
|
223
|
+
errorCode="ERROR_CAPTCHA_UNSOLVABLE",
|
224
|
+
errorDescription="Captcha not recognized",
|
225
|
+
taskId=self.created_task_data.taskId,
|
226
|
+
status=ResponseStatusEnm.Failed,
|
227
|
+
)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
from typing import Generator
|
2
|
+
|
3
|
+
from tenacity import AsyncRetrying, wait_fixed, stop_after_attempt
|
4
|
+
from requests.adapters import Retry
|
5
|
+
|
6
|
+
RETRIES = Retry(total=5, backoff_factor=0.9, status_forcelist=[500, 502, 503, 504])
|
7
|
+
ASYNC_RETRIES = AsyncRetrying(wait=wait_fixed(5), stop=stop_after_attempt(5), reraise=True)
|
8
|
+
|
9
|
+
REQUEST_URL = "https://api.capsolver.com"
|
10
|
+
VALID_STATUS_CODES = (200, 202, 400, 401, 405)
|
11
|
+
|
12
|
+
APP_ID = "6F895B2F-F454-44D1-8FE0-77ACAD3DBDC8"
|
13
|
+
|
14
|
+
|
15
|
+
# Connection retry generator
|
16
|
+
def attempts_generator(amount: int = 16) -> Generator:
|
17
|
+
"""
|
18
|
+
Function generates a generator of length equal to `amount`
|
19
|
+
|
20
|
+
Args:
|
21
|
+
amount: number of attempts generated
|
22
|
+
|
23
|
+
Yields:
|
24
|
+
int: The next number in the range of 1 to ``amount`` - 1.
|
25
|
+
|
26
|
+
Examples:
|
27
|
+
Examples should be written in doctest format, and should illustrate how
|
28
|
+
to use the function.
|
29
|
+
|
30
|
+
>>> print([i for i in attempts_generator(5)])
|
31
|
+
[1, 2, 3, 4]
|
32
|
+
|
33
|
+
Returns:
|
34
|
+
Attempt number
|
35
|
+
"""
|
36
|
+
yield from range(1, amount)
|
@@ -0,0 +1,66 @@
|
|
1
|
+
from enum import Enum
|
2
|
+
from types import DynamicClassAttribute
|
3
|
+
from typing import List
|
4
|
+
|
5
|
+
|
6
|
+
class MyEnum(Enum):
|
7
|
+
@classmethod
|
8
|
+
def list(cls) -> List[Enum]:
|
9
|
+
return list(map(lambda c: c, cls))
|
10
|
+
|
11
|
+
@classmethod
|
12
|
+
def list_values(cls) -> List[str]:
|
13
|
+
return list(map(lambda c: c.value, cls))
|
14
|
+
|
15
|
+
@classmethod
|
16
|
+
def list_names(cls) -> List[str]:
|
17
|
+
return list(map(lambda c: c.name, cls))
|
18
|
+
|
19
|
+
@DynamicClassAttribute
|
20
|
+
def name(self) -> str:
|
21
|
+
"""
|
22
|
+
The name of the Enum member
|
23
|
+
"""
|
24
|
+
return self._name_
|
25
|
+
|
26
|
+
@DynamicClassAttribute
|
27
|
+
def value(self) -> str:
|
28
|
+
"""
|
29
|
+
The name of the Enum member
|
30
|
+
"""
|
31
|
+
return self._value_
|
32
|
+
|
33
|
+
|
34
|
+
class EndpointPostfixEnm(str, MyEnum):
|
35
|
+
"""
|
36
|
+
Enum stored URL postfixes for API endpoints
|
37
|
+
"""
|
38
|
+
|
39
|
+
GET_BALANCE = "getBalance"
|
40
|
+
CREATE_TASK = "createTask"
|
41
|
+
GET_TASK_RESULT = "getTaskResult"
|
42
|
+
AKAMAI_BMP_INVOKE = "akamaibmp/invoke"
|
43
|
+
AKAMAI_WEB_INVOKE = "akamaiweb/invoke"
|
44
|
+
|
45
|
+
|
46
|
+
class FunCaptchaTypeEnm(str, MyEnum):
|
47
|
+
FunCaptchaTask = "FunCaptchaTask"
|
48
|
+
FunCaptchaTaskProxyLess = "FunCaptchaTaskProxyLess"
|
49
|
+
|
50
|
+
|
51
|
+
class FunCaptchaClassificationTypeEnm(str, MyEnum):
|
52
|
+
FunCaptchaClassification = "FunCaptchaClassification"
|
53
|
+
|
54
|
+
|
55
|
+
class ResponseStatusEnm(str, MyEnum):
|
56
|
+
"""
|
57
|
+
Enum store results `status` field variants
|
58
|
+
|
59
|
+
Notes:
|
60
|
+
https://docs.capsolver.com/guide/api-createtask.html
|
61
|
+
"""
|
62
|
+
|
63
|
+
Idle = "idle" # Task created
|
64
|
+
Processing = "processing" # Task is not ready yet
|
65
|
+
Ready = "ready" # Task completed, solution object can be found in solution property
|
66
|
+
Failed = "failed" # Task failed, check the errorDescription to know why failed.
|
@@ -0,0 +1,85 @@
|
|
1
|
+
from typing import Any, Dict, List, Literal, Optional
|
2
|
+
|
3
|
+
from pydantic import Field, BaseModel, conint
|
4
|
+
|
5
|
+
from .enum import ResponseStatusEnm
|
6
|
+
from .config import APP_ID
|
7
|
+
|
8
|
+
"""
|
9
|
+
HTTP API Request ser
|
10
|
+
"""
|
11
|
+
|
12
|
+
|
13
|
+
class PostRequestSer(BaseModel):
|
14
|
+
clientKey: str = Field(..., description="Client account key, can be found in user account")
|
15
|
+
task: dict = Field(None, description="Task object")
|
16
|
+
|
17
|
+
|
18
|
+
class TaskSer(BaseModel):
|
19
|
+
type: str = Field(..., description="Task type name", alias="captcha_type")
|
20
|
+
|
21
|
+
|
22
|
+
class RequestCreateTaskSer(PostRequestSer):
|
23
|
+
appId: Literal[APP_ID] = APP_ID
|
24
|
+
|
25
|
+
|
26
|
+
class RequestGetTaskResultSer(PostRequestSer):
|
27
|
+
taskId: Optional[str] = Field(None, description="ID created by the createTask method")
|
28
|
+
|
29
|
+
|
30
|
+
"""
|
31
|
+
HTTP API Response ser
|
32
|
+
"""
|
33
|
+
|
34
|
+
|
35
|
+
class ResponseSer(BaseModel):
|
36
|
+
errorId: int = Field(..., description="Error message: `False` - no error, `True` - with error")
|
37
|
+
# error info
|
38
|
+
errorCode: Optional[str] = Field(None, description="Error code")
|
39
|
+
errorDescription: Optional[str] = Field(None, description="Error description")
|
40
|
+
|
41
|
+
|
42
|
+
class CaptchaResponseSer(ResponseSer):
|
43
|
+
taskId: Optional[str] = Field(None, description="Task ID for future use in getTaskResult method.")
|
44
|
+
status: ResponseStatusEnm = Field(ResponseStatusEnm.Processing, description="Task current status")
|
45
|
+
solution: Dict[str, Any] = Field(None, description="Task result data. Different for each type of task.")
|
46
|
+
|
47
|
+
class Config:
|
48
|
+
populate_by_name = True
|
49
|
+
|
50
|
+
|
51
|
+
class ControlResponseSer(ResponseSer):
|
52
|
+
balance: Optional[float] = Field(0, description="Account balance value in USD")
|
53
|
+
|
54
|
+
|
55
|
+
"""
|
56
|
+
Other ser
|
57
|
+
"""
|
58
|
+
|
59
|
+
|
60
|
+
class CaptchaOptionsSer(BaseModel):
|
61
|
+
api_key: str
|
62
|
+
sleep_time: conint(ge=5) = 5
|
63
|
+
|
64
|
+
|
65
|
+
"""
|
66
|
+
Captcha tasks ser
|
67
|
+
"""
|
68
|
+
|
69
|
+
|
70
|
+
class FunCaptchaClassificationOptionsSer(TaskSer):
|
71
|
+
images: List[str] = Field(..., description="Base64-encoded images, do not include 'data:image/***;base64,'")
|
72
|
+
question: str = Field(
|
73
|
+
...,
|
74
|
+
description="Question name. this param value from API response game_variant field. Exmaple: maze,maze2,flockCompass,3d_rollball_animals",
|
75
|
+
)
|
76
|
+
|
77
|
+
|
78
|
+
class FunCaptchaSer(TaskSer):
|
79
|
+
websiteURL: str = Field(..., description="Address of a webpage with Funcaptcha")
|
80
|
+
websitePublicKey: str = Field(..., description="Funcaptcha website key.")
|
81
|
+
funcaptchaApiJSSubdomain: Optional[str] = Field(
|
82
|
+
None,
|
83
|
+
description="A special subdomain of funcaptcha.com, from which the JS captcha widget should be loaded."
|
84
|
+
"Most FunCaptcha installations work from shared domains.",
|
85
|
+
)
|