# captcha-router

Reusable captcha router with pluggable providers.

## Install

```bash
pip install .
```

## Publish automation (GitHub Actions)

1. Configure Trusted Publishers in PyPI:
- Production: workflow `/.github/workflows/publish.yml`, environment `pypi`
- Test: workflow `/.github/workflows/publish-testpypi.yml`, environment `testpypi`
2. Bump `version` in `pyproject.toml` and commit.
3. For TestPyPI (release candidate), tag with `-rc`:
```bash
git tag v0.1.1-rc1
git push origin v0.1.1-rc1
```
4. For production PyPI, push a stable tag:
```bash
git tag v0.1.1
git push origin v0.1.1
```

## Optional: publish on version change

The workflow `/.github/workflows/publish-on-version-change.yml` is manual-only by default.

1. Open GitHub Actions and run `Publish on Version Change (Optional)`.
2. Choose target: `testpypi` or `pypi`.

If you want auto-publish on `main` when `pyproject.toml` changes, uncomment the `push` trigger block in that workflow file.

## Supported providers

- `anticaptcha` (alias: `anti-captcha`)
- `2captcha` (alias: `twocaptcha`)

## Router methods

- `CaptchaRouter.list_providers()`: returns all registered provider names and aliases.
- `CaptchaRouter.list_provider_capabilities(include_aliases=False)`: returns provider -> supported captcha kinds.
- `CaptchaRouter.get_supported_task_kinds(provider_name)`: returns supported captcha kinds for one provider.
- `CaptchaRouter.list_supported_task_kinds()`: returns union of captcha kinds across providers.
- `CaptchaRouter.get_solver(provider_name=None, api_key=None, **kwargs)`: creates a solver instance and uses env fallbacks when `api_key` is omitted.

## Usage

### 1) Create a solver
```python
from captcha_router import CaptchaRouter

solver = CaptchaRouter.get_solver(provider_name="anticaptcha", api_key="YOUR_KEY")
```

### 2) Solve a task
```python
import asyncio
from captcha_router import CaptchaRouter, CaptchaTaskSpec


async def main():
    solver = CaptchaRouter.get_solver(provider_name="anticaptcha", api_key="YOUR_KEY")
    try:
        result = await solver.solve_task(
            CaptchaTaskSpec(
                kind="recaptcha_v2",
                params={
                    "website_url": "https://example.com",
                    "site_key": "SITE_KEY_HERE",
                },
            )
        )
        print(result.status, result.token, result.error)
    finally:
        await solver.close()


asyncio.run(main())
```

### 3) Inspect capabilities
```python
from captcha_router import CaptchaRouter

print(CaptchaRouter.list_providers())
print(CaptchaRouter.list_provider_capabilities())
```
