tweepy-self 1.6.3__tar.gz → 1.10.0b1__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (24) hide show
  1. {tweepy_self-1.6.3 → tweepy_self-1.10.0b1}/PKG-INFO +16 -9
  2. {tweepy_self-1.6.3 → tweepy_self-1.10.0b1}/README.md +8 -5
  3. {tweepy_self-1.6.3 → tweepy_self-1.10.0b1}/pyproject.toml +10 -4
  4. {tweepy_self-1.6.3 → tweepy_self-1.10.0b1}/twitter/__init__.py +15 -5
  5. tweepy_self-1.10.0b1/twitter/_capsolver/__init__.py +0 -0
  6. tweepy_self-1.10.0b1/twitter/_capsolver/core/__init__.py +0 -0
  7. tweepy_self-1.10.0b1/twitter/_capsolver/core/base.py +227 -0
  8. tweepy_self-1.10.0b1/twitter/_capsolver/core/config.py +36 -0
  9. tweepy_self-1.10.0b1/twitter/_capsolver/core/enum.py +66 -0
  10. tweepy_self-1.10.0b1/twitter/_capsolver/core/serializer.py +85 -0
  11. tweepy_self-1.10.0b1/twitter/_capsolver/fun_captcha.py +260 -0
  12. {tweepy_self-1.6.3 → tweepy_self-1.10.0b1}/twitter/account.py +17 -13
  13. {tweepy_self-1.6.3 → tweepy_self-1.10.0b1}/twitter/base/__init__.py +2 -2
  14. {tweepy_self-1.6.3 → tweepy_self-1.10.0b1}/twitter/base/client.py +4 -4
  15. {tweepy_self-1.6.3 → tweepy_self-1.10.0b1}/twitter/client.py +388 -222
  16. {tweepy_self-1.6.3 → tweepy_self-1.10.0b1}/twitter/errors.py +14 -7
  17. tweepy_self-1.10.0b1/twitter/models.py +155 -0
  18. {tweepy_self-1.6.3 → tweepy_self-1.10.0b1}/twitter/utils/__init__.py +2 -0
  19. {tweepy_self-1.6.3 → tweepy_self-1.10.0b1}/twitter/utils/other.py +13 -0
  20. tweepy_self-1.6.3/twitter/models.py +0 -79
  21. {tweepy_self-1.6.3 → tweepy_self-1.10.0b1}/twitter/base/session.py +0 -0
  22. {tweepy_self-1.6.3 → tweepy_self-1.10.0b1}/twitter/enums.py +0 -0
  23. {tweepy_self-1.6.3 → tweepy_self-1.10.0b1}/twitter/utils/file.py +0 -0
  24. {tweepy_self-1.6.3 → tweepy_self-1.10.0b1}/twitter/utils/html.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tweepy-self
3
- Version: 1.6.3
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 (==1.1.1)
14
- Requires-Dist: curl_cffi (==0.6.0b9)
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: python3-capsolver (>=0.9,<0.10)
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.request_user_data()
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.request_user_data("@elonmusk")
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.request_user_data()
122
- print(f"New username: {account.data.username}")
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.request_user_data("@username")
176
+ bro = await twitter_client.request_user("@username")
170
177
  await twitter_client.send_message(bro.id, "I love you!")
171
178
  ```
172
179
 
@@ -77,9 +77,10 @@ Automating user accounts is against the Twitter ToS. This library is a proof of
77
77
 
78
78
  ### Примеры работы
79
79
  Запрос информации о пользователе:
80
+
80
81
  ```python
81
82
  # Запрос информации о текущем пользователе:
82
- me = await twitter_client.request_user_data()
83
+ me = await twitter_client.request_user()
83
84
  print(f"[{account.short_auth_token}] {me}")
84
85
  print(f"Аккаунт создан: {me.created_at}")
85
86
  print(f"Following (подписан ты): {me.followings_count}")
@@ -87,17 +88,18 @@ print(f"Followers (подписаны на тебя): {me.followers_count}")
87
88
  print(f"Прочая информация: {me.raw_data}")
88
89
 
89
90
  # Запрос информации об ином пользователе:
90
- elonmusk = await twitter.request_user_data("@elonmusk")
91
+ elonmusk = await twitter.request_user("@elonmusk")
91
92
  print(elonmusk)
92
93
  ```
93
94
 
94
95
  Смена имени пользователя и пароля:
96
+
95
97
  ```python
96
98
  account = twitter.Account("auth_token", password="password")
97
99
  ...
98
100
  await twitter_client.change_username("new_username")
99
- await twitter_client.request_user_data()
100
- print(f"New username: {account.data.username}")
101
+ await twitter_client.request_user()
102
+ print(f"New username: {account.username}")
101
103
 
102
104
  await twitter_client.change_password("new_password")
103
105
  print(f"New password: {account.password}")
@@ -143,8 +145,9 @@ bind_code = await twitter_client.oauth_2(**bind_data)
143
145
  ```
144
146
 
145
147
  Отправка сообщения:
148
+
146
149
  ```python
147
- bro = await twitter_client.request_user_data("@username")
150
+ bro = await twitter_client.request_user("@username")
148
151
  await twitter_client.send_message(bro.id, "I love you!")
149
152
  ```
150
153
 
@@ -1,22 +1,28 @@
1
1
  [tool.poetry]
2
2
  name = "tweepy-self"
3
- version = "1.6.3"
3
+ version = "1.10.0.b1"
4
4
  description = "Twitter (selfbot) for Python!"
5
5
  authors = ["Alen <alen.kimov@gmail.com>"]
6
6
  readme = "README.md"
7
7
  repository = "https://github.com/alenkimov/tweepy-self"
8
8
  packages = [{include = "twitter"}]
9
9
 
10
+ [tool.poetry.urls]
11
+ Source = "https://github.com/alenkimov/tweepy-self"
12
+
10
13
  [tool.poetry.dependencies]
11
14
  python = "^3.11"
12
- curl_cffi = {version = "0.6.0b9", allow-prereleases = true}
13
- python3-capsolver = "^0.9"
14
- better-proxy = "1.1.1"
15
+ curl_cffi = "0.6.2"
16
+ better-proxy = "^1.1"
15
17
  beautifulsoup4 = "^4"
16
18
  pydantic = ">=1"
17
19
  lxml = "^5"
18
20
  pyotp = "^2"
19
21
  yarl = "^1"
22
+ aiohttp = "^3.9"
23
+ tenacity = "^8"
24
+ requests = "^2"
25
+ loguru = "^0.7"
20
26
 
21
27
  [tool.poetry.group.dev.dependencies]
22
28
  black = "^24"
@@ -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 Account, AccountStatus, load_accounts_from_file, extract_accounts_to_file
10
- from .models import Tweet, UserData
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('ignore', module='curl_cffi')
36
+ warnings.filterwarnings("ignore", module="curl_cffi")
27
37
 
38
+ from loguru import logger
28
39
 
29
- from python3_capsolver.core import config
30
- config.APP_ID = "6F895B2F-F454-44D1-8FE0-77ACAD3DBDC8"
40
+ logger.disable("twitter")
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
+ )