upd structure && upd control class
This commit is contained in:
parent
ef352bae56
commit
36c8b1c851
|
@ -4,7 +4,7 @@ omit =
|
|||
*/tests/*
|
||||
|
||||
include =
|
||||
*/python3_anticaptcha/*
|
||||
*/src/python3_anticaptcha/*
|
||||
|
||||
|
||||
[report]
|
||||
|
@ -13,4 +13,4 @@ omit =
|
|||
*/tests/*
|
||||
|
||||
include =
|
||||
*/python3_anticaptcha/*
|
||||
*/src/python3_anticaptcha/*
|
|
@ -20,9 +20,6 @@ jobs:
|
|||
- name: Build docs requirements
|
||||
run: pip install -r docs/requirements.txt
|
||||
|
||||
- name: Build library requirements
|
||||
run: pip install -r src/requirements.txt
|
||||
|
||||
- name: Build docs
|
||||
run: make doc
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@ jobs:
|
|||
run: |
|
||||
pip install --upgrade pip
|
||||
pip install -r requirements.test.txt
|
||||
pip install -r src/requirements.txt
|
||||
|
||||
- name: Test
|
||||
run: make tests
|
||||
|
|
23
Makefile
23
Makefile
|
@ -1,8 +1,7 @@
|
|||
install:
|
||||
cd src/ && pip install -e .
|
||||
|
||||
tests:
|
||||
cd src/ && \
|
||||
tests: install
|
||||
coverage run --rcfile=.coveragerc -m pytest -s tests --disable-warnings && \
|
||||
coverage report --precision=3 --sort=cover --skip-empty --show-missing && \
|
||||
coverage html --precision=3 --skip-empty -d coverage/html/ && \
|
||||
|
@ -12,31 +11,25 @@ refactor:
|
|||
black docs/
|
||||
isort docs/
|
||||
|
||||
cd src/ && \
|
||||
autoflake --in-place \
|
||||
--recursive \
|
||||
--remove-unused-variables \
|
||||
--remove-duplicate-keys \
|
||||
--remove-all-unused-imports \
|
||||
--ignore-init-module-imports \
|
||||
python3_anticaptcha/ tests/ && \
|
||||
black python3_anticaptcha/ tests/ && \
|
||||
isort python3_anticaptcha/ tests/
|
||||
src/ tests/ && \
|
||||
black src/ tests/ && \
|
||||
isort src/ tests/
|
||||
|
||||
lint:
|
||||
cd src/ && \
|
||||
autoflake --in-place --recursive python3_anticaptcha/ --check && \
|
||||
black python3_anticaptcha/ --check && \
|
||||
isort python3_anticaptcha/ --check-only
|
||||
|
||||
release:
|
||||
pip install twine
|
||||
python setup.py upload
|
||||
autoflake --in-place --recursive src/ --check && \
|
||||
black src/ --check && \
|
||||
isort src/ --check-only
|
||||
|
||||
upload:
|
||||
pip install twine
|
||||
cd src/ && python setup.py upload
|
||||
|
||||
doc:
|
||||
doc: install
|
||||
cd docs/ && \
|
||||
make html -e
|
||||
|
|
|
@ -11,7 +11,7 @@ sys.path.insert(0, os.path.abspath("src/"))
|
|||
for x in os.walk("src/python3_anticaptcha/"):
|
||||
sys.path.insert(0, x[0])
|
||||
|
||||
from python3_anticaptcha import core, turnstile
|
||||
from python3_anticaptcha import core, control, turnstile
|
||||
from python3_anticaptcha.__version__ import __version__
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
@ -45,9 +45,7 @@ html_show_sourcelink = False
|
|||
html_context = {
|
||||
"project_links": [
|
||||
ProjectLink("PyPI Releases", "https://pypi.org/project/python3-anticaptcha/"),
|
||||
ProjectLink(
|
||||
"Source Code", "https://github.com/AndreiDrang/python3-anticaptcha"
|
||||
),
|
||||
ProjectLink("Source Code", "https://github.com/AndreiDrang/python3-anticaptcha"),
|
||||
ProjectLink(
|
||||
"AntiCaptcha",
|
||||
"http://getcaptchasolution.com/vchfpctqyz",
|
||||
|
|
|
@ -23,6 +23,7 @@ The library is intended for software developers and is used to work with the `An
|
|||
:caption: Captcha examples:
|
||||
|
||||
modules/turnstile/example.rst
|
||||
modules/control/example.rst
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
Control
|
||||
=======
|
||||
|
||||
To import this module:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from python3_anticaptcha.control import Control
|
||||
|
||||
|
||||
.. autoclass:: python3_anticaptcha.control.Control
|
||||
:members:
|
|
@ -24,6 +24,10 @@ To import this module:
|
|||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. autoclass:: core.enum.ProxyType
|
||||
.. autoclass:: core.enum.ProxyTypeEnm
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
.. autoclass:: core.enum.ControlPostfixEnm
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
|
|
@ -8,5 +8,5 @@ To import this module:
|
|||
from python3_anticaptcha.turnstile import Turnstile
|
||||
|
||||
|
||||
.. autoclass:: turnstile.Turnstile
|
||||
.. autoclass:: python3_anticaptcha.turnstile.Turnstile
|
||||
:members:
|
|
@ -1,63 +0,0 @@
|
|||
import aiohttp
|
||||
import requests
|
||||
|
||||
from python3_anticaptcha import get_app_stats_url
|
||||
|
||||
|
||||
class AntiCaptchaAppStats:
|
||||
def __init__(self, anticaptcha_key: str):
|
||||
"""
|
||||
Синхронный метод работы с балансом и жалобами
|
||||
:param anticaptcha_key: Ключ антикапчи
|
||||
"""
|
||||
self.ANTICAPTCHA_KEY = anticaptcha_key
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
if exc_type:
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_stats(self, softId: int, mode: str = "errors"):
|
||||
"""
|
||||
Получение баланса аккаунта
|
||||
:return: Возвращает актуальный баланс
|
||||
"""
|
||||
answer = requests.post(
|
||||
get_app_stats_url,
|
||||
json={"clientKey": self.ANTICAPTCHA_KEY, "softId": softId, "mode": mode},
|
||||
verify=False,
|
||||
)
|
||||
|
||||
return answer.json()
|
||||
|
||||
|
||||
class aioAntiCaptchaAppStats:
|
||||
def __init__(self, anticaptcha_key: str):
|
||||
"""
|
||||
Асинхронный метод работы с балансом и жалобами
|
||||
:param anticaptcha_key: Ключ антикапчи
|
||||
"""
|
||||
self.ANTICAPTCHA_KEY = anticaptcha_key
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
if exc_type:
|
||||
return False
|
||||
return True
|
||||
|
||||
async def get_stats(self, softId: int, mode: str = "errors"):
|
||||
"""
|
||||
Получение баланса аккаунта
|
||||
:return: Возвращает актуальный баланс
|
||||
"""
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(
|
||||
get_app_stats_url,
|
||||
json={"clientKey": self.ANTICAPTCHA_KEY, "softId": softId, "mode": mode},
|
||||
) as resp:
|
||||
return await resp.json()
|
|
@ -1,348 +0,0 @@
|
|||
import aiohttp
|
||||
import requests
|
||||
|
||||
# Адрес для получения баланса
|
||||
get_balance_url = "https://api.anti-captcha.com/getBalance"
|
||||
# Адрес для отправки жалобы на неверное решение капчи-изображения
|
||||
incorrect_imagecaptcha_url = "https://api.anti-captcha.com/reportIncorrectImageCaptcha"
|
||||
# Адрес для отправки жалобы на неверное решение ReCaptcha
|
||||
incorrect_recaptcha_url = "https://api.anti-captcha.com/reportIncorrectRecaptcha"
|
||||
# Адрес для получения информации о очереди
|
||||
get_queue_status_url = "https://api.anti-captcha.com/getQueueStats"
|
||||
# С помощью этого метода можно получить статистику трат за последние 24 часа.
|
||||
get_spend_stats_url = "https://api.anti-captcha.com/getSpendingStats"
|
||||
# Адрес для получения информации о приложении
|
||||
get_app_stats_url = "https://api.anti-captcha.com/getAppStats"
|
||||
# С помощью этого метода можно получить статистику трат за последние 24 часа.
|
||||
send_funds_url = "https://api.anti-captcha.com/sendFunds"
|
||||
|
||||
# available app stats mods
|
||||
mods = ("errors", "views", "downloads", "users", "money")
|
||||
# available complaint captcha types
|
||||
complaint_types = ("image", "recaptcha")
|
||||
# availalbe queue ID's
|
||||
queue_ids = (1, 2, 5, 6, 7, 10, 11, 12, 13, 18, 19, 20, 21, 22)
|
||||
|
||||
queues_names = (
|
||||
"English ImageToText",
|
||||
"Russian ImageToText",
|
||||
"Recaptcha Proxy-on",
|
||||
"Recaptcha Proxyless",
|
||||
"FunCaptcha",
|
||||
"Funcaptcha Proxyless",
|
||||
"Square Net Task",
|
||||
"GeeTest Proxy-on",
|
||||
"GeeTest Proxyless",
|
||||
)
|
||||
|
||||
|
||||
class AntiCaptchaControl:
|
||||
def __init__(self, anticaptcha_key: str):
|
||||
"""
|
||||
Синхронный метод работы с балансом и жалобами
|
||||
:param anticaptcha_key: Ключ антикапчи
|
||||
"""
|
||||
self.ANTICAPTCHA_KEY = anticaptcha_key
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
if exc_type:
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_balance(self) -> dict:
|
||||
"""
|
||||
Получение баланса аккаунта
|
||||
:return: Возвращает актуальный баланс
|
||||
"""
|
||||
answer = requests.post(get_balance_url, json={"clientKey": self.ANTICAPTCHA_KEY}, verify=False)
|
||||
|
||||
return answer.json()
|
||||
|
||||
def send_funds(self, accountLogin: str = None, accountEmail: str = None, amount: float = None) -> dict:
|
||||
"""
|
||||
Отправить средства другому пользователю
|
||||
В вашем аккаунте должна быть включена опция отправки средств через API.
|
||||
Включается через службу поддержки, нужно указать причину зачем вам это требуется.
|
||||
|
||||
:param accountLogin: Логин целевого аккаунта
|
||||
:param accountEmail: Адрес почты целевого аккаунта
|
||||
:param amount: Сумма
|
||||
"""
|
||||
payload = {
|
||||
"clientKey": self.ANTICAPTCHA_KEY,
|
||||
"accountLogin": accountLogin,
|
||||
"accountEmail": accountEmail,
|
||||
"amount": amount,
|
||||
}
|
||||
# get response
|
||||
answer = requests.post(send_funds_url, json=payload, verify=False)
|
||||
return answer.json()
|
||||
|
||||
def get_spend_stats(self, date: int = None, queue: str = None, softId: int = None, ip: str = None) -> dict:
|
||||
f"""
|
||||
С помощью этого метода можно получить статистику трат за последние 24 часа.
|
||||
:param date: Unix timestamp начала периода 24-х часового отчета
|
||||
:param queue: Имя очереди, может быть найдено в статистике Антикапчи.
|
||||
Если не указано, то возвращается суммированная статистика по всем очередям.
|
||||
:param softId: ID приложения из Developers Center
|
||||
:param ip: IP с которого шли запросы к API
|
||||
:return: Возвращает словарь с данными трат
|
||||
"""
|
||||
if queue and queue not in queues_names:
|
||||
raise ValueError(f"\nWrong `queue` parameter. Valid params: {queues_names}." f"\n\tYour param - `{queue}`")
|
||||
payload = {
|
||||
"clientKey": self.ANTICAPTCHA_KEY,
|
||||
"date": date,
|
||||
"queue": queue,
|
||||
"softId": softId,
|
||||
"ip": ip,
|
||||
}
|
||||
# get response
|
||||
answer = requests.post(get_spend_stats_url, json=payload, verify=False)
|
||||
return answer.json()
|
||||
|
||||
def get_app_stats(self, softId: int, mode: str = "errors") -> dict:
|
||||
"""
|
||||
Получение статистики приложения
|
||||
:return: Возвращает актуальный баланс
|
||||
"""
|
||||
if mode not in mods:
|
||||
raise ValueError(f"\nWrong `mode` parameter. Valid params: {mods}." f"\n\tYour param - `{mode}`")
|
||||
payload = {"clientKey": self.ANTICAPTCHA_KEY, "softId": softId, "mode": mode}
|
||||
answer = requests.post(get_app_stats_url, json=payload, verify=False)
|
||||
|
||||
if answer.text:
|
||||
return answer.json()
|
||||
else:
|
||||
return {"errorId": 1}
|
||||
|
||||
def complaint_on_result(self, reported_id: int, captcha_type: str = "image") -> dict:
|
||||
f"""
|
||||
Позволяет отправить жалобу на неправильно решённую капчу.
|
||||
:param reported_id: Отправляете ID капчи на которую нужно пожаловаться
|
||||
:param captcha_type: Тип капчи на который идёт жалоба. Возможные варианты:
|
||||
{complaint_types}
|
||||
:return: Возвращает True/False, в зависимости от результата
|
||||
"""
|
||||
if captcha_type not in complaint_types:
|
||||
raise ValueError(
|
||||
f"\nWrong `captcha_type` parameter. Valid params: {complaint_types}."
|
||||
f"\n\tYour param - `{captcha_type}`"
|
||||
)
|
||||
payload = {"clientKey": self.ANTICAPTCHA_KEY, "taskId": reported_id}
|
||||
# complaint on image captcha
|
||||
if captcha_type == "image":
|
||||
answer = requests.post(incorrect_imagecaptcha_url, json=payload, verify=False)
|
||||
# complaint on re-captcha
|
||||
elif captcha_type == "recaptcha":
|
||||
answer = requests.post(incorrect_recaptcha_url, json=payload, verify=False)
|
||||
return answer.json()
|
||||
|
||||
@staticmethod
|
||||
def get_queue_status(queue_id: int) -> dict:
|
||||
"""
|
||||
Получение информации о загрузке очереди, в зависимости от ID очереди.
|
||||
|
||||
Метод позволяет определить, насколько в данный момент целесообразно загружать новое задание в очередь.
|
||||
Данные в выдаче кешируются на 10 секунд.
|
||||
|
||||
Список ID очередей:
|
||||
1 - стандартная ImageToText, язык английский
|
||||
2 - стандартная ImageToText, язык русский
|
||||
5 - Recaptcha NoCaptcha
|
||||
6 - Recaptcha Proxyless
|
||||
7 - Funcaptcha
|
||||
10 - Funcaptcha Proxyless
|
||||
11 - Square Net Task
|
||||
12 - GeeTest Proxy-On
|
||||
13 - GeeTest Proxyless
|
||||
18 - Recaptcha V3 s0.3
|
||||
19 - Recaptcha V3 s0.7
|
||||
20 - Recaptcha V3 s0.9
|
||||
|
||||
Пример выдачи ответа:
|
||||
{
|
||||
"waiting":242,
|
||||
"load":60.33,
|
||||
"bid":"0.0008600982",
|
||||
"speed":10.77,
|
||||
"total": 610
|
||||
}
|
||||
:param queue_id: Номер очереди
|
||||
:return: JSON-объект
|
||||
"""
|
||||
|
||||
if queue_id not in queue_ids:
|
||||
raise ValueError(f"\nWrong `mode` parameter. Valid params: {queue_ids}." f"\n\tYour param - `{queue_id}`")
|
||||
payload = {"queueId": queue_id}
|
||||
|
||||
answer = requests.post(get_queue_status_url, json=payload, verify=False)
|
||||
|
||||
return answer.json()
|
||||
|
||||
|
||||
class aioAntiCaptchaControl:
|
||||
def __init__(self, anticaptcha_key: str):
|
||||
"""
|
||||
Асинхронный метод работы с балансом и жалобами
|
||||
:param anticaptcha_key: Ключ антикапчи
|
||||
"""
|
||||
self.ANTICAPTCHA_KEY = anticaptcha_key
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
if exc_type:
|
||||
return False
|
||||
return True
|
||||
|
||||
async def get_balance(self) -> dict:
|
||||
"""
|
||||
Получение баланса аккаунта
|
||||
:return: Возвращает актуальный баланс
|
||||
"""
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(get_balance_url, json={"clientKey": self.ANTICAPTCHA_KEY}) as resp:
|
||||
if await resp.text():
|
||||
return await resp.json()
|
||||
else:
|
||||
return {"errorId": 1}
|
||||
|
||||
async def send_funds(self, accountLogin: str = None, accountEmail: str = None, amount: float = None) -> dict:
|
||||
"""
|
||||
Отправить средства другому пользователю
|
||||
В вашем аккаунте должна быть включена опция отправки средств через API.
|
||||
Включается через службу поддержки, нужно указать причину зачем вам это требуется.
|
||||
|
||||
:param accountLogin: Логин целевого аккаунта
|
||||
:param accountEmail: Адрес почты целевого аккаунта
|
||||
:param amount: Сумма
|
||||
"""
|
||||
payload = {
|
||||
"clientKey": self.ANTICAPTCHA_KEY,
|
||||
"accountLogin": accountLogin,
|
||||
"accountEmail": accountEmail,
|
||||
"amount": amount,
|
||||
}
|
||||
# get response
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(send_funds_url, json=payload) as resp:
|
||||
if await resp.text():
|
||||
return await resp.json()
|
||||
else:
|
||||
return {"errorId": 1}
|
||||
|
||||
async def get_spend_stats(self, date: int = None, queue: str = None, softId: int = None, ip: str = None) -> dict:
|
||||
f"""
|
||||
С помощью этого метода можно получить статистику трат за последние 24 часа.
|
||||
:param date: Unix timestamp начала периода 24-х часового отчета
|
||||
:param queue: Имя очереди, может быть найдено в статистике Антикапчи.
|
||||
Если не указано, то возвращается суммированная статистика по всем очередям.
|
||||
:param softId: ID приложения из Developers Center
|
||||
:param ip: IP с которого шли запросы к API
|
||||
:return: Возвращает словарь с данными трат
|
||||
"""
|
||||
if queue and queue not in queues_names:
|
||||
raise ValueError(f"\nWrong `queue` parameter. Valid params: {queues_names}." f"\n\tYour param - `{queue}`")
|
||||
payload = {
|
||||
"clientKey": self.ANTICAPTCHA_KEY,
|
||||
"date": date,
|
||||
"queue": queue,
|
||||
"softId": softId,
|
||||
"ip": ip,
|
||||
}
|
||||
# get response
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(get_spend_stats_url, json=payload) as resp:
|
||||
if await resp.text():
|
||||
return await resp.json()
|
||||
else:
|
||||
return {"errorId": 1}
|
||||
|
||||
async def get_app_stats(self, softId: int, mode: str = "errors") -> dict:
|
||||
"""
|
||||
Получение баланса аккаунта
|
||||
:return: Возвращает актуальный баланс
|
||||
"""
|
||||
if mode not in mods:
|
||||
raise ValueError(f"\nWrong `mode` parameter. Valid params: {mods}." f"\n\tYour param - `{mode}`")
|
||||
payload = {"clientKey": self.ANTICAPTCHA_KEY, "softId": softId, "mode": mode}
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(get_app_stats_url, json=payload) as resp:
|
||||
if await resp.text():
|
||||
return await resp.json()
|
||||
else:
|
||||
return {"errorId": 1}
|
||||
|
||||
async def complaint_on_result(self, reported_id: int, captcha_type: str = "image") -> dict:
|
||||
f"""
|
||||
Позволяет отправить жалобу на неправильно решённую капчу.
|
||||
:param reported_id: Отправляете ID капчи на которую нужно пожаловаться
|
||||
:param captcha_type: Тип капчи на который идёт жалоба. Возможные варианты:
|
||||
{complaint_types}
|
||||
:return: Возвращает True/False, в зависимости от результата
|
||||
"""
|
||||
if captcha_type not in complaint_types:
|
||||
raise ValueError(
|
||||
f"\nWrong `captcha_type` parameter. Valid params: {complaint_types}."
|
||||
f"\n\tYour param - `{captcha_type}`"
|
||||
)
|
||||
payload = {"clientKey": self.ANTICAPTCHA_KEY, "taskId": reported_id}
|
||||
# complaint on image captcha
|
||||
if captcha_type == "image":
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(incorrect_imagecaptcha_url, json=payload) as resp:
|
||||
if await resp.text():
|
||||
return await resp.json()
|
||||
else:
|
||||
return {"errorId": 1}
|
||||
# complaint on re-captcha
|
||||
elif captcha_type == "recaptcha":
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(incorrect_recaptcha_url, json=payload) as resp:
|
||||
if await resp.text():
|
||||
return await resp.json()
|
||||
else:
|
||||
return {"errorId": 1}
|
||||
|
||||
@staticmethod
|
||||
async def get_queue_status(queue_id: int) -> dict:
|
||||
"""
|
||||
Получение информации о загрузке очереди, в зависимости от ID очереди.
|
||||
|
||||
Метод позволяет определить, насколько в данный момент целесообразно загружать новое задание в очередь.
|
||||
Данные в выдаче кешируются на 10 секунд.
|
||||
|
||||
Список ID очередей:
|
||||
1 - стандартная ImageToText, язык английский
|
||||
2 - стандартная ImageToText, язык русский
|
||||
5 - Recaptcha NoCaptcha
|
||||
6 - Recaptcha Proxyless
|
||||
7 - Funcaptcha
|
||||
10 - Funcaptcha Proxyless
|
||||
|
||||
Пример выдачи ответа:
|
||||
{
|
||||
"waiting":242,
|
||||
"load":60.33,
|
||||
"bid":"0.0008600982",
|
||||
"speed":10.77,
|
||||
"total": 610
|
||||
}
|
||||
:param queue_id: Номер очереди
|
||||
:return: JSON-объект
|
||||
"""
|
||||
if queue_id not in queue_ids:
|
||||
raise ValueError(f"\nWrong `mode` parameter. Valid params: {queue_ids}." f"\n\tYour param - `{queue_id}`")
|
||||
payload = {"queueId": queue_id}
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(get_queue_status_url, json=payload) as resp:
|
||||
if await resp.text():
|
||||
return await resp.json()
|
||||
else:
|
||||
return {"errorId": 1}
|
|
@ -0,0 +1,627 @@
|
|||
from typing import Optional
|
||||
|
||||
from .core.base import BaseCaptcha
|
||||
from .core.enum import CaptchaTypeEnm, ControlPostfixEnm
|
||||
|
||||
|
||||
class Control(BaseCaptcha):
|
||||
def __init__(
|
||||
self,
|
||||
api_key: str,
|
||||
*args,
|
||||
**kwargs,
|
||||
):
|
||||
"""
|
||||
The class is used to work with Turnstile.
|
||||
|
||||
Args:
|
||||
api_key: Capsolver API key
|
||||
captcha_type: Captcha type
|
||||
websiteURL: Address of the webpage
|
||||
websiteKey: Turnstile sitekey
|
||||
proxyType: Type of the proxy
|
||||
proxyAddress: Proxy IP address IPv4/IPv6. Not allowed to use:
|
||||
host names instead of IPs,
|
||||
transparent proxies (where client IP is visible),
|
||||
proxies from local networks (192.., 10.., 127...)
|
||||
proxyPort: Proxy port.
|
||||
sleep_time: The waiting time between requests to get the result of the Captcha
|
||||
kwargs: Additional not required params for main request body.
|
||||
Like `callbackUrl`/`languagePool` and etc.
|
||||
More info - https://anti-captcha.com/apidoc/methods/createTask
|
||||
|
||||
Examples:
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").get_balance()
|
||||
{
|
||||
"errorId": 0,
|
||||
"balance": 14.12396
|
||||
}
|
||||
|
||||
>>> Control.get_queue_status(queue_id=1)
|
||||
{
|
||||
"waiting": 234,
|
||||
"load": 46.58,
|
||||
"bid": 0.000576,
|
||||
"speed": 8.43,
|
||||
"total": 438
|
||||
}
|
||||
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").get_spending_stats(softId=867)
|
||||
{
|
||||
"errorId":0,
|
||||
"data":[
|
||||
{
|
||||
"dateFrom":1679183850,
|
||||
"dateTill":1679187449,
|
||||
"volume":0,
|
||||
"money":0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").get_app_stats(softId=867, mode='views')
|
||||
{
|
||||
"errorId":0,
|
||||
"chartData":[
|
||||
{
|
||||
......
|
||||
}
|
||||
],
|
||||
"fromDate":"17 Feb 23:48",
|
||||
"toDate":"19 Mar 23:48"
|
||||
}
|
||||
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").report_incorrect_image(taskId=425436541)
|
||||
{
|
||||
"errorId":0,
|
||||
"status":"success"
|
||||
}
|
||||
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").report_incorrect_recaptcha(taskId=425436541)
|
||||
{
|
||||
"errorId":0,
|
||||
"status":"success"
|
||||
}
|
||||
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").report_correct_recaptcha(taskId=425436541)
|
||||
{
|
||||
"errorId":0,
|
||||
"status":"success"
|
||||
}
|
||||
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").report_incorrect_hcaptcha(taskId=425436541)
|
||||
{
|
||||
"errorId":0,
|
||||
"status":"success"
|
||||
}
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/getBalance
|
||||
|
||||
https://anti-captcha.com/apidoc/methods/getQueueStats
|
||||
|
||||
https://anti-captcha.com/apidoc/methods/getSpendingStats
|
||||
|
||||
https://anti-captcha.com/apidoc/methods/getAppStats
|
||||
|
||||
https://anti-captcha.com/apidoc/methods/reportIncorrectHcaptcha
|
||||
|
||||
https://anti-captcha.com/apidoc/methods/reportCorrectRecaptcha
|
||||
|
||||
https://anti-captcha.com/apidoc/methods/reportIncorrectRecaptcha
|
||||
|
||||
https://anti-captcha.com/apidoc/methods/reportIncorrectImageCaptcha
|
||||
"""
|
||||
|
||||
super().__init__(api_key=api_key, captcha_type=CaptchaTypeEnm.Control, *args, **kwargs)
|
||||
|
||||
def get_balance(self) -> dict:
|
||||
"""
|
||||
Retrieve an account balance with its account key.
|
||||
|
||||
Examples:
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").get_balance()
|
||||
{
|
||||
"errorId": 0,
|
||||
"balance": 14.12396
|
||||
}
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/getBalance
|
||||
"""
|
||||
return self._send_post_request(
|
||||
session=self._session,
|
||||
url_postfix=ControlPostfixEnm.GET_BALANCE,
|
||||
payload={"clientKey": self._params.clientKey},
|
||||
)
|
||||
|
||||
async def aio_get_balance(self) -> dict:
|
||||
"""
|
||||
Async retrieve an account balance with its account key.
|
||||
|
||||
Examples:
|
||||
>>> await Control(api_key="99d7d111a0111dc11184111c8bb111da").aio_get_balance()
|
||||
{
|
||||
"errorId": 0,
|
||||
"balance": 14.12396
|
||||
}
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/getBalance
|
||||
"""
|
||||
|
||||
return await self._aio_send_post_request(
|
||||
url_postfix=ControlPostfixEnm.GET_BALANCE, payload={"clientKey": self._params.clientKey}
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_queue_status(queue_id: int) -> dict:
|
||||
"""
|
||||
This method makes it possible to define a suitable time for uploading a new task
|
||||
|
||||
Args:
|
||||
queue_id: Identifier of a queue
|
||||
|
||||
Examples:
|
||||
>>> Control.get_queue_status(queue_id=1)
|
||||
{
|
||||
"waiting": 234,
|
||||
"load": 46.58,
|
||||
"bid": 0.000576,
|
||||
"speed": 8.43,
|
||||
"total": 438
|
||||
}
|
||||
|
||||
>>> Control.get_queue_status(queue_id=20)
|
||||
{
|
||||
"waiting": 90,
|
||||
"load": 38.36,
|
||||
"bid": 0.002,
|
||||
"speed": 7.38,
|
||||
"total": 146
|
||||
}
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/getQueueStats
|
||||
"""
|
||||
|
||||
return BaseCaptcha._send_post_request(
|
||||
url_postfix=ControlPostfixEnm.GET_QUEUE_STATS, payload={"queueId": queue_id}
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
async def aio_get_queue_status(queue_id: int) -> dict:
|
||||
"""
|
||||
Async method makes it possible to define a suitable time for uploading a new task
|
||||
|
||||
Args:
|
||||
queue_id: Identifier of a queue
|
||||
|
||||
Examples:
|
||||
>>> await Control.aio_get_queue_status(queue_id=1)
|
||||
{
|
||||
"waiting": 234,
|
||||
"load": 46.58,
|
||||
"bid": 0.000576,
|
||||
"speed": 8.43,
|
||||
"total": 438
|
||||
}
|
||||
|
||||
>>> await Control.aio_get_queue_status(queue_id=20)
|
||||
{
|
||||
"waiting": 90,
|
||||
"load": 38.36,
|
||||
"bid": 0.002,
|
||||
"speed": 7.38,
|
||||
"total": 146
|
||||
}
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/getQueueStats
|
||||
"""
|
||||
|
||||
return await BaseCaptcha._aio_send_post_request(
|
||||
url_postfix=ControlPostfixEnm.GET_QUEUE_STATS, payload={"queueId": queue_id}
|
||||
)
|
||||
|
||||
def get_spending_stats(self, **kwargs) -> dict:
|
||||
"""
|
||||
This method grabs account spendings and task volume statistics for a 24 hour period.
|
||||
|
||||
Examples:
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").get_spending_stats(softId=867)
|
||||
{
|
||||
"errorId":0,
|
||||
"data":[
|
||||
{
|
||||
"dateFrom":1679183850,
|
||||
"dateTill":1679187449,
|
||||
"volume":0,
|
||||
"money":0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").get_spending_stats(softId=867,
|
||||
... queue="English ImageToText")
|
||||
{
|
||||
"errorId":0,
|
||||
"data":[
|
||||
{
|
||||
"dateFrom":1679183850,
|
||||
"dateTill":1679187449,
|
||||
"volume":0,
|
||||
"money":0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").get_spending_stats(queue="English ImageToText")
|
||||
{
|
||||
"errorId":0,
|
||||
"data":[
|
||||
{
|
||||
"dateFrom":1679183850,
|
||||
"dateTill":1679187449,
|
||||
"volume":0,
|
||||
"money":0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/getSpendingStats
|
||||
"""
|
||||
return self._send_post_request(
|
||||
session=self._session,
|
||||
url_postfix=ControlPostfixEnm.GET_SPENDING_STATS,
|
||||
payload={"clientKey": self._params.clientKey, **kwargs},
|
||||
)
|
||||
|
||||
async def aio_get_spending_stats(self, **kwargs) -> dict:
|
||||
"""
|
||||
Async method grabs account spendings and task volume statistics for a 24 hour period.
|
||||
|
||||
Examples:
|
||||
>>> await Control(api_key="99d7d111a0111dc11184111c8bb111da").aio_get_spending_stats(softId=867)
|
||||
{
|
||||
"errorId":0,
|
||||
"data":[
|
||||
{
|
||||
"dateFrom":1679183850,
|
||||
"dateTill":1679187449,
|
||||
"volume":0,
|
||||
"money":0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
>>> await Control(api_key="99d7d111a0111dc11184111c8bb111da").aio_get_spending_stats(softId=867,
|
||||
... queue="English ImageToText")
|
||||
{
|
||||
"errorId":0,
|
||||
"data":[
|
||||
{
|
||||
"dateFrom":1679183850,
|
||||
"dateTill":1679187449,
|
||||
"volume":0,
|
||||
"money":0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
>>> await Control(api_key="99d7d111a0111dc11184111c8bb111da").aio_get_spending_stats(queue="English ImageToText")
|
||||
{
|
||||
"errorId":0,
|
||||
"data":[
|
||||
{
|
||||
"dateFrom":1679183850,
|
||||
"dateTill":1679187449,
|
||||
"volume":0,
|
||||
"money":0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/getSpendingStats
|
||||
"""
|
||||
return await self._aio_send_post_request(
|
||||
url_postfix=ControlPostfixEnm.GET_SPENDING_STATS, payload={"clientKey": self._params.clientKey, **kwargs}
|
||||
)
|
||||
|
||||
def get_app_stats(self, softId: int, mode: Optional[str] = None) -> dict:
|
||||
"""
|
||||
This method retrieves daily statistics for your application, which you register in Developer Center.
|
||||
Statistics are available only to the application owner. Improper access returns `ERROR_ACCESS_DENIED`.
|
||||
|
||||
Examples:
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").get_app_stats(softId=867, mode='views')
|
||||
{
|
||||
"errorId":0,
|
||||
"chartData":[
|
||||
{
|
||||
......
|
||||
}
|
||||
],
|
||||
"fromDate":"17 Feb 23:48",
|
||||
"toDate":"19 Mar 23:48"
|
||||
}
|
||||
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").get_app_stats(softId=867, mode='errors')
|
||||
{
|
||||
"errorId":0,
|
||||
"chartData":[
|
||||
{
|
||||
......
|
||||
}
|
||||
],
|
||||
"fromDate":"17 Feb 23:48",
|
||||
"toDate":"19 Mar 23:48"
|
||||
}
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/getAppStats
|
||||
"""
|
||||
|
||||
return self._send_post_request(
|
||||
session=self._session,
|
||||
url_postfix=ControlPostfixEnm.GET_APP_STATS,
|
||||
payload={"clientKey": self._params.clientKey, "softId": softId, "mode": mode},
|
||||
)
|
||||
|
||||
async def aio_get_app_stats(self, softId: int, mode: Optional[str] = None) -> dict:
|
||||
"""
|
||||
Async method retrieves daily statistics for your application, which you register in Developer Center.
|
||||
Statistics are available only to the application owner. Improper access returns `ERROR_ACCESS_DENIED`.
|
||||
|
||||
Examples:
|
||||
>>> await Control(api_key="99d7d111a0111dc11184111c8bb111da").aio_get_app_stats(softId=867, mode='views')
|
||||
{
|
||||
"errorId":0,
|
||||
"chartData":[
|
||||
{
|
||||
......
|
||||
}
|
||||
],
|
||||
"fromDate":"17 Feb 23:48",
|
||||
"toDate":"19 Mar 23:48"
|
||||
}
|
||||
|
||||
>>> await Control(api_key="99d7d111a0111dc11184111c8bb111da").aio_get_app_stats(softId=867, mode='errors')
|
||||
{
|
||||
"errorId":0,
|
||||
"chartData":[
|
||||
{
|
||||
......
|
||||
}
|
||||
],
|
||||
"fromDate":"17 Feb 23:48",
|
||||
"toDate":"19 Mar 23:48"
|
||||
}
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/getAppStats
|
||||
"""
|
||||
|
||||
return await self._aio_send_post_request(
|
||||
url_postfix=ControlPostfixEnm.GET_APP_STATS,
|
||||
payload={"clientKey": self._params.clientKey, "softId": softId, "mode": mode},
|
||||
)
|
||||
|
||||
def report_incorrect_image(self, taskId: int) -> dict:
|
||||
"""
|
||||
Complaints are accepted for image captchas only.
|
||||
|
||||
Examples:
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").report_incorrect_image(taskId=425436541)
|
||||
{
|
||||
"errorId":0,
|
||||
"status":"success"
|
||||
}
|
||||
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/reportIncorrectImageCaptcha
|
||||
"""
|
||||
|
||||
return self._send_post_request(
|
||||
session=self._session,
|
||||
url_postfix=ControlPostfixEnm.REPORT_INCORRECT_IMAGE_CAPTCHA,
|
||||
payload={"clientKey": self._params.clientKey, "taskId": taskId},
|
||||
)
|
||||
|
||||
async def aio_report_incorrect_image(self, taskId: int) -> dict:
|
||||
"""
|
||||
Async complaints are accepted for image captchas only.
|
||||
|
||||
Examples:
|
||||
>>> await Control(api_key="99d7d111a0111dc11184111c8bb111da").aio_report_incorrect_image(taskId=425436541)
|
||||
{
|
||||
"errorId":0,
|
||||
"status":"success"
|
||||
}
|
||||
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/reportIncorrectImageCaptcha
|
||||
"""
|
||||
|
||||
return await self._aio_send_post_request(
|
||||
url_postfix=ControlPostfixEnm.REPORT_INCORRECT_IMAGE_CAPTCHA,
|
||||
payload={"clientKey": self._params.clientKey, "taskId": taskId},
|
||||
)
|
||||
|
||||
def report_incorrect_recaptcha(self, taskId: int) -> dict:
|
||||
"""
|
||||
Complaints are accepted for V2 and V3 Recaptchas only, including Enterprise Recaptcha.
|
||||
|
||||
Examples:
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").report_incorrect_recaptcha(taskId=425436541)
|
||||
{
|
||||
"errorId":0,
|
||||
"status":"success"
|
||||
}
|
||||
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/reportIncorrectRecaptcha
|
||||
"""
|
||||
|
||||
return self._send_post_request(
|
||||
session=self._session,
|
||||
url_postfix=ControlPostfixEnm.REPORT_INCORRECT_RECAPTCHA,
|
||||
payload={"clientKey": self._params.clientKey, "taskId": taskId},
|
||||
)
|
||||
|
||||
async def aio_report_incorrect_recaptcha(self, taskId: int) -> dict:
|
||||
"""
|
||||
Async complaints are accepted for V2 and V3 Recaptchas only, including Enterprise Recaptcha.
|
||||
|
||||
Examples:
|
||||
>>> await Control(api_key="99d7d111a0111dc11184111c8bb111da").aio_report_incorrect_recaptcha(taskId=425436541)
|
||||
{
|
||||
"errorId":0,
|
||||
"status":"success"
|
||||
}
|
||||
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/reportIncorrectRecaptcha
|
||||
"""
|
||||
return await self._aio_send_post_request(
|
||||
url_postfix=ControlPostfixEnm.REPORT_INCORRECT_RECAPTCHA,
|
||||
payload={"clientKey": self._params.clientKey, "taskId": taskId},
|
||||
)
|
||||
|
||||
def report_correct_recaptcha(self, taskId: int) -> dict:
|
||||
"""
|
||||
Reporting correctly solved ReCaptcha
|
||||
|
||||
Examples:
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").report_correct_recaptcha(taskId=425436541)
|
||||
{
|
||||
"errorId":0,
|
||||
"status":"success"
|
||||
}
|
||||
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/reportCorrectRecaptcha
|
||||
"""
|
||||
|
||||
return self._send_post_request(
|
||||
session=self._session,
|
||||
url_postfix=ControlPostfixEnm.REPORT_CORRECT_RECAPTCHA,
|
||||
payload={"clientKey": self._params.clientKey, "taskId": taskId},
|
||||
)
|
||||
|
||||
async def aio_report_correct_recaptcha(self, taskId: int) -> dict:
|
||||
"""
|
||||
Async reporting correctly solved ReCaptcha
|
||||
|
||||
Examples:
|
||||
>>> await Control(api_key="99d7d111a0111dc11184111c8bb111da").aio_report_correct_recaptcha(taskId=425436541)
|
||||
{
|
||||
"errorId":0,
|
||||
"status":"success"
|
||||
}
|
||||
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/reportCorrectRecaptcha
|
||||
"""
|
||||
return await self._aio_send_post_request(
|
||||
url_postfix=ControlPostfixEnm.REPORT_CORRECT_RECAPTCHA,
|
||||
payload={"clientKey": self._params.clientKey, "taskId": taskId},
|
||||
)
|
||||
|
||||
def report_incorrect_hcaptcha(self, taskId: int) -> dict:
|
||||
"""
|
||||
Use this method to send us information about tokens which did not pass on target service
|
||||
|
||||
Examples:
|
||||
>>> Control(api_key="99d7d111a0111dc11184111c8bb111da").report_incorrect_hcaptcha(taskId=425436541)
|
||||
{
|
||||
"errorId":0,
|
||||
"status":"success"
|
||||
}
|
||||
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/reportIncorrectHcaptcha
|
||||
"""
|
||||
|
||||
return self._send_post_request(
|
||||
session=self._session,
|
||||
url_postfix=ControlPostfixEnm.REPORT_INCORRECT_HCAPTCHA,
|
||||
payload={"clientKey": self._params.clientKey, "taskId": taskId},
|
||||
)
|
||||
|
||||
async def aio_report_incorrect_hcaptcha(self, taskId: int) -> dict:
|
||||
"""
|
||||
Async method to send us information about tokens which did not pass on target service
|
||||
|
||||
Examples:
|
||||
>>> await Control(api_key="99d7d111a0111dc11184111c8bb111da").aio_report_incorrect_hcaptcha(taskId=4256541)
|
||||
{
|
||||
"errorId":0,
|
||||
"status":"success"
|
||||
}
|
||||
|
||||
|
||||
Returns:
|
||||
Dict with full server response
|
||||
|
||||
Notes:
|
||||
https://anti-captcha.com/apidoc/methods/reportIncorrectHcaptcha
|
||||
"""
|
||||
return await self._aio_send_post_request(
|
||||
url_postfix=ControlPostfixEnm.REPORT_INCORRECT_HCAPTCHA,
|
||||
payload={"clientKey": self._params.clientKey, "taskId": taskId},
|
||||
)
|
|
@ -1,7 +1,7 @@
|
|||
import time
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Union
|
||||
from typing import Union, Optional
|
||||
from urllib import parse
|
||||
|
||||
import aiohttp
|
||||
|
@ -35,24 +35,30 @@ class BaseCaptcha:
|
|||
request_url: API address for sending requests
|
||||
"""
|
||||
|
||||
def __init__(self, api_key: str, captcha_type: Union[CaptchaTypeEnm, str], sleep_time: int, **kwargs):
|
||||
def __init__(
|
||||
self,
|
||||
api_key: str,
|
||||
captcha_type: Union[CaptchaTypeEnm, str],
|
||||
sleep_time: int = 15,
|
||||
**kwargs,
|
||||
):
|
||||
# validate captcha_type parameter
|
||||
if captcha_type not in CaptchaTypeEnm.list_values():
|
||||
raise ValueError(f"Invalid `captcha_type` parameter set, available - {CaptchaTypeEnm.list_values()}")
|
||||
self.__sleep_time = sleep_time
|
||||
|
||||
# assign args to validator
|
||||
self.__params = CreateTaskRequestSer(clientKey=api_key, **locals())
|
||||
self._params = CreateTaskRequestSer(clientKey=api_key, **locals())
|
||||
# `task` body for task creation payload
|
||||
self.task_params = {}
|
||||
# prepare `get task result` payload
|
||||
self._get_result_params = GetTaskResultRequestSer(clientKey=api_key)
|
||||
|
||||
# prepare session
|
||||
self.__session = requests.Session()
|
||||
self.__session.mount("http://", HTTPAdapter(max_retries=RETRIES))
|
||||
self.__session.mount("https://", HTTPAdapter(max_retries=RETRIES))
|
||||
self.__session.verify = False
|
||||
self._session = requests.Session()
|
||||
self._session.mount("http://", HTTPAdapter(max_retries=RETRIES))
|
||||
self._session.mount("https://", HTTPAdapter(max_retries=RETRIES))
|
||||
self._session.verify = False
|
||||
|
||||
"""
|
||||
Sync part
|
||||
|
@ -60,7 +66,7 @@ class BaseCaptcha:
|
|||
|
||||
def _processing_captcha(self) -> dict:
|
||||
# added task params to payload
|
||||
self.__params.task = self.task_params
|
||||
self._params.task = self.task_params
|
||||
|
||||
created_task = self._create_task()
|
||||
|
||||
|
@ -69,12 +75,12 @@ class BaseCaptcha:
|
|||
return self._get_result().dict()
|
||||
return created_task.dict()
|
||||
|
||||
def _create_task(self) -> CreateTaskResponseSer:
|
||||
def _create_task(self, url_postfix: str = CREATE_TASK_POSTFIX) -> CreateTaskResponseSer:
|
||||
"""
|
||||
Function send SYNC request to service and wait for result
|
||||
"""
|
||||
try:
|
||||
resp = self.__session.post(parse.urljoin(BASE_REQUEST_URL, CREATE_TASK_POSTFIX), json=self.__params.dict())
|
||||
resp = self._session.post(parse.urljoin(BASE_REQUEST_URL, url_postfix), json=self._params.dict())
|
||||
if resp.status_code == 200:
|
||||
return CreateTaskResponseSer(**resp.json())
|
||||
else:
|
||||
|
@ -93,7 +99,7 @@ class BaseCaptcha:
|
|||
attempts = attempts_generator()
|
||||
for _ in attempts:
|
||||
try:
|
||||
task_result_response = self.__session.post(
|
||||
task_result_response = self._session.post(
|
||||
parse.urljoin(BASE_REQUEST_URL, GET_RESULT_POSTFIX), json=self._get_result_params.dict()
|
||||
)
|
||||
if task_result_response.status_code == 200:
|
||||
|
@ -114,13 +120,32 @@ class BaseCaptcha:
|
|||
logging.exception(error)
|
||||
raise
|
||||
|
||||
@staticmethod
|
||||
def _send_post_request(
|
||||
payload: Optional[dict] = None,
|
||||
session: requests.Session = requests.Session(),
|
||||
url_postfix: str = CREATE_TASK_POSTFIX,
|
||||
) -> dict:
|
||||
"""
|
||||
Function send SYNC request to service and wait for result
|
||||
"""
|
||||
try:
|
||||
resp = session.post(parse.urljoin(BASE_REQUEST_URL, url_postfix), json=payload)
|
||||
if resp.status_code == 200:
|
||||
return resp.json()
|
||||
else:
|
||||
raise ValueError(resp.raise_for_status())
|
||||
except Exception as error:
|
||||
logging.exception(error)
|
||||
raise
|
||||
|
||||
"""
|
||||
Async part
|
||||
"""
|
||||
|
||||
async def _aio_processing_captcha(self) -> dict:
|
||||
# added task params to payload
|
||||
self.__params.task = self.task_params
|
||||
self._params.task = self.task_params
|
||||
|
||||
created_task = await self._aio_create_task()
|
||||
|
||||
|
@ -130,15 +155,13 @@ class BaseCaptcha:
|
|||
return result.dict()
|
||||
return created_task.dict()
|
||||
|
||||
async def _aio_create_task(self) -> CreateTaskResponseSer:
|
||||
async def _aio_create_task(self, url_postfix: str = CREATE_TASK_POSTFIX) -> CreateTaskResponseSer:
|
||||
"""
|
||||
Function send SYNC request to service and wait for result
|
||||
"""
|
||||
async with aiohttp.ClientSession() as session:
|
||||
try:
|
||||
async with session.post(
|
||||
parse.urljoin(BASE_REQUEST_URL, CREATE_TASK_POSTFIX), json=self.__params.dict()
|
||||
) as resp:
|
||||
async with session.post(parse.urljoin(BASE_REQUEST_URL, url_postfix), json=self._params.dict()) as resp:
|
||||
if resp.status == 200:
|
||||
return CreateTaskResponseSer(**await resp.json())
|
||||
else:
|
||||
|
@ -180,6 +203,25 @@ class BaseCaptcha:
|
|||
logging.exception(error)
|
||||
raise
|
||||
|
||||
@staticmethod
|
||||
async def _aio_send_post_request(payload: Optional[dict] = None, url_postfix: str = CREATE_TASK_POSTFIX) -> dict:
|
||||
"""
|
||||
Function send ASYNC request to service and wait for result
|
||||
"""
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
try:
|
||||
async with session.post(parse.urljoin(BASE_REQUEST_URL, url_postfix), json=payload) as resp:
|
||||
if resp.status == 200:
|
||||
return await resp.json()
|
||||
else:
|
||||
raise ValueError(resp.reason)
|
||||
except Exception as error:
|
||||
logging.exception(error)
|
||||
raise
|
||||
|
||||
# Context methods
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ class ResponseStatusEnm(str, MyEnum):
|
|||
ready = "ready" # Task is complete; you'll find a solution in the solution property
|
||||
|
||||
|
||||
class ProxyType(str, MyEnum):
|
||||
class ProxyTypeEnm(str, MyEnum):
|
||||
"""
|
||||
Enum store proxy types
|
||||
"""
|
||||
|
@ -87,3 +87,20 @@ class ProxyType(str, MyEnum):
|
|||
https = "https"
|
||||
socks4 = "socks4"
|
||||
socks5 = "socks5"
|
||||
|
||||
|
||||
class ControlPostfixEnm(str, MyEnum):
|
||||
"""
|
||||
Enum store control methods URLs postfix
|
||||
"""
|
||||
|
||||
# get account info
|
||||
GET_BALANCE = "getBalance"
|
||||
GET_QUEUE_STATS = "getQueueStats"
|
||||
GET_APP_STATS = "getAppStats"
|
||||
GET_SPENDING_STATS = "getSpendingStats"
|
||||
# reports
|
||||
REPORT_INCORRECT_IMAGE_CAPTCHA = "reportIncorrectImageCaptcha"
|
||||
REPORT_INCORRECT_RECAPTCHA = "reportIncorrectRecaptcha"
|
||||
REPORT_CORRECT_RECAPTCHA = "reportCorrectRecaptcha"
|
||||
REPORT_INCORRECT_HCAPTCHA = "reportIncorrectHcaptcha"
|
||||
|
|
|
@ -2,7 +2,7 @@ from typing import Dict
|
|||
|
||||
from pydantic import Field, BaseModel, constr
|
||||
|
||||
from python3_anticaptcha.core.enum import ProxyType, CaptchaTypeEnm, ResponseStatusEnm
|
||||
from python3_anticaptcha.core.enum import ProxyTypeEnm, CaptchaTypeEnm, ResponseStatusEnm
|
||||
from python3_anticaptcha.core.config import APP_KEY
|
||||
|
||||
|
||||
|
@ -17,7 +17,7 @@ class BaseAPIRequestSer(MyBaseModel):
|
|||
|
||||
|
||||
class BaseAPIResponseSer(MyBaseModel):
|
||||
errorId: int = Field(..., description="Error identifier.")
|
||||
errorId: int = Field(None, description="Error identifier.")
|
||||
errorCode: str = Field(None, description="An error code.")
|
||||
errorDescription: str = Field(None, description="Short description of the error.")
|
||||
|
||||
|
@ -34,7 +34,7 @@ class CreateTaskRequestTaskSer(MyBaseModel):
|
|||
|
||||
|
||||
class ProxyDataOptionsSer(MyBaseModel):
|
||||
proxyType: ProxyType = Field(..., description="Type of proxy")
|
||||
proxyType: ProxyTypeEnm = Field(..., description="Type of proxy")
|
||||
proxyAddress: str = Field(
|
||||
...,
|
||||
description="Proxy IP address ipv4/ipv6. No host names or IP addresses from local networks",
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from typing import Union, Optional
|
||||
|
||||
from python3_anticaptcha.core.base import BaseCaptcha
|
||||
from python3_anticaptcha.core.enum import ProxyType, CaptchaTypeEnm
|
||||
from python3_anticaptcha.core.serializer import TurnstileOptionsSer, TurnstileProxylessOptionsSer
|
||||
from .core.base import BaseCaptcha
|
||||
from .core.enum import ProxyTypeEnm, CaptchaTypeEnm
|
||||
from .core.serializer import TurnstileOptionsSer, TurnstileProxylessOptionsSer
|
||||
|
||||
|
||||
class Turnstile(BaseCaptcha):
|
||||
|
@ -12,7 +12,7 @@ class Turnstile(BaseCaptcha):
|
|||
captcha_type: Union[CaptchaTypeEnm, str],
|
||||
websiteURL: str,
|
||||
websiteKey: str,
|
||||
proxyType: Optional[Union[ProxyType, str]] = None,
|
||||
proxyType: Optional[Union[ProxyTypeEnm, str]] = None,
|
||||
proxyAddress: Optional[str] = None,
|
||||
proxyPort: Optional[int] = None,
|
||||
sleep_time: Optional[int] = 10,
|
||||
|
|
|
@ -7,11 +7,17 @@ import pytest
|
|||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def delay():
|
||||
time.sleep(1)
|
||||
def delay_func():
|
||||
time.sleep(5)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("delay")
|
||||
@pytest.fixture(scope="class")
|
||||
def delay_class():
|
||||
time.sleep(10)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("delay_func")
|
||||
@pytest.mark.usefixtures("delay_class")
|
||||
class BaseTest:
|
||||
API_KEY = os.getenv("API_KEY", "ad9053f3182ca81755768608fa75")
|
||||
sleep_time = 5
|
|
@ -1,7 +1,7 @@
|
|||
from tenacity import AsyncRetrying
|
||||
from urllib3.util.retry import Retry
|
||||
|
||||
from src.tests.conftest import BaseTest
|
||||
from tests.conftest import BaseTest
|
||||
from python3_anticaptcha.core.base import BaseCaptcha
|
||||
from python3_anticaptcha.core.enum import CaptchaTypeEnm
|
||||
from python3_anticaptcha.core.config import RETRIES, ASYNC_RETRIES, BASE_REQUEST_URL, attempts_generator
|
Loading…
Reference in New Issue