AttributeError: 'CogLoader' object has no attribute '_BotBase__extensions' - discord.py

As a part of learning OOP, I'm trying to create a class that will handle the loading and unloading cogs. However I'm getting the following error
Traceback (most recent call last):
File "c:\Users\mirza\Desktop\Work\Working Directory\Project\Bots\2B\bot.py", line 50, in <module>
main()
File "c:\Users\mirza\Desktop\Work\Working Directory\Project\Bots\2B\bot.py", line 43, in main
bot = CustomBotClient()
File "c:\Users\mirza\Desktop\Work\Working Directory\Project\Bots\2B\bot.py", line 21, in __init__
raise e
File "c:\Users\mirza\Desktop\Work\Working Directory\Project\Bots\2B\bot.py", line 18, in __init__
self.load_extension(f"cogs.{filename[:-3]}")
File "C:\Users\mirza\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 671, in load_extension
if name in self.__extensions:
AttributeError: 'CustomBotClient' object has no attribute '_BotBase__extensions'
This the code from bot.py that is giving me the error
import discord
from discord.ext import commands
import os
from dotenv import load_dotenv
class CogLoader(commands.Bot):
def __init__(self):
for filename in os.listdir('./cogs'):
if filename.endswith(".py"):
try:
self.load_extension(f"cogs.{filename[:-3]}")
except Exception as e:
print(f"cogs.{filename[:-3]} cannot be loaded")
raise e
#commands.command()
async def load(self, ctx, extension):
self.load_extension(f"cogs.{extension}")
#commands.command()
async def unload(self, ctx, extension):
self.unload_extension(f"cogs.{extension}")
#commands.command()
async def reload(self, ctx, extension):
self.unload_extension(f"cogs.{extension}")
self.load_extension(f"cogs.{extension}")
class CustomBotClient(CogLoader):
async def on_ready(self):
print(f"Bot {self.user} is connected to Discord and ready to roll!")
def main():
bot = CustomBotClient()
load_dotenv()
bot.run(os.getenv("TOKEN"))
if __name__ == "__main__":
main()
This is the cog that I'm trying to load
from discord.ext import commands
class Greetings(commands.Cog):
def __init__(self, bot):
self.bot = bot
#commands.command(name="GreetME")
async def greet_me(self, ctx):
await ctx.send("Hello! {author.user}")
def setup(bot):
bot.add_cog(Greetings(bot))
I'm following a youtube tutorial but he didnot used a class for this. So, I'm a loss here. Any help would be appreciated.

You need to initialize the commands.Bot in your CogLoader.__init__
This can be accomplished through the following code:
class CogLoader(commands.Bot):
def __init__(self, command_prefix, **options):
super().__init__(command_prefix, **options)
for filename in os.listdir('./cogs'):
if filename.endswith(".py"):
try:
self.load_extension(f"cogs.{filename[:-3]}")
except Exception as e:
print(f"cogs.{filename[:-3]} cannot be loaded")
raise e
and
def main():
bot = CustomBotClient(command_prefix="!")
This way, commands.Bot and BotBase, their attributes and their methods are loaded.

Related

Discord.py - AttributeError: 'NoneType' object has no attribute 'connect'

I’m trying to write a simple music bot using discord.py to play music using youtube_dl. I’m having problems with my 'join’ command. When I try to use it on discord it gives this error
Ignoring exception in command join:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "/home/runner/Discord-Bot-2/commands.py", line 44, in join
await ctx.voice_client.connect(ctx.author.voice_channel)
AttributeError: 'NoneType' object has no attribute 'connect'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 939, in invoke
await ctx.command.invoke(ctx)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 863, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "/opt/virtualenvs/python3/lib/python3.8/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 'connect'
This error happens when I’m in a voice channel. If I’m not, the bot follows the code that I wrote and sent a message in discord “You are not connected to a voice channel”. But when I am in a voice channel it gives the error.
The code for the join command is
#commands.command()
async def join(self, ctx):
if ctx.author.voice is None:
return await ctx.send("You are not connected to a voice channel")
if ctx.voice_client is not None:
await ctx.voice_client.disconnect()
await ctx.voice_client.connect(ctx.author.voice_channel)
await ctx.send(f"Connected to {ctx.author.voice_channel}")
I’m pretty sure that I set up everything correctly, but here’s all the code above the join command where I set up the cog for my commands
import discord
from discord.ext import commands
import youtube_dl
import pafy
import asyncio
class Commands(commands.Cog):
def __init__(self, client):
self.client = client
self.song_queue = {}
#commands.Cog.listener()
async def on_ready(self):
for guild in self.client.guilds:
self.song_queue[guild.id] = []
print("Cog 'commands' loaded")
async def check_queue(self, ctx):
if len(self.song_queue[ctx.guild.id]) > 0:
ctx.voice_client.stop()
await self.play_song(ctx, self.song_queue[ctx.guild.id][0])
self.song_queue[ctx.guild.id].pop(0)
async def search_song(self, amount, song, get_url=False):
info = await self.client.loop.run_in_executor(None, lambda: youtube_dl.YoutubeDL({"format": "bestaudio", "quiet" : True}).extract_info(f"ytsearch{amount}:{song}", download=False, ie_key="YoutubeSearch"))
if len(info["entries"]) == 0:
return None
return [entry["webpage_url"] for entry in info["entries"]] if get_url else info
async def play_song(self, ctx, song):
url = pafy.new(song).getbestaudio().url
ctx.voice_client.play(discord.PCMVolumeTransformer(discord.FFmpegPCMAudio(url)), after=lambda error: self.client.loop.create_task(self.check_queue(ctx)))
ctx.voice_client.source.volume = 0.5
I was using an outdated method (voice_client)
#commands.command()
async def join(self, ctx):
if ctx.author.voice is None:
return await ctx.send("You are not connected to a voice channel")
else:
channel = ctx.author.voice.channel
await channel.connect()
await ctx.send(f"Connected to voice channel: '{channel}'")

Sending a looped message in discord.py

I would like to make it so that once you do the command h!start, it sends you a message every 10 seconds and it stops when the user types h!stop. However, the discord bot never sends a message in the discord chat. I just started to learn how to make discord bots, so excuse me if this is basic. Error is under the code.
import discord
import random
from discord.ext import commands, tasks
from itertools import cycle
client = commands.Bot(command_prefix = 'h!')
#client.event
async def on_ready():
await client.change_presence(status=discord.Status.idle, activity=discord.Game('Work In Progress'))
print('Bot is ready')
#tasks.loop(seconds=10)
async def reminder():
channel = client.get_channel(797915093954199565)
await channel.send('It has been 10 seconds')
#client.command()
async def start():
reminder.start()
print('Reminder Started')
#client.command()
async def stop():
reminder.cancel()
print('Reminder stopped')
Error:
Traceback (most recent call last):
File "C:\Python39\lib\site-packages\discord\client.py", line 343, in _run_event
await coro(*args, **kwargs)
File "C:\Python39\lib\site-packages\discord\ext\commands\bot.py", line 942, in on_message
await self.process_commands(message)
File "C:\Python39\lib\site-packages\discord\ext\commands\bot.py", line 939, in process_commands
await self.invoke(ctx)
File "C:\Python39\lib\site-packages\discord\ext\commands\bot.py", line 902, in invoke
await ctx.command.invoke(ctx)
File "C:\Python39\lib\site-packages\discord\ext\commands\core.py", line 856, in invoke
await self.prepare(ctx)
File "C:\Python39\lib\site-packages\discord\ext\commands\core.py", line 790, in prepare
await self._parse_arguments(ctx)
File "C:\Python39\lib\site-packages\discord\ext\commands\core.py", line 693, in _parse_arguments
raise discord.ClientException(fmt.format(self))
discord.errors.ClientException: Callback for start command is missing "ctx" parameter.
Task exception was never retrieved
future: <Task finished name='Task-13' coro=<Loop._loop() done, defined at C:\Python39\lib\site-packages\discord\ext\tasks\__init__.py:88> exception=NameError("name 'channel' is not defined")>
Traceback (most recent call last):
File "C:\Python39\lib\site-packages\discord\ext\tasks\__init__.py", line 125, in _loop
raise exc
File "C:\Python39\lib\site-packages\discord\ext\tasks\__init__.py", line 101, in _loop
await self.coro(*args, **kwargs)
File "C:\Users\zedga\source\repos\Hydrate\Hydrate\Hydrate.py", line 16, in reminder
await channel.send('It has been 10 seconds')
NameError: name 'channel' is not defined
Unhandled exception in internal background task 'reminder'.
Traceback (most recent call last):
File "C:\Python39\lib\site-packages\discord\ext\tasks\__init__.py", line 101, in _loop
await self.coro(*args, **kwargs)
File "C:\Users\zedga\source\repos\Hydrate\Hydrate\Hydrate.py", line 16, in reminder
await channel.send('It has been 10 seconds')
NameError: name 'channel' is not defined
Yeah sure, just get the id of the channel the command was sent in and global it so it can be used in the task.
#client.command()
async def start(ctx):
global start_channel
start_channel = ctx.channel.id
reminder.start()
print('Reminder Started')
#tasks.loop(seconds=4)
async def reminder():
channel = client.get_channel(int(start_channel))
await channel.send('It has been 10 seconds')
#client.command()
async def stop(ctx):
reminder.cancel()
print('Reminder stopped')
In your error, it includes "channel not defined"
Its because it's channel is defined as a "local" variable, which means it can only be used in the same block of code or within the command. You can simply fix this by adding a global, A global makes a variable accessible throughout the whole code, it can be used like this:
global channel
channel = client.get_channel(797915093954199565)
You are also missing the "ctx" decorator and your task should be below the below the command to trigger it
#client.command()
async def start(ctx):
reminder.start()
print('Reminder Started')
#tasks.loop(seconds=10)
async def reminder():
global channel
channel = client.get_channel(797915093954199565)
await channel.send('It has been 10 seconds')
#client.command()
async def stop(ctx):
reminder.cancel()
print('Reminder stopped')

async def on_ready(): SyntaxError: invalid syntax

I was making an discord bot and im new to python and i have looked up but didn't find any answer on how to fix this but i got error from this code
Code:
import discord
from discord.ext import commands
client = command.Bot(command_prefix="<")
#client.event
async def on_ready():
print("Bot is online")
#client.command()
synd def Test(ctx):
await ctx.send("Test successful")
client.run(Token)
line with error:
#client.event
async def on_ready():
print("Bot is online")
Error:
async def on_ready():
^
SyntaxError: invalid syntax
Does anyone know how to fix this? i am using Python version: pip 19.2.3 (python 3.8)
EDITED
The print function needs to be intended another 4 spaces to be like:
async def on_ready():
print("Bot is online")
you can try use command "python3 file_name.py"

Discord.py: How do I solve "Command start is already registered" error?

#tasks.loop(minutes=1)
async def FunctionTask():
print("Task running")
#client.event
async def on_ready():
FunctionTask.start()
#client.command()
async def start(ctx):
FunctionTask.restart()
#client.command()
async def start(ctx):
FunctionTask.stop()
I'm trying to stop and restart a task, but I get errors. What I am doing wrong? Thank you in advance
edit: Added error code
Traceback (most recent call last):
File "Test.py", line 39, in <module>
async def start(ctx):
File "C:\Users\Vortex\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\ext\commands\core.py", line 1163, in decorator
self.add_command(result)
File "C:\Users\Vortex\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\ext\commands\core.py", line 1071, in add_command
raise discord.ClientException('Command {0.name} is already registered.'.format(command))
discord.errors.ClientException: Command start is already registered.
you have literally made the start command twice
async def start(ctx):
FunctionTask.restart()
#client.command()
async def start(ctx):
FunctionTask.stop()```
you might wanna change their names like:
#client.command()
async def start(ctx):
FunctionTask.restart()
#client.command()
async def starta(ctx):
FunctionTask.stop()```

Accessing variables from a discord cog

I want to know if there is away I can access any of the variables num and char from the cog file without having to import them into the main file
Thank for you the help in advance!.
Main file:
bot=commands.Bot(command_prefix='.')
#bot.event
async def on_ready():
print(bot.user.name)
The cog file:
num=123
class Commands:
def __init__(self,bot):
self.bot=bot
char='abc'
def setup(bot):
bot.add_cog(Commands(bot))

Resources