Tuesday 31 August 2021

call an async def when a cog is initialized

So what I want to do is call an async function when a cog is initialized,

I've came up with couple of ideas but none worked,
I mostly tried to call the async function with __init__ but i can't since it's considered a sync initializer.

for context this is main.py

import discord
import os
from discord.ext import commands



intents = discord.Intents.default()
intents.members = True
bot = commands.Bot(command_prefix=',', intents=intents)



for filename in os.listdir('./Cogs'):
    if filename.endswith('.py'):
        bot.load_extension(f'Cogs.{filename[:-3]}')
        print(filename)



@bot.event
async def on_ready():

    print(f'The bot has logged in as {bot.user}')
    print('''LOADING COGS:---''')



@bot.command()
async def load(ctx, extension):
    bot.load_extension(f'Cogs.{extension}')
    await ctx.send(f'loaded {extension}')

@bot.command()
async def reload(ctx, extension):
    bot.reload_extension(f'Cogs.{extension}')
    await ctx.send(f'reloaded {extension}')

@bot.command()
async def unload(ctx, extension):
    bot.unload_extension(f'Cogs.{extension}')
    await ctx.send(f'unloaded {extension}')





bot.run('TOKEN')

this is the closest I've come to a working code but it returns coroutine instead of None,
this is foo.py:

import discord
from discord.ext import commands
from main import bot


class variables(commands.Cog):

    async def _async_init_(self, bot):
        print('''async init''')
        self.bot = bot
        await variables.funcs_variables
        # return None # this does nothing as far as i understand

    __init__ = _async_init_



    global guild_id
    guild_id = # **guild's ID**



    @commands.command()
    async def funcs_variables():

        global guild
        # i want this to run once the cog is initialized
        guild = discord.utils.find(lambda g : g.id == guild_id, bot.guilds)



def setup(bot):
    bot.add_cog(variables(bot))
    

this is the error it throws:

d:\Discord bots\Discord bot - Cogs NEW\Cogs\foo.py:32: RuntimeWarning: coroutine 'variables._async_init_' was never awaited
  bot.add_cog(variables(bot))
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Traceback (most recent call last):
  File "C:\Users\Bruh\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 618, in _load_from_module_spec
    setup(self)
  File "d:\Discord bots\Discord bot - Cogs NEW\Cogs\foo.py", line 32, in setup
    bot.add_cog(variables(bot))
TypeError: __init__() should return None, not 'coroutine'

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

Traceback (most recent call last):
  File "C:\Users\Bruh\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 606, in _load_from_module_spec
    spec.loader.exec_module(lib)
  File "<frozen importlib._bootstrap_external>", line 850, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "d:\Discord bots\Discord bot - Cogs NEW\Cogs\foo.py", line 3, in <module>
    from main import bot
  File "d:\Discord bots\Discord bot - Cogs NEW\main.py", line 15, in <module>
    bot.load_extension(f'Cogs.{filename[:-3]}')
  File "C:\Users\Bruh\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 678, in load_extension    
    self._load_from_module_spec(spec, name)
  File "C:\Users\Bruh\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 623, in _load_from_module_spec
    raise errors.ExtensionFailed(key, e) from e
discord.ext.commands.errors.ExtensionFailed: Extension 'Cogs.foo' raised an error: TypeError: __init__() should return None, not 'coroutine'
During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "d:\Discord bots\Discord bot - Cogs NEW\main.py", line 15, in <module>
    bot.load_extension(f'Cogs.{filename[:-3]}')
  File "C:\Users\Bruh\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 678, in load_extension    
    self._load_from_module_spec(spec, name)
  File "C:\Users\Bruh\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 608, in _load_from_module_spec
    del sys.modules[key]
KeyError: 'Cogs.foo'

Edit1:

I've come accross this code which works nicely
But i've got another problem it's that bot comes back as a nontype

import discord
from discord.ext import commands
import inspect
# from main import bot
import asyncio

def setup(bot):
    print('''setup''')
    bot.add_cog(variables(bot))

class variables(commands.Cog):

    def __init__(self, bot):
        self.bot = bot
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        result = loop.run_until_complete(variables.funcs_variables(self))





    global guild_id
    guild_id = # guild's id

    @commands.command()
    async def funcs_variables(self):
        print('''Loading Variables''')
        #primaries
        global frame, guild
        frame = inspect.stack()[0][0]
        guild = discord.utils.find(lambda g : g.id == guild_id, self.bot.guilds)

        # commands like so will return the error: 'NoneType' object has no attribute 'attribute'
        await self.bot.change_presence(activity=discord.Streaming(name='''Author: Author''', url='https://www.youtube.com/watch?v=dQw4w9WgXcQ'))
        global special_role
        special_role = discord.utils.get(guild.roles, id='special_role id')

    @commands.command()
    async def test(self, ctx):
        await ctx.send(f'''{guild}''') #sends "None"
        print(guild)

edit2:

this is the working code:

main.py

import discord
import os
from discord.ext import commands



intents = discord.Intents.default()
intents.members = True
bot = commands.Bot(command_prefix=',', intents=intents)



async def load_cogs():

    for filename in os.listdir('./Cogs'):
        if filename.endswith('.py'):
            # await asyncio.sleep(1)
            bot.load_extension(f'Cogs.{filename[:-3]}')
            print(filename)



@bot.event
async def on_ready():

    #print in the console once it starts
    print(f'The bot has logged in as {bot.user}')
    print('''LOADING COGS:---''')

    await load_cogs()



@bot.command()
async def load(ctx, extension):
    bot.load_extension(f'Cogs.{extension}')
    await ctx.send(f'loaded {extension}')

@bot.command()
async def reload(ctx, extension):
    bot.reload_extension(f'Cogs.{extension}')
    await ctx.send(f'reloaded {extension}')

@bot.command()
async def unload(ctx, extension):
    bot.unload_extension(f'Cogs.{extension}')
    await ctx.send(f'unloaded {extension}')





bot.run('TOKEN')

and foo.py you can find it in the beautiful top answer



from call an async def when a cog is initialized

No comments:

Post a Comment