7.5.3. Demo: Trolling a Discord Command Bot#

Choose Social Media Platform: Reddit | Discord | Bluesky | No Coding

We are going to build a Discord Command Bot.

  • It will have a slash command called do_action which will ask us to provide an “action”

  • The bot will then reply, “I will now ____” (where the ___ is the action the user provided).

Then we will try trolling it, and fixing it, and trolling it again.

Log into Discord (with a different python library)#

In order to create a discord command, we will use a different Python library to help us build a Discord Bot. This library is called interactions.py.

This different library works fairly similarly to the discord.py library we used before, but is better for creating slash commands

# Load some code called "interactions" that will help us make Discord commands
import interactions

# Load another library that helps the bot work in Jupyter Noteboook
import nest_asyncio
nest_asyncio.apply()

(optional) make a fake Discord connection with the fake_discord_interactions library

For testing purposes, we’ve added this line of code, which loads a fake version of the “interactions” Discord library, so it wont actually connect to Discord. If you want to try to actually connect to Discord, don’t run this line of code.

# (optional)
%run ../../fake_apis/fake_discord_interactions.ipynb
Fake interactions discord is replacing the interactions.py library. Fake discord doesn't need real passwords, and prevents you from accessing real discord

save your discord token and the server/guild id you want your command to work on#

Note: To get the server/guild id, see the discord instructions here.

# Set up your Discord connection
# TODO: put the discord token for your bot below
discord_token = "m#5@_fake_discord_token_$%Ds"

# TODO: put the server/guild id you want your bot command to work on below
server_id = "123456"

Bot 1: do whatever we are told#

Our first bot will make an action that creates a post, doing whatever the user told it to do

Create a “/do_action” command#

This code starts a bot that creates a discord slash command on the server with the server_id we saved above.

The bot logs into discord, then starts (and displays a message showing it has started)

The bot then creates a slash command called “do_action” which requires users to enter a piece of text for the “action.”

The bot then creates a post that says “I will now ___” where the “___” is the action the user provided.

# Log into discord
bot = interactions.Client(token=discord_token)

# Listen for when the bot is logged in and ready, then print that the bot has started
@interactions.listen()
async def on_ready():
    print("The bot has started running")    

# Define a slash command called "do_action" for the given server_id
@interactions.slash_command(name="do_action", description="A bot that does what it's told.", scopes=[server_id])
# make the slash command require an option called "action"
@interactions.slash_option(
    name="action",
    description="Action for bot to do",
    required=True,
    opt_type=interactions.OptionType.STRING
)
# Define a function to call when the "/do_action" command is used
async def do_action_function(ctx: interactions.SlashContext, action: str):
    print('We recieved the following action: "' + action + '"')
    
    # Make a post using the "action" provided by the user
    await ctx.send("I will now " + action)
    
    # For testing purposes, we close the bot after one response
    # normally we wouldn't stop and leave the bot running so it
    # can continue responding
    print("Bot is now stopping")
    bot.stop()
    

# start running your bot
bot.start()
Fake interactions.py is pretending to set up a Discord client connection
fake discord interactions setting a slash command called: 'do_action'. With options: action
Fake discord bot is fake logging in and starting to run
The bot has started running
We recieved the following action: "jump"
Bot is posting:
I will now jump
Bot is now stopping
Fake discord bot is stopping

Yay! It worked! Our bot posted I will now jump. But there is a problem!

Trolling bot 1#

This bot is really easy to troll, so if I repeat my steps and get a new action (this code is just a duplication of the code above):

# Log into discord
bot = interactions.Client(token=discord_token)

# Listen for when the bot is logged in and ready, then print that the bot has started
@interactions.listen()
async def on_ready():
    print("The bot has started running")    

# Define a slash command called "do_action" for the given server_id
@interactions.slash_command(name="do_action", description="A bot that does what it's told.", scopes=[server_id])
# make the slash command require an option called "action"
@interactions.slash_option(
    name="action",
    description="Action for bot to do",
    required=True,
    opt_type=interactions.OptionType.STRING
)
# Define a function to call when the "/do_action" command is used
async def do_action_function(ctx: interactions.SlashContext, action: str):
    print('We recieved the following action: "' + action + '"')
    
    # Make a post using the "action" provided by the user
    await ctx.send("I will now " + action)
    
    # For testing purposes, we close the bot after one response
    # normally we wouldn't stop and leave the bot running so it
    # can continue responding
    print("Bot is now stopping")
    bot.stop()
    

# start running your bot
bot.start()
Fake interactions.py is pretending to set up a Discord client connection
fake discord interactions setting a slash command called: 'do_action'. With options: action
Fake discord bot is fake logging in and starting to run
The bot has started running
We recieved the following action: "do something horrible!"
Bot is posting:
I will now do something horrible!
Bot is now stopping
Fake discord bot is stopping

Asked our bot to do the action: do something horrible!, and we replied I will now do something horrible!.

They could have made us post something much worse!

Bot 2: Trying to limit actions#

Let’s try this again, but limit the actions we will do.

  • If someone asks us to “run”, “jump”, or “fly”, we will do it

  • If someone asks us to do something else we will say:

    • “I do not recognize the command ___” (with __ being whatever they said)

If tweet matches our pattern, reply#

We do the same code for this as before, but after we get the action we are told to do, we put another if/else to either do the action if we recognize it, or say we didn’t recognize the action.

We will use in to see if the action is in our list of allowed actions (called an allow_list)

# list the actions that we'll allow
actions_allow_list = ["run", "jump", "fly"]
    
# Log into discord
bot = interactions.Client(token=discord_token)

# Listen for when the bot is logged in and ready, then print that the bot has started
@interactions.listen()
async def on_ready():
    print("The bot has started running")    

# Define a slash command called "do_action" for the given server_id
@interactions.slash_command(name="do_action", description="A bot that does what it's told.", scopes=[server_id])
# make the slash command require an option called "action"
@interactions.slash_option(
    name="action",
    description="Action for bot to do",
    required=True,
    opt_type=interactions.OptionType.STRING
)
# Define a function to call when the "/do_action" command is used
async def do_action_function(ctx: interactions.SlashContext, action: str):
    print('We recieved the following action: "' + action + '"')
    
     # See if it is one of our recognized actions
    if(action in actions_allow_list):
        # send our message in reply
        await ctx.send("I will now " + action)

    else: # we didn't recognize the action
        # make a new message which says we will NOT do the action
        await ctx.send( "I do not recognize the command " + action)
    
    # For testing purposes, we close the bot after one response
    # normally we wouldn't stop and leave the bot running so it
    # can continue responding
    print("Bot is now stopping")
    bot.stop()
    
# start running your bot
bot.start()
Fake interactions.py is pretending to set up a Discord client connection
fake discord interactions setting a slash command called: 'do_action'. With options: action
Fake discord bot is fake logging in and starting to run
The bot has started running
We recieved the following action: "fly"
Bot is posting:
I will now fly
Bot is now stopping
Fake discord bot is stopping

That one was in our allow list so it worked. Let’s do it all again, with the tweet that caused us problems last time

Note: the code below is just copied from the code sections above

# list the actions that we'll allow
actions_allow_list = ["run", "jump", "fly"]
    
# Log into discord
bot = interactions.Client(token=discord_token)

# Listen for when the bot is logged in and ready, then print that the bot has started
@interactions.listen()
async def on_ready():
    print("The bot has started running")    

# Define a slash command called "do_action" for the given server_id
@interactions.slash_command(name="do_action", description="A bot that does what it's told.", scopes=[server_id])
# make the slash command require an option called "action"
@interactions.slash_option(
    name="action",
    description="Action for bot to do",
    required=True,
    opt_type=interactions.OptionType.STRING
)
# Define a function to call when the "/do_action" command is used
async def do_action_function(ctx: interactions.SlashContext, action: str):
    print('We recieved the following action: "' + action + '"')
    
     # See if it is one of our recognized actions
    if(action in actions_allow_list):
        # send our message in reply
        await ctx.send("I will now " + action)

    else: # we didn't recognize the action
        # make a new message which says we will NOT do the action
        await ctx.send( "I do not recognize the command " + action)
    
    # For testing purposes, we close the bot after one response
    # normally we wouldn't stop and leave the bot running so it
    # can continue responding
    print("Bot is now stopping")
    bot.stop()
    
# start running your bot
bot.start()
Fake interactions.py is pretending to set up a Discord client connection
fake discord interactions setting a slash command called: 'do_action'. With options: action
Fake discord bot is fake logging in and starting to run
The bot has started running
We recieved the following action: "do something horrible!"
Bot is posting:
I do not recognize the command do something horrible!
Bot is now stopping
Fake discord bot is stopping

Ok, this time we said I do not recognize the command do something horrible!.

That looks a little better! Are we safe now?

Trolling bot 2#

No, it turns out we are not safe.

Let’s find the latest mention again and see what happens

# list the actions that we'll allow
actions_allow_list = ["run", "jump", "fly"]
    
# Log into discord
bot = interactions.Client(token=discord_token)

# Listen for when the bot is logged in and ready, then print that the bot has started
@interactions.listen()
async def on_ready():
    print("The bot has started running")    

# Define a slash command called "do_action" for the given server_id
@interactions.slash_command(name="do_action", description="A bot that does what it's told.", scopes=[server_id])
# make the slash command require an option called "action"
@interactions.slash_option(
    name="action",
    description="Action for bot to do",
    required=True,
    opt_type=interactions.OptionType.STRING
)
# Define a function to call when the "/do_action" command is used
async def do_action_function(ctx: interactions.SlashContext, action: str):
    print('We recieved the following action: "' + action + '"')
    
     # See if it is one of our recognized actions
    if(action in actions_allow_list):
        # send our message in reply
        await ctx.send("I will now " + action)

    else: # we didn't recognize the action
        # make a new message which says we will NOT do the action
        await ctx.send( "I do not recognize the command " + action)
    
    # For testing purposes, we close the bot after one response
    # normally we wouldn't stop and leave the bot running so it
    # can continue responding
    print("Bot is now stopping")
    bot.stop()
    
# start running your bot
bot.start()
Fake interactions.py is pretending to set up a Discord client connection
fake discord interactions setting a slash command called: 'do_action'. With options: action
Fake discord bot is fake logging in and starting to run
The bot has started running
We recieved the following action: "stop talking. But that doesn't mean I won't say horrible things like: I hate everybody!"
Bot is posting:
I do not recognize the command stop talking. But that doesn't mean I won't say horrible things like: I hate everybody!
Bot is now stopping
Fake discord bot is stopping

Oh no! Someone told us the action was:

  • stop talking. But that doesn't mean I won't say horrible things like: I hate everybody!

And we replied:

  • I do not recognize the command stop talking. But that doesn't mean I won't say horrible things like: I hate everybody!

Making a bot that is troll proof is very difficult! You either need to severely limit how your bot engages with people, or do a ton of work trying to prevent trolling and fix problems when people find a new way of trolling you.

If you want to learn more, you can revisit the story of what went wrong with the Microsoft Tay bot: How to Make a Bot That Isn’t Racist