I have a channel that has an embed with a button, when the button is clicked it brings up an ephemeral survey.
If a user clicks the initial button multiple times then the survey will come up as many times. Is there a way to prevent this? The first button isn't ephemeral, everyone can use it so I can't really disable it after its clicked.
Is there a way to deactivate the button for that particular user or timeout the user from clicking it again?
class surveyView(discord.ui.View):
def __init__(self):
super().__init__(timeout=None)
self.value = None
@discord.ui.button(label="Let's get started!",
style=discord.ButtonStyle.blurple)
async def survey(self, interaction:discord.Interaction, button:discord.ui.Button):
view = questions()
await interaction.response.send_message(content=f"", embed=surveyEmbed,
view=view, ephemeral=True)
There's no way to disable buttons natively for a user and not for others if the view is visible to everyone in the channel (aka, not ephemerally). But you could easily prevent users from clicking it multiple times with a bit of code.
class SurveyView(discord.ui.View):
def __init__(self):
super().__init__(timeout=None)
self.value = None
self.clicked_users = []
@discord.ui.button(
label="Let's get started!",
style=discord.ButtonStyle.blurple
)
async def survey(self, interaction:discord.Interaction, button:discord.ui.Button):
user_id = interaction.user.id
if user_id in self.clicked_users:
# user has already pressed the button
await interaction.response.send_message(content=f"You have already pressed this button/done this survey.", ephemeral=True)
return
self.clicked_users.append(user_id)
view = questions()
await interaction.response.send_message(
content=f"", embed=surveyEmbed, view=view, ephemeral=True
)
We define a variable called clicked_users
in the view which is an empty list. Every time a user presses the button, we check if their user ID is already in the list. If it is, we tell them as such and exit. Otherwise, we do what you want to do and add the user to the list.
One possible downside, is that if the questions
view expires and the user doesn't complete the survey, then they won't be able to press the button again. You could mitigate that by passing a reference to this view to the questions
view and removing the user ID from clicked_users
if the view expires or the user cancels, etc.
Example passing reference to questions
:
class QuestionsView(discord.ui.View):
def __init__(self, survey, user_id):
# whatever your super and other __init__ stuff is
self.survey = survey
self.user_id = user_id
async def on_timeout(self):
self.survey.users_clicked.remove(self.user_id)
# rest of your code
Then, in async def survey
when we create it:
view = QuestionsView(self, user_id)
Now, the view has a reference to the "survey view" and the user that clicked it. When it times out, it will remove the user ID.
Alternatively, instead of using self.clicked_users = []
, we can have a database that tracks which users have done the survey. And use that to check if they can press the button or not.