Trying to send a message to a specific channel from a different file , discord.py

Issue

i splitted some code into another file and i get "’NoneType’ object has no attribute ‘send’"
as i read , its should be a error like "the channel dont exist" "the bot dont have permission"
but tahts wrong , i can send messages just fine from the main.py in the specific channel just not from the loging.py . here my code .

#bot.py
import discord
import asyncio
from discord.ext import commands
import os
from dotenv import load_dotenv
from datetime import datetime, timedelta, date, time, timezone
import time
import loging
load_dotenv()

TOKEN = os.getenv("DISCORD_TOKEN")

bot = commands.Bot(command_prefix=commands.when_mentioned_or("$"), help_command=None)

@bot.command(name='test', help='this command will test')
async def test(ctx):
    await loging.comlog(ctx)

bot.run(TOKEN)
#loging.py
import discord
import asyncio
from discord.ext import commands
import os
from datetime import datetime, timedelta, date, time, timezone
import time

bot = commands.Bot(command_prefix=commands.when_mentioned_or("$"), help_command=None)
timestamp = datetime.now()
timenow = str(timestamp.strftime(r"%x, %X"))

async def comlog(ctx):
    channel = ctx.channel
    channelid = ctx.channel.id
    username = ctx.author
    usernameid = ctx.author.id
    logingchan = await bot.fetch_channel(983811124929630239)
    em = discord.Embed(title=f'${ctx.command}', description=f'{timenow}', color=0x00FF00)
    em.set_thumbnail(url=username.avatar_url)
    em.add_field(name="Channel:", value=f'{ctx.channel.mention} \n{channelid}', inline=True)
    em.add_field(name="User:", value=f'{username}\n{usernameid}', inline=True)
    print(f'{timenow}: $help: in "{channel}" by "{username}"')
    await logingchan.send(embed=em)
    await ctx.message.delete()

for testing i replaced the cahnnel with "ctx" and this works just fine

Ignoring exception in command test:
Traceback (most recent call last):
  File "C:\Users\Asuka\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped
    ret = await coro(*args, **kwargs)
  File "C:\Users\Asuka\Desktop\PROJECT\Discord_Bot\bot.py", line 149, in test
    await loging.comlog(ctx)
  File "C:\Users\Asuka\Desktop\PROJECT\Discord_Bot\loging.py", line 23, in comlog
    await logingchan.send(embed=em)
AttributeError: 'NoneType' object has no attribute 'send'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\Asuka\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\bot.py", line 939, in invoke
    await ctx.command.invoke(ctx)
  File "C:\Users\Asuka\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\core.py", line 863, in invoke
    await injected(*ctx.args, **ctx.kwargs)
  File "C:\Users\Asuka\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'NoneType' object has no attribute 'send'

yea i know ppl say now , the cahnnel dont exist , the bot dont have premmision . false , why can i send in the exact same channel with my main.py but not with the loging.py . also , if i dont send in a specific channel , and send the embed in channel where the command got used , and i use the channel with the id , my bot can reply in the exact same channel.

Solution

You have two separate bots in your two modules.

In the bot.py, you make a bot that you later run with the run method. This bot is fine, and it’s connected to discord and can do a bunch of things.

However, you made a second bot in logging.py. This bot isn’t actually doing anything and it was never started, so any attempts to get or fetch anything from discord will fail. What you need to do is to give the bot instance to the other module.

You can do this by either putting it into a class, or passing the bot as an argument, which I will show here:

async def comlog(bot, ctx):
    channel = ctx.channel
    channelid = ctx.channel.id
    username = ctx.author
    usernameid = ctx.author.id
    logingchan = await bot.fetch_channel(983811124929630239)
    em = discord.Embed(title=f'${ctx.command}', description=f'{timenow}', color=0x00FF00)
    em.set_thumbnail(url=username.avatar_url)
    em.add_field(name="Channel:", value=f'{ctx.channel.mention} \n{channelid}', inline=True)
    em.add_field(name="User:", value=f'{username}\n{usernameid}', inline=True)
    print(f'{timenow}: $help: in "{channel}" by "{username}"')
    await logingchan.send(embed=em)
    await ctx.message.delete()

# Then pass in the bot when you call the function
@bot.command(name='test', help='this command will test')
async def test(ctx):
    await loging.comlog(bot, ctx)

Then you can just delete your second bot definition in logging.py.


If you want permission failure messages you need to use try/except:

try:
    await logingchan.send(embed=em)
except discord.errors.Forbidden:
    # don't have permissions, do something here

Answered By – Eric Jin

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published