I can't figure out how to do it in discord.py so that pressing a button reads the user who pressed it, then writes all users who pressed the button to a temporary array. And if it's not difficult if you know YouTube lessons on this, please give a link. (translated with google translator, sorry)
You can add a callback function to your button for that, like this:
#bot.command()
async def button(ctx):
users = []
button = discord.ui.Button(style = discord.ButtonStyle.primary, label="Add a user")
async def button_callback(i):
users.append(i.user)
print(users)
button.callback = button_callback
# Need to create a view
buttons_view = discord.ui.View()
# and add the button component to the view
buttons_view.add_item(button)
# send the view with the message
await ctx.send("Add a user by clicking the button", view=buttons_view)
Related
I'm trying to follow this thread: https://stackoverflow.com/a/75396860. I would have commented on it to get clarity, but SO won't allow me to.
I'm just trying to accomplish one simple thing: when Button 1 is pressed, enable Button 2
View Class
import discord
class Signup(discord.ui.View):
def __init__(self):
super().__init__()
#discord.ui.button(label="Button 1")
async def one_callback(self, button: discord.ui.Button, interaction: discord.Interaction):
await interaction.response.defer()
for child in self.children:
if type(child) == discord.ui.Button and child.label == "Button 2":
child.disabled = False
await interaction.message.edit(view=self)
await interaction.followup.send("Button 1 Pressed, Button 2 Enabled")
#discord.ui.button(label="Button 2", disabled=True)
async def two_callback(self, button: discord.ui.Button, interaction: discord.Interaction):
pass
I initially send the message like this:
await channel.send(content="Click Button 1 to get Button 2!", view=Signup())
With this code, I receive the following error when it gets to interaction.response.defer():
AttributeError: 'Button' object has no attribute 'response'
It seems like the Interaction is always type discord.Button for me, which doesn't have response or message as attributes. The same code appears to work for others, though, as this SO thread is not the only place that I've seen the same logic being used. I'm not quite sure where I've gone wrong.
Turns out the issue was in the answer at the other SO thread. The arguments were out of order in the callback function.
I had:
async def one_callback(self, button: discord.ui.Button, interaction: discord.Interaction):
Should be:
async def one_callback(self, interaction: discord.Interaction, button: discord.ui.Button):
The docs state the order here: https://discordpy.readthedocs.io/en/stable/interactions/api.html#discord.ui.button
The function being decorated should have three parameters, self representing the discord.ui.View, the discord.Interaction you receive and the discord.ui.Button being pressed.
Thanks to the discord.py Discord for saving me from my self!
Its my first time using buttons in discord.py
I want the embed to delete itself when someone clicks the delete button. This is my code but there are some problems.
Anyone can delete the message by clicking the button. I only want the user who ran the command to interact with the button.
When I click delete button, it automatically deletes all messages which were previously sent by the bot.
msg = await ctx.channel.send(embed=embed,components = [Button(label = "Delete", style=ButtonStyle.red)])
interaction = await bot.wait_for("button_click")
if interaction.component.label.startswith("Delete"):
await msg.delete()
I am not familiar with this components, but you could add an if statement to check for author id == user id who press said button,
msg = await ctx.send(embed = embed,components=[[copy,delete]])
#Copy and delete are buttons
def check(res):
return ctx.author == res.user and res.channel == ctx.channel and msg == res.message
while True:
res = await bot.wait_for("button_click",timeout=60, check=check)
if res.component.label.startswith("Copy User Name"):
await msg.edit(embed=embed_copy,components = [[back,delete]])
elif res.component.label.startswith("Back"):
await msg.edit(embed=embed,components=[[copy,delete]])
elif res.component.label.startswith("Delete"):
await msg.delete()
As LeSauvage suggested , this problem can easily be solved by using checks!
I have a python telegram bot that sends messages with Buttons on them like this:
keyboard = [[telegram.InlineKeyboardButton("Finish", callback_data='1'),
telegram.InlineKeyboardButton("Edit", callback_data='2')]]
update_obj.message.reply_text(message_text, reply_markup=reply_markup,
parse_mode=telegram.ParseMode.MARKDOWN)
Now when the user hits the "Edit" button I want the ConversationHandler to move to another state.
Here is a part of my ConversationHandler:
WELCOME = 0
SEARCH = 2
EDITTITLE = 3
[...]
handler = telegram.ext.ConversationHandler(
entry_points=[telegram.ext.CommandHandler('start', start)],
states={
WELCOME: [
telegram.ext.MessageHandler(filters=telegram.ext.Filters.all, callback=welcome),
updater.dispatcher.add_handler(telegram.ext.CallbackQueryHandler(button))
],
SEARCH: [
telegram.ext.MessageHandler(filters=telegram.ext.Filters.all, callback=search),
updater.dispatcher.add_handler(telegram.ext.CallbackQueryHandler(button))
], EDITTITLE: [
telegram.ext.MessageHandler(filters=telegram.ext.Filters.all, callback=editTitle)
]
[...]
Now normally I can just return the new state in the callback function from the MesageHandler like so:
def search(update_obj, context):
[...]
return WELCOME
But if I return the new state in my button function it does not switch to that state. Here's the code:
def button(update_obj, context):
[...]
return EDITTITLE
How can I make the button change the ConversationHandler state or is there something I am missing?
Am I using the Buttons the right way?
Thanks :)
You're adding the CallbackQueryHandlers wrongly to the conversation. updater.dispatcher.add_handler(telegram.ext.CallbackQueryHandler(button)) returns None, so None will be added to the list of handlers in the states WELCOME and SEARCH. Instead it should be just telegram.ext.CallbackQueryHandler(button).
It could be that there are additional issues, but I'd have to see a full minimal working example to judge that.
Disclaimer: I'm currently the maintainer of python-telegram-bot.
My goal
Here is the documentation I'm trying to follow.
// Display a dialog box with a title, message, input field, and "Yes" and "No" buttons. The
// user can also close the dialog by clicking the close button in its title bar.
var ui = SpreadsheetApp.getUi();
var response = ui.prompt('Getting to know you', 'May I know your name?', ui.ButtonSet.YES_NO);
// Process the user's response.
if (response.getSelectedButton() == ui.Button.YES) {
Logger.log('The user\'s name is %s.', response.getResponseText());
} else if (response.getSelectedButton() == ui.Button.NO) {
Logger.log('The user didn\'t want to provide a name.');
} else {
Logger.log('The user clicked the close button in the dialog\'s title bar.');
}
What I expect to happen and what happens instead
I expect the UI to display a dialog box with a title, message, input field, and "Yes" and "No" buttons. The user can also close the dialog by clicking the close button in its title bar.
But instead, nothing happens.
Steps to reproduce.
Open a Google Sheet.
Open Script Editor: Tools > Script editor
Paste above code into script editor.
Close script editor.
Navigate to Google Sheet.
But as I mentioned, nothing actually happened.
How do I trigger the UI instance to initiate? What am I doing wrong?
Run this function:
function runIt() {
var ui = SpreadsheetApp.getUi();
var response = ui.prompt('Getting to know you', 'May I know your name?', ui.ButtonSet.YES_NO);
if (response.getSelectedButton() == ui.Button.YES) {
Logger.log('The user\'s name is %s.', response.getResponseText());
} else if (response.getSelectedButton() == ui.Button.NO) {
Logger.log('The user didn\'t want to provide a name.');
} else {
Logger.log('The user clicked the close button in the dialog\'s title bar.');
}
}
After getting the function to run go look at the spreadsheet.
I'm facing the following situation: When an user clicks a submit button, the app disables the button. Then, when the callback function of the ReCaptcha is called, I can enable the button again. But if the user closes the verify window how can I know that and then enable my button again?
I was facing the same problem using invisible recaptcha. The way I solve it is observing when the captcha was getting closed.
First get the div Element containing the captcha.
let iframe = document.querySelector('iframe[src^="https://www.google.com/recaptcha"][src*="bframe"]');
let container = iframe.parentNode.parentNode;
Then
let observer = new MutationObserver( mutations => {
if(container && container.style.visibility === 'hidden'){
// Re enable the button
}
});
observer.observe(container, { attributes : true, attributeFilter : ['style'] });