Bagle
Bagle

Reputation: 2346

Retrieving TextChannel Object in command

I've come to a bit of a standstill with retrieving channel objects within a command. Instead of using async def command(ctx, channel:discord.TextChannel) or similar, I would like to get the channel object from the product of a user's wait_for message content, which I will not include here.

For example, if the user said general, the id 757115231377031169, or simply mentioned the channel #general, the bot would be able to retrieve the TextChannel object no matter the valid output.

In short: How do I get a TextChannel Object within the code itself?


Here are a few things that I have tried:

I had tried to retrieve the channel object via invoking another command with the help of a converter. This would often raise the error 'str' object has no attribute 'mention' (this was my most recent option, I had better ideas than this)

@client.command()
async def chan_convert(ctx, channel:discord.TextChannel):
    return channel

@client.command()
async def test(ctx, channel):
    try:
        ch = await ctx.invoke(client.get_command("chan_convert"), channel=channel)
        await ctx.send(ch.mention)
    except Exception as e:
        await ctx.send(str(e))

Another way I had approached my problem was with a custom function I attempted to create, but this only worked up until a point, such as if you inputted a channel id, it would raise the error AttributeError: 'NoneType' object has no attribute 'mention'.

def custom_chan(guild:discord.Guild, channel):
    if channel.isnumeric(): # if it's all numbers, it could be an id
        try:
            channel = guild.get_channel(channel)
            return [True, channel]
        except:
            return [False, "ID was not valid"]
    else:
        if channel.startswith("<#") and channel.endswith(">"): # <#123123123123123123> format of channel mention
            channel = channel.replace("<#", "")
            channel = channel.replace(">", "")
            try:
                channel = guild.get_channel(channel)
                return [True, channel]
            except:
                return [False, "ID was not valid"]
        else: # otherwise, it's just a name, check if it exists
            try:
                channel = discord.utils.get(guild.channels, name=channel)
                return [True, channel]
            except:
                return [False, "No channel with that name was found"]

def channel_check(channel):
    return type(channel)

chan = custom_chan(ctx.guild, "757115231377031169") # an id I put in here originally
await ctx.send(chan[1].mention)
await ctx.send(channel_check(chan))

Thank you in advance.

Upvotes: 0

Views: 160

Answers (1)

Eleiber
Eleiber

Reputation: 62

If you are using discord.ext, you can use TextChannelConverter() in order to get the TextChannel object, using a string containing the ID, the mention, or the name as input.

Following your first example:

from discord.ext.commands import TextChannelConverter

@client.command()
async def chan_convert(ctx, channel):
    ch = await TextChannelConverter().convert(ctx=ctx, argument=channel)
    return ch

This worked for me in my own channel, using the ID, the name, or the mention as input. But if you aren't going to use this as an actual command, instead of using ctx.invoke(), you can just remove the @client.command() decorator and call the function using await chan_converter().

Upvotes: 2

Related Questions