Rapptz / discord.py

An API wrapper for Discord written in Python.
http://discordpy.rtfd.org/en/latest
MIT License
14.82k stars 3.75k forks source link

AppCommands Autocomplete forcing value for choice to be of type Int53 #9985

Open rrenode opened 1 day ago

rrenode commented 1 day ago

Summary

Regardless of type sent, autocomplete forces and expects the type of the value to be Int53

Reproduction Steps

Created an autocomplete function for a hybrid command. Set value to be a string.

Minimal Reproducible Code

# Assuming a bot is setup and this is a cog
from discord.ext import commands
from discord import app_commands, Interaction
from typing import Optional, List

# Simulated database functions returning mock team data
def get_league_teams(league_id):
    class LeagueTeam:
        def __init__(self, name, id):
            self.name = name
            self.id = id # Where id is a Discord role id
    return([LeagueTeam("Wombats", 1288528472402038784), LeagueTeam("Kangaroos", 1288528593680470109)])

async def team_autocomplete(interaction: Interaction, current: str) -> List[app_commands.Choice[str]]:
    teams = get_league_teams(interaction.guild.id) # returns list[LeagueTeam]

    return [
        app_commands.Choice(name=team.name, value=str(team.id)) # Throws: In data.choices.0.value: int53 value should be less than or equal to 9007199254740991.
        for team in teams if current.lower() in team.name.lower()
    ]

# Simulated database functions returning mock tier data
def get_league_tiers(league_id):
    """Finds league from db and returns all tiers as objects"""
    class LeagueTier:
        def __init__(self, name, id):
            self.name = name
    return([LeagueTier("Wombat Joeys"), LeagueTier("Kangaroo Joeys")])

async def tier_autocomplete(interaction: Interaction, current: str) -> List[app_commands.Choice[str]]:
    teams = get_league_tiers(interaction.guild.id) # returns list[LeagueTier]

    return [
        app_commands.Choice(name=team.name, value=team.name) # Throws: In data.choices.0.value: Value "Wombats" is not int53.
        for team in teams if current.lower() in team.name.lower()
    ]

class Scheduling(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.hybrid_command(name="test")
    @app_commands.autocomplete(team=team_autocomplete)
    async def test(self, ctx: commands.Context, team: Optional[str]):
        await ctx.send(f"Team ID: {team}")

    @commands.hybrid_command(name="test2")
    @app_commands.autocomplete(tier=tier_autocomplete)
    async def test2(self, ctx: commands.Context, tier: Optional[str])

async def setup(bot):
    cmds = Scheduling(bot)
    cmds.setup_checks()
    await bot.add_cog(cmds)

Expected Results

Utilizing a role id as the value, I did not expect it to work as the discord role ids are indeed outside the expected integer range for value. However, even after type converting to a string, it still responds with In data.choices.0.value: int53 value should be less than or equal to 9007199254740991.

What's more is when I instead did value=f"ID_{team.id}", autocomplate still expects this as an int53 value by responding:In data.choices.1.value: Value "ID_1288528593680470109" is not int53.`

You can see that with the tier in the example above. In using a string, a team name, as the value, we get a simialar error which can be seen below.

In short:

Actual Results

For the team autocomplete in the example, the logs state: In data.choices.0.value: int53 value should be less than or equal to 9007199254740991.

For the tier autocomplete in the example, the logs state: In data.choices.0.value: Value "Wombat Joeys" is not int53. In data.choices.1.value: Value "Kangaroos Joeys" is not int53.

Intents

Default, message_content, members

System Information

Checklist

Additional Context

get_league_teams and get_league_tiers are simulated functions representing typical usage and that you’re using Discord role IDs (which are large integers).

I would like to not that this behavior limits usage for applications that rely on Discord IDs or similarly large integers, especially when autocomplete functions are expected to accept large identifiers.

For workarounds, I attempted using a surrogate by setting the value as a string representation of the original large integer, but the issue persisted. However, when mapping small integer surrogates to represent the larger integer values, the issue was resolved.

It's possible that I missed something but the docs say nothing about specific supported types for autocomplete. Further, I know from using DiscordPy in other projects that command choices can support strings as values.

PasteBin for logs: https://pastebin.com/dfVpqPN6

If for some reason a full traceback is neccessary, do let me know.

LeoCx1000 commented 1 day ago

Have you synced your CommandTree properly? This error would be because you at some point had the parameter team set as int, and have not synced the command after you changed it to str. As per the discord API docs, integer-type choices must be between -2^53 and 2^53. This is NOT enforced nor handled by discord.py (you got an HTTPException after all, which means it is an error that was returned by the discord API).