Through this walkthrough, you should have a discord bot, hosted on either your local machine, or through the online IDE Repl.it. This tutorial just builds upon a few existing online resources that you can directly reference, if you would prefer.
You will now be redirected to a page where you can configure all the options for your app, creating a bot user and more.
Now you have to add your bot to the discord servers you want it to run in. For this project, we'll add all of our bots to the server I've created 'A Place to Talk to Bots'
In this tutorial, there are two options for running the code for your bot. You can run the code locally on your machine, or you can use an online IDE like Repl.it
Repl.it is simpler to setup and get started, and will include hosting, so you can keep your bot online all the time. However, there are storage, CPU and RAM limitations that might get in the way.
A local machine setup will be slightly more complicated if you don't have python already setup, and if you close your computer, your bot will go offline. But, you won't face as many of the resource limitations as you will with Repl.it.
I reccomend starting with Repl.it, and then moving over to a local setup if necessary in the future.
Before we start writing code, we have to add the Discord Bot Token to our Repl.it project. This will connect our code to the Bot we created.
DISCORD_BOT_SECRET and in the value field paste the Token that you copied from the Discord Developer Portal.
Finally, lets install the main packages that we will be using. You can use this same process to install other useful python packages in the future.
To actually create our Hello World bot, we'll have to write some python code into our main.py file.
import discord
import osNext let's define our bot's "intents." This is an object that we define to tell Discord what events our bots wants to listen to. For our bot, we want all the message_content events.
(See the documentation here for a list of all the intents.)
# Create an empty intents object
intents = discord.Intents.default()
# Set all required intents True
intents.message_content = Trueclient = discord.Client(intents=intents)@client.event
async def on_ready():
print(f'We have logged in as {client.user.name}')@client.event
async def on_message(message):
# Check the user who sent the message
if message.author == client.user:
return
# Check the content of the message
if message.content.startswith('$hello'):
# Send our response
await message.channel.send('Hello!')
token = os.getenv("DISCORD_BOT_SECRET")
client.run(token)python main.py from the project folder in your terminal.
You can copy paste the full main.py file below or fork the file from my example Repl.it: https://replit.com/@andoncemore/Basic-Discord-Bot#main.py
import discord
import os
# Create an empty intents object
intents = discord.Intents.default()
# Set all required intents True
intents.message_content = True
client = discord.Client(intents=intents)
@client.event
async def on_ready():
print(f'We have logged in as {client.user.name}')
@client.event
async def on_message(message):
# Check the user who sent the message
if message.author == client.user:
return
# Check the content of the message
if message.content.startswith('$hello'):
# Send our response
await message.channel.send('Hello!')
token = os.getenv("DISCORD_BOT_SECRET")
client.run(token)Source: https://www.codementor.io/@garethdwyer/building-a-discord-bot-with-python-and-repl-it-miblcwejz
When using Repl.it, your bot will only stay online as long as you keep the browser tab open. There are two ways to keep your bot alive:
Use the "Always On" Feature. This will cost "20 cycles/day" where a cycle is a token you buy from Repl.it for $0.01/cycle. So keeping your Repl "always on" will cost you $0.20 a day.
Create a web server and ping the web server every hour. Repl.it will keep your code running if it is running a web server. If your web server doesn't get any traffic for one hour, it will stop the code. We can then use Uptime Bot to ping the web server every hour to keep it alive.
Create a new file in the project called keep_alive.py
from flask import Flask
from threading import Thread
app = Flask('')
@app.route('/')
def home():
return "I'm alive"
def run():
app.run(host='0.0.0.0',port=8080)
def keep_alive():
t = Thread(target=run)
t.start()in your main file, import the keep_alive snippet you just created.
from keep_alive import keep_alive
and then run the keep_alive function at the top or bottom of the file.
keep_alive()
In the Hello World, we activate the bot by listening to all messages and looking for a keyword. Here are some very basic ideas for triggering your bot in other ways.
# 1. Look at the reference
@client.event
async def on_message(message):
# Whatever we want to do...
# 2. A different event
@client.event
async def on_reaction_add(reaction, user):
# Whatever we want to do...
@client.event
async def on_message(message):
# Check the user who sent the message
if(client.user in message.mentions):
await message.channel.send('You called for me?')
# replace() Remove part of the string
# message.content: "$hello what is your name"
# simpleContent: " what is your name"
simpleContent = message.content.replace('$hello', '')
# strip() Remove leading or trailing whitespace
# simpleContent: " what is your name"
# result: "what is your name"
result = simpleContent.strip()
# startswith() Check if the beginning of the string starts with substring
# message.content: "$hello try to do this"
# result: True
result = message.content.startswith('$hello')
# contains() Check if substring exists anywhere in the string
# message.content: "try to do this $hello"
# result: True
result = message.content.contains('$hello')
The discord.py library documentation will have the most comprehensive description of all the features of the library, but I've written out some helpful tips some common behaviors.
All of the example code can be found here
Guild vs DM As a note, in the documentation, you will notice references to Guilds and DMs. A guild is another word for server. The variation in intents (from messages, guild_messages, dm_messages) lets you specify where the bot can listen to messages (everywhere, in the server, or in the DMs)
You can send various UI elements with any message you send. To do this, you make a "view" and add any UI elements to it. Then you can send this view along with your message to see those UI elements
from discord.ui import View
class MyCustomView(View):
def __init__(self):
super().__init__()
from discord.ui import View
class MyCustomView(View):
def __init__(self):
super().__init__()
# adding button code
@discord.ui.button(label="Press the Button")
async def myButtonCallback(self, interaction, button):
await interaction.response.send_message("Thanks!")
@client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('$hello'):
# Create our View
myView = MyCustomView()
# Send our response with our view
await message.channel.send('Hello!', view=myView)
If you run the code now and send $hello to the channel, the response should include a button.
Here are some different patterns for adding and using buttons in your bots
First here are two different patterns for how you can add buttons.
from discord.ui import View
class MyCustomView(View):
def __init__(self):
super().__init__()
@discord.ui.button(label="Button Label")
async def buttonCallback(self, interaction, button):
# what should happen when the button is clicked?
# ...
# you can add multiple buttons this same way
@discord.ui.button(label="Button Label")
async def buttonCallback2(self, interaction, button):
# what should happen when the button is clicked?
# ...from discord.ui import View, Button
# 1. Create a custom Button class that we will use when programatically creating our Buttons
class CustomButton(Button):
def __init__(self, name):
super().__init__(label=name)
async def callback(self, interaction):
await interaction.response.send_message(f'{self.label} Press')
# 2. In the View class, edit the init function to accept a list. Then use a for-loop to create all of our Custom Buttons
class MyCustomView(View):
def __init__(self, buttonList):
super().__init__()
for b in buttonList:
self.add_item(CustomButton(name=b))
# 3. When sending a message, we now can provide a list to our view to create all of our buttons.
mybuttons = ["Button X", "Help", "Two"]
myView = MyCustomView(buttonList=mybuttons)
await message.channel.send('Hello!', view=myView)
import discord
# 1. Button Styles: Discord has many different styles for their buttons. See the documentation for all options
discord.ui.Button(label="button", style=discord.ButtonStyle.green)
# 2. Disabled: You can make a button disabled
discord.ui.Button(label="button", disabled=True)
# 3. Emojis: You can add an emojis to any button
discord.ui.Button(label="button", emoji='🔥')
There are lots of ways you can respond to a button click once it happens. Here are some basic ones, but you can be creative. There are three callback elements you can use: the View itself (self), the InteractionResponse (interaction), and the Button that was clicked (button)
from discord.ui import View
class MyCustomView(View):
def __init__(self):
super().__init__()
@discord.ui.button(label="Button Label")
async def buttonCallback(self, interaction, button):
# 1. you can send a reply in the thread of the message
await interaction.response.send_message("Thanks for Pressing")
from discord.ui import View
class MyCustomView(View):
def __init__(self):
super().__init__()
@discord.ui.button(label="Button Label")
async def buttonCallback(self, interaction, button):
# 1. you can send a new message in the same channel
await interaction.channel.send("A New message to the channel")
# 2. afterwards, you have to defer the response. Otherwise the button will say it failed
await interaction.response.defer()
from discord.ui import View
class MyCustomView(View):
def __init__(self):
super().__init__()
@discord.ui.button(label="Button Label")
async def buttonCallback(self, interaction, button):
# 1. make changes to the button that was clicked
button.disabled = True
# 2. respond to the message with updated message content and the updated view
await interaction.response.edit_message(content="Edited Message", view=self)
from discord.ui import View
class MyCustomView(View):
def __init__(self):
super().__init__()
# 1. Defer the message. Otherwise the button "fail"
await interaction.response.defer()
Just like a button, we can add dropdowns to our views. In this case, we will need to extend the Select class, and then add that to our view. This should look similar the "Programmatically Adding Button code"
import discord
from discord.ui import View, Select
# 1. Create a new CustomSelect class
class CustomSelect(Select):
def __init__(self):
# 2. Setup a list of all the options
options = [
discord.SelectOption(label="Option 1"),
discord.SelectOption(label="Option 2"),
discord.SelectOption(label="Option 3")
]
# 3. Initalize the dropdown. You can change the number of max and min values the users can select
super().__init__(placeholder="Select an option", options=options, min_values=1, max_values=1)
# 4. Decide what to do once an option is selected
async def callback(self, interaction):
# 5. Get access to the current selection in the list self.values
await interaction.response.send_message(f'{self.values[0]} Press')
# 6. In the View class, use add_item to add the CustomSelect you've created
class MyCustomView(View):
def __init__(self):
super().__init__()
self.add_item(CustomSelect())
To use Modals, we don't use Views like above. Instead we extend the Modal Class, add any of the fields we want, and then send it with the "send_modal" function. Take a look at the Modal documentation and the TextInput documentation for more details.
from discord.ui import Modal, TextInput
class MyModal(Modal, title='Give Feedback'):
name = TextInput(label="Name")
answer = TextInput(label="Answer")
async def on_submit(self, interaction):
await interaction.response.send_message(f'Your Answer:{self.name}!')
from discord.ui import View
class MyCustomView(View):
def __init__(self):
super().__init__()
@discord.ui.button(label="Open Modal")
async def buttonCallback(self, interaction, button):
interaction.response.send_modal(MyModal())