Skip to main content

Disagreement

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

Features

  • Internationalization helpers
  • Hybrid context for commands
  • Built-in rate limiting
  • Asynchronous design using aiohttp
  • Gateway and HTTP API clients
  • Slash command framework
  • Message component helpers
  • Message.jump_url property for quick links to messages
  • Built-in caching layer
  • Experimental voice support
  • Helpful error handling utilities

Installation

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

Requires Python 3.10 or newer.

To run the example scripts, you'll need the python-dotenv package to load environment variables. Install the development extras with:

pip install "disagreement[dev]"

Basic Usage

import asyncio
import os

import disagreement
from disagreement.ext import commands
from dotenv import load_dotenv
load_dotenv()


class Basics(commands.Cog):
    def __init__(self, client: disagreement.Client) -> None:
        super().__init__(client)

    @commands.command()
    async def ping(self, ctx: commands.CommandContext) -> None:
        await ctx.reply(f"Pong! Gateway Latency: {self.client.latency_ms} ms.")


token = os.getenv("DISCORD_BOT_TOKEN")
if not token:
    raise RuntimeError("DISCORD_BOT_TOKEN environment variable not set")

intents = disagreement.GatewayIntent.default() | disagreement.GatewayIntent.MESSAGE_CONTENT
client = disagreement.Client(token=token, command_prefix="!", intents=intents, mention_replies=True)
async def main() -> None:
    client.add_cog(Basics(client))
    await client.run()


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:

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.

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")

HTTP Session Options

Pass additional keyword arguments to aiohttp.ClientSession using the http_options parameter when constructing :class:disagreement.Client:

client = disagreement.Client(
    token=token,
    http_options={"proxy": "http://localhost:8080"},
)

These options are forwarded to HTTPClient when it creates the underlying aiohttp.ClientSession. You can specify a custom connector or any other session parameter supported by aiohttp.

Default Allowed Mentions

Specify default mention behaviour for all outgoing messages when constructing the client:

from disagreement.models import AllowedMentions
client = disagreement.Client(
    token=token,
    allowed_mentions=AllowedMentions.none().to_dict(),
)

This dictionary is used whenever send_message or helpers like Message.reply are called without an explicit allowed_mentions argument.

Defining Subcommands with AppCommandGroup

from disagreement.ext.app_commands import AppCommandGroup, slash_command
from disagreement.ext.app_commands.context import AppCommandContext

settings_group = AppCommandGroup("settings", "Manage settings")
admin_group = AppCommandGroup("admin", "Admin settings", parent=settings_group)


@slash_command(name="show", description="Display a setting.", parent=settings_group)
async def show(ctx: AppCommandContext, key: str):
    ...


@slash_command(name="set", description="Update a setting.", parent=admin_group)
async def set_setting(ctx: AppCommandContext, 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.

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

Call Client.fetch_guilds to list all guilds the current user has access to.

guilds = await client.fetch_guilds()
for g in guilds:
    print(g.name)

Sharding

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

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

If you want the library to determine the recommended shard count automatically, use AutoShardedClient:

client = disagreement.AutoShardedClient(token=BOT_TOKEN)

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 directory for detailed guides on components, slash commands, caching, and voice features.

License

This project is licensed under the BSD 3-Clause license. See the LICENSE file for details.

Metadata

Release files for disagreement 0.8.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for disagreement 0.8.1
File Size Uploaded
disagreement-0.8.1.tar.gz 180.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for disagreement 0.8.1
File Interpreter ABI Platform
disagreement-0.8.1-py3-none-any.whl Python 3 none any Details

Total release size: 328.1 kB

Release files / disagreement-0.8.1.tar.gz

Download URL disagreement-0.8.1.tar.gz
Size 180.5 kB
Tags Source
SHA-256 checksum
How to use checksums
7187878f7a2b780fde4c430e33f6b0caebbf84da6a5cb3d4d3c75344ce0a238c
BLAKE2b-256 checksum
How to use checksums
4469edd5310c5e18ff7afeec775a9bcb33c7768f8c78f4eb1af9cd885bb49c04
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / disagreement-0.8.1-py3-none-any.whl

Download URL disagreement-0.8.1-py3-none-any.whl
Size 147.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a1e656a4d718e7bc5b522910672959b3556c38baa578ac9dd6f246e12ff29c48
BLAKE2b-256 checksum
How to use checksums
92dffcfb1830cd80f2ab2eba3044c3f64d5231eac9714cdd68a69a6378fe52b0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page