Python client — `disband-bot`

The official Python client. Uses only the standard library (threading + urllib), so there is nothing to install except the client itself. Works on Python 3.9+.

Install

pip install disband-bot

or, from this monorepo:

pip install ./packages/disband-bot-python

Quick start

from disband_bot import Client

client = Client(token=DISBAND_BOT_TOKEN)

@client.on("ready")
def on_ready(me):
    print(f"Logged in as {me['name']} ({', '.join(me['scopes'])})")

@client.on("messageCreate")
def on_message(message):
    if message.author_is_bot:
        return
    if message.content == "!ping":
        message.reply("pong")

client.run()  # connects and blocks forever

Handlers may be plain or async def; both are supported.

Constructor

`Client(token, base_url="https://www.disband.dev", gateway_timeout=20)`

Argument Default Description
token (required) The bot token from Settings → Bots.
base_url "https://www.disband.dev" API root (change for a custom domain).
gateway_timeout 20 Seconds per gateway poll (1–20).

Lifecycle

Method Description
run() Connects, emits ready, starts the gateway loop in a background thread, and blocks forever.
close() Stops the loop.

Events

Register with client.on("name", handler) — as a decorator or a plain call — plus once for single-shot handlers.

Event Args Notes
ready user user["id"], user["name"], user["scopes"], etc.
messageCreate message A new message in a server the bot can see.
messageUpdate message A message was edited (content, edited_at updated).
messageDelete message A message was deleted (content empty; id/channel_id valid).
error error Gateway errors. The loop retries automatically unless the token is invalid, in which case it stops.

`Message`

Field Type Description
id str Message id.
channel_id str Channel id.
server_id str | None Server id.
author dict | None { "id", "username", "display_name", "avatar_url", "is_bot" }.
content str Message text.
reply_to_id str | None The message this replies to, if any.
mentions list Mentioned users.
attachment dict | None { "url", "type" } when the message has a file.
created_at str | None ISO timestamp.
edited_at str | None ISO timestamp of the last edit.
display_id int | None The sequential display number.
author_is_bot bool True when the sender was a bot (property).

Methodsmessage.reply(content) replies in the same channel.

Methods

client.send_message(channel_id, "Deploy finished")            # send
message.reply("pong")                                          # reply to a received message

messages = client.list_messages(channel_id, limit=25, before="…")
channels = client.list_channels(server_id)
members  = client.list_members(server_id)

channel_id = client.create_channel(server_id, "deploys")
client.rename_channel(channel_id, "deploys-2")
client.delete_channel(channel_id)

client.leave_server(server_id)

invite = client.create_invite(server_id, ["messages.read", "messages.write"])
# invite["invite_url"] -> send to the server owner

Errors

The client raises subclasses of DisbandError with a .status and .body:

Error When
AuthError 401 — invalid or revoked token. The gateway loop stops on this.
PermissionError 403 — missing scope or role permission.
RateLimitError 429 — includes retry_after seconds.
HttpError Any other non-2xx status.

Internally the client is a thin wrapper over the HTTP API: REST.get/post/patch/delete with Authorization: Bot <token>.