Discord Self Bot Tester (DSBT) Library
Package for testing commands using discord selfbot. Assertions (messages, and autocomplete) and requests (interactions, events, reactions) can be made using the bot.
Install
pip install discord-self-bot-tester
Needs python 3.11 or newer.
Setup
- Create a
Botwith a user token - Run it with
bot.run(). This has to be called inside a running event loop, and every test has to use that same loop - Wait for it with
await bot.wait_ready() - Index the commands with
await bot.index_application_commands(GUILD_ID)(has to happen before sending any command) - Make tests and have fun or pain, idk ur pick
- Call
await bot.stop()in afinallyso a failed test still closes the socket
from discord_self_bot_tester import Bot
import asyncio
async def main():
bot = Bot(USER_TOKEN)
bot.run()
try:
await bot.wait_ready()
await bot.index_application_commands(GUILD_ID)
# tests go here
finally:
await bot.stop()
asyncio.run(main())
Commands
Build the command, then assert on the reply. assert_request sends it for you.
from discord_self_bot_tester.requests import ApplicationCommandBuilder, InteractionType
from discord_self_bot_tester.assertions import MessageAssertionBuilder
cmd = ApplicationCommandBuilder(InteractionType.APP_COMMAND, "ping")\
.set_arg("count", 3)\
.compile(APPLICATION_ID, GUILD_ID, CHANNEL_ID)
msg = await MessageAssertionBuilder()\
.assert_by_message_content("pong")\
.compile()\
.assert_request(bot, cmd)
set_main_command("sub") for subcommands. await cmd.send(bot) if u dont care about the reply.
Filters
Which message to pick. Leave them all out and it picks the reply to the command.
filter_by_author(user_id)filter_by_channel(channel_id)filter_by_message_update()for deferred or edited repliesfilter_by_message_flags(64)for ephemeral repliesfilter_by_followup_message()ties a filtered assertion back to the command
Checks
assert_by_message_content(regex)assert_by_mentions([ids])assert_by_mention_roles([ids])
Default deadline is 5 seconds, change it with deadline= on assert_request. Raises TimeoutError if nothing shows up.
Views
Assert what buttons and dropdowns are on the message.
from discord_self_bot_tester.gateway import ButtonStyle
msg = await MessageAssertionBuilder()\
.assert_by_button("Confirm", style=ButtonStyle.SUCCESS)\
.assert_by_button_labels(["Confirm", "Cancel"])\
.assert_by_dropdown(placeholder="Pick one", option_labels=["A", "B"])\
.compile()\
.assert_request(bot, cmd)
Then click stuff. Ids get pulled off the message so u only need the label.
from discord_self_bot_tester.requests import press_button, select_dropdown, select_dropdown_values
await MessageAssertionBuilder()\
.filter_by_message_update()\
.compile()\
.assert_request(bot, press_button(msg, "Confirm"))
await select_dropdown(msg, "A", "B", dropdown="Pick one").send(bot)
await select_dropdown_values(msg, USER_ID, dropdown="pick_user").send(bot)
dropdown can be left out if the message only has one. User, role and channel selects take snowflakes, so use select_dropdown_values for those.
Modals
Open it, fill it in by label, submit it.
from discord_self_bot_tester.requests import ModalResponseBuilder
from discord_self_bot_tester.assertions import ModalAssertionBuilder
modal = await ModalAssertionBuilder()\
.assert_by_modal_title("Sign up")\
.compile()\
.assert_request(bot, press_button(msg, "Register"))
submit = ModalResponseBuilder(modal)\
.select("Name").set_text("oliver")\
.select("Colour").choose("Green")\
.select("Agree").set_checked()\
.compile(GUILD_ID, CHANNEL_ID, APPLICATION_ID)
await MessageAssertionBuilder().compile().assert_request(bot, submit)
set_text(str)for text inputschoose(*labels)for selects, radios and checkbox groupsset_values(*values)andset_option(value)if u want raw values instead of labelsset_checked(bool)for checkboxesselect_by_custom_id(id)if the label is annoying
Nested labels work like select("Address", "Postcode"). Required fields left empty fail at compile, not on discord.
Autocomplete
from discord_self_bot_tester.assertions import AutoCompleteAssertionBuilder
res = await AutoCompleteAssertionBuilder().compile().assert_request(
bot,
ApplicationCommandBuilder(InteractionType.APPLICATION_COMMAND_AUTOCOMPLETE, "search")
.set_arg("query", "ab", focused=True)
.compile(APPLICATION_ID, GUILD_ID, CHANNEL_ID)
)
Other requests
Reactions, events and attachments all have builders. .send(bot) sends them.
from discord_self_bot_tester.requests import build_reaction, build_attachment
await build_reaction("🖥️", MESSAGE_ID, CHANNEL_ID).send(bot)
file = build_attachment(data, "image.png", CHANNEL_ID)
await file.send(bot)
file.get_attachment_id() # pass this to set_values on a modal file upload
Metadata
Release files for discord-self-bot-tester 0.8.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| discord_self_bot_tester-0.8.0.tar.gz | 42.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| discord_self_bot_tester-0.8.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 90.4 kB
Release files / discord_self_bot_tester-0.8.0.tar.gz
| Download URL | discord_self_bot_tester-0.8.0.tar.gz |
|---|---|
| Size | 42.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5fc5e1c82ebcad84ab8bdfaaf677f9f12c97032467bb16b2d70211130ddf9370
|
|
BLAKE2b-256 checksum How to use checksums |
5f9c42eb2bceba7ca207fc23a11cf3b981954ef7ab22ea599f72dfb34631ceb1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.
Transparency logRelease files / discord_self_bot_tester-0.8.0-py3-none-any.whl
| Download URL | discord_self_bot_tester-0.8.0-py3-none-any.whl |
|---|---|
| Size | 48.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
105d0142d0b47cd1c976cc56c41137f432881d19dcf97af2d33d53a7604fe0f4
|
|
BLAKE2b-256 checksum How to use checksums |
7dd941de986c6e8c64551525e9a2e0bdc43d7bda9c3c5296d2cacd047c4e9fb8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.
Transparency log