How do i make a bot send a message in a specific channel with on_message

Viewed 62

I didnt really wanna ask this but ive been having trouble, I keep getting errors when i want to try and send a message in a specifc channel, heres the code thats important:


channel = client.get_channel(CHANNELID)

@client.event
async def on_message(message):
    if message.author.id != BOTID:
        await channel.send(f"**{message.author.name}** - {datetime.today().strftime('%Y-%m-%d')} {datetime.today().strftime('%H:%M:%S')} - {message.content}")
        await client.process_commands(message)

The error i get is

AttributeError: 'NoneType' object has no attribute 'send'

Another side question, it is possible to make it send it in a different server?

Thanks

3 Answers

The easiest way is to hard-code guild and channel IDs. Like this:

@client.event
async def on_message(message):
    if message.author.id != BOTID:
        guild = client.get_guild(guildID)
        channel = guild.get_channel(channelID)
        await channel.send(f"**{message.author.name}** - {datetime.today().strftime('%Y-%m-%d')} {datetime.today().strftime('%H:%M:%S')} - {message.content}")
        await client.process_commands(message)

Instead of guildID and channelID put IDs of your choice. If you don't know how to get IDs:

  1. Go to user settings
  2. Go to advanced tab
  3. Turn on developer mode
  4. Right click on anything that you want an ID of
  5. Click Copy ID

It looks like when you defined channel = client.get_channel(CHANNELID), your guild cache wasn't filled and therefore the get_channel returned None. One option is to go as loloToster said and get the guild and channel every time. I find it easier to just set it on_ready:

channel = client.get_channel(CHANNELID)  # Will be None originally (I won't write None as if you work with some linters, they will send warnings about 'send' not found in NoneType). Also, get_guild().get_channel() is more efficient as it involves less iteration (although this will only affect u if u have a large number of servers on your bot)

@client.event
async def on_ready():
    global channel
    channel = client.get_channel(CHANNELID)

@client.event
async def on_message(message):
    if message.author != client.user and channel is not None:
        await channel.send(f"**{message.author.name}** - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - {message.content}")
        await client.process_commands(message)

For your side question of can you send it to a different server, yes of course, just provide the channel id of a channel in another server as your argument to get_channel

While other answers are all valid and pretty insightful, there is an easier fix here. You can send a message to a specific channel using the fetch_channel(CHANNELID). It is an API call and thus there is no issue of cache or anything else.

channel = await client.fetch_channel(CHANNELID)

@client.event
async def on_message(message):
    if message.author.id != BOTID:
        await channel.send(f"**{message.author.name}** - {datetime.today().strftime('%Y-%m-%d')} {datetime.today().strftime('%H:%M:%S')} - {message.content}")
        await client.process_commands(message)
Related