Search code examples
pythondiscord.pynextcord

How to prevent the user from selecting an option from nextcord.ui.Select


I wanted to implement a list of options where the user cannot select anything.

I tried the following:

  • Read the Nextcord documentation. They do not offer any way to achieve this.

  • Look at the source code to see if I could create a class derived from ui.Select that does not send data to Discord and thus force a failed interaction (since I saw that failed interactions cancel the user's selection).

  • Set within the ui.Select callback the values ​​attribute to an empty list. But it sends me the error "Can't set attribute".

  • Call asyncio.sleep to put the callback to sleep until Discord considers the interaction failed. But that although it works, produces an ugly error in console.

Conclusion

I came to the conclusion that throwing a Python error on the callback would be the only way I could recognize of forcing a failed interaction and thus preventing the user from selecting something. But I don't like to generate an error with the sole objective of interrupting the course of the code.

Ask

How can I make the user unable to select anything from the ui.Select? Or, if this is not possible, how can I force a failed interaction every time the user selects something?

Edit

I forgot to add a minimal, complete and verifiable example to you so you can test, excuse me.

from nextcord.ext import commands
from nextcord import ui
import nextcord

import asyncio

#-----------------------------------------------#
# Bot
#-----------------------------------------------#

bot = commands.Bot(command_prefix="!")

@bot.command()
async def play(ctx):
    view = ui.View()

    select = ui.Select(options=[nextcord.SelectOption(label="option1"), nextcord.SelectOption(label="option2")])
    view.add_item(select)

    await ctx.send("Test Message", view=view)
        
@bot.event
async def on_ready():
    print("Bot listo!")

bot.run(bot_key)

Solution

  • While there is no official way to do this, there are a few workarounds:

    First method: Overriding interaction_check:

    The interaction_check function is called every time an interaction is dispatched, and the interaction will only be responded to, if this function returns True. So if this function always returns False, the interaction will always fail, resulting in "This interaction failed" and resetting the choice in the select in discord:

    async def interaction_check(interaction: nextcord.Interaction):
        return False
    

    You can then add this function to the select in the same way as you add the callback function.

    Second method: Editing the message:

    This is the cleaner option, since it doesn't show "This interaction failed" in discord and has a shorter waiting time in resetting the choice. This works by simply editing the message, but not changing anything:

    async def callback(interaction: nextcord.Interaction):
        await interaction.edit()