I am creating a Discord bot and am not experiencing any success creating custom commands with a command_prefix=‘!’.
E.g. I want to create, using the !-sign as the prefix, multiple commands that can even accept other arguments if you know exactly what you want within that command. Something like this:
!creeds
-or if you know what creed, you could use “!creeds Nicene” or “!creeds Athanasian” or if you want a list just use the base command “!creeds” and it will provide a list.
I have been told to use cogs and have not had any success with those, yet. Though I know I will need a database (using SQLite3) which I am also working on.
#jh316, all I have is this so far:
#client.event #basic event using a !command.
async def on_message(msg):
if msg.author != client.user:
if msg.content.lower().startswith("!hi"):
await msg.channel.send(f"Hi, {msg.author.display_name}!")
Something like this? https://onecompiler.com/python/3yc5xaqce
def purify(string):
return string.lower().strip()
def handleMessage(msg):
prefix = "!"
delimiter = ":"
if msg[0:1] != "!":
print("This is not a command")
#exit
splitMessage = msg[1:len(msg)].split(":")
cmd = purify(splitMessage[0])
param = "" if len(splitMessage) <= 1 else purify(splitMessage[1])
response = executeCommand(cmd, param)
#Now use the response
print(response)
def executeCommand(command, parameter):
#Actually use command here...
response = "Sorry, we don't have that one!"
if command == "creed":
if parameter == "nicene":
response = "We believe in one God, the Father almighty, maker of heaven and earth, of all things visible and invisible..."
elif parameter == "apostles":
response = "I believe in God, the Father almighty, creator of heaven and earth."
return response
#Examples
handleMessage("!creed: Nicene")
handleMessage("!creed: Apostles")
handleMessage("!creed: Athanasian")
Obviously you would want to remove the examples and put a single handleMessage reference in your discord client event message handler. Does this help?
Anyway, I love the idea!
Are you using a Client or a Bot? You should be importing from discord.ext.commands import Bot. The Bot class has a decorator to create commands:
from discord import Intents
from discord.ext.commands import Bot
TOKEN = "your secret bot token from the Discord developer page"
bot = Bot(command_prefix="!", intents=Intents.all())
#bot.command()
async def settings(context):
await context.reply("You executed command `settings`!")
#bot.command()
async def hello(context):
await context.reply("You executed command `hello`!")
bot.run(TOKEN)
Now your users will be able to type !settings and !hello in Discord to trigger these commands.
Be careful though, because if you define your own on_message like you did in your code, these commands will not automatically be called. You have to invoke them yourself:
#bot.event
async def on_message(message):
context = await bot.get_context(message)
await bot.invoke(context)
There is plenty of information online about how these commands work and how you can pass in arguments and cast them to the correct type automatically. This tutorial is one of the first Google Search results when I search "discord.py commands", and it looks like a decent tutorial that you could read.
Related
New to coding. I want to prevent my bot from responding to itself/other bots, and I'm trying to invoke a cog_check but can't make it work properly. Help would be greatly appreciated.
class CommandsMisc(commands.Cog):
def __init__(self, client):
self.client = client
async def cog_check(self, ctx):
if ctx.author.bot: # also tried: if ctx.author == self.client.user:
await exit()
#commands.Cog.listener("on_message") # example cog command
async def print(self, message):
if '!guide' in message.content:
await message.reply(Guide_Text)
else:
pass
Since some people seem to lack reading comprehension skills, my question is how can I best utilize "cog_check" in Discord.py so that all subsequent commands/listeners in the cog will check whether the message.author is the bot and then won't execute if it is?
It seems like what you want is a custom command decorator. You can do this as follows:
def is_not_bot():
async def predicate(ctx):
return not ctx.author.bot
return commands.check(predicate)
You place this in your cog class, then on any command inside the cog you can use the decorator #is_not_bot()
What does this do, exactly? Well, we create a function which can be used as a command decorator (#is_not_bot()). Inside this, we create a function called predicate. This predicate will return True if the user is not a bot. We then call return commands.check(predicate) inside the parent function. This will allow us to use this as a decorator.
discord.py docs reference
what you can have is a on_message event, which can do checks on the message before processing the command, something like this
bot = commands.Bot(command_prefix="!", intents=discord.Intents.all())
# or if you made your subclass of Bot or its variants
class CustomBot(commands.Bot):
def __init__(self):
...
bot = CustomBot()
#bot.event
async def on_message(message):
if message.author.bot:
return # this is a bot, so we can early exit
# any other checks
await bot.process_commands(message)
exit() will just make your entire program close. cog_check should return a Boolean that indicates if the command should run or not. In your case, you don't return anything if it's okay, so it returns None which is falsey, so your check always fails.
Make it return True if it should succeed, and False if it should fail.
Edit
The ext.commands framework already prevents bots from running your commands, so this is not something you should even have to worry about.
The reason your cog_check still doesn't do anything is because you don't have any commands. You're using an on_message listener to manually parse messages, instead of creating commands. Your "example cog command" is not a command, it's just an event listener. Those are two very different concepts.
cog_check is only invoked when actual commands are run, not before dispatching events like on_message, so this doesn't have any effect here. If you parse commands in on_message, checks aren't used at all.
See the docs for ext.commands for how to create commands: https://discordpy.readthedocs.io/en/stable/ext/commands/index.html
I would like to create a bot which can delete number of recently chat and history chat
import discord
import random
class MyClient(discord.Client):
async def on_ready(self):
print('Logged on as {0}!'.format(self.user))
async def on_message(self, message):
channel = message.channel.name
restricted_channels = ["command-bot"]
prefix = "-" # Replace with your prefix
# If the message starts with the prefix
if message.content.startswith(prefix):
if channel in restricted_channels:
command = message.content[len(prefix):]
if command.startswith("clear"):
await message.delete()
I have try this
if command.startswith("clear"):
await message.delete()
But it only delete the chat which have command "clear"
First off, personally, I would change the structure/ layout of your code. This is so that it is easier to read, and easier to change and add commands/ different functions to. This is the way I have my bot setup and how I have seen many other bots setup as well:
import discord
client = commands.Bot(command_prefix='your prefix', intents=discord.Intents.all()) # creates client
#client.event # used commonly for different events such as on_ready, on_command_error, etc...
async def on_ready():
print('your bot is online') # basic on_ready event and print statement so you can see when your bot has gone online
Now that we've gone through that part, let's get onto the purge/ clear command you're trying to make. I have one in my bots which generally looks something like this:
#client.command() # from our client declaration earlier on at the start
#commands.has_permissions(moderate_members=True) # for if you want only certain server members to be able to clear messages. You can delete this if you'd like
async def purge(ctx, amount=2): # ctx is context. This is declared so that it will delete messages in the channel which it is used in. The default amount if none is specified in the command is set to 2 so that it will delete the command call message and the message before it
await ctx.channel.purge(limit=amount) # ctx.channel.purge is used to clear/ delete the amount of messages the user requests to be cleared/ deleted within a specific channel
Hope this helps! If you have any questions or issues just let me know and I'll help the best I can
I am a beginner at programming and just recently started using python. I'm trying to create a discord bot in an IDE called replit. Replit doesn't seem to be detecting errors since it lets me run the code without underlining or pointing any lines out. However, when I run the bot and type the command into discord the bot does not respond. When I go back to replit, it still doesn't detect any errors or point anything out in the console. I tried making bot commands in two different formats. The first one (in which the user says hello and the bot responds) works but the other two commands after that have multiple responses in which the bot is supposed to choose a randomized response from that list. Those two commands do not work. Here is the code:
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith ('^hello'):
await message.channel.send('Hello...( ・_・)ノ')
client.run(os.getenv('TOKEN'))
import os
import random
from discord.ext import commands
from dotenv import load_dotenv
load_dotenv()
#help commands
bot = commands.Bot(command_prefix='^')
#bot.command(name='help')
async def help(ctx):
omori_responses = [
'OMORI’s main command categories are: FUN, CURRENCY, OMORI, SUNNY, BASIL, MARI, HERO, KEL, AUBREY, WHITESPACE, DREAMWORLD, and BLACKSPACE. Please use the command omo help <insert command category>',
'OMORI’s main command categories are: FUN, CURRENCY, OMORI, SUNNY, BASIL, MARI, HERO, KEL, AUBREY, WHITESPACE, DREAMWORLD, and BLACKSPACE. Please use the command omo help <insert command category>'
]
response = random.choice(omori_responses)
await ctx.send(response)
client.run(os.getenv('TOKEN'))
#whitespace commands
bot = commands.Bot(command_prefix='^')
#bot.command(name='ws')
async def white_space(ctx):
omori_responses = [
'Whitespace. A single black lightbulb hangs from the ceiling above...wherever above is',
'Whitespace. You have been here since as far back as you can remember...whenever that is. Everything is bright white. There are no walls. There is a floor...it is always cold.',
'Whitespace. Everything you need is here. A laptop, sketchbook, tissue box, blanket, and MEWO, your cat.',
'Whitespace. There is a door here. Beyond this door is a colorful world, unlike here...'
]
response = random.choice(omori_responses)
await ctx.send(response)
client.run(os.getenv('TOKEN'))
Whenever you write your own on_message() event reference (overriding the default discord.py on_message()), you need to call the Bot.process_commands() method.
#bot.event
async def on_message(message):
if message.author == bot.user:
return
if message.content.startswith ('^hello'):
await message.channel.send('Hello...( ・_・)ノ')
await bot.process_commands(message)
I am very new to coding, and am struggling to understand how I can make my discord bot (which I am creating through python) respond to different lines of code.
I have made an initial question and answer, however after that I cannot get the bot to respond to anything.
For example, my bot will respond correctly up until it is asked to Check / Back on the timetable area.
def setup():
return "Hello! Welcome to the timetable bot. What service would you like? (Timetable / Subjects /
Homework)"
#End of setup
global userState
def overheard(message, user):
if "Timetable" in message:
return timetableenquiry()
elif "Homework" in message:
return homeworkenquiry()
elif "Subjects" in message:
return subjectsenquiry()
return "I'm sorry I don't understand that."
def timetableenquiry():
return ("Okay. What would you like to do with your timetable? (Check / Back)")
def timetablecheck():
if "Check" in message:
print("Okay. You can check your timetable at: www.timetableaccess.com")
def homeworkenquiry():
return ("Okay. What would you like to know about your homework?")
def subjectsenquiry():
return ("Okay. What would you like to do with your subjects?")
I appreciate any help and apologise if it isn't clear what I am asking.
You Should Use Message.Content to Detect it, You Also Want the Bot To Actually Type in the Discord CHANNEL. Also Try to Add a Prefix so the bot won't type randomly.
Take a Look a This:
import discord
import os
client = discord.Client()
#client.event
async def on_message(message): #Defines Message
#If You Type TimeTable, And Role Requirement to Do So
if message.content.startswith('-timetable'):
await message.channel.send("Okay. What would you like to do with your timetable? (Check / Back)")
elif message.content.startswith('-homework'):
await message.channel.send("Okay. What would you like to know about your homework?")
elif message.content.startswith('-subject'):
await message.channel.send("Okay. What would you like to know about your subject?")
client.run(os.getenv('TOKEN'))
#Reminder: Put Your Token in a .env File and Write TOKEN=YOUR TOKEN.
EDIT: I FORGOT TO DEFINE CLIENT, try to use the updated one
I've just started writing Discord bots. I'm currently working on a bot that helps with Dungeons & Dragons games (dice rolling and initiative tracking are working at the moment). I've gotten my bot to send private rolls to a DM with the user that called the command within the server, but within the actual DM, the bot only responds to the help command.
I've read through this explanation, but it still doesn't seem useful to me, since I want it to respond to commands in DMs rather than grab the content of the messages sent to it in DMs. For example, let's say I'm in a server with the bot, and I use the whisperRoll command, which causes the bot to send me a DM with my dice roll result. Now that I have a private chat with the bot, I'd like to make another roll just for myself so that other players can't see it, so I try to use the roll command in the DM channel. What I'd like it to do is respond to the command in the DM in the same way it would respond in a server.
I'm wondering if there's possibly a set of default commands that are registered as "valid" for the bot to respond to in DMs that I'm missing? I can't really find an answer to this anywhere, and I don't even know where to start.
Thanks so much for the help!
EDIT: My current code, which is giving me a CommandInvokeError:
def _prefix_callable(bot, msg):
prefix = '!'
guild = msg.guild
if p.prefixInfo == []:
pass
else:
prefix = p.getPrefix(guild)
if not guild:
return commands.when_mentioned_or(prefix)(bot, msg)
return commands.when_mentioned_or(prefix)(bot, msg)
bot = commands.Bot(command_prefix=_prefix_callable, description=description, help_command = None)
p.getPrefix(guild) calls this code:
def getPrefix(self, guild):
for data in self.prefixInfo:
if data[0] == str(hash(guild)):
return data[1]
return "!"
I'm currently having it search through a csv to find the right prefix for the given guild.
You can use the discord.channel.DMChannel object
For example:
async def check(ctx, arg):
if isinstance(ctx.channel, discord.channel.DMChannel):
await ctx.send(arg)
For usage in dms with prefix
def get_prefix(message):
prefix = "?" # default prefix
if not message.guild: # if in dms
return commands.when_mentioned_or(prefix)(bot, message)
#you can set a guild/server specific one here
return commands.when_mentioned_or(prefix)(bot, message)
bot = commands.Bot(command_prefix=get_prefix, case_insensitive=True) #bot allows you to make commands
Then for the command, you would need to do:
#bot.command()
async def whisperroll(ctx):
await ctx.author.send("some random thing")