Metadata-Version: 2.4
Name: tbcpay-recaptcha
Version: 2.0.0
Summary: reCAPTCHA v3 token solver and utility bill checker for TBCPay (Georgia)
License-Expression: MIT
License-File: LICENSE
Keywords: billing,georgia,recaptcha,tbcpay,utility
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: AsyncIO
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.10
Requires-Dist: aiohttp>=3.9.0
Provides-Extra: all
Requires-Dist: 2captcha-python>=1.2.0; extra == 'all'
Requires-Dist: capsolver>=1.0.0; extra == 'all'
Requires-Dist: zendriver>=0.7.0; extra == 'all'
Provides-Extra: capsolver
Requires-Dist: capsolver>=1.0.0; extra == 'capsolver'
Provides-Extra: dev
Requires-Dist: aioresponses>=0.7; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Provides-Extra: twocaptcha
Requires-Dist: 2captcha-python>=1.2.0; extra == 'twocaptcha'
Provides-Extra: zendriver
Requires-Dist: zendriver>=0.7.0; extra == 'zendriver'
Description-Content-Type: text/markdown

# TBCPay reCAPTCHA Solver

Get reCAPTCHA v3 tokens from TBCPay and check your utility bills in Tbilisi.

Now with pluggable solver backends -- use a real browser, a CAPTCHA solving service, or both.

## What it does

- Grabs reCAPTCHA v3 tokens from TBCPay website
- Checks utility bills (water, electricity, telecom, etc.)
- Supports multiple CAPTCHA solving methods:
  - **zendriver** (default) -- runs a real browser, gets high-score tokens for free
  - **2captcha** -- API service, human-powered, ~25-36s per token
  - **capsolver** -- API service, AI-powered, ~3.4s per token
- Retries with exponential backoff, token caching, fallback chains

## Setup

```bash
# Browser-based solver (default)
pip install tbcpay-recaptcha[zendriver]

# API-based solver
pip install tbcpay-recaptcha[capsolver]
# or
pip install tbcpay-recaptcha[twocaptcha]

# Everything
pip install tbcpay-recaptcha[all]
```

For API-based solvers, set your key:

```bash
export TBCPAY_CAPSOLVER_API_KEY="your-key-here"
# or
export TBCPAY_TWOCAPTCHA_API_KEY="your-key-here"
```

## Basic usage

### Checking water bill

```python
import asyncio
from tbcpay_recaptcha import create_service

async def main():
    async with create_service("water") as service:
        result = await service.check_balance_async("YOUR_ACCOUNT_NUMBER")
        print(result)

asyncio.run(main())
```

### Checking electricity

```python
import asyncio
from tbcpay_recaptcha import create_service

async def main():
    async with create_service("electricity") as service:
        result = await service.check_balance_async("YOUR_ACCOUNT_NUMBER")
        print(result)

asyncio.run(main())
```

### Using an API solver instead of a browser

```python
import asyncio
from tbcpay_recaptcha import create_service

async def main():
    async with create_service("water", backend="capsolver") as service:
        result = await service.check_balance_async("YOUR_ACCOUNT_NUMBER")
        print(result)

asyncio.run(main())
```

### Hybrid: browser first, API fallback

If the browser fails, automatically fall back to an API solver:

```python
import asyncio
from tbcpay_recaptcha import (
    CachedSolver, FallbackSolver, RetrySolver,
    SolverConfig, TBCPayService, get_service_config, get_solver,
)

async def main():
    config = SolverConfig.from_env()
    solver = CachedSolver(RetrySolver(FallbackSolver([
        get_solver("zendriver", config),
        get_solver("capsolver", config),
    ])))

    svc = get_service_config("water")
    service = TBCPayService(svc.service_id, svc.service_name, solver)

    async with service:
        result = await service.check_balance_async("YOUR_ACCOUNT_NUMBER")
        print(result)

asyncio.run(main())
```

## Running the examples

```bash
python examples/example_water.py YOUR_ACCOUNT_NUMBER
python examples/example_electricity.py YOUR_ACCOUNT_NUMBER
python examples/example_api_solver.py YOUR_ACCOUNT_NUMBER
python examples/example_hybrid.py YOUR_ACCOUNT_NUMBER
```

## Adding other services

You need two things:
1. The service ID from TBCPay
2. Whether it uses step 1 or 2 (most use 2)

### Finding service IDs

Open tbcpay.ge, go to your service, open browser devtools (F12), check the Network tab, and look for `GetNextSteps` requests. The service ID is right there in the payload.

### Known services

These are built into the registry -- just use the name:

| Service | Name | ID | Step |
|---------|------|----|------|
| Tbilisi Water | `"water"` | 2758 | 2 |
| Tbilisi Energy | `"electricity"` | 771 | 2 |
| TELMICO | `"telmico"` | 2817 | 2 |
| Tbilservice Group | `"tbilservice"` | 765 | 2 |
| CityCom | `"citycom"` | 915 | 1 |

### Adding a custom service

```python
from tbcpay_recaptcha import register_service, ServiceConfig, create_service

register_service("myservice", ServiceConfig(
    service_id=1234,
    service_name="My Service",
    step_order=2,
))

async with create_service("myservice") as svc:
    result = await svc.check_balance_async("YOUR_ACCOUNT")
```

Or just use the ID directly:

```python
async with create_service(1234) as svc:
    result = await svc.check_balance_async("YOUR_ACCOUNT")
```

## How it works

The **solver** layer handles reCAPTCHA tokens:
- `ZendriverSolver` -- starts a real Chromium browser via CDP, loads TBCPay, calls `grecaptcha.execute()` to get tokens. High scores because it's a real browser.
- `TwoCaptchaSolver` / `CapSolverSolver` -- sends site key + URL to an API, gets a token back. Fast but lower scores.
- `CachedSolver` -- wraps any solver, caches tokens for 110 seconds
- `RetrySolver` -- wraps any solver, retries with exponential backoff
- `FallbackSolver` -- tries multiple solvers in order until one works

The **service** layer handles TBCPay:
- Makes async API requests to `api.tbcpay.ge`
- Parses the responses into something usable
- Returns standardized result dicts

## Configuration

All settings can be set via environment variables:

| Variable | Default | Description |
|----------|---------|-------------|
| `TBCPAY_HEADLESS` | `true` | Hide browser window |
| `TBCPAY_TWOCAPTCHA_API_KEY` | | 2captcha API key |
| `TBCPAY_CAPSOLVER_API_KEY` | | capsolver API key |
| `TBCPAY_SITE_KEY` | *(auto)* | reCAPTCHA site key override |
| `TBCPAY_MAX_RETRIES` | `3` | Retry attempts |
| `TBCPAY_RETRY_DELAY` | `1.0` | Initial retry delay (seconds) |
| `TBCPAY_TOKEN_LIFETIME` | `110` | Token cache duration (seconds) |
| `TBCPAY_REQUEST_TIMEOUT` | `15.0` | HTTP request timeout (seconds) |

Or pass a `SolverConfig` directly:

```python
from tbcpay_recaptcha import SolverConfig, create_service

config = SolverConfig(headless=False, max_retries=5)
service = create_service("water", config=config)
```

## Response format

When everything works:

```python
{
    'account_id': '123456',
    'service': 'Tbilisi Water',
    'status': 'success',
    'customer_name': 'John Doe',
    'balance': 0.0,
    'amount_to_pay': 0.0,
    'currency': 'GEL',
    'can_pay': True,
    'raw_data': {...}
}
```

When something breaks:

```python
{
    'account_id': '123456',
    'service': 'Tbilisi Water',
    'status': 'error',
    'error': 'Request timeout'
}
```

## Which solver should I use?

| Solver | Cost | Speed | Score | Best for |
|--------|------|-------|-------|----------|
| zendriver | Free | ~5s | High (0.7-0.9) | Default, personal use |
| capsolver | $1/1000 | ~3.4s | Low (~0.1) | Fast fallback, high volume |
| 2captcha | $1.45-2.99/1000 | ~25-36s | Low (~0.1) | Most reliable API |

Browser-based (zendriver) gets much higher scores because it runs real Chromium. API services generate tokens remotely, so Google gives them low scores. For TBCPay this doesn't seem to matter -- they accept low-score tokens. But if they tighten the threshold, zendriver is the way to go.

## Requirements

- Python 3.10+
- One of: zendriver, 2captcha-python, capsolver

## License

MIT. Do whatever you want with it.

## Notes

This is for personal use. Don't abuse TBCPay's API or you might get rate limited. Account numbers and tokens are sensitive -- don't commit them to git or share them publicly.

Check out SERVICES.md if you want more details on adding new services.
