Skip to content
← Back to Community
Making a discord bot with disco-py (not!)
Profile icon
has Hacker Plan

Creating a discord bot with disco-py

This is not a tutorial! This is a tutorial for a discord bot library that I prefer, and made by one of discord's own developers! disco-py.

Getting Started

First, let's create a python3 repl. We're going to create a requirements.txt file, can put the following text inside it.

disco-py flask will look to this file for external dependencies, disco-py for bot obviously, and flask, if you want to use uptimerobot. Then we're also going to create a folder for the plugins called plugins. Plugins are exactly like's cogs, it's just a set of commands grouped together, that can be loaded / unloaded. By now you should have created a bot application here, and you can now copy the bot's token. Now create a .env file, and write

token=<token here>

.env files are special on, as other people can't see them. will load these files on startup and create environment variables. Alright, now time to write some code!

Creating a plugin!

Let's create a file in the plugin folder called (plugins/ and create the class that will hold all the commands / listeners.

from import Plugin class HelloPlug(Plugin): ...

We'll get into loading the plugins later (For those of you that've used, you'll notice there's no function like setup to add the plugin. That's because disco-py doesn't need one.) Let's create a command that says hello to us.

from import Plugin class HelloPlug(Plugin): @Plugin.command("hello", "<name:str...>") def hello(self, event, name: str): event.msg.reply(f"Hello {name}!")

Ok, let's break down all this code. First we use @Plugin.command to tell disco that this function is a command. The first argument we pass into that in the name of the command that people will use to invoke the command. The second argument specifies what information the command requires. The syntax is pretty simple, however it requires an explanation.

  • The < > characters specify that this argument is required. If I had used [``], it would have been optional.
  • name:str tells disco-py to pass the value provide into the function's name argument. the str tells disco-py to cast the value to a string, if it's not already.
  • The ... tells disco-py to match the whole input. Without this, if someone did !hello Johny Jenkins, name would only be Johny.
  • command("add", "<num1:int> <num2:int>") will match !add 5 4
  • command("kick", "<user:str> <reason:str...>") will match !kick Johny Called me ugly
  • Pro Tip: You cannot use ... if it's not the last argument.

As you can see, an event variable is provided, this will contain information on the event, and exposes things such as

  • event.msg
  • event.guild

In this case, we want to send a message back in the same channel, so we can do event.msg.reply for that. If you've used, you'll notice we're not using async / await. That's because disco-py uses the (arguably better) gevent lib. This means you can use packages such as requests, almost any database driver, and still be asynchronous!

Running the bot

Disco-py has a very different way of running bots, for better or worse. We're going to create a config.json file. Here we're going to put information like the prefix and plugin locations. The config.json actually stores a lot more information, but for right now that's all we'll need.

{ "bot": { "plugins": [ "plugins.hello" ], "commands_prefix": "!" } }

You can copy paste this, it's pretty self-explanatory. Don't use / or \\ paths to provide the location of the bot, instead use . like you're importing it.

Now, disco bots must be run by the command line, but doing something like:

python3 -m disco.cli --token <token here>

Pro Tip: Make sure you run this command in the same directory as the config file

However that's quite inconvenient on Instead, we're going that some command in the file, like so:

from os import environ, system token = environ['token'] system("python3 -m disco.cli --token {token}".format(token=token))

And at this point, we have everything we need! You can start the repl and everything should be ready to go! This is just a small part of disco-py. Sadly, the docs right now are quite lacking. That's why I'm going to continue to work on this tutorial, and expose all of disco's hidden treasures!

You can view the complete bot here:

Using it with uptimerobot (Optional)

If you'd like to run your bot on, it's actually even easier with disco-py than disco-py has flask integration built right in, making it super easy to combine a website and discord bot. Let's return to the file, and add the following route to the Plugin class:

@Plugin.route("/") def index(self): return "Hello World"

If you've used flask before, this should look very familiar. All this code does is return the text Hello World when someone visits the website. Now we just have to edit the config, and add 2 pits of information flask requires.

{ "bot": { "plugins": [ "plugins.hello" ], "commands_prefix": "!", "http_enabled": true } }

All we added was "http_enabled": true to tell disco-py that we're using flask. And just like that if you visit the repl's website it should say Hello World! See the link to the example bot above to see it in action.

Thanks for reading! Hopefully you'll give disco-py a try. At first glace it's not much, but I promise you, it's much more complicated then that! Any feedback or questions are greatly appreciated!

Profile icon
Profile icon
Profile icon
Profile icon
Profile icon
Profile icon
Profile icon
Profile icon
Profile icon
Profile icon
Profile icon


Profile icon