Close Discord message on button click - python

I have a select menu with a submit button. When submit is clicked I want to close the current message, submit the data and then open a new select menu but I am having trouble figuring out how to have the message close.
How can I have the current menu and button close when the submit button is clicked?
Thanks in advance for your help.

To turn my comment into an answer; you can just delete the message on button press. For example, my Cancel buttons look a little like this:
#discord.ui.button(label="Cancel", style=discord.ButtonStyle.red, row=3, disabled=False, emoji="✖️")
async def cancel_callback(self, button: discord.ui.Button, interaction: discord.Interaction):
await interaction.message.delete()
This is within a custom View class so might have to be adapted for your needs - but using the interaction.message attribute to delete the message is the way to go.

Related

Subclassing the creation of Buttons with their respective callback

I am currently learning about discord.ui buttons and i want them to be subclassed since I find them to static otherwise.
I have come a long way of figuring it out but I can't quiet get the view to reset correctly (I have commented the code so you will see where the problem lies).
This is the code of the ButtonCreation subclass with Button from discord.ui import (this is the old code (I leave it as reference))
class ButtonCreation(Button):
def __init__(self, label, style, emoji):
super().__init__(label=label, style=style, emoji=emoji)
async def callback(self, interaction):
# define view again... this will make it empty. Some way to pass on the content of original view?
# or maybe subclassing View instead of Button
view = discord.ui.View()
# checking if current pressed buttons style equals "success"/green
if self.style == discord.ButtonStyle.success:
# change the style to gray
self.style = discord.ButtonStyle.gray
view.add_item(self)
# edit the original message with new view
await interaction.response.edit_message(view=view)
else:
await interaction.response.send_message('This Button has the style: ' + str(self.style))
This is the command cog where the button gets created by passing the arguments.
(arguments were changed to how the new version needs them to be)
#client.command()
async def myroles(self, ctx):
# Buttons being created
button1 = ButtonCreation(ctx=ctx, label='TSLinked', style=discord.ButtonStyle.green, custom_id="tslinked", emoji=None, row=0)
button2 = ButtonCreation(ctx=ctx, label='TSLinked', style=discord.ButtonStyle.gray, custom_id="tsadmin", emoji=None, row=1)
button3 = ButtonCreation(ctx=ctx, label='TSLinked', style=discord.ButtonStyle.danger, custom_id="tsserveradmin", emoji=None, row=2)
# defining view plus adding buttons into view
view = View()
view.add_item(button1)
view.add_item(button2)
view.add_item(button3)
# send view with text above
await ctx.channel.send('Test!', view=view)
There is actually everything working except that I can't get the original view over to the callback to get all of the original buttons.
So the current flow is that all 3 buttons are shown with their according colour and when you press button1 (since green == "ButtonStyle.success") the button colour is changed to gray and gets put into the view which afterwards gets send to the channel.
What should happen: After the green button being pressed the buttons should stay the same except the green button which should switch to gray.
Thanks in advance to anyone willing to lend a hand.
Solution
# ButtonCreation subclass with Button from discord.ui import
class ButtonCreation(Button):
# init needs ctx and at best custom_id or row to do all you need
def __init__(self, ctx, label, style, emoji, custom_id, row):
super().__init__(label=label, style=style, custom_id=custom_id, emoji=emoji, row=row)
self.ctx = ctx
async def callback(self, interaction):
# checks if Button style is green
if self.style == discord.ButtonStyle.green:
# changes button to grey
self.style = discord.ButtonStyle.grey
# self.ctx can interact with channel and user just like ctx would in normal commands
await self.ctx.channel.send('test')
# remove your button (self) before adding it again since you can't "replace" it just like that
self.view.remove_item(self)
# add the Button (self) to the view by using self.view.add_item.
self.view.add_item(self)
# add the view to the edit or send_message method with self.view
await interaction.response.edit_message(view=self.view)
If you need a little clarification:
self is the Button thats how you call the arguments.
the Button also has "View" as object so you can actually get all the buttons that are saved in it.
so before adding the button to the view (self.view) you can change the values of the button and add them again.
Things like row are fixed for the single purpose of the buttons actually needing to stay in the same position, otherwise they would be added behind all others.
Really hope this helps others aswell.

Remove Keyboard after clicking URL from InlineKeyboardButton

I'm creating a wrapper for /commands in python
I created an InlineKeyboardButton with a URL to chat the bot in private. I want the button to remove or disappear, just not show after the user clicks the url button.
I have used the generic wrapper from the telegram tutorials.
However, I am a "newb" :) Always trying to learn something new I can share.
In this case, I've become stuck.
Unlike callback_data where data can be sent to another button to edit the message. The URL doesn't send anything. I just want the button to vanish or the best alternative hide or something.
Any Ideas??
what direction to move in :)
I have looked into ReplyKeyboardRemove and OneTimeKeyboard but either my syntax is off or It isn't possible with a URL button
def myrestricted(func):
#wraps(func)
def wrapped(bot, update):
user = update.message.from_user.username
if update.message.chat.type != "private" :
group = update.message.chat.id
if user not in ADMIN_ONLY:
button = [InlineKeyboardButton("7heUnknown_Bot", url='t.me/7heUnknown_Bot',],
bot.send_message(chat_id=update.message.chat_id, text="Please click the button below to talk with me privately")
return
return func(bot, update)
return wrapped```
When the user clicks on the URL button I want the button to disappear.
Unfortunately, you can't.
InlineKeyboardButton with a URL only displays the button for users to open a link. As far as I know, there's no event in Telegram's API that can be fired when the user actually opens the link (or even clicks on the button!)

Python tkinter raise exceptions and wait for button press

I'm new in Tkinter and I'm currently trying to create a small game. When something happens in the game I want to create a pop-up window which will inform the user about any changes. This is the code that I have written for it.
def message(self, text):
top = tkinter.Toplevel(width=50, height=25)
top.title("Message")
msg = tkinter.Message(top, text=text)
msg.pack()
ok = tkinter.Button(top, text="OK", command=top.destroy)
ok.pack()
My two questions are:
Can I replace this by an exception that will create an "Error Message" window? If it isn't necessary then can I use it to be raised by the exception?
I want the user to be forced to see and read the message, so how can I freeze the main window(the user can't click on anything else) until he presses the OK button on the pop-up window?
Use:
top.grab_set()
To show Error Message you can use tkmessagebox.showerror().

How to click button in 'alert' message on the webpage with PyQt4

On the webpage, when I create a new user, alert message displayed that 'New user was created'. And in order to continue, I have to click button 'ok'. So the thing is I don't really know how to click it.
when I need to click a regular button I do something like this:
doc = self.page().currentFrame().documentElement()
submit_button = doc.findFirst('input[id=my-submit-button]')
submit_button.evaluateJavaScript('this.click()')
But how to click button in alert message?
You are looking for the QWebPage::javaScriptAlert ( QWebFrame * frame, const QString & msg ) function:
This function is called whenever a JavaScript program running inside
frame calls the alert() function with the message msg.
The default implementation shows the message, msg, with
QMessageBox::information.

Python tkinter, how to disable background buttons from being clicked

When opening a new tkinter window, I only want the user to be able to click buttons on the new window. They should not be able to click on buttons from other windows that are part of the application. How would I accomplish this?
Here is a snip of my code:
def exportEFS(self):
self.exportGUI = Toplevel()
Button(self.exportGUI, text='Backup', command=self.backup).pack(padx=100,pady=5)
Button(self.exportGUI, text='Restore', command=self.restore).pack(padx=100,pady=5)
def backup(self):
self.backupWindow = Toplevel()
message = "Enter a name for your Backup."
Label(self.backupWindow, text=message).pack()
self.entry = Entry(self.backupWindow,text="enter your choice")
self.entry.pack(side=TOP,padx=10,pady=12)
self.button = Button(self.backupWindow, text="Backup",command=self.backupCallBack)
self.button.pack(side=BOTTOM,padx=10,pady=10)
In this snip, once the backupWindow is opened, the exportGUI remains open, but the user should not be able to click "Backup" or "Restore" while the backupWindow is opened.
Thanks!
You will want to call grab_set on the TopLevel window so that all keyboard and mouse events are sent to that.
def exportEFS(self):
self.exportGUI = Toplevel()
Button(self.exportGUI, text='Backup', command=self.backup).pack(padx=100,pady=5)
Button(self.exportGUI, text='Restore', command=self.restore).pack(padx=100,pady=5)
def backup(self):
self.backupWindow = Toplevel()
self.backupWindow.grab_set()
message = "Enter a name for your Backup."
Label(self.backupWindow, text=message).pack()
self.entry = Entry(self.backupWindow,text="enter your choice")
self.entry.pack(side=TOP,padx=10,pady=12)
self.button = Button(self.backupWindow, text="Backup",command=self.backupCallBack)
self.button.pack(side=BOTTOM,padx=10,pady=10)
What you can do is set the state to disabled. As so:
self.button.config(state="disabled")
And to enable it, you just use:
self.button.config(state="normal")
However, you must assign your buttons to variables first, like this:
self.backup=Button(self.exportGUI, text='Backup', command=self.backup)
self.backup.pack(padx=100,pady=5)
self.restore=Button(self.exportGUI, text='Restore', command=self.restore)
self.restore.pack(padx=100,pady=5)
so you would disable these using:
self.backup.config(state="disabled")
self.restore.config(state="disabled")
and re-enable using:
self.backup.config(state="normal")
self.restore.config(state="normal")
Please note however, that while the button is disabled, nothing can be changed to that button, both through the code, or through the user using it. So that means if you wanted to change the text of that button, you would have to change the state of the button to "normal" before changing it (if it already isn't in that state, which by default, all widgets are in that state when first created).
Cheers :)

Categories

Resources