Public | Automated Build

Last pushed: 5 months ago
Short Description
Main image for the bot at
Full Description


A plugin-based, extensible bot for Discord


The bot configuration is read from a yaml file (specified with --config-path)
You can copy the existing config.example.yaml file and fill in the values yourself

You must at least provide a valid token for your bot under the top level bot configuration key
There must also be a top level web key as well as a top level db

A minimalistic configuration file could look like this:

  # A valid discord application token
  token: 'MyaWes0mebOtT0k3n'

  # Plugins to enable
    some_plugin: {}
      conf_key: 'conf value'

  # Ids of people able to use "master commands"
    - 'Some snowflake id for a discord account'

  port: 80

  host: db
  user: postgres

Deployment :whale:

If you want to use the webserver:

Place/generate your SSL/TLS certificate in ./web/server/fullchain.pem
Place the associated private key in ./web/server/privkey.pem

Then make sure docker >= 1.10 and docker-compose >= 1.6 are installed and run:

./dev run --rm web-builder npm install # Fetch node dependencies
./dev run --rm web-builder webpack -p # Bundle the website

./prod up -d db # Boots up the db
./dev run --rm db flyway migrate # Populate the db

./prod up -d # Boots up the bot and the webserver

./prod logs -f bot # To access the bot's stdout logs

Using plugins

Globibot comes with a minimalistic set of plugins

Plugins are python modules loaded from the directory specified by --plugin-path

To enable a plugin, you can just add its name in the configuration file under the plugins key

Creating plugins

For globibot to be able to load a plugin, your plugin module must export a symbol called plugin_cls which would point to a class that inherits Plugin from bot.lib.plugin

Let's create a simple plugin called foo

In ./bot/plugins/foo/

from .foo_plugin import Foo

plugin_cls = Foo

In ./bot/plugins/foo/

from globibot.lib.plugin import Plugin

class Foo(Plugin):

In ./bot/config.yaml let's add our plugin with a dummy config:

  # ...


      bar: 1337

  # ...

Now if you start/restart the bot:

./script/dev up -d bot # To start the bot
# Or
./script/dev restart -t 0 bot # To restart the bot

You should see in the logs that Globibot loaded your plugin:

From this moment on, any changes to your foo modules will be reloaded automatically when module files change

Let's add a simple command to the plugin:

In ./bot/src/bot/plugins/foo/

from globibot.lib.plugin import Plugin

from globibot.lib.decorators import command # Command declaration helper

from globibot.lib.helpers import parsing as p # Parser combinator tools
from globibot.lib.helpers.hooks import master_only # Hook to only allow master users

class Foo(Plugin):

    def load(self):
        Called on plugin load/reload

        # Loads the value of the `bar` configuration key with a default value
        # if the key were to be absent = self.config.get('bar', 42)

    @command(p.string('!foo') + p.bind(p.integer, 'number'))
    async def foo_command(self, message, number):
        Called on inputs starting with the string '!foo' (case insensitive)
        followed by an integer whose value will be bound to the `number`

        await self.send_message(
  , # Sends a message in the same channel as the input
            '{} * {} = {}'.format(number,, number *

    @command(p.string('!id') + p.bind(p.mention, 'user_id'), master_only)
    async def id_command(self, message, user_id):
        Called on inputs starting with the string '!id' (case insensitive)
        followed by a discord user mention (usually displayed '@SomeUser' on
        discord's client)

        We have access to SomeUser's discord's ID in the `user_id` variable

        The command is marked as `master_only` and will execute only if the
        input was sent by someone who was registered as 'master' in the
        configuration file

        await self.send_message(
            '{}: the id is {}'
                .format(, user_id),
            delete_after = 30 # Message deletes itself after 30 seconds

Upon saving this file, you should see this:

And then you can simply test the results in discord directly:

Docker Pull Command
Source Repository