Learn to Code via Tutorials on Repl.it!

← Back to all posts
[Discord.py] Discord Bot Web Dashboard Tutorial
h
CoolJames1610 (774)

[Discord.py] Discord Bot with fully functioning web dashboard!

Hello everyone and today I will be going through how to make a discord bot, a website dashboard and have them sync with each other!

Here are what I will be going through today!

Contents

  • Introduction
    • What is Discord.py?
    • Flash vs Quart.
    • Databases.
  • Making a Discord Bot
    • Creating an application.
    • Coding the Discord Bot.
    • Setting up the database.
  • Making the web dashboard
    • Creating and designing the website.
    • Using routes.
    • Domains.
  • Outro
    • Keeping the bot and the website "alive".
    • More ideas to think about.
    • Closing.

Introduction

What is Discord.py?

The official answer to this question is:

Discord.py is a modern, easy to use, feature-rich, and async ready API wrapper for Discord

Discord.py is relatively simple to use providing that you actually know how to code in Python. Learning the commands just to send a simple message is extremely easy, and when you adapt your Python knowledge to Discord.py, you can create an incredibly powerful Discord bot.
Discord.py has two versions: async and rewrite. The rewrite version is the predecessor of the async version, so if you are ever searching Google for help, just remember to include rewrite in the question! 😉
Discord.py provides a gateway into the Discord API which developers can use to create Discord bots. The library is updated whenever Discord releases a new feature (for example: slash commands) and there is a Discord server where you can ask for help.
There are many versions of Discord on many languages, but Discord.py is my favourite because I can only code in Python since I'm a noob.

Flask vs Quart.

I am not sure how many people actually know of Quart.
Many people know of Flask as being this library that allows you to render html pages using Python and other alternatives include things like Django.
However, Discord.py is an asynchronous library and Flask is not. Which means that the two are incompatible. But this is where Quart comes in.
Quart is basically asynchronous Flask.

Quart is an asyncio reimplementation of the popular Flask microframework API.
This means that if you understand Flask you understand Quart.

Obviously to achieve this, the two librares aren't exactly the same, but the differences are quite insignificant. I will delve more into this later.
So, to be able to create a web dashboard, we will need to use Quart instead of Flask.

Databases.

In this tutorial, we are going to create a very simple economy bot. This means that we need to be able to store people's data. However, we cannot use files on replit as they will not save. This is where databases come in.
For this tutorial, we will be using easypydb made by @Minx28 just to keep the tutorial a bit simpler. I personally would use an online database such as MongoDB :p

But now, lets start coding our Discord bot!


Making a Discord Bot

Creating an application.

SKIP THIS IF YOU ALREADY KNOW HOW TO MAKE A DISCORD.PY BOT

To create a Discord bot, first we need to create an application. And we can do so here.
To create an application, you just have to press New application in the top right hand corner.

Next, we give our application a name. In this instance, I have called it Economy Bot.

Now we want to head over to the Bot section of the application, which can be found at the left hand side.

We then press Add Bot and then Yes, do it! to create our bot.

Awesome! Now you have just created your Discord bot!

Before we start to code our Discord bot, we want to be able to test it out. So, we are going to invite it to a server.
Note: You must have manage_server in order to invite a Discord bot
Head over to the OAuth2 section, again at the left hand side.

Now, in order to create a invite link, we need to press Bot.

This will now open up permissions at the bottom. For now, we aren't going to add any permissions to our bot.
Next, click Copy to copy the link, then paste it into your browser.

Add it to a server that you have the manage_server permissions for. If you don't have one, create one! 😉
As you can see, I am adding it to a bot-testing server which I have created.

Click authorize and your bot should now be in your server!
As you can see, your bot is offline because we haven't coded anything!
So, IT'S TIME TO CODE!

Coding the Discord Bot.

By no means is this the best way to code a Discord bot.

Now don't fall into the trap that making an application and a bot means that you've somehow magically gotten yourself a bot, like I did. We actually need to code our bot and we can do this by interacting with the discord.py library!
So let's import!

import discord
from discord.ext import commands
from pretty_help import Navigation, PrettyHelp

These are some of the basic imports that we can have. We are using the rewrite version of Discord.py, so we are using commands.
We are going to import pretty_help to easily create help commands using cogs. More on that later. If you get an error of ModuleNotFound, simply open up the terminal and put

pip install discord-pretty-help

We can also import some essential python modules for our bot:

from asyncio import sleep
import os
import random

We are going to use asyncio so that our bot can sleep asynchronously (is asynchronously even a word xD). We import os to retrieve our token from our .env file (more on that later). Finally we import random so we can generate random numbers (also more on that later).
So your code should be looking like this now:

import discord
from discord.ext import commands
from pretty_help import Navigation, PrettyHelp

from asyncio import sleep
import os
import random

Now we have to define our prefix. A prefix is simply the start of a commands/sentence which tells the bot that it should respond to it. Since $ is a universally known sign for money, this is what our prefix is.

bot = commands.Bot(command_prefix="$", description="Simple economy bot")

Now go back to the developer hub and get your bot's TOKEN. Simply click copy.

Now made a file called .env and type this:

token=[YOUR TOKEN HERE]

Now go back to your main.py file and type:

token = os.environ.get("token")

We will use our token to run our bot.
We want to know when our bot has been sucessfully connected to Discord and we can do this by using the on_ready function with the bot.event decorator:

@bot.event
async def on_ready():
  print("I'm in")

So when you bot has successfully connected to Discord, you should see I'm in pop up in your terminal.
Now, at the end of your program, we want to run our bot and we can do this by the following:

def run():
  bot.run(token)

if __name__ == "__main__":
  run()

This will run our code after importing all the libraries that we have defined.
Once you see I'm in pop up in the console, go back to your Discord server and your bot should now be online!

This is our code so far:

import discord
from discord.ext import commands
from pretty_help import Navigation, PrettyHelp

from asyncio import sleep
import os
import random

bot = commands.Bot(command_prefix="$")
token = os.environ.get("token")

@bot.event
async def on_ready():
  print("I'm in")

def run():
  bot.run(token)

if __name__ == "__main__":
  run()

Now we can create our help command using pretty_help!
Now, before the bot = commands.Bot(command_prefix="$") line, we are going to define our navigation buttons.
You can define custom emojis by doing :name:ID (a: for animated).
You can simply use an emoji website and copy and paste.
Or by its unicode.
For this tutorial, I will be using the emoji website.

nav = Navigation("◀️", "▶️", "❌")

Then we define our bot's help command after bot = commands.Bot(command_prefix="$") by doing:

bot.help_command = PrettyHelp(navigation=nav, color=discord.Colour.green()

You can properly check out all the attributes in this module here.
And here for discord colours.
Now let's create a cog! 👏
This is the definition of a cog in discord.py:

Each cog is a Python class that subclasses commands.

We use cogs in discord.py to organise our commands by using python classes!
Please refer to this tutorial about Python OOP (Object Orientated Programming

Now we are going to create a command inside an Economy cog: work .
So lets create a class:

class Economy(commands.Cog):
  """ All Economy commands """

We can provide a short sentence in triple quotation marks to give a bit of insight into what the category is about.
Now, let's code in the two commands:

class Economy(commands.Cog):
  """ All Economy commands """
  @commands.command(
    name="work",
    brief="Work and get some money",
    help="Use this command to work and earn a random amount of money"
  )
  async def _work(self, ctx):
    pass

Let's break this down.
When we have a command inside a cog, we use commands.command instead of bot.command. The three arguments that I have defined are optional. If you do not provide a name, the name of the command will delegate to the function name. brief should give a quick summary of what the command does and help should be a little bit more detailed. You will see all this come into work when we run the bot.
As you can see, I have defined the function as _work. The leading underscore tells our program that we don't want anyone to be able to access the function.
Now, let's code the command!
So we want to generate a random amount of money for the user, and we can achieve this by using the randint function of the random module. So let's do that!

async def _work(self, ctx):
  money = random.randint(1,10)

This will assign a random number from 1 to 10 to the variable money.
We want to tell the user how much they received, so we will use the ctx.send function.

async def _work(self, ctx):
  money = random.randint(1,10)
  await ctx.send(f"{ctx.message.author.mention} worked really hard and earnt {money}!")

We use f-strings to make formatting easier (can also be achieved by doing .format()) and we also mention the user, so that they know that the bot is talking to them.
Remember, ctx.send is a coroutine, so we need to await it.
Before we move onto telling the user their balance, we should test what we already have.
We need to load our new cog, and this can be done by doing bot.add_cog in our run function.

def run():
  bot.add_cog(Economy(bot))
  bot.run(token)

Boom! That's it! Now let's Run our program and test it out!

POG! We earnt 7 xD. One cool feature of pretty_help is that after a certain amount of time, it removes the reactions of the message. The default is 30 seconds, but can be overridden when we initialise it at the start.
Now we should create a balance command so that the user can keep track of how much money they have. But to do that we need to create a database!

Setting up the database.

There are many alternatives out there. I am using one that is one of the easiest to implement.

As I mentioned before, we will be using easypydb and to use it, we need to import it xD!
So, we add a line at the top of our code to do so!

from easypydb import DB

Again, if an error comes up, simply type pip install easypydb in the terminal!
Now in order to use this database, we need to get a token, and it is super easy! We just need to go to this website which generates a token for us to use!
Once you have that token, we can add it to our .env file:

token=[YOUR DISCORD BOT TOKEN HERE]
tokendb=[YOUR DB TOKEN HERE]

Now we get our token from the .env as before:

tokendb = os.environ.get("tokendb")

To initaliase the database, we simply give the name of the database along with our token:

database = DB("EconomyDB", tokendb)

Now we can use database as a dictionary. If you do not know how to use dictionaries, I would advice going here.
Now we can add our user to the database. So, when the program generates a random amount of money, we can simply add whatever value to what is currently in the database. We also need to include an error handler in case the person does not exist in the database. To keep things simple, we will be using the user's ID as you cannot change it. This is how we are certain of the user that is "working".
So let's code!

class Economy(commands.Cog):
  """ All Economy commands """
  @commands.command(
      name="work",
      brief="Work and get some money",
      help="Use this command to work and earn a random amount of money"
    )
  async def _work(self, ctx):
    database.load()
    money = random.randint(1,10)
    await ctx.send(f"{ctx.message.author.mention} worked really hard and earnt {money}!")
    try:
      balance = database[str(ctx.message.author.id)]
    except:
      balance = 0
    database[str(ctx.message.author.id)] = balance + money

Simple right! But let's break down what we have just coded.

database.load()

This loads the information from the database. This is key when working with the database between the bot and the website.

try:
  balance = database[str(ctx.message.author.id)]
except:
  balance = 0
database[str(ctx.message.author.id)] = balance + money

First we need to get the balance of the user. So that we can add money to their existing balance. However, if the user does not exist, we will be presented with an error. Therefore, this means that they don't have any existing balance, so we can set balance to 0.
Now, we can add their balance to the money that they have just earnt!
Note: A user's ID is in an integer form and our keys in dictionaries have to be string, that is why there is the str function which will turn the integers into a string.

Now we can create our balance function:

@commands.command(
  name="balance",
  brief="Check your balance",
  help="Get the total amount of money that is in your balance"
)
async def _balance(self, ctx):
  database.load
  try:
    balance = database[str(ctx.message.author.id)]
  except:
    balance = 0
  await ctx.send(f"{ctx.message.author.mention}'s balance is {balance}")

BOOM! We just get their balance from the database, and just output it to them! Incredibly easy :P!
So let's test out our new code!

WoW it works!
Now obviously, it doesn't look too good and you can use embeds to make it look nicer.
And also people can spam the command and get lots of money.
We can add the cooldown decorator:

@commands.cooldown(1, 30, commands.BucketType.user)

which will limit 1 use of the command per 30 seconds per user. You can check here for more information.
Note: if a user tries to use the command again, it will produce an error in the console. In order to infrom the user, you need an on_command_error function in your code.
For your economy bot, you may want to make the random amount of money greater than 10. So simply create a command that puts the information into the database and when needed, just call up the information:

async def _set_money(self, ctx, minMoney: int, maxMoney: int):
  database["minMoney"] = minMoney
  database["maxMoney"] = maxMoney

async def _work(self, ctx):
  minMoney = database["minMoney"]
  maxMoney = database["maxMoney"]
  money = random.randint(minMoney, maxMoney)

Obviously you don't want anyone to use this command. So you can import the is_owner decorator from discord.ext.commands if you want it to be soley for you or has_permissions so that only people with a certain permission can use it.
One last thing: If you want your bot to be public (i.e. anybody can invite it to their server), you can make nested dictionaries in the database. This would mean that certain rules apply to a certain guild. So, if you wanted people to be able to have different amounts in different servers, you would simply do this:

database[str(ctx.message.guild.id)][str(ctx.message.author.id)] = money

And when you want to get the money, you simply do:

money = database[str(ctx.message.guild.id)][str(ctx.message.author.id)]

This also applies to anything including the minMoney and maxMoney settings.
But enough about that, lets go create our web dashboard!


Making the web dashboard

Creating and designing the website.

To make things easier, we are going to code the website in the same repl as the discord bot. Now, for whatever reasons that you don't want to do this then that is fine. All you have to do is whenever you are accessing the database, you will need to do database.load() to load the data from the database.

Now let's create and design our website.
If you are fortunate enough to have a creative mind, then you can just go ahead and create your own web dashboard using HTML, CSS, JS. But if you are like me and lack a creative mind, you can go online and get a web template. For me, one of the best website templates is HTML5UP and that is where I got the design for my website!
So let's browse the site and find ourselves a cool loooking website template

A FEW MINUTES LATER (LIKE 10 I WENT TO DISCORD XD)

Okay, I'm back. I found this template and I think it would look really good for our economy bot.
So what you want to do is to download the zip, then extract all files.
Go back to your repl and create three folders: static, templates and routes. Inside routes, create utils.py
Go back to your file explorer and open up the assets folder. You should see css, js, sass and webfonts. Select all and drag into the static folder.
Go back one level and you should see some .html files. Select all and drag into the templates folder.
Now go into index.html and do CTRL + H. Type in assets in the first box, and static in the second box and click the second ICON (Replace ALL).
Now we need to do some coding in utils.py:

import quart
import os
import requests

app=quart.Quart("")
app.secret_key=bytes(os.environ.get("session"),"utf-8")

We are going to use Quart to render our HTML files and we need to create this utils file.
For the session, you can simply do:

app.secret_key=bytes(os.urandom(24), "utf-8)

or if you want to keep it secret, then generate it in the console and put it in your .env file:

token=[YOUR DISCORD BOT TOKEN HERE]
tokendb=[YOUR DATABASE TOKEN HERE]
session=[SESSION KEY HERE]

Then in main.py we can add:

from routes.utils import app
from quart import Quart, redirect, url_for, render_template, request

app = Quart(__name__)

@app.route("/")
async def home():
  return "I'm alive"

This imports what we need from the utils file, and imports Quart and other common necessities. We then create a route "/" which means this is the "home" page.

Then we add: bot.loop.create_task(app.run_task('0.0.0.0')) to our run function at the bottom of the program. Now, when you press Run, a little window should pop up to your right and it should say "I'm alive".

Now, we want to render our HTML template, so we go back to routes.py and change return "I'm alive" to return await render_template("index.html").
Then we can Run the program and see our HTML come to life! Remember to click the refresh button to see it in the little window, or open the URL in a new tab.
The CSS may have not loaded and to fix this, go to index.html and replace:

<link rel="stylesheet" href="static/css/main.css" />
<noscript><link rel="stylesheet" href="static/css/noscript.css" /></noscript>

with

<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='/css/main.css') }}">
<noscript><link rel="stylesheet" href="{{ url_for('static', filename='css/noscript.css') }}"></noscript>

and add:

<script>location.href.match("https://")||(location.href=location.href.replace("http","https"))</script>
<script src="https://kit.fontawesome.com/f890ad0835.js" crossorigin="anonymous"></script>

to your head (not your head, inside the head tag xD). This will make your site https and also imports the fontawesome logos that is used in the template.
If your CSS still isn't loading, refresh the page by doing CTRL + SHIFT + R.
It should now load.

Now, if you have got a web template, you can now edit and customise it in anyway!
If you would like to use my web template, then head down to the end of the post where I have posted a template!

Now once you are happy with your template, we need to install quart-discord so that we can interact with the user on the site.

from quart_discord import DiscordOAuth2Session, requires_authorization, Unauthorized

If the program cannot find it, simply do pip install quart-discord.
Now we need to go back to the Discord Developers section and get some data!
You should still be at the OAuth2 section, if not, it can be located at the left hand side.
Now we need to create a redirect uri. If you are using the pre-made repl url, just copy and paste that and add /callback to the end of it. If you are using a custom domain, put that in and add /callback to the end of it.

Go back to your .env file and enter it in:

RI=[YOUR REDIRECT URI HERE]

Next, go to the General Information page:

Copy your client ID:

Go to your .env file and put:

CLIENT_ID=[YOUR CLIENT ID HERE]

Then copy your client secret:

Go to your .env file and put:

CLIENT_SECRET=[YOUR CLIENT SECRET HERE]

Now we can configure our quart-discord:

app.secret_key = os.environ.get("session")
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "true"
app.config["DISCORD_CLIENT_ID"] = os.environ.get("CLIENT_ID")
app.config["DISCORD_CLIENT_SECRET"] = os.environ.get("CLIENT_SECRET")
app.config["DISCORD_REDIRECT_URI"] = os.environ.get("RI")
app.config["DISCORD_BOT_TOKEN"] = os.environ.get("token")

Now, we initialise quart-discord by doing the following:

discordd = DiscordOAuth2Session(app)

Note: I have named the variable discordd so the discord module does not get mixed up with it
Now let's start using routes to create the dashboard!

Using routes.

We want the user to be able to log into the website via Discord, and that is the purpose of quart-discord. However, we would want to show them something different if they aren't logged into Discord on our website. This is where we use jinja2 formatting.
First we will tweak our home route:

@app.route("/")
async def home():
  return await render_template("index.html")

We are now going to add a line which tells our program if the user has logged in or not:

@app.route("/")
async def home():
  logged = ""
  if await discordd.authorized:
    logged = True
  return await render_template("index.html", logged=logged)

When we pass this to our html template, we can make it so if the user is not logged in, then a button will pop up that they should log in. Otherwise, the dashboard will be shown to them. So let's now code this into our HTML template.

So, Jinja2 uses curly brackets {} and percentages % in HTML templates.
So let's start!
Go to your index.html and for me, the dashboard is going to be in section, id="four".
Basically some HTML for feature cards - pretty neat.
So I am going to add the code that will tell jinja2 what to show:

{% if logged %} <!-- if logged == True -->
  ...
{% else %}
  ...
{% endif %}

As you can see here, jinja2 has end statements which you need to put in.
If you have got a web template, then you can add a button for the else statement, otherwise, create one.

{% if logged %} <!-- if logged == True -->
  <ul class="actions">
    <li><a href="/logout/" class="button">Logout</a></li>
  </ul>
{% else %}
  <ul class="actions">
    <li><a href="/login/" class="button">Log into Discord</a></li>
  </ul>
{% endif %}

For the href, we are putting a route so when the user clicks the button, we can code exactly what happens in the background. So, lets do that!
Go back to your main.py and we will create a new route called login:

@app.route("/login/")
async def login():
  return await discordd.create_session(scope=["identify", "guilds"])

We will create a session using quart-discord. We only need to know who is accessing our website hence the indentify scope, but you can add more if you need to.
While we are at it, we will also create a login route:

@app.route("/logout/")
async def logout():
  discordd.revoke()
  return redirect(url_for(".home"))

This will log our the user and then redirect them to the home page.
Similarly, when the user has finished authenticating, we need to redirect them to back to the home page:

@app.route("/me/")
@requires_authorization
async def me():
  user = await discordd.fetch_user()
  return redirect(url_for(".home"))

This makes sure that the user is authorised before their details are fetched. Then it redirects to the home - just makes everything a bit more professional xD!
We also need to define the callback route... remember? xD

@app.route("/callback/")
async def callback():
  await discordd.callback()
  try:
    return redirect(bot.url)
  except:
    return redirect(url_for(".me"))

You may be wondering, where did bot.url come from? Well, if you wanted to access a part of the website that needed authenticating, wouldn't you be annoyed if after you did that, the website took you all the way back to the home screen? Yeah, you probably would be. So we can create an error_handler and remember where the user wanted to go in the first place. Then, when they have authenticated, we can redirect them to the webpage that they wanted to go to! Neat, right?

@app.errorhandler(Unauthorized)
async def redirect_unauthorized(e):
  bot.url = request.url
  return redirect(url_for(".login"))

Now when you go to your website (after pressing Run lmao), and try to login, it should hopefully work! Now you can ahve a bit of fun logging in and out xD!
Now we want to let the user know how much money they have without going to Discord. So, we are going to add more code to our "home" route:

@app.route("/")
async def home():
  logged = ""
  lst = []
  data = {}
  balance = 0
  if await discordd.authorized:
    logged = True
    user = await discordd.fetch_user()
    database.load()
    try:
      balance = database[str(user.id)]
    except:
      database[str(user.id)] = 0
      balance = 0
  return await render_template("index.html", logged=logged, balance=balance)

This will load in the database, get the balance of the user if it exists (initialises their account if not) and then pass the value to the html template.
Now, let's add some HTML to show the user's balance:

{% if logged %} 
  <ul class="actions">
    <li><a href="/logout/" class="button">Logout</a></li>
  </ul>
  <h3> Your balance is {{balance}}</h3>
  <br>
{% else %}
  <ul class="actions">
    <li><a href="/login/" class="button">Log into Discord</a></li>
  </ul>
{% endif %}

Now, if the user is logged in, their balance will be shown! Neat right?
So let's check if it works. First, let's go to Discord and find out how much we have.

Alright, we have 13 cash. Now, let's go to the website and login.

Let's authorise our application to access data about us.

And boom! If we scroll down to the "dashboard" section, our balance should show up!

Awesome! Now, we can go back to Discord and work. Then, if we refresh the page, it should show our new total!

13 + 4 is 17, the moment of truth...

YAY! It works!

Domains

As you probably know, the url that repl gives you isn't exactly the most exciting thing in the world. And, to be more professional, it would be better to have your own domain name to show off your new bot and website.
No "good" domain names are FREE. Yes, you could go to freenom and get a free .tf or .ga etc domains, but most people know that those are free and doesn't look authentic as something like .com.
So, my advice would be to get a free frenom domain to test out your website. Because, the last thing that you want is to buy a domain and then abandon your project since you cannot edit the domain name once you have bought it.
There are many popular domain sites out there, but I recommend using Google domains.
1) Because it's Google. Google is a famous and respected organisation.
2) Their prices are low. For a .com domain, I paid £10 for one year. Some domain providers may charge monthly for a domain, and one that I came across was about £3 a month, which is £36 a year. Yes, paying monthly gives you more flexibility, but paying yearly means that you don't have to worry about paying every month and in the end, it even may be cheaper! Some domain endings are more expensive than others (for example .dev), but a simple .com domain should be good! (If you are buying a domain from Google, I would recommend using CloudFlare as a 3rd party DNS provider.)


Outro

Keeping the bot and the website "alive".

This part is relatively simple. If you have the Hacker plan, then you can use the AlwaysOn feature. Otherwise, you can use Uptimerobot.
Simply create an account, create a new monitor, set it to http(s), enter your URL (either the repl.co one or a custom one), add a friendly name and an interval (5 mins is fine) and BOOM! Your website and bot should be kept alive!

I would recommend creating without an contact, otherwise you may receive many emails! xD

More ideas to think about.

Between starting this tutorial and finishing it is more than a month xD!
I had started strong, but some difficulties and other projects made me put it on hold for a while. And between then, I have learnt much more things in discord.py!

Closing.

Well, that's all I have to talk about today!
This tutorial will be as a template if you want to mess around with it.
You can invite the bot if you want :p
The website is here

I hope you've enjoyed reading this tutorial and that you've learnt something new!
Please leave comments about this tutorial. I haven't really made a tutorial this long before xD

All the images used can be found in this repl.

Thanks and GG if you read it all xD
@CoolJames1610 (658 lines woah)

Comments
hotnewtop
FlaminHotValdez (715)

Now THIS is the kind of tutorial I like.

A Python tutorial that's NOT about the basics.

Sir, I commend you.

RafaelRigo (2)

In the part he says to press control + h it didn't work for me because I'm in a Mac. Does somebody know how can I do that in a mac? I don't even know what he did.

CoolJames1610 (774)

@RafaelRigo Try command + h or search how to replace using a keyboard

RafaelRigo (2)

@CoolJames1610 thanks it worked with command + option + F

justinhs (1)

hey mine just keeps saying, can you help me out please

Traceback (most recent call last):
  File "main.py", line 4, in <module>
    from pretty_help import Navigation, PrettyHelp
ImportError: cannot import name 'Navigation' from 'pretty_help' (/opt/virtualenvs/python3/lib/python3.8/site-packages/pretty_help/__init__.py)
CoolJames1610 (774)

@justinhs Change Navigation to DefaultMenu

MusaIbn (1)

Thanks so much Amazing!!
Exactly what I was looking for

CoolJames1610 (774)

@MusaIbn Awesome! Thanks for the support

tomaspinoperez0 (4)

How can I do to solve it, this part of the code is the same that yours.

Traceback (most recent call last):
  File "main.py", line 7, in <module>
    from pretty_help import Navigation, PrettyHelp
ModuleNotFoundError: No module named 'pretty_help'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "main.py", line 10, in <module>
    from pretty_help import Navigation, PrettyHelp
ImportError: cannot import name 'Navigation' from 'pretty_help' (/opt/virtualenvs/python3/lib/python3.8/site-packages/pretty_help/__init__.py)
CoolJames1610 (774)

@tomaspinoperez0 In terminal post

pip install discord-pretty-help

Or you can add:

import sys
import subprocess
try:
  from pretty_help import Navigation, PrettyHelp
except:
  subprocess.check_call(["pip", "install", "discord-pretty-help"])
  from pretty_help import Navigation, PrettyHelp
tomaspinoperez0 (4)

@CoolJames1610 I think I resolve it, it´s because PrettyHelp change this in V1.3.0

Changelog
[1.3.0]
Replaced Navigation with DefaultMenu
AnnaLou1 (0)

@CoolJames1610 I tried this and got an error again:

WARNING: You are using pip version 19.3.1; however, version 21.1.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Traceback (most recent call last):
File "main.py", line 4, in <module>
from pretty_help import Navigation, PrettyHelp
ImportError: cannot import name 'Navigation' from 'pretty_help' (/opt/virtualenvs/python3/lib/python3.8/site-packages/pretty_help/init.py)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "main.py", line 7, in <module>
from pretty_help import Navigation, PrettyHelp
ImportError: cannot import name 'Navigation' from 'pretty_help' (/opt/virtualenvs/python3/lib/python3.8/site-packages/pretty_help/init.py)

shinchanOP1 (3)

HOW TO SETUP A ROUTE TO CHECK IF THE USER HAS ADMIN PERMISSIONS IN THE SERVER ??

CoolJames1610 (774)

@shinchanOP1 get the has_permissions from discord.ext.commands and then have the administrator=True in the decorator

from discord.ext.commands import has_permissions

@bot.command(name=“ban”)
@has_permissions(administrator=true)

shinchanOP1 (3)

@CoolJames1610 No Like I want to make this a bit more advance so
I want to display the server user has admin permission and bot is used in that server how can I make that ?

CoolJames1610 (774)

@shinchanOP1 You mean display on the website that the user has admin permission?

shinchanOP1 (3)

@CoolJames1610 Display the server in which the user has admin permission to the website(SO HE CAN MANAGE THE BOT IN THOSE SERVERS
)

AimanFayaz (6)

I just started following this tutorial and I put the token in the code and tried running it, but then it says,

Traceback (most recent call last):
File "main.py", line 3, in <module>
from pretty_help import Navigation
ModuleNotFoundError: No module named 'pretty_help'

I have matched my code with yours, but the problem is still there. My code is,

import discord
from discord.ext import commands
from pretty_help import Navigation

from asyncio import sleep
import os
import random

bot = commands.Bot(command_prefix = "$", description = "Simple economy bot")

token = os.environ.get("token")

@bot.event
async def on_ready():
  print("I am in")```

Either I am blind or my repl has some problem. Please help me.
CoolJames1610 (774)

@AimanFayaz In terminal, simply put pip install discord-pretty-help! https://pypi.org/project/discord-pretty-help/

AimanFayaz (6)

@CoolJames1610 Thanks, but I just ran into another problem 😅. I had installed the package properly, but then the console said that I am using an older version of pip so I should consider upgrading it, and I did, but as soon as the installation was over, it said that the current(the one I just downloaded) version is incompatible with my device. I tried running my code after this, it didn't have any error but the message that was supposed to be printed,'I am in' did not come in. Instead, the code stopped instantly. What to do now? 😅

CoolJames1610 (774)

@AimanFayaz Perhaps you could invite me to your repl and I could help you out!

AimanFayaz (6)

@CoolJames1610 I had opened another repl file, installed the package using the old version, copied your code directly, but it is still showing errors. I have invited you to it, hope you can solve the problem.

AimanFayaz (6)

@CoolJames1610 Aight, Thanks a lot!! Just one last question, do you know why is my code different? i.e. have to import packages different way?

CoolJames1610 (774)

@AimanFayaz eh sometimes repl doesnt install the packages from pip. So I use subprocess so I dont have to run pip install everytime in terminal :)

tomaspinoperez0 (4)

Hi, amazing tutorial, but how I could link other pages from the template to the main page, I’m trying to do a web with the dashboard and a blog to put information, could you help me?

CoolJames1610 (774)

@tomaspinoperez0 Yep, just create routes

@app.route("/blog/")
async def _blog():
  await render_template("blog.html")

I would recommend looking into jinja2 inheritance!

tomaspinoperez0 (4)

@CoolJames1610 Thank you so much, finally I can link pages. I don’t know much about programming, but thanks to you I could finish my proyect. 👏🏻👏🏻

twjjjj (4)

Is there anyone from HY?I'm 231XX

twjjjj (4)

Obviously I can't understand this article at all!What a PITY!!!

[deleted]

SUPER pog

this is the best tut i've seen, u are amazing bro! :D

mazen10samir (1)

How can I make that user(1) can send money to another user(2) and the money go to the user(2) database and lose from user(1) ?

CoolJames1610 (774)

@mazen10samir Alright!
So you would make the command, lets say donate
Then as a parameter, you would have user: discord.User, so that it automatically converts what you put (i.e. ID, mention or tag) into a user object.
Then you would also have money as a parameter
First you would check whether user1 has enough money and if they don't, return an error message.
Otherwise, you would remove the money from their account:

database.load()
database[str(ctx.message.author.id)] = database[str(ctx.message.author.id)] - money

Then you would get the ID of the other user and do the exact same thing:

database.load()
database[str(user.id)] = database[str(user.id)] + money

Then you can send a message saying that it was successful and then perhaps a DM message to the user2.

If you wanted, you could integrate this into the website :P

RafaelRigo (2)

Congratulations, best discord.py tutorial I've ever seen, thank you!
If I could I would reward you for this, some people would even pay for this tutorial

CoolJames1610 (774)

@RafaelRigo Thank you for these kind words! :D

AsaKramer (2)

I'm trying to run your code and I keep getting a syntax error on the async command. Any idea why?

@bot.event
async def on_ready():
print("I'm in")

CoolJames1610 (774)

@AsaKramer Can you please share the error message :D

AsaKramer (2)

@CoolJames1610 I don't Know what happened to that error but now I get this,

File "main.py", line 35
async def _work(self, ctx):
^
IndentationError: unindent does not match any outer indentation level

And this is line 35,

async def _work(self, ctx):

I'm not experienced in Python and I haven't done anything like this before so it could be obvious.

CoolJames1610 (774)

@AsaKramer the code has to be inline with each other. If you can invite me to your repl, I can help you :)

RayhanADev (2606)

Woah

I used to make Discord bots (with Discord.js) and I can tell this is really nice!
My stars:
⭐️ You have really good Python skill!
⭐️ Very detailed tutorial :D
⭐️ Unique af, I've never seen a Discord Bot Dashboard tutorial on Replit!

Keep up the great work dude!

CoolJames1610 (774)

@RayhanADev Thanks, really appreciate this!

EpicGamer007 (1751)

wow this is a very underrated tutorial, good job.

RocketSpot (7)

It gives me this error:

  File "main.py", line 21, in <module>
    from routes.utils import app
  File "/home/runner/economybot-5/routes/utils.py", line 6
    app.secret_key=bytes(os.urandom(24), "utf-8)
                                               _
AnnaLou1 (0)

I keep getting this error for some reason. Kindly help.

Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/http.py", line 300, in static_login
data = await self.request(Route('GET', '/users/@me'))
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/di
Traceback (most recent call last):
File "main.py", line 27, in <module>
run()
File "main.py", line 25, in run
bot.run(token)
NameError: name 'token' is not defined

This is the code"

import sys
import subprocess
try:
from pretty_help import DefaultMenu, PrettyHelp
except:
subprocess.check_call(["pip", "install", "discord-pretty-help"])
from pretty_help import Navigation, PrettyHelp

import discord
from discord.ext import commands
from pretty_help import DefaultMenu, PrettyHelp

from asyncio import sleep
import os
import random
bot = commands.Bot(command_prefix="Asteria", description="Simple economy bot")
bot = commands.Bot(command_prefix="A", description="Simple economy bot")
bot = commands.Bot(command_prefix="asteria", description="Simple economy bot")
bot = commands.Bot(command_prefix="a", description="Simple economy bot")
os.environ.get("token")
@bot.event
async def on_ready():
print("Asteria has been activated.")
def run():
bot.run(token)
if name == "main":
run()

PS: If I want to add multiple prefixes, do I simply copy the prefix code again?
How can I code the bot so that users can change prefix as per their wishes?

OlauPla (159)

Hmm... Nice, I have not seen in full depth the tutorial but I see that this tutorial could help people start creating discord bots. I will recommend this to people when they ask the famous question "where do I start in discord.py" or "how do I create a discord bot". Nevertheless I think that this tutorial in not for beginners on python or the API discord.py

UnicornEF (0)

Hey @CoolJames1610 can you help me i don`t understand this :( please add me in Discord as friend. Plssss | Elias3#3506

DillonB07 (25)

Hi!

I'm getting an error in the console and I don't know how to fix it.

Traceback (most recent call last):
  File "main.py", line 1, in <module>
    import discord
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/__init__.py", line 25, in <module>
    from .client import Client
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/client.py", line 27, in <module>
    import asyncio
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/asyncio/__init__.py", line 21, in <module>
    from .base_events import *
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/asyncio/base_events.py", line 296
    future = tasks.async(future, loop=self)
                   ^
SyntaxError: invalid syntax

Please can someone help me here?

Snowy1011 (2)

When I run the code I keep getting an error saying:
" File "main.py", line 36
@commands.command(
^
TabError: inconsistent use of tabs and spaces in indentation"
Can you help me out?

nishgovind (0)

Traceback (most recent call last):
File "main.py", line 11, in <module>
class informations(commands.Cog):
File "main.py", line 23, in informations
async def _money(self,ctx):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 1432, in decorator
raise TypeError('Callback is already a command.')
TypeError: Callback is already a command.

StarChamp (0)

HI thanks for the tutorial!! Also I had a problem in making class can anyone help me? It said this

File "main.py", line 14
class.Financial(commands.Cog):
^
SyntaxError: invalid syntax

IMightBeMe (33)

Is there a tutorial for this in discord.js? Trying to move away from Python now. Great tutorial tho.

dwomg380 (0)

@IMightBeMe okay just a quick thing- as someone whose used discord.js and discord.py, I can say that discord.py has way more capabilities

IMightBeMe (33)

Yea I know. I’ve used discord py a lot i just don’t like python that much anymore. It doesn’t give me that feeling when I’m coding. @dwomg380

BillyAlbus (0)

Saving this for when I know more about Python. I'm still learning but making a Discord bot is a goal of mine. Great tutorial 😊