I am trying to use nextcord to get all the choices from a user's inventory, but I am having trouble getting the user_id for my fetch_choices function. See below for some more details.
My slash command looks like this, (... is where I want userid):
async def duel(interaction: nextcord.Interaction, item: str = nextcord.SlashOption("item", choices=fetch_choices(...)), quantity: int = 1, side: str = "h"):
This is my fetch_choices code:
def fetch_choices(user_id):
c.execute("SELECT * FROM items WHERE user_id=?", (user_id,))
rows = c.fetchall()
items = {}
for row in rows:
item = row[1],
items.update({item[0]: item[0]})
return items
My question is how can I get the user id, and pass it to fetch_choices?
Unfortunately, this isn't possible at the moment. It would be great if we could somehow pass the interaction into the SlashOption
class and use it to generate a different default value for every user, but as a comment on this post states, default values in python are calculated one time. Ideally, nextcord would allow us to provide a callback function, which could generate these options on-the-fly for each interaction, but that feature doesn't exist yet.
BUT
We can get almost the same experience by using the autocomplete feature, instead of choices
:
async def duel(interaction: nextcord.Interaction, item: str = nextcord.SlashOption("item"), quantity: int = 1, side: str = "h"):
pass
@duel.on_autocomplete("item")
async def item_autocomplete(interaction: nextcord.Interaction, item: str):
choices = fetch_choices(interaction.user.id, item)
await interaction.response.send_autocomplete(choices)
def fetch_choices(user_id, name_substr=''):
pattern = f'%{name_substr}%'
c.execute("SELECT * FROM items WHERE user_id=? AND name LIKE ?", (user_id, pattern))
rows = c.fetchall()
items = []
for row in rows:
items.append(row[1])
return items
A couple caveats:
fetch_choices
function will run every time a character is typed into the slash option. If number of queries isn't an issue, this is probably fine. Otherwise, some caching might be a good idea.%
character (or any other special sqlite pattern characters), pattern = f'%{name_substr}%'
might not always work. There are other options, like using instr
, but I figured I'd give the simplest solution first.At the time of writing, this works almost exactly the same as providing choices to SlashOption
. However, it takes a bit longer for the options to appear, and there is no error for invalid items, since autocomplete is just a suggestion. Of course, you can handle invalid arguments in your slash function, but you won't get the nice red box that discord displays for an invalid SlashOption
.