Skip to content

Instantly share code, notes, and snippets.

@ranguli
Forked from wilfreddv/discord_py_cookbook.md
Created April 11, 2019 23:34
Show Gist options
  • Save ranguli/03e075221b85e4f11fc8e51a168c86d1 to your computer and use it in GitHub Desktop.
Save ranguli/03e075221b85e4f11fc8e51a168c86d1 to your computer and use it in GitHub Desktop.
A cookbook for getting started with discord.py rewrite

Cookbook for discord.py rewrite

This document contains snippets that I've used and tested. It's not meant to be an official guide, but rather a document for looking up small snippets of code. For an extensive reference on the API, please visit the official documentation.

Contents

Installing discord.py

At the time of writing, this may or may not be the case, but the package on PyPi was an older version of discord.py. To be certain to install rewrite, execute this command: pip install -U git+https://github.com/Rapptz/discord.py@rewrite#egg=discord.py[voice].

Note: This requires git to be installed.

Note: pip might have to be pip3 on some Linux/MacOS systems.

Installing without Git

Another way for Linux (probably MacOS too) is using wget: wget https://github.com/Rapptz/discord.py/archive/rewrite.zip This will download a zip-file containing the branch. Next, unpack the zip using unzip rewrite.zip. After that, install it by cd-ing into the directory discord.py-rewrite and run python3 setup.py install. This will install the package. You'll need to be root or add the --user switch at the end.

On Windows, run this instead: curl https://codeload.github.com/Rapptz/discord.py/zip/rewrite --output rewrite.zip. Next, decompress the zip. Go into the discord.py-rewrite and open up CMD. Run python setup.py install to install system-wide. Else add --user (doesn't require Admin privileges).

To download the zipfile, you can also directly access this link.

Initiating a bot:

from discord.ext import commands

bot = commands.Bot()

The Bot class can take the following arguments (and more):

  • case_insensitive: bool: Bot command is case insensitive
  • description: str: Description for the bot
  • help_command: discord.ext.commands.HelpCommand: ...
  • self_bot: bool: Bot will only listen to commands invoked by itself if True (default: False)

The full docs can be found here.

Setting up configurations

You might not want to pollute your main file with settings. This is how you can include your setting in another file.

config.py

TOKEN=""        # Your bots token
CMD_PREFIX=""   # The command prefix
DESCRIPTION=""  # The description (optional)

main.py

from discord.ext import commands
from config import *

bot = commands.Bot(command_prefix=CMD_PREFIX, description=DESCRIPTION)

bot.run(TOKEN)

Bot events

A bot can listen for certain events. Two common ones are on_ready and on_message:

@bot.event
async def on_ready():
    print("Bot is ready!")

@bot.event
async def on_message(msg):
    print("A message was sent!")

Rich Presence

Ever see those user playing game things in Discord? They're called rich presence. You can easily add them to your bot. This will need to happen in the on_ready listener.

import discord

@bot.event
async def on_ready():
    await bot.change_presence(status=discord.Status.online, activity=discord.Game("a game of blackjack."), afk=False)

You can also pass the presence when initiating the bot.

import discord
from discord.ext import commands

activity = discord.Game("a game of blackjack.")
bot = commands.bot(activity=activity)

Note that bot.change_presence will overwrite this.

discord.Status is an enum which contains the following statuses: online, offline, idle, dnd, invisible

For more information, visit the docs.

Adding commands

discordpy makes it very easy to add commands to your bot.

@bot.commands()
async def foo(ctx):
    ...

This will add a command named foo to your bot. In Discord, this command would be called like this: {CMD_PREFIX}foo.

Combining commands and on_message

You may have noticed on_message and commands don't work well together: it will always only execute on_message, and not the commands. In order to still process the commands, use bot.process_commands.

@bot.event
async def on_message(msg):
    # Do your on_message duties
    await bot.process_commands(msg)

To see if a user said a particular phrase, you can use the in keyword:

if "hello" in msg.content: await msg.channel.send("Hello back!")

Adding aliases to your commands

Sometimes it's handy to have multiple ways to call the same command. Instead of writing the same function over and over again, you can add aliases.

@bot.command(aliases=["bar", "baz"])
async def foo(ctx):
    print("foo, bar or baz was called!")

You can run this command in Discord using {CMD_PREFIX}[foo|bar|baz].

Sending back messages

In the newest version, you're able to send messages to the context immediately, without having to grab the channel first.

@bot.command()
async def foo(ctx):
    await ctx.send("foo called!")

discord.Message (which is passed to on_message) however, doesn't have this luxury.

@bot.event
async def on_message(msg):
    await msg.channel.send("A message was sent!")

About users and mentions

Getting the author of a message:

@bot.event
async def on_message(msg):
    print(f"Author: {msg.author}")

@bot.command()
async def foo(ctx):
    print(f"Author: {ctx.author}")
    # OR
    print(f"Author: {ctx.message.author}")

Sometimes, you want to mention the author of the command. This can be done as such.

@bot.command()
async def foo(ctx):
    await ctx.send(f"foo was called by: {ctx.author.mention}")

You can also check the message to see what people were mentioned.

@bot.event
async def on_message(msg):
    people_mentioned = ctx.message.mentions
    channels_mentioned = ctx.message.channel_mentions
    roles_mentioned = ctx.message.role_mentions

This is a list of Users, Channels and Roles mentioned.

Interactivity

Sometimes you want to "communicate" with a user invoking your bot. You can do this by awaiting messages in your code manually.

import asyncio

@bot.command()
async def doAction(ctx):

    await ctx.send("Are you sure you want to do this? [y(es)/n(o)]")

    def check(m):
        return m.author == ctx.author

    try:
        msg = await bot.wait_for('message', check=check, timeout=10)
        # OR `check=lambda m: m.author == ctx.author`

        if msg.content.lower() in ['y', 'yes']:
            await ctx.send("Doing it!")
        elif  msg.content.lower() in ['n', 'no']:
            await ctx.send("Not doing it!")
        else:
            await ctx.send("I did not understand that, aborting!")
    except asyncio.TimeoutError as e:
        await ctx.send("Looks like you waited to long.")

wait_for takes in a string which tells discordpy what to wait for. The docs are not explicit on which events can be awaited.

The check parameter checks incoming messages for a certain condition. If that condition is met, it will return the Message.

The timeout parameter is the timeout in seconds.

Both check and timeout are optional.

Basic "dad bot" implementation

from discord.ext import commands

bot = commads.Bot(command_prefix='d!')


@bot.event
async def on_message(msg):
    content = msg.content.lower():

    if "shut up" in content:
        await msg.channel.send(f"Listen here {msg.author.name}, I will not tolerate you saying the words that consist of the letters 's h u t  u p' being said in this server, so take your own advice and close thine mouth in the name of the christian minecraft server owner.")

    if "i'm" in content:
        await msg.channel.send(f"Hello {content.split("i'm")[1]}, I'm dad!")

    await bot.process_commands(msg)

@bot.command()
async def dadjoke(ctx):
    await ctx.send("I bought shoes from a drug dealer once, I don't know what he laced them with, but I was tripping all day.")


bot.run("Super Secret Token")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment