I'm not sure why but can't get this to work no matter what I try, just trying to do a test button to see if I can do it, and I'll I get is interaction Fail.
#bot.command()
async def test(ctx):
view = View()
view.add_item(Button(label="test", custom_id="test"))
message = await ctx.send("Click the button below to test!", view=view)
#bot.listen("button_click")
async def on_button_click(interaction):
try:
if interaction.component.custom_id == "test":
response = "Test worked!"
await interaction.response.send_message(response)
except Exception as e:
print(e)
try:
await bot.wait_for("button_click", check=lambda inter: inter.message.id == message.id, timeout=15.0)
except asyncio.TimeoutError:
await message.edit(content="Timed out.")
view.clear_items()
except Exception as e:
await ctx.send(f"An error occurred: {e}")
I keep getting interaction failed with this test command with the discord ui buttons, no matter what I try it's not working correct the command works, but the button doesn't just says interaction failed.
on_button_click doesn't exist. You can't just make up a random event and assume the library will fire it. Read the official examples that show how to attach a callback to a button.
Related
I am trying to make some slash commands only visible to the bot owner, like commands to load/unload my cogs, etc.
The following is my code:
#client.slash_command(name="load", description="Cog Loader",guild_ids=[937755377901133896])
#commands.is_owner()
async def load(interaction: Interaction, cog: str = nextcord.SlashOption(name="cogs", description="Name of the Cog.")):
try:
await client.load_extension(cog)
await interaction.response.send_message(f"Loaded: {cog}")
except Exception as e:
await interaction.response.send_message(f"Error: {e}")
#client.slash_command(name="unload", description="Cog Unloader",guild_ids=[937755377901133896])
#commands.is_owner()
async def unload(interaction: Interaction, cog: str = nextcord.SlashOption(name="cogs", description="Name of the Cog.")):
try:
await client.unload_extension(cog)
await interaction.response.send_message(f"Unloaded: {cog}")
except Exception as e:
await interaction.response.send_message(f"Error: {e}")
You could make it only accessible to admins by doing
(this is normal discord.py not nextcord.py, didn't see it was nextcord until after posting)
if not interaction.user.guild_permissions.administrator:
await interaction.response.send_message("You are not authorized to run this command.", ephemeral=True)
else:
#do your admin command here
Besides making the command only accessible to admins you can also add , ephemeral=True at the end of your ctx.send to make it only appear to the user that sent it. such as.
#commands.is_owner()
async def load(interaction: Interaction, cog: str = nextcord.SlashOption(name="cogs", description="Name of the Cog.")):
try:
await client.load_extension(cog)
await interaction.response.send_message(f"Loaded: {cog}", ephemeral=True)
except Exception as e:
await interaction.response.send_message(f"Error: {e}", ephemeral=True)
#client.slash_command(name="unload", description="Cog Unloader",guild_ids=[937755377901133896])
#commands.is_owner()
async def unload(interaction: Interaction, cog: str = nextcord.SlashOption(name="cogs", description="Name of the Cog.")):
try:
await client.unload_extension(cog)
await interaction.response.send_message(f"Unloaded: {cog}", ephemeral=True)
except Exception as e:
await interaction.response.send_message(f"Error: {e}", ephemeral=True)
I'm trying to make a small spambot with discord.js, as one of my first python bots. It honestly works fine, but there's one problem. The bot is supposed to spam every channel in a server, but it only sends one message. I don't know python that well, and I know where the problem is and what I need to do to fix it, I just don't know how to fix it. I'm guessing I need to put an amount of messages that I want the bot to send, but I don't know how to do that. I'm hoping someone can help! (P.S. I'm not using the bot for anything bad, I just wanna test it out.) Anyway, here's my code:
#bot.command()
async def sall(ctx, *, message=None):
if message == None:
for channel in ctx.guild.channels:
try:
await channel.send(random.choice(spam_messages))
except discord.Forbidden:
print(f"{C.RED}Spam Error {C.WHITE}[Cannot send messages]")
return
except:
pass
else:
for channel in ctx.guild.channels:
try:
await channel.send(message)
except discord.Forbidden:
print(f"{C.RED}Sall Error {C.WHITE}[Cannot send messages]")
return
except:
pass
Well, you really only send one message!
#bot.command()
#bot.is_owner()
async def sall(ctx, *, message=None):
if message == None:
for channel in ctx.guild.channels:
try:
for i in range(10):
await channel.send(random.choice(spam_messages))
except discord.Forbidden:
print(f"{C.RED}Spam Error {C.WHITE}[Cannot send messages]")
return
except:
pass
else:
for channel in ctx.guild.channels:
try:
for i in range(10):
await channel.send(message)
except discord.Forbidden:
print(f"{C.RED}Sall Error {C.WHITE}[Cannot send messages]")
return
except:
pass
It should work like this. I added a for i in range(10), what it does is, it repeats this 10 times. So just change it to number of times you want it to send a message.
Like how Dank memer bot does in help command
I also want that feature in my custom help command
enter image description here
I used this Code but it failed for custom decorators
import traceback
#This is the command
#bot.command()
#commands.has_permissions(administrator=True, manage_messages=True)
async def func(ctx):
pass
# In your whatever file or error handler.
command = bot.get_command("func") # Get the Command object
try:
# You can pretty much loop these to get all checks from the command.
check = command.checks[0] # get the first check
check(0) # This would raise an error, because `0` is passed as ctx
except Exception as e:
frames = [*traceback.walk_tb(e.__traceback__)] # Iterate through the generator
last_trace = frames[-1] # get the last trace
frame = last_trace[0] # get the first element to get the trace
print(frame.f_locals['perms']) # Output: {'administrator': True, 'manage_messages': True}
If you have the command in the error handler you can simply use the missing_perms attribute
#bot.event
async def on_command_error(ctx, error):
if isinstance(error, commands.MissingPermissions):
missing_perms = error.missing_perms
await ctx.send(f"You are missing: {missing_perms} to run this command")
Reference:
MissingPermissions.missing_perms
I'm trying to make a discord bot have the same functionality as an
input()command, but as discord.py rewrite didn't have that command, I searched the API and found wait_for. But, of course, it brought a whole load of problems with it. I searched the internet for this, but most of the answers were in a #command.command and not async def on_message(message) and the others weren't really helpful. the furthest I got was:
def check(m):
if m.author.name == message.author.name and m.channel.name == message.channel.name:
return True
else:
return False
msg = "404 file not found"
try:
msg = await client.wait_for('message', check=check, timeout=60)
await message.channel.send(msg)
except TimeoutError:
await message.channel.send("timed out. try again.")
pass
except Exception as e:
print(e)
pass
```
First of all, you're using the same variable msg for multiple things. Here is a working example I can make with the information you've given.
msg = "404 file not found"
await message.channel.send(msg)
def check(m):
return m.author == message.author and m.channel == message.channel
try:
mesg = await client.wait_for("message", check=check, timeout=60)
except TimeoutError: # The only error this can raise is an asyncio.TimeoutError
return await message.channel.send("Timed out, try again.")
await message.channel.send(mesg.content) # mesg.content is the response, do whatever you want with this
mesg returns a message object.
Hope this helps!
It's not finished but I'm adding a poll feature to my bot. But I want to be able to do something if no question or options are provided. I don't want to make an error handler because I feel it is extremely far beyond what I know.
#bot.command(pass_context=True)
async def poll(ctx, *, msg):
try:
split_msg = msg.split(";")
question = split_msg[0]
option1 = split_msg[1]
option2 = split_msg[2]
embed = discord.Embed(title="Question", description=question)
embed.add_field(name="Option 1", value=option1, inline=True)
embed.add_field(name="Option 2", value=option2, inline=True)
error = discord.Embed(title=":warning: Incorrect Syntax!", description="Usage: {}poll <question>; <option1>; <option2>".format(prefix))
await bot.say(embed=embed)
except CommandInvokeError:
print("CommandInvokeError")
No. CommandInvokeError is the exception that is raised by the bot invoking the command when command execution raises any uncaught error. Your code won't raise a CommandInvokeError, so you can't catch it. If you examine the full error message, you'll likely see that your CommandInvokeError is being caused by another error, which you can catch.