Cutgrey
Cutgrey

Reputation: 25

bot.get_channel() occasionally returning none in discord.py,

I am trying to write a discord.py bot. The following is an abridgement of my full code.

intents = discord.Intents.default()
intents.message_content = True

load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')

bot = commands.Bot(intents=intents, command_prefix="!", sort_commands=False)
client = discord.Client(intents=intents)


@bot.event
async def on_ready():
    print(f'{bot.user.name} has connected to Discord!')
    channel = bot.get_channel(12345678912345678912)
    await channel.send("This is a test.")

bot.run(TOKEN)

Sometimes, the code above will work as intended, printing the connection message and sending the desired message into the target channel.

This is not always the case, however! I am getting an issue where the bot.get_channel() command returns none instead of the correct data. I assume this means that the channel cannot be found, except for the fact that the channel does exist.

The error that is sent to the console is;
AttributeError: 'NoneType' object has no attribute 'send'

I am very, very new to discord.py so I would appreciate any help I can get to better understand what's going on under the hood here. Thank you very much for your help.

Upvotes: 1

Views: 1954

Answers (2)

stijndcl
stijndcl

Reputation: 5647

The accepted answer is not recommended.

The reason it doesn't work is because the cache isn't populated yet in on_ready, but you should not make API requests (fetch_X & send) in on_ready! Making API calls in there has a high chance for Discord to just disconnect your bot.

Also, on_ready gets triggered multiple times, so you'll end up sending this message constantly even though you only started it once.

There's rarely a reason to do anything at all in there. If you want something to run once on startup you can create a Task & start it in setup_hook.

Upvotes: 1

Catgal
Catgal

Reputation: 718

The get_channel method is a cache lookup method, so it's not always reliable, or the bot doesn't have access to the channel, and since it doesn't raise an exception if the cache wasn't found and returns None instead, you can't know the reason for sure. You can use fetch_channel to make an API request after get_channel if it returns none; this method will raise an exception if the channel was not found or it doesn't have permission to fetch.

channel = (bot.get_channel(1234567890) or await bot.fetch_channel(1234567890))
await channel.send("This is a test.")

Also it seems like you have both discord.ext.commands.Bot and discord.Client instance, please choose one and remove the other.

Upvotes: 3

Related Questions