I built a Discord Bot

I built a Discord Bot

Last week, I found myself discussing potential bots for the MonolithTracker Discord Server, when a user mentioned the name "MonolithBot". It seemed like a joke at the time, but as I thought about the idea, it became more and more of a reasonable project to undertake.

I wanted to use Python for this project; So, I did a bit of research.

It turns out, there's a few ways for you to send Discord API requests. One is using a Websocket REST api (Representional-State-Transfer, the most common type of api) and another more alike to a SDK called Discord.py

Discord.py is a Python library for easy interfacing with the Discord API, without worrying about JSON formatting and URL Schemas.

Firstly, I created an application and a bot using the Discord Developer Console. This gave me some API keys for interfacing with my application and controlling my bot.

Then I found a few tutorials to get a base code, I liked the one here at RealPython.com, here it is:

# bot.py
import os

import discord
from dotenv import load_dotenv

load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
GUILD = os.getenv('DISCORD_GUILD')

client = discord.Client()

@client.event
async def on_ready():
    for guild in client.guilds:
        if guild.name == GUILD:
            break

    print(
        f'{client.user} is connected to the following guild:\n'
        f'{guild.name}(id: {guild.id})'
    )

client.run(TOKEN)
I disliked the idea of using Dotenv, as sometimes it has errors when running on repl.it (which is my quick-testing IDE of choice)
import discord

TOKEN = "INSERT TOKEN HERE"
GUILD = "INSERT NAME OF DISCORD SERVER(GUILD) HERE"

client = discord.Client()

@client.event
async def on_ready():
    for guild in client.guilds:
        if guild.name == GUILD:
            break

    print(
        f'{client.user} is connected to the following guild:\n'
        f'{guild.name}(id: {guild.id})'
    )

client.run(TOKEN)
So I removed it.

What's going on here? Well...

import discord

TOKEN = "INSERT TOKEN HERE"
GUILD = "INSERT NAME OF DISCORD SERVER(GUILD) HERE"
These lines import the Discord.py library and tell our instance what bot and server to use
client = discord.Client()
This tells our program to initiate a Discord.py Instance
@client.event
async def on_ready():
    for guild in client.guilds:
        if guild.name == GUILD:
            break

    print(
        f'{client.user} is connected to the following guild:\n'
        f'{guild.name}(id: {guild.id})'
    )
This says "When ready, print what the bot name and the server name is"
client.run(TOKEN)
Run with Token

Let's run it!

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'discord'
Oh No.

Oh dear, we forgot to install Discord.py. No worries though, we just use pip to install it.

pip install discord

or maybe use:

pip3 install discord

Great, we're connected!

Well, let's make it useful and add this into our code, before "client.run(TOKEN)":

@client.event
async def on_message(message):
    if message.author == client.user:
        return
    
    if message.content == '!hello':
        output = "hello"
        
    await message.channel.send(output)
This says, "if a message is sent by a user, check if it is "!hello", if it is; then reply "hello"

This can be adapted to output anything; as long as it's a string

@client.event
async def on_message(message):
    if message.author == client.user:
        return
    
    if message.content == '!hello':
        output = "hello"
        
    await message.channel.send(output)
If message is sent by a user, and the message is "!hello", return "hello"

My code

I edited my code to message the MonolithMapper API and collect data, here is my code:

import requests
import time

r = requests.get("https://monolithtracker.com/json-export")
numberofmonoliths = (len(r.json()))

import os
import discord
import random

TOKEN = ""
GUILD ="Monolithtracker"

client = discord.Client()

@client.event
async def on_ready():
    guild = discord.utils.get(client.guilds, name=GUILD)
    print(
        f'{client.user} is connected to the following guild:\n'
        f'{guild.name}(id: {guild.id})'
    )
 
commands = {"!help" : "Show help menu",
            "!howmany" : "Get amount of Monoliths",
            "!random"  : "Select a random monolith"     
            }
commandstring = ""

for i in commands:
  commandstring = commandstring+   i+" : "+commands[i]+"\n"

@client.event
async def on_message(message):
    if message.author == client.user:
        return
    
    if message.content == '!help':
        output = """__**Commands**__\n"""+"```"+commandstring+"```"

    if message.content == '!howmany':
        output = "*There are "+str(len(requests.get("https://monolithtracker.com/json-export").json()))+" total monoliths.*"
    
    if message.content == '!random':
        response = requests.get("https://monolithtracker.com/json-export").json()

        index = random.randint(0,len(response))
        output = "*Here's a random monolith:\n"+response[index]["title"][0]["value"]+" ["+"https://monolithtracker.com/node/"+str(response[index]["nid"][0]["value"]) + "]*"

    await message.channel.send(output)


client.run(TOKEN)

But when I close the Python, it turns off!

You can use

nohup python3 [file.py] &
This runs the file specified in the background using Nohup
ps
This will list the processes running
kill -9 [process id]
This will let you kill the process
The end of this article