Metadata-Version: 2.4
Name: taverns.py
Version: 0.2.3
Summary: Python SDK for building Tavern bots
License: Apache-2.0
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiohttp>=3.9
Requires-Dist: websockets>=12.0
Provides-Extra: dev
Requires-Dist: mypy; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Dynamic: license-file

<p align="center">
  <img src="https://raw.githubusercontent.com/Tav-gg/taverns.py/main/assets/banner.jpg" alt="taverns.py" width="100%" />
</p>

# taverns.py

Python SDK for building Tavern bots on the [Taverns](https://tav.gg) platform.

## Installation

```bash
pip install taverns.py
# or from source:
pip install -e .
```

Requires Python 3.10+.

## Quick Start

```python
import os
from taverns import Client, Intents

client = Client(intents=Intents.MESSAGES | Intents.MESSAGE_CONTENT)

@client.event
async def on_ready():
    print(f"Logged in as {client.user.display_name}")

@client.event
async def on_message_create(message):
    if message.sender_id == client.user.id:
        return
    if message.content == "!ping":
        await client.send_message(message.tavern_id, message.channel_id, content="Pong!")

client.run(os.environ["BOT_TOKEN"])
```

## Slash Commands

```python
from taverns import Client, Intents, Interaction
from taverns.commands import command, option
from taverns.types import CommandOptionType

client = Client(intents=Intents.MESSAGES | Intents.INTERACTIONS)

@client.event
async def on_ready():
    await client.register_commands([
        command("ping", "Check latency"),
        command("greet", "Greet someone", options=[
            option("name", "Who to greet", CommandOptionType.STRING, required=True),
        ]),
    ])

@client.event
async def on_interaction_create(interaction: Interaction):
    if interaction.command_name == "ping":
        await interaction.reply("Pong!")
    elif interaction.command_name == "greet":
        name = interaction.get_option("name", "World")
        await interaction.reply(f"Hello, {name}!")

client.run(os.environ["BOT_TOKEN"])
```

### Deferred Responses

```python
@client.event
async def on_interaction_create(interaction: Interaction):
    if interaction.command_name == "slow":
        await interaction.defer_reply()      # Shows "thinking..." to the user
        result = await do_slow_work()
        await interaction.follow_up(f"Done: {result}")
```

### Ephemeral Responses

```python
await interaction.reply("Only you can see this", ephemeral=True)
```

## Webhook Verification

```python
from taverns import verify_webhook_signature

is_valid = verify_webhook_signature(
    raw_body=request.data,
    signature=request.headers["X-Tavern-Signature"],
    secret=WEBHOOK_SECRET,
    timestamp=request.headers.get("X-Tavern-Timestamp"),
)
```

## Intents

Control which events your bot receives:

```python
from taverns import Intents

# Specific intents
client = Client(intents=Intents.MESSAGES | Intents.INTERACTIONS)

# All non-privileged intents
client = Client(intents=Intents.DEFAULT)

# All intents (including privileged)
client = Client(intents=Intents.ALL)
```

Privileged intents (`MESSAGE_CONTENT`, `MEMBERS`) are self-serve for private bots.

## REST Client

For direct API access:

```python
# Available after login
channels = await client.rest.get_channels(tavern_id)
members = await client.rest.get_members(tavern_id)
messages = await client.rest.get_messages(tavern_id, channel_id, limit=50)
```

## Links

- [PyPI package](https://pypi.org/project/taverns.py/)
- [API Documentation](https://tav.gg/developers/docs)
- [Developer Portal](https://tav.gg/developers/home)
- [taverns.js](https://github.com/Tav-gg/taverns.js) (Node.js SDK)
