Search code examples
pythonserverdiscord

I made a Discord Bot, but It can't reply me on server


I'm new on Python and Discord programming, and I made a bot there, but I can't see my Bot send me a message on my server, but only in private chats. I follow the freecodecamp tutorial to made it.

How could I fix it there?

`

import os
import discord
import requests
import json
import random
from replit import db
from keep_alive import keep_alive

my_secret = os.getenv('TOKEN')

client = discord.Client()

sad_words = ["sad", "depressed", "unhappy", "angry", "miserable"]

starter_encouragements = [
    "Cheer up!", "Hang in there.", "You are a great person / bot!"
]

cool_words = ["happy", "kind", "cheer", "great", "beautiful"]

if "responding" not in db.keys():
    db["responding"] = True


def get_quote():
    response = requests.get("https://zenquotes.io/api/random")
    json_data = json.loads(response.text)
    quote = json_data[0]["q"] + " -" + json_data[0]["a"]
    return (quote)


def update_encouragements(encouraging_message):
    if "encouragements" in db.keys():
        encouragements = db["encouragements"]
        encouragements.append(encouraging_message)
        db["encouragements"] = encouragements
    else:
        db["encouragements"] = [encouraging_message]


def delete_encouragment(index):
    encouragements = db["encouragements"]
    if len(encouragements) > index:
        del encouragements[index]
    db["encouragements"] = encouragements


@client.event
async def on_ready():
    print("We have logged in as {0.user}".format(client))


@client.event
async def on_message(message):
    if message.author == client.user:
        return

    msg = message.content

    if msg.startswith("$inspire"):
        quote = get_quote()
        await message.channel.send(quote)

    if db["responding"]:
        options = starter_encouragements
        if "encouragements" in db.keys():
            options = options + db["encouragements"]

        if any(word in msg for word in sad_words):
            await message.channel.send(random.choice(options))
        if any(word in msg for word in cool_words):
            await message.channel.send(random.choice(options))

    if msg.startswith("$new"):
        encouraging_message = msg.split("$new ", 1)[1]
        update_encouragements(encouraging_message)
        await message.channel.send("New encouraging message added.")

    if msg.startswith("$del"):
        encouragements = []
        if "encouragements" in db.keys():
            index = int(msg.split("$del", 1)[1])
            delete_encouragment(index)
            encouragements = db["encouragements"]
        await message.channel.send(encouragements)

    if msg.startswith("$list"):
        encouragements = []
        if "encouragements" in db.keys():
            encouragements = db["encouragements"]
        await message.channel.send(encouragements)

    if msg.startswith("$responding"):
        value = msg.split("$responding ", 1)[1]

        if value.lower() == "true":
            db["responding"] = True
            await message.channel.send("Responding is on.")
        else:
            db["responding"] = False
            await message.channel.send("Responding is off.")


keep_alive()
client.run(my_secret)

`

I want to know if I forgot something to make my bot reply me on server and private chat.


Solution

  • I followed the same tutorial when I started making bots, and honestly it is kind of a misleading tutorial. Having your commands in the on_message event can be pretty inconsistent in my experience. I would reccommend that instead, you create defined commands. This can be done like this:

    from discord.ext import commands
    
    client = commands.Bot(command_prefix='$') # there are other things you can define here like if you don't want the default help command for example, and you can make the prefix whatever you want I just put it as $ since thats what you had in your code
    
    @client.event
    async def on_message(message):
      if message.author == client.user:
          return # stops commands if your bot is the one messaging. I didn't do this at first and just ended up with a lot of infinite loops
      await client.process_commands(message) # processes commands, especially important with a return statement inside the event
    
    @client.command # similar to client.event, this is how if you want to, you would set up a command
    async def inspire(ctx): # ctx is context, which will be good to have in most commands
      quote = get_quote()
      await ctx.send(quote) # I used ctx.send here because ctx grabs the channel that the command was called in. So instead of grabbing the channel manually through message.channel, we can just use the context (ctx) parameter
    

    This is just a small start on commands and you would still your other functions from where you pull the quote or get the words from defined. However i've found that using and creating commands like this is easier for the user to use, easier to debug, and easier to write. Here's a link to the discord.py docs which I would definitely reccommend reading a good bit of. https://discordpy.readthedocs.io/en/stable/api.html It's been super helpful to me in developing my learning of both the discord api, and python. It's a super good resource and I hope it can help you too. Hope this answer helps