How to make author only click button - python

i want to make author only button if someone clicked and if this is not the author of the message, then the bot will send an error.but my code is not working
#bot.command()
async def button(ctx):
await ctx.send(content="test", components=[Button(style=ButtonStyle.blue, label="Default Button", custom_id="button")])
interaction = await bot.wait_for("button_click", check = lambda i: i.custom_id == "button")
if interaction.user == ctx.author:
await ctx.send("successful test")

Change the check function to this:
check = lambda i: i.custom_id == "button" and i.user == ctx.author
This checks if the user associated with the interaction is the author of the message.

Related

How to give and take a role by clicking on the same button?

I created a button that, when pressed, adds a role to the user. However, I need to make sure that when pressed again the role is removed. I've tried to do it, but the role is added and immediately removed.
How do I make it so that the role is added and when the same button is pressed again, it is removed?
Code:
#bot.event
async def on_button_click(inter):
res = 'You give role!'
guild = bot.get_guild(inter.guild.id)
if inter.component.id == "button":
role = guild.get_role(IDROLE)
member = inter.author
await member.add_roles(role)
await member.remove_roles(role)
res = 'You remove role!'
await inter.reply(res, ephemeral = True)
Rather than adding and then removing the role right after, you need to check, when they press the button, if they have the role or not to then add or remove it.
#bot.event
async def on_button_click(inter):
guild = bot.get_guild(inter.guild.id)
if inter.component.id == "button":
role = guild.get_role(IDROLE)
member = inter.author
if role not in member.roles:
# give the role if they do not have it
await member.add_roles(role)
res = 'You give role!'
await inter.reply(res, ephemeral = True)
else:
# remove the role if they do have it
await member.remove_roles(role)
res = 'You remove role!'
await inter.reply(res, ephemeral = True)

Discord.py: How can I make a toggleable system to turn on/off a message content detection?

I've been trying to work on a system where if you run the "AWM" command, the bot will check all further messages from anyone in a given server, if the message contains a key-phrase (in this case being 's') the bot will send "FlyingWiener go brrrrrrrrrrrrr" in the same channel as the message it found. But I don't know why my code isn't working, could I please have some help? Thanks!
def MessageContentDetection(): #on_message event definition where it detects "s" in a given message's content
#bot.event
def on_message(message):
if 's' in message.content:
await message.channel.send("FlyingWiener go brrrrrrrrrrrrr")
variables = {}
Messages = {}
#commands.command() #Activation Command
async def AWM(ctx):
User = ctx.author
Owner = ctx.guild.owner
if User == Owner:
var = variables.get(ctx.guild.id, 0)
if var == 0:
variables[ctx.guild.id] = 1
await ctx.send("WienerMode Now Active!")
Messages[ctx.guild.id] = 1
else:
await ctx.send("WienerMode is still active Sherlock")
else:
await ctx.send(f"Access Denied, No access granted to **{User}**")
#bot.event #Message Send Event
async def on_message(ctx):
MSG = Messages.get(ctx.guild.id, 0)
if MSG==1:
MessageContentDetection()
#commands.command() #Deactivation Command
async def DWM(ctx):
User = ctx.author
Owner = ctx.guild.owner
if User == Owner:
var = variables.get(ctx.guild.id, 0)
if var == 1:
variables[ctx.guild.id] = 0
await ctx.send("WienerMode Nolonger Active!")
Messages[ctx.guild.id] = 0
else:
await ctx.send("WienerMode is still off Idiot")
else:
await ctx.send(f"Access Denied, No access granted to **{User}**")```
You don't need the MessageContentDetection function, instead you should just check the condition inside the existing on_message event itself as the event is running either way. It can be done this way instead:
#bot.event
async def on_message(message):
if Messages.get(message.guid.id, 0) == 1:
if 's' in message.content:
await message.channel.send('FlyingWiener go brrrrrrrrrrrrr')
This way, if the condition isn't true, the on_message event will be passed and no code runs inside that.

Is there anyway to use a dropdown without sending a response in discord.py?

I have made a dropdown select in discord.py but when the user selects an option i dont want to respond with a message but if i dont respond with a message i get "Interaction Failed" in discord.
#commands.command()
async def shop(self,ctx):
em = discord.Embed(title = "Store",description = "Buy smthing", colour = ctx.author.colour)
await ctx.send(embed = em,
components=
[
Select(placeholder="Choose a item",
options=[
SelectOption(
label = "A",
value = "a",
description = ""
),
SelectOption(
label = "B",
value = "b",
description = ""
),
]),
Button(style = ButtonStyle.blue, label="button 1")
])
def check(msg):
return msg.author == ctx.author and msg.channel == ctx.channel
while True:
try:
res = await self.client.wait_for("select_option", check=check, timeout=10)
label = res.values[0]
await res.respond(content=f"U have clicked {label}") #If I don't write this line i get the message "Interaction failed"
print(label) #This was just for checking the output.
break
except asyncio.TimeoutError:
await ctx.send("Sorry, you didn't reply in time!")
break
except discord.NotFound:
print("error")
I dont fully understand how dropdown works, can someone please explain how to go abt this.
For example dank memer doesnt send response when i click on a option.
NO respones from bot when i clicked on the option
You can try
res.edit_origin(content = "This message can be exactly the same as your original message")
This function does not send any message, but it does stop the interaction failed message to appear
You can also do the following to change the embed and buttons / select menu:
res.edit_origin(content = "just some random message",component =[newButtons],embed=EmbedObject)
BTW: The image in your question was done by disabling the message's button (basically editing the buttons).
You can try this :
await interaction.response.defer()
will complete the interaction without the error
This interaction failed'
This is especially helpful while doing edit messages or add roles to users without any output
You must respond to a message when a dropdown is clicked. This is a Discord API limit.
There is a way but it isn't that clean:
#client.command(name='test')
async def text(ctx):
global ctxn #make a global variable named for example ctxn
ctxn = ctx #double the value from the ctx ;)
global msgTest
#Define the Fields you want to have in the Dropdown
msgTest = await ctx.send(f'```Select a component```',components = [
[Select(placeholder="Select Settings",
options=[SelectOption(label="Label1", value="Value1"), #Label is the Display Name, Value is for Interaction Selection
SelectOption(label="Label2", value="Value2"),
SelectOption(label="Label3", value="Value3")])]
]
)
#client.event
async def on_select_option(interaction):
#After the selection it searches for the value="XXXXX"
if interaction.values[0] == "Value1":
await msgTest.delete() #Here you delete the dropdown after you selected an entry
await TEST1(ctx=ctxn) #Call the Function with the copied ctx start value
if interaction.values[0] == "Value2":
await msgTest.delete() #Here you delete the dropdown after you selected an entry
await TEST2(ctx=ctxn) #Call the Function with the copied ctx start value
if interaction.values[0] == "Value3":
await msgTest.delete() #Here you delete the dropdown after you selected an entry
await TEST3(ctx=ctxn) #Call the Function with the copied ctx start value
#Here you can programm your functions
async def TEST1(ctx): #First Function
return await ctx.send("Function 1 were selected")
async def TEST2(ctx): #Second Function
return await ctx.send("Function 2 were selected")
async def TEST3(ctx): #Third Function
return await ctx.send("Function 3 were selected")
If you don't delete the dropdown menu which you sendet within the msgTest variable, you will still get the interaction failed msg.

Discord Python button press triggers all buttons in a command

I am trying to create a bot for Discord in Python. However I am running into an issue with the newly added buttons. The issue is as follows: I use a command multiple times and this results into multiple embeds with buttons, however when I press the button in one of the embeds, the button with the same label in the other embed is also triggered.
The behaviour I would like to have is having the button only triggering in the embed that is being clicked on.
The code I have is
async def open(ctx):
def check(res):
return ctx.author == res.user and res.channel == ctx.channel
blue = ["Possibly", "No"]
blueresult = random.choice(blue)
em = discord.Embed(title= f"Congratulations!",description =f"The result is **{blueresult}**!",color = discord.Color.blue())
yes = Button(style=ButtonStyle.green, label="Yes")
no = Button(style=ButtonStyle.red, label="No")
m = await ctx.send(embed = em,components=[[no,yes]])
res = await client.wait_for("button_click", check=check)
user = res.component.label
if player=="Yes":
await m.edit(embed=em,components=[])
elif player=="No":
await m.edit(embed=em,components=[])
You can change the check function to:
def check(res):
return ctx.author == res.user and res.channel == ctx.channel and m == res.message
But you have to place it under this piece of code:
yes = Button(style=ButtonStyle.green, label="Yes")
no = Button(style=ButtonStyle.red, label="No")
m = await ctx.send(embed = em,components=[[no,yes]])
So the result should be:
yes = Button(style=ButtonStyle.green, label="Yes")
no = Button(style=ButtonStyle.red, label="No")
m = await ctx.send(embed = em,components=[[no,yes]])
def check(res):
return ctx.author == res.user and res.channel == ctx.channel and m == res.message
The new code checks if the embed message the bot sent is the responded message. I tested it, and it worked for me.

Discord.py collect emoji reactions and make a function out of them

I am trying to make a function whenever the user reacts with the check emoji or if they react with the x. So basically I have a check if the user has a phone, if the user has a phone then you can call them. The bot sends a message in dms and reacts with a check and a x, if you click the check I want a function to happen, how can I do this?
#commands.command()
#commands.cooldown(1,120,commands.BucketType.user)
async def call(self, ctx, member : discord.Member):
phone = False
users = await bank_data()
user = ctx.author
client = discord.Client
try:
bag=users[str(user.id)]["bag"]
except:
bag=[]
for item in bag:
name = item["item"]
if name == "phone":
phone = True
if phone == False:
await ctx.reply("You must buy a phone to call someone idiot.")
if phone == True:
try:
targetBag = users[str(target.id)]["bag"]
except:
targetBag=[]
targetPhone = False
if target:
for item in targetBag:
name = item["item"]
if name =="phone":
targetPhone = True
if targetPhone == False:
await ctx.reply("Attempted user to call does not have a phone.")
if targetPhone == True:
channel = await target.create_dm()
emojis=['✅', '❌']
confirmEmoji = '✅'
message=await channel.send(f"{ctx.author} is calling you. Do you want to answer?")
for emoji in emojis:
await message.add_reaction(emoji)
You can use the wait_for() for this case. Create a response variable so that you can check and use the response to answer the phone or decline it.
You can read more about it here-
https://discordpy.readthedocs.io/en/stable/api.html#discord.Client.wait_for
There are different types of events which you can pass into wait_for() in your case it's reaction_add
Hope this helped :D

Categories

Resources