简体   繁体   中英

Discord.py - How can I make cogs per-server

I have a public bot that has cogs, but I just tested that if I load/unload a cog then it'll load/unload that cog across every server it's in, this of course is something that's horrible for a public bot

I'll show my load & unload command:

@client.command()
async def load(ctx, extension):
 client.load_extension(f"cogs.{extension}")

 await ctx.send(f"Successfully loaded the {extension} module :thumbsup: ")

@load.error
async def load_error(ctx, error):
 await ctx.send(f"The following error occured:```\n{error}\n```")

is the load command, and:

@client.command()
async def unload(ctx, extension):
 client.unload_extension(f"cogs.{extension}")

 await ctx.send(f"Successfully unloaded the {extension} module :thumbsup: ")

@unload.error
async def unload_error(ctx, error):
 await ctx.send(f"The following error occured:```\n{error}\n```")

is the unload command

Edit: I wouldn't mind trying something other than what I'm attempting

You can use a cog_check to check each command in a cog: eg

class MyCog(commands.Cog):
   def cog_check(self, ctx):
      return ctx.guild.id == 123

Since cogs are bound to the bot, loading and unloading them will effect the bot everywhere, there is no better way to make guild only cogs than using this.

A solution to this would be adding a simple check to each command in the cogs you don't want public

#add a check to the top of the cog
def isPrivateCommand():
    async def predicate(ctx):
        return ctx.guild.id == YOURGUILDIDHERE
    return commands.check(predicate)

.
.
.

@commands.command
@isPrivateCommand()
async def ...

This check should make sure that the command will only be executed in your guild (the guild ID you put in the check).

Documentation on checks can be found here for discord.py rewrite

Happy coding!

cogs belong to the bot, not to a server. So what you try to do is not possible. But (i guess you want to do something like dyno has to activate commands in a guild)

you can save all guilds that "loaded" a command in a database and then add a check to all commands if they are loaded

example_data = {
    "command_name": "example",
    "loaded_guilds": []
}


def isCommandLoaded():
    async def predicate(ctx):
        return ctx.guild.id in example_data["loaded_guilds"]:
    return commands.check(predicate)



@commands.command()
@isCommandLoaded()
async def example(self, ctx):
    """Example ..."""

than just build a load/unload command and save it to the db

at the setup from cog you could define an Guild array were to sync the tree

async def setup(bot):
     await bot.add_cog(MyCog(bot), guilds=[discord.Object(id=...)])

now u only need a function that returns all gildsid/where_cogs_synced and u will solve your problem...

in a settings.py

def GuildsAktive() -> (int, ...):
    GUILDXYZ = 12312213121213121312      # NOQA
    return [GUILDXYZ]

in your bot file

    async def test_sync_tree(self):
        guilds = []
        for gid in settings.GuildsAktive():
            x = await self.fetch_guild(gid)
            guilds.append(x)
        return guilds

in your COG

async def setup(bot):
    await bot.add_cog(YOURCOG(bot), guilds=await bot.test_sync_tree())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM