Skip to main content

Python client library for the Etoneya Subscription Management API.

Project description

Etoneya API Client

CI Python License

Fully-typed Python client for the Etoneya Subscription Management API. Ships both a synchronous (EtoneyaClient) and asynchronous (AsyncEtoneyaClient) flavour built on top of httpx.

Highlights

  • 🔁 Sync + async clients with identical APIs
  • 🧱 Typed dataclass models — including BanCheckResult and HealthInfo
  • 🚦 Granular exceptions mapped from HTTP status codes (401/403, 404, 4xx, 409, 429, 5xx, transport)
  • 🧰 Context-manager support (with / async with)
  • 🧪 First-class testability — built around httpx.MockTransport
  • 📦 PEP 561 typed (py.typed shipped)

Installation

Requires Python 3.10+.

pip install etoneya-api

Or from source:

git clone https://github.com/keys-nloverx/etoneya-lib.git
cd etoneya-lib
pip install -e ".[dev]"

Quick start

Synchronous

from etoneya import EtoneyaClient

with EtoneyaClient(
    base_url="https://api.example.com",
    auth_token="your_auth_token_here",
) as client:
    user = client.create_user(
        tg_id=123456789,
        type_sub="premium",
        udid="udid-1",
        limit_devices=3,
    )
    print(user.id)

    info = client.health_check()
    print(info.status, info.build)

Asynchronous

import asyncio
from etoneya import AsyncEtoneyaClient

async def main() -> None:
    async with AsyncEtoneyaClient(
        base_url="https://api.example.com",
        auth_token="your_auth_token_here",
    ) as client:
        info = await client.health_check()
        print(info.status)

asyncio.run(main())

API surface

User management

client.create_user(tg_id=..., type_sub="premium", udid="...", limit_devices=3)
client.get_user(1)
client.get_user_by_telegram(123456789)
client.list_users()                        # all users
client.list_users(filter="active")         # active only
client.list_users(filter="banned")         # banned only
client.update_user(1, limit_devices=5)
client.ban_user(1, reason="Spam")
client.unban_user(1)
client.delete_user(1)

The legacy aliases get_all_users, get_active_users, and get_banned_users are kept for backwards compatibility.

Devices

client.get_device(1)
client.get_device_by_hwid("hwid-1")
client.get_user_devices("udid-1")
client.delete_device(1)

IP bans

client.create_ip_ban("192.168.1.1", reason="abuse")

result = client.check_ip_ban("192.168.1.1")
if result.is_banned:
    print(result.ban_info.reason)

client.get_all_bans()
client.delete_ip_ban(1)
client.delete_ip_ban_by_address("192.168.1.1")

System

info = client.health_check()           # HealthInfo
client.update_subscriptions("hook-token")

Error handling

from etoneya import (
    AuthenticationError,
    ConflictError,
    EtoneyaAPIError,
    NotFoundError,
    RateLimitError,
    ServerError,
    TransportError,
    ValidationError,
)

try:
    client.get_user(999)
except NotFoundError as exc:
    print(exc.status_code, exc.message, exc.response)
except AuthenticationError:
    ...
except RateLimitError:
    ...
except TransportError:
    # connection refused / timeouts / DNS — preserves the underlying httpx error
    ...
except EtoneyaAPIError:
    ...
HTTP status Exception
400, 422 ValidationError
401, 403 AuthenticationError
404 NotFoundError
409 ConflictError
429 RateLimitError
5xx ServerError
transport TransportError
anything else EtoneyaAPIError

Models

All models are slotted, keyword-only dataclasses; convert to/from JSON-style dicts via from_dict / to_dict.

@dataclass(slots=True, kw_only=True)
class User:
    id: int
    tg_id: int
    type_sub: str
    udid: str
    limit_devices: int
    reason: str = ""
    is_banned: bool = False
    is_active: bool = True
    allowed_useragents: list[str] = []
    status: str = "user"  # "user" | "volunteer"

Device, BannedIP, BanCheckResult, and HealthInfo follow the same pattern.

Configuration

import httpx

EtoneyaClient(
    base_url="https://api.example.com",
    auth_token="...",
    timeout=httpx.Timeout(10.0, read=30.0),
    user_agent="my-bot/1.0",
)

You can also inject a custom httpx.BaseTransport (or httpx.AsyncBaseTransport) — handy for tests, retries via httpx-retries, or custom proxying.

Development

git clone https://github.com/keys-nloverx/etoneya-lib.git
cd etoneya-lib
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pre-commit install

ruff check .
black --check .
mypy etoneya/
pytest

The CI matrix runs lint + type-check + tests on Python 3.10 – 3.13 across Linux/macOS/Windows.

License

MIT — see LICENSE.

Contact

  • Author: nloverx (owner@nloverx.best)
  • Telegram: @nloverx

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

etoneya_api-0.2.0.tar.gz (14.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

etoneya_api-0.2.0-py3-none-any.whl (12.0 kB view details)

Uploaded Python 3

File details

Details for the file etoneya_api-0.2.0.tar.gz.

File metadata

  • Download URL: etoneya_api-0.2.0.tar.gz
  • Upload date:
  • Size: 14.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for etoneya_api-0.2.0.tar.gz
Algorithm Hash digest
SHA256 93aabdcfafb2d70ccf67ec157980db0f0b51e6be47e8428ffcdad4043d01d7ad
MD5 a76556dddbfc4689b2e525daad8219f5
BLAKE2b-256 5359e17a1851f6891ace58298c43dbd33a85c81806d51962cc9bec4acab98684

See more details on using hashes here.

File details

Details for the file etoneya_api-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: etoneya_api-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 12.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for etoneya_api-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 947617677c0359190d40a4d2a94f71bfeaa0531a4353d5ca5f0fd2cdbfce028e
MD5 253a446f5855d69b3320765dc68df1f3
BLAKE2b-256 83b75251fe1f86561a5566a5acf8578564e12e05ba2f464d3557bb909d1b58b1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page