discord.py rewrite/delete standard help command - discord.py

I want to make a custom !help command but I have to disable the standard one first. When I do:
client = commands.Bot(command_prefix='!')
client.remove_command('help')
Or
client = commands.Bot(command_prefix='!', help_command=None)
It still shows this message:
[1]: https://i.stack.imgur.com/Ut9dO.png
Anyone how to delete it?

A better way of making a help command is by using groups.
Firstly remove the default command;
client.remove_command("help")
After that make a help command by using this method:
#client.group(invoke_without_command= True)
async def help(ctx):
# insert your help command embed or message here
embed= discord.Embed(title="Help", description="List of commands")
embed.add_field(name="Moderation", value="!help moderation")
embed.add_field(name="Misc", value="!help misc")
await ctx.send(embed=embed)
You are done with the help command, now when you have to make help for a category or command. You can do it like this:
#help.command()
async def moderation(ctx):
embed= discord.Embed(title="Moderation", description="List of Moderation commands")
embed.add_field(name="Commands", value="ban, kick, warn, mute, unban")
await ctx.send(embed=embed)
Now if user will type, !help moderation the above embed/message will be sent.

With the recent changes in discord.py-rewrite you do not need to delete the standard help command to create your own help command. To achieve what you want you will need to subclass HelpCommand or MinimalHelpCommand, then pass it to bot.help_command.
The following code shows the standard way of subclassing MinimalHelpCommand:
class MyHelpCommand(commands.MinimalHelpCommand):
def get_command_signature(self, command):
return '{0.clean_prefix}{1.qualified_name} {1.signature}'.format(self, command)
class MyCog(commands.Cog):
def __init__(self, bot):
self._original_help_command = bot.help_command
bot.help_command = MyHelpCommand()
bot.help_command.cog = self
def cog_unload(self):
self.bot.help_command = self._original_help_command
Following the code above you will get the behaviour that you want to achieve, but if you still want to disable the default help command for any reasons, nowadays you can do it passing None to the help_command kwarg.
For more info, discord.py documentation:
https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#help-commands

Related

How to replace ctx in app_commands? - Discord.py

I'm using the code:
#app_commands.command(name='command', description='desc command')
async def command_(self, interaction: discord.Interaction):
#body command
For example I need to know the author who sent the team. Usually (if I use not App_Commands), I in the argument of the command of the command set ctx parameter:
#commands.command(name='command', description='desc command')
async def command_(self, ctx):
await ctx.send(ctx.author.name)
But app_commands does not support ctx. So, how can you replace the ctx in app_commands?
Somehow yes, in my opinion should look code look:
#app_commands.command(name='command', description='desc command')
async def command_(self, interaction: discord.Interaction):
ctx = <replacement of ctx>
await interaction.response.send_message(ctx.author.name)
Don't know, it is probably a MessageInteracion, but I don't know how to extract information from it like from ctx.
Many things can be done from the interaction but you can use
ctx = await bot.get_context(interaction) to get the context.
Just note (happened to me) that if you want to transform your old commands to app_commands, check that the messages are sent quickly enough, or you will get an error that didn't happen with #commands.command()

Multiple asyncs in discord.py but only first one is working

So i startet today with python and wanted to code a discord bot. Now I ran into that problem that I have 4 asyncs all of them back to back but only the first one is working.
bot = commands.Bot(command_prefix="$")
async def Member(ctx):
await ctx.channel.send("||#Member||")
async def Supporter(ctx):
await ctx.channel.send("||#Supporter||")
async def everyone(ctx):
await ctx.channel.send("||#everyone||")```
So, I think you might be new to this. But when we post questions here we provide the code along with an error if there is one. Otherwise, how are we going to know your issue. But I am going to try to guess. Your bot.start() before the other functions because if so, the bot wont recognize them.
Needs to be like this.
#commands.has_permissions(administrator=True)
#bot.command()
async def setdefaultrole(ctx, defualtRole):
guildID = ctx.guild.id
updateDefualtRole(guildID, defualtRole)
################################ Add Defualt Role ##################################################
##commands.has_permissions(administrator=True)
##bot.command()
#async def setdefualtrole(ctx, defualtRole):
#guildID = ctx.guild.id
#updateDefualtRole(guildID, defualtRole)
bot.run("TOKEN")
See how the bot.run() or bot.start() is at the bottom of all the functions. If this is not the problem, then add a code snippet from your code and then at me. Good luck.
So the answer to this question for anyone in the future. He need to add bot.command() to every new command he was trying to make. Otherwise, it will not register as a command.
New code:
#bot.command()
async def Member(ctx):
await ctx.channel.send("||#Member||")
#bot.command()
async def Supporter(ctx):
await ctx.channel.send("||#Supporter||")
#bot.command()
async def everyone(ctx):
await ctx.channel.send("||#everyone||")

Custom help command

Hi I’m trying to code a simple discord bot using discord.py, and one of the things I want my bot to do is send a nice custom embed when a user uses the !help command. So far I know that this simple code, which some people provided in other questions on stackoverflow about custom help commands:
class help(commands.MinimalHelpCommand):
async def send_pages(self):
destination = self.get_destination()
e = discord.Embed(title="Help:", description="description", colour=discord.Colour.blurple(), timestamp=datetime.datetime.utcnow())
await destination.send(embed=e)
client.help_command = help()
works, but the thing is when someone wants to use !help on a specific command or category, the bot will only send the send_pages command. I tried modifying the code and added
async def send_page_command(self, *, command):
destination = self.get_destination
command_e = discord.Embed(title="Dogluva:robot's Help:", description=f"{command.description}", colour=discord.Colour.blurple(), timestamp=datetime.datetime.utcnow())
await destination.send(embed=command_e)
But this doesn’t help. Anyone know what I’m doing wrong here? I’ve set the description for all the commands I wrote in my cogs using commands.command(description=“description") but I don’t know how to make a custom help command access those descriptions.
First, remember to delete the default help command (discord automatically has help command), so you need to delete it first:
client.remove_command('help') # before your own "help" command
# or
client = commands.Bot(command_prefix="<your prefix>", help_command=None) # when you create client
Basic help command:
#client.command()
async def help(ctx):
embed = discord.Embed(title="Help", description="Write your own description here", colour=discord.Color.blue())
await ctx.send(embed=embed)
But you can make it even better. Read more about Embeds in the documentation and check this template:
instead of send_page_command(self, *, command): you can try using send_command_help(self, command):
https://gist.github.com/InterStella0/b78488fb28cadf279dfd3164b9f0cf96
#client.command()
async def help(ctx, *, command=None):
if command == None:
e = discord.Embed(title="Dogluva:robot:'s Help:", description=“Custom Description", colour=discord.Colour.blurple(), timestamp=datetime.datetime.utcnow())
elif command == “{command}":
e = discord.Embed(title="Dogluva:robot:'s Help:", description=“Command Description", colour=discord.Colour.blurple(), timestamp=datetime.datetime.utcnow())
await ctx.send(embed=e)
I just created different cases for each command

Why cant I restrict command use for my bot - discord.py

'''
#client.event
#commands.has_role('xrole')
async def on_message(message):
#Commands
if message.content.startswith("!set"):
credits_message = message.content.split(" ", 2)
user_name = credits_message[1]
credit_add_amount = credits_message[2]
db[user_name] = int(credit_add_amount)
#DB Stuff
await message.channel.send(user_name + "has been set with " + credit_add_amount + ", For further credit adgustment use !add")
'''
For some reason Users with or without the xrole can acces the bot even with the #commands restriction
User without xrole^
user with xrole ^
firstly don't use on_message for commands, it's much better to use #bot.command
second: this code should work well for you
#bot.command(pass_context=True)
#commands.has_role("xrole")
async def role_check(ctx):
await ctx.channel.send('''you have the role "xrole"''')
#role_check.error
async def info_error(ctx, error):
if isinstance(error, (commands.MissingRole, commands.MissingAnyRole)):
await ctx.channel.send('''you do not have the role "xrole"''')
Because Checks are for Commands, not for Events, so the has_role decorator will never be used. You should be using commands instead of manually parsing everything in on_message anyways, it makes a lot of stuff way less cumbersome.
Here's an explanation from the docs how to make proper commands instead: https://discordpy.readthedocs.io/en/latest/ext/commands/commands.html

Check if a user id is in a list of user ids to allow command access - discord.py

im fairly new to python and have been writing a discord bot for a server with me and a few friends as practice. I've added a few commands that could be pretty disruptive if all users had access to them at all times and have been trying to add a method to enable and disable access to them without using discord roles but a python list instead. I added a command that i can use to to add their user id to a list, but when the user tries to use the command they receive a permission error.
the code below is the problematic code from a cog
modlist = []
def ListCheck():
async def IsInList(ctx):
member = ctx.message.author.id
return member in modlist
return commands.check(IsInList)
#commands.command()
async def AddUser(self, ctx, *, question):
modlist.append(question)
#commands.command()
async def ViewModList(self, ctx):
await ctx.send('User ids that have access:')
for i in range(0, len(modlist)):
await ctx.send(modlist[i])
#commands.command()
async def ClearModList(self, ctx):
modlist.clear()
await ctx.send('Modlist cleared')
#commands.command()
#ListCheck()
async def PermTest(self, ctx):
await ctx.send('user is in modlist')
Any help would be hugely appreciated
One way you could do it would be to use commands.check(). The function in the code below checks if the message author, ctx.author, is in the given list, modList. If the author is in this list when the command 'test' is invoked, then the bot will send "You are a mod!", otherwise it will raise a check error.
modList = [394506589350002688, 697725862128386048] # just some ids as examples
def check_Mod(ctx):
if ctx.author.id in modList:
return ctx.author.id in modList
#commands.command()
#commands.check(check_Mod)
async def test(ctx):
await ctx.send("You are a mod!")
The above working is shown in the image below:
To answer is there is a way to add user ids to the list via a command?, you may either use a json or text file. In this case, I will use a text file since it's simpler, and also because my json isn't as fluent as others.
Here's an example of how your text file may look like:
394506589350002688
697725862128386048
First you need to read the file and check whether the author's id is in the file. We will be changing the check_Mod function for this. If you want to know more about reading through a text file, or feel that you may need a more efficient way, you may have a look at this: How to search for a string in text files?
def check_Mod(ctx):
with open('Mod.txt') as f: # do change the 'Mod.txt' to the name that suits you. Ensure that this file is in the same directory as your code!
if str(ctx.author.id) in f.read(): # this is reading the text file and checking if there's a matching string
return ctx.author.id
Now for writing the author id into your text file.
#commands.command()
#commands.check(check_Mod)
async def add_Mod(ctx, user:discord.Member=None):
if user == None:
await ctx.send("Please provide a user to add as a Mod!")
return
# First we'll make some functions for cleaner, more readable code #
def is_Mod(user_id):
## This function will check if the given id is already in the file. True if in file, False if not ##
with open('Mod.txt', 'r') as f:
if str(user_id) in f.read():
return True
else:
return False
def add_Mod(user_id):
## This function will add the given user id into the given text file, Mod.txt ##
with open('Mod.txt', 'a') as f: # 'a' is used for appending, since we don't want to overwrite all the ids already in the file
f.write(f"{str(user_id)}\n")
f.close()
# Now we put those functions to use #
if is_Mod(user.id) == True:
await ctx.send(f"The user {user} is already a Mod!")
else:
add_Mod(user.id)
await ctx.send(f"{user} added as a Mod!")
The above should work as seen in the image below.
p.s. If you have any other questions, please post them as a new question, thank you!

Resources