Metadata-Version: 2.4
Name: disagreement
Version: 0.0.1
Summary: A Python library for the Discord API.
Author-email: Slipstream <me@slipstreamm.dev>
License: BSD 3-Clause
Project-URL: Homepage, https://github.com/Slipstreamm/disagreement
Project-URL: Issues, https://github.com/Slipstreamm/disagreement/issues
Keywords: discord,api,bot,async,aiohttp
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Internet
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiohttp<4.0.0,>=3.9.0
Provides-Extra: test
Requires-Dist: pytest>=8.0.0; extra == "test"
Requires-Dist: pytest-asyncio>=1.0.0; extra == "test"
Requires-Dist: hypothesis>=6.89.0; extra == "test"
Provides-Extra: dev
Requires-Dist: dotenv>=0.0.5; extra == "dev"
Dynamic: license-file

# Disagreement

A Python library for interacting with the Discord API, with a focus on bot development.

## Features

- Asynchronous design using `aiohttp`
- Gateway and HTTP API clients
- Slash command framework
- Message component helpers
- Built-in caching layer
- Experimental voice support
- Helpful error handling utilities

## Installation

```bash
python -m pip install -U pip
pip install disagreement
# or install from source for development
pip install -e .
```

Requires Python 3.11 or newer.

## Basic Usage

```python
import asyncio
import os
import disagreement

# Ensure DISCORD_BOT_TOKEN is set in your environment
client = disagreement.Client(token=os.environ.get("DISCORD_BOT_TOKEN"))

@client.on_event('MESSAGE_CREATE')
async def on_message(message: disagreement.Message):
    print(f"Received: {message.content} from {message.author.username}")
    if message.content.lower() == '!ping':
        await message.reply('Pong!')

async def main():
    if not client.token:
        print("Error: DISCORD_BOT_TOKEN environment variable not set.")
        return
    try:
        async with client:
            await asyncio.Future()  # run until cancelled
    except KeyboardInterrupt:
        print("Bot shutting down...")
    # Add any other specific exception handling from your library, e.g., disagreement.AuthenticationError

if __name__ == '__main__':
    asyncio.run(main())
```

### Global Error Handling

To ensure unexpected errors don't crash your bot, you can enable the library's
global error handler:

```python
import disagreement

disagreement.setup_global_error_handler()
```

Call this early in your program to log unhandled exceptions instead of letting
them terminate the process.

### Configuring Logging

Use :func:`disagreement.logging_config.setup_logging` to configure logging for
your bot. The helper accepts a logging level and an optional file path.

```python
import logging
from disagreement.logging_config import setup_logging

setup_logging(logging.INFO)
# Or log to a file
setup_logging(logging.DEBUG, file="bot.log")
```

### Defining Subcommands with `AppCommandGroup`

```python
from disagreement.ext.app_commands import AppCommandGroup

settings = AppCommandGroup("settings", "Manage settings")

@settings.command(name="show")
async def show(ctx):
    """Displays a setting."""
    ...

@settings.group("admin", description="Admin settings")
def admin_group():
    pass

@admin_group.command(name="set")
async def set_setting(ctx, key: str, value: str):
    ...
## Fetching Guilds

Use `Client.fetch_guild` to retrieve a guild from the Discord API if it
isn't already cached. This is useful when working with guild IDs from
outside the gateway events.

```python
guild = await client.fetch_guild("123456789012345678")
roles = await client.fetch_roles(guild.id)
```

## Sharding

To run your bot across multiple gateway shards, pass `shard_count` when creating
the client:

```python
client = disagreement.Client(token=BOT_TOKEN, shard_count=2)
```

See `examples/sharded_bot.py` for a full example.

## Contributing

Contributions are welcome! Please open an issue or submit a pull request.

See the [docs](docs/) directory for detailed guides on components, slash commands, caching, and voice features.

