I'm trying to create a verification function for Discord Bot using buttons. I have tried creating it, but not sure if it works (testing purpose) .
I need it to give a role to verify a user like a role called Verified, would also like a suggestion on how I can make it not a command and just make it a embed in a single channel where new members can just simply click on it and get the role to be verified.
I'm not getting any errors in the console of development, it's just saying when I click the button in the UI (Discord App) I get an message saying "Interaction failed".
#client.command()
async def verify(ctx):
member = ctx.message.author
role = get(member.guild.roles, name="Sexy EGirl")
await ctx.send(
embed = discord.Embed(description="Click below to verify", color=getcolor(client.user.avatar_url)),
components = [
Button(style=ButtonStyle.blue, label = 'Verify')
]
)
interaction = await client.wait_for("button_click", check=lambda i: i.component.label.startswith("Verify"))
await interaction.respond(member.add_roles(role))
You get "Interaction failed", if you don't send a respond message.
#client.event
async def on_button_click(interaction):
message = interaction.message
button_id = interaction.component.id
if button_id == "verify_button":
member = message.guild.get_member(interaction.user.id)
role = message.guild.get_role(859852728260231198) # replace role_id with your roleID
await member.add_roles(role)
response = await interaction.respond(embed=discord.Embed(title="Verified"))
#client.command()
#commands.has_permissions(administrator=True) # you need to import command from discord.ext if you want to use this -> from discord.ext import commands
async def verify(ctx):
await ctx.send(
embed=discord.Embed(title="Embed - Title", description="Click below to verify"),
components=[
Button(style=ButtonStyle.blue, label='Verify', custom_id="verify_button")
])
With this code you are able to send an embed with a verify button in a channel. (if you have administrator permissions) Then the user can press on the button and the on_button_click event will be triggered.
To handle the Interaction failed, you are sending a respond message.
Related
Im working on my discord bot, And upon sending a slash command, the bot always seems to send a "The application did not respond" message even if the command works.
No errors show up in my log, Curious if anyone has a similar experience?
#Verify command
#bot.slash_command()
async def verify(ctx):
await ctx.send(f"Welcome to the Galaxy!", delete_after=10)
member = discord.utils.get(ctx.guild.roles, id=891110682110623806 )
unverified = discord.utils.get(ctx.guild.roles, id=1012034653613477961)
await ctx.author.add_roles(member)
await ctx.author.remove_roles(unverified)
This is the code the message shows up on. Using /verify it gives the user roles, Takes away the other role correctly. Then still sends the message "The application did not respond" right after.
You should always send a response when using Slash Commands to prevent this error message to show up:
#Verify command
#bot.slash_command()
async def verify(ctx):
await ctx.send(f"Welcome to the Galaxy!", delete_after=10)
member = discord.utils.get(ctx.guild.roles, id=891110682110623806 )
unverified = discord.utils.get(ctx.guild.roles, id=1012034653613477961)
await ctx.author.add_roles(member)
await ctx.author.remove_roles(unverified)
ctx.send("Roles added successfully")
I'm trying to make my discord bot DM a person when I kick them. I have tried some stuff but nothing ended up working. This is the current kick code:
#bot.command(name="kick", aliases=["k"], help= "Kicks specified user from the server.")
async def kick(ctx, member: discord.Member, *, reason=None):
await member.kick(reason=reason)
await ctx.send(f'User {member} has been kicked.')
embed=discord.Embed(
title= f"{bot.user} kicked {member}",
color=bot.embed_color,
timestamp = datetime.datetime.now(datetime.timezone.utc)
)
embed.set_author(
name = ctx.author.name,
icon_url = ctx.author.avatar_url
)
embed.set_footer(
text = bot.footer,
icon_url = bot.footerimg
)
await bot.debug_channel.send(embed = embed)
print("Sent and embed")
await ctx.message.add_reaction('✅')
print("Added a reaction to a message")
Does anyone know how to make the bot send a DM?
You have to send a message to the kicked user.
Since you already have the member object, you can just do await member.send("What you want to send")
Also the message should be before await member.kick(), as the bot will not be able to message people that they don't have mutual servers with.
Another thing you should do is check if the user is kickable before sending a message to the member.
Some cases in which you can not kick the user are:
They have a higher role than the discord bot. (Can be solved by comparing the member.top_role and the bots top role)
They do not have permissions to kick. (Can be solved by checking for bots guild permissions)
Another thing is that you should also create a try except to catch any errors that can occur when trying to message the user. Some users have DM's off, so you would get an error when trying to message the member.
Im trying to create a command wherein the user will be able to kick a member while the bot will ask the user to confirm whether to kick or not. When I tested the code, I dont get any errors in the terminal although I do get one on Discord saying "Interaction Failed." How may I fix this issue?Is there also a way for me to add a function wherein if the cancelled button is pressed? Saying "Cancelled kick." Im also quite new to dpy
#bot.command()
#commands.has_permissions(kick_members=True)
async def kick(ctx, member: discord.Member, *, reason=None):
username_1 = ctx.message.author.name
avatar_1 = ctx.message.author.avatar_url
embed = discord.Embed(description=f"**Kick {member}?**", color= 0x303136)
await ctx.send(embed = embed, components = [
[Button(label="Confirm", style="3", emoji = "✅", custom_id="button1"), Button(label="Cancel", style="4", emoji = "❌", custom_id="button2")]
])
username_1 = ctx.message.author.name
avatar_1 = ctx.message.author.avatar_url
conf=discord.Embed(title=f'{member} has been kick', color= 0x303136)
conf.set_author(name=f"kicked by {username_1}", icon_url=avatar_1)
interaction = await bot.wait_for("button_click", check = lambda i: i.custom_id == "button1")
await member.kick(reason=reason)
await interaction.send(content = conf, ephemeral=True)
You need to respond to the interaction for the discord to confirm that everything went well.
Try:
await interaction.response.send_message(content = conf, ephemeral=True)
This way you will be responding to an interaction by sending a message.
About your second question, please specify which fork of discord.py you are using.
I would like my discord bot to respond with a certain message back within a server based on the reaction given by the user: either 👍 or 👎.
I am not too familiar with discord.py and the docs I have read are slightly confusing, I followed a youtube tutorial and made edits. I get to see the reaction printed in the console, however I get the error message:
Instance of 'Bot' has no 'channel' member
Here is my code:
import os
import datetime
import discord
from discord.ext import commands
from dotenv import load_dotenv
load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
client = commands.Bot(command_prefix = '!')
#client.event
async def on_ready():
print('Bot is logged in.')
#client.command(name='feedback', help='Ask person for feedback')
async def roll(ctx):
await ctx.send('Are you enjoying this bot? \n :thumbsup: :-1: ')
#client.event
async def on_raw_reaction_add(reaction, user):
print(reaction.emoji)
channel = reaction.message.channel
await client.channel.send_message(channel, reaction.emoji)
if reaction.emoji == ':thumbsup:':
await client.channel.send_message(channel, 'Thank you for your feedback')
elif reaction.emoji == ':-1:':
await client.channel.send_message(channel, 'Sorry you feel that way')
client.run(TOKEN)
All help greatly appreciated
Instead of using the on_raw_reaction_add event, it's better in this case to use a wait_for command event. This would mean the event can only be triggered once and only when the command was invoked. However with your current event, this allows anyone to react to a message with that emoji and the bot would respond.
By using client.wait_for("reaction_add"), this would allow you to control when a user can react to the emoji. You can also add checks, this means only the user would be able to use the reactions on the message the bot sends. Other parameters can be passed, but it's up to you how you want to style it.
In the example below shows, the user can invoke the command, then is asked to react with a thumbs up or thumbs down. The bot already adds these reactions, so the user would only need to react. The wait_for attribute would wait for the user to either react with the specified emojis and your command would send a message.
Here is the example applied in your code.
#client.command(name='feedback', help='Ask person for feedback')
async def roll(ctx):
message = await ctx.send('Are you enjoying this bot? \n :thumbsup: :-1: ')
thumb_up = '👍'
thumb_down = '👎'
await message.add_reaction(thumb_up)
await message.add_reaction(thumb_down)
def check(reaction, user):
return user == ctx.author and str(
reaction.emoji) in [thumb_up, thumb_down]
member = ctx.author
while True:
try:
reaction, user = await client.wait_for("reaction_add", timeout=10.0, check=check)
if str(reaction.emoji) == thumb_up:
await ctx.send('Thank you for your feedback')
if str(reaction.emoji) == thumb_down:
await ctx.send('Sorry you feel that way')
You are also getting the error, Instance of 'Bot' has no 'channel' member because you are using an event which limits attributes from the "Bot". However using this within a command allows you to use ctx.send
I'm trying to make a ticketing system in which a user does .ticket.
I'm having an issue where 'bot' doesn't have the attribute 'delete_channel', and I also want to make it so the bot ignores the reaction if a bot reacts to the message, but acknowledges that a normal guild member has reacted to it.
Here's my code:
#bot.command()
async def ticket(ctx):
global ticket_channel
name = "tickets"
category = discord.utils.get(ctx.guild.categories, name=name)
guild = ctx.message.guild
ticket_id = randint(0, 100)
ticket_channel = await guild.create_text_channel(f"ticket-0{ticket_id}", category=category)
embed = discord.Embed(title="Tickets", description="Support will be with you shortly.\nTo close this ticket, react with :lock:.")
message = await ticket_channel.send(embed=embed)
await message.add_reaction(emoji="\N{LOCK}")
#bot.event
async def on_reaction_add(reaction: discord.Reaction, user: discord.Member):
if reaction.message.channel != ticket_channel:
return
if reaction.emoji == "\N{LOCK}":
await bot.delete_channel(ticket_channel)
I've been trying for a while to figure out the issue, but I'm clueless.
Seems like you're asking several questions here:
I'm having an issue where 'bot' doesn't have the attribute 'delete_channel'
The bot does not have a delete_channel() function. However, a Discord.TextChannel class has a .delete() function (shown in the docs).
and I also want to make it so the bot ignores the reaction if a bot reacts to the message
Alternative 1
Every user, including bot users, have the attribute .bot. You can use that to check if the user is a bot, and if so, return the function early.
#bot.event
async def on_reaction_add(reaction, user):
if user.bot: return
# Code goes here
Note that this listens for all reactions, not just that specific message; thus comes:...
Alternative 2
As Patrick Haugh mentions, you could use the discord.Client.wait_for() function (doc link) and parse a function to as the check argument of the function.
reaction, user = bot.wait_for('reaction', check=lambda reac: reac.author == ctx.author)
*Note that this approach doesn't add this code under any event (as in the first alternative), except the command event. It will only be run once per command received unless put in a loop of some sorts.