Metadata-Version: 2.4
Name: cb-events
Version: 8.0.9
Summary: Async Python client for the Chaturbate Events API.
Project-URL: Homepage, https://github.com/MountainGod2/cb-events
Project-URL: Documentation, https://cb-events.readthedocs.io/latest/
Project-URL: Repository, https://github.com/MountainGod2/cb-events.git
Project-URL: Changelog, https://github.com/MountainGod2/cb-events/blob/main/CHANGELOG.md
Project-URL: Issue Tracker, https://github.com/MountainGod2/cb-events/issues
Author-email: MountainGod2 <admin@reid.ca>
Maintainer-email: MountainGod2 <admin@reid.ca>
License: MIT
License-File: LICENSE
Keywords: api,async,chaturbate,client,events,real-time,streaming,webcam
Classifier: Development Status :: 5 - Production/Stable
Classifier: Framework :: AsyncIO
Classifier: Framework :: Pydantic
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Internet
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: aiohttp>=3.13.5
Requires-Dist: aiolimiter>=1.2.1
Requires-Dist: pydantic>=2.13.3
Requires-Dist: stamina>=26.1.0
Requires-Dist: typing-extensions>=4.15.0
Description-Content-Type: text/markdown

# CB Events

Async Python client for the Chaturbate Events API.

[![PyPI](https://img.shields.io/pypi/v/cb-events)](https://pypi.org/project/cb-events/)
[![Tag](https://img.shields.io/github/v/tag/MountainGod2/cb-events)](https://github.com/MountainGod2/cb-events/releases)
[![Python](https://img.shields.io/pypi/pyversions/cb-events)](https://pypi.org/project/cb-events/)
[![OpenSSF Best Practices](https://img.shields.io/cii/summary/12375?label=openssf%20best%20practices)](https://www.bestpractices.dev/en/projects/12375)
[![Builds](https://img.shields.io/github/actions/workflow/status/MountainGod2/cb-events/ci-cd.yml?label=builds)](https://github.com/MountainGod2/cb-events/actions/workflows/ci-cd.yml)
[![License](https://img.shields.io/github/license/MountainGod2/cb-events?label=license)](https://github.com/MountainGod2/cb-events/blob/main/LICENSE)

## Requirements

Python 3.10+

## Installation

```bash
pip install cb-events
```

With [uv](https://docs.astral.sh/uv/) (recommended):

```bash
uv add cb-events
```

## Quick Start

```python
import asyncio
from cb_events import EventClient, Router, EventType, Event

router = Router()

username = "your_username"
token = "your_api_token"

@router.on(EventType.TIP)
async def handle_tip(event: Event) -> None:
    if event.user and event.tip:
        print(f"{event.user.username} tipped {event.tip.tokens} tokens")

async def main():
    async with EventClient(username, token) as client:
        async for event in client:
            await router.dispatch(event)

asyncio.run(main())
```

```text
mountaingod2 tipped 100 tokens
```

For usage examples, see the [examples folder](https://github.com/MountainGod2/cb-events/blob/main/examples).

> Generate an API token at https://chaturbate.com/statsapi/authtoken/ with `Events API` scope.

## Working with Events

### Event Types

`TIP` · `FANCLUB_JOIN` · `MEDIA_PURCHASE` · `CHAT_MESSAGE` · `PRIVATE_MESSAGE` · `USER_ENTER` · `USER_LEAVE` · `FOLLOW` · `UNFOLLOW` · `BROADCAST_START` · `BROADCAST_STOP` · `ROOM_SUBJECT_CHANGE`

### Event Object

```python
event.user          # User object (most events)
event.tip           # Tip object (TIP only)
event.message       # Message object (CHAT_MESSAGE, PRIVATE_MESSAGE)
event.media         # Media object (MEDIA_PURCHASE)
event.room_subject  # RoomSubject object (ROOM_SUBJECT_CHANGE)
event.broadcaster   # Broadcaster username string or None
```

[See full docs for additional details](https://cb-events.readthedocs.io/latest/event_models.html).

## Configuration

```python
from cb_events import ClientConfig

config = ClientConfig(
    timeout=10,                   # Server long-poll timeout (seconds)
    use_testbed=False,            # Use testbed endpoint (https://www.testbed.cb.dev)
    strict_validation=False,      # False skips & logs invalid events; True raises.
    retry_attempts=8,             # Total attempts (initial + retries)
    retry_backoff=1.0,            # Initial backoff (seconds)
    retry_factor=2.0,             # Backoff multiplier
    retry_max_delay=30.0,         # Max retry delay (seconds)
)

client = EventClient(username, token, config=config)
```

> **Testbed:** Register at <https://www.testbed.cb.dev>. New accounts include preloaded tokens for testing. Generate an API token the same way as a live account, then pass `use_testbed=True` with those credentials.

### Rate Limiting

Default: 2000 req/60s per client. Multiple clients each get an independent
budget unless a shared limiter is passed:

```python
from aiolimiter import AsyncLimiter

limiter = AsyncLimiter(max_rate=2000, time_period=60)
client1 = EventClient(username1, token1, rate_limiter=limiter)
client2 = EventClient(username2, token2, rate_limiter=limiter)
```

## Error Handling

`AuthError` is a subclass of `EventsError` — `except EventsError` catches both. Put `AuthError` first if you need to distinguish them.

```python
import logging
import sys

from cb_events import AuthError, EventsError

logger = logging.getLogger(__name__)

try:
    async with EventClient(username, token) as client:
        async for event in client:
            await router.dispatch(event)
except AuthError:
    # Authentication failed (401/403) — never retried
    logger.error("Invalid credentials — check username and token")
    sys.exit(1)
except EventsError as e:
    # All other API/network errors — check e.status_code, e.response_text
    logger.error("API error %s: %s", e.status_code, e.response_text)
    raise
```

**Retries:** 429, 5xx, Cloudflare 521-524. Not retriable: 401/403.

**Handlers:** Sequential execution. Errors logged but don't stop processing.

## Logging

Set the logger to `DEBUG` for verbose polling data:

```python
import logging
logging.getLogger("cb_events").setLevel(logging.DEBUG)
```

Example output:

```text
DEBUG:cb_events.client:Polling https://eventsapi.chaturbate.com/events/user/************************/?timeout=10
DEBUG:cb_events.client:Received 1 events for user
DEBUG:cb_events.router:Dispatching chatMessage event 1775683684418-0 to 2 handlers
```

## Star History

<a href="https://www.star-history.com/?repos=mountaingod2%2Fcb-events&type=timeline&logscale=&legend=top-left">
 <picture>
   <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=mountaingod2/cb-events&type=timeline&theme=dark&logscale&legend=top-left" />
   <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=mountaingod2/cb-events&type=timeline&logscale&legend=top-left" />
   <img alt="Star History Chart" src="https://api.star-history.com/chart?repos=mountaingod2/cb-events&type=timeline&logscale&legend=top-left" />
 </picture>
</a>

## License

MIT

---

Not affiliated with Chaturbate.
