GoldyBot.objects

 1from . import command, member, role, slash, channel, currency
 2
 3Command = command.Command
 4""""""
 5Member = member.Member
 6""""""
 7Role = role.Role
 8""""""
 9InteractionToCtx = slash.InteractionToCtx
10""""""
11Channel = channel.Channel
12""""""
13Currency = currency.Currency
14""""""
15
16"""
17class GoldyBotObjectInterfaceBaseClass():
18    '''Most GoldyBot objects inherent from this class to have similar programming interface. Don't worry about this class.
19"""
class Command(GoldyBot.objects.command.Embeds):
 30class Command(Embeds):
 31    def __init__(self, func, command_object:nextcord.BaseApplicationCommand | commands.Command=None, command_name=None, 
 32        required_roles:list=[], slash_options:dict={}, help_des:str=None, hidden:bool=False, 
 33        parent_cmd:Command=None
 34    ):
 35        """Generates goldy bot command object with command function object."""
 36        self.func:function = func
 37        self.command = command_object
 38        """Nextcord command object."""
 39
 40        if command_name == None:
 41            self.command_name = self.func.__name__
 42        else:
 43            self.command_name = command_name
 44        self.required_roles_ = required_roles
 45        self.slash_options_ = slash_options
 46        self.params_ = list(self.func.__code__.co_varnames)
 47        self.params_amount_ = self.func.__code__.co_argcount
 48        self.help_des_ = help_des
 49        self.is_hidden_ = hidden
 50
 51        self.parent_cmd_ = parent_cmd
 52        
 53        self.in_extension_ = False
 54
 55        if self.params[0] == "self":
 56            self.in_extension_ = True
 57            self.params_.pop(0)
 58
 59        # Add command to extension in cache.
 60        if self.in_extension:
 61            if self.module.is_internal_module:
 62                GoldyBot.cache.main_cache_dict["internal_modules"][f"{self.module_name}"]["extensions"][f"{self.extension_name}"]["commands"].append(self)
 63            else:
 64                GoldyBot.cache.main_cache_dict["modules"][f"{self.module_name}"]["extensions"][f"{self.extension_name}"]["commands"].append(self)
 65        else:
 66            GoldyBot.cache.main_cache_dict["internal_modules"]["goldy"]["extensions"]["core"]["commands"].append(self)
 67
 68        super().__init__()
 69
 70    @property
 71    def code_name(self) -> str:
 72        """Returns code name of command."""
 73        return self.command_name
 74
 75    @property
 76    def params(self) -> list:
 77        """Returns list of function parameters."""
 78        if self.in_extension:
 79            return self.params_[0:self.params_amount_ - 1]
 80        else:
 81            return self.params_[0:self.params_amount_]
 82
 83    @property
 84    def extension_name(self) -> str | None:
 85        """Returns extension's code name."""
 86        if self.in_extension:
 87            # Command is in extension.
 88            return str(self.func).split(" ")[1].split(".")[0]
 89        else:
 90            # Command is not in any extension.
 91            return None
 92
 93    @property
 94    def extension(self) -> GoldyBot.ext.extensions.Extension | None:
 95        """Finds and returns the object of the command's extension."""
 96        if self.in_extension:
 97            return GoldyBot.cache.FindExtensions().find_object_by_extension_name(extension_name=self.extension_name)
 98        else:
 99            None
100
101    @property
102    def in_extension(self) -> bool:
103        """Returns true/false if the command is in a extension."""
104        if self.in_extension_:
105            return True
106        else:
107            return False
108
109    @property
110    def module_name(self) -> str:
111        """Returns name of module the command is located in."""
112        return self.extension.module_name
113
114    @property
115    def module(self) -> GoldyBot.modules.Module:
116        return GoldyBot.cache.FindModules().find_object_by_module_name(module_name=self.module_name)
117
118    @property
119    def is_hidden(self):
120        """Is the command hidden."""
121        return self.is_hidden_
122
123    @property
124    def parent_cmd(self) -> Command|None:
125        """Returns the command object of the parent command if command has parent."""
126        return self.parent_cmd_
127
128    @property
129    def is_child(self):
130        """Returns if command is child or not."""
131        if self.parent_cmd == None:
132            return False
133        else:
134            return True
135
136    def mention(self) -> str:
137        """Returns mention of slash command, if registered as a slash command."""
138        #TODO: Perhaps have this return codeblock if this command is not a slash command.
139        try:
140            if self.is_child == False:
141                return f"</{self.code_name}:{self.command.command_ids[0]}>"
142            else:
143                return f"</{self.parent_cmd.code_name} {self.code_name}:{self.command.command_ids[0]}>"
144        except (TypeError, AttributeError):
145            GoldyBot.log("warn", f"[{MODULE_NAME}] Tried to mention slash command '{self.code_name}' but could not find it's command id so I'm returning the mention without it.")
146            
147            if self.is_child == False: return f"</{self.code_name}:0>"
148            else: return f"</{self.parent_cmd.code_name} {self.code_name}:0>"
149
150    def create_slash(self) -> nextcord.BaseApplicationCommand:
151        """Creates slash command."""
152
153        GoldyBot.logging.log(f"[{MODULE_NAME}] [{self.command_name.upper()}] Creating slash command...")
154        slash_command_params = self.slash_commands_params_generator()
155
156        return_data = {}
157
158        #  Make slash command only visible to admins if it is hidden.
159        default_member_permissions = None
160        if self.is_hidden: default_member_permissions = nextcord.Permissions(permissions=8)
161        
162
163        if self.in_extension == True: # Run in EXTENSION!
164            exec(f"""
165@client.slash_command(name=command_name, description=help_des, guild_ids=guilds_allowed_in, default_member_permissions=default_member_permissions)
166async def slash_command_(interaction: Interaction{slash_command_params[0]}):
167    ctx = GoldyBot.objects.slash.InteractionToCtx(interaction)
168    try:
169        if self.allowed_to_run(ctx):
170            await func(class_, ctx{slash_command_params[1]})
171            GoldyBot.logging.log(f"[{MODULE_NAME}] The slash command '{self.code_name}' was executed.")
172
173    except GoldyBot.errors.MemberHasNoPermsForCommand:
174        if hidden == False:
175            no_perms_embed.description = GoldyBot.utility.msgs.bot.CommandNoPerms.Embed.des.format(ctx.author.mention)
176            message = await ctx.send(embed=no_perms_embed)
177            await asyncio.sleep(6)
178            await message.delete()
179
180    except GoldyBot.errors.GuildNotRegistered:
181        if hidden == False:
182            guild_not_registered_embed.description = GoldyBot.utility.msgs.bot.CommandGuildNotRegistered.Embed.des.format(ctx.author.mention)
183            message = await ctx.send(embed=guild_not_registered_embed)
184            await asyncio.sleep(15)
185            message.delete()
186
187    except Exception as e:
188        GoldyBot.logging.log("error", e)
189            """, 
190            
191            {"func":self.func, "client":GoldyBot.cache.main_cache_dict["client"], "command_name":self.command_name, "help_des":self.get_help_des(), "self":self,
192            "Interaction": GoldyBot.nextcord.Interaction, "GoldyBot": GoldyBot, "asyncio":asyncio, "nextcord":nextcord, "class_":self.extension, "no_perms_embed":self.no_perms_embed, 
193            "guild_not_registered_embed":self.guild_not_registered_embed, "hidden":self.is_hidden, "guilds_allowed_in":self.guilds_allowed_in, 
194            "default_member_permissions":default_member_permissions}, return_data)
195            
196        else: # Run as NORMAL command!
197            exec(f"""
198@client.slash_command(name=command_name, description=help_des, guild_ids=guilds_allowed_in, default_member_permissions=default_member_permissions)
199async def slash_command_(interaction: Interaction{slash_command_params[0]}):
200    ctx = GoldyBot.objects.slash.InteractionToCtx(interaction)
201    try:
202        if self.allowed_to_run(ctx):
203            await func(ctx{slash_command_params[1]})
204            GoldyBot.logging.log(f"[{MODULE_NAME}] The slash command '{self.code_name}' was executed.")
205
206    except GoldyBot.errors.MemberHasNoPermsForCommand:
207        if hidden == False:
208            no_perms_embed.description = GoldyBot.utility.msgs.bot.CommandNoPerms.Embed.des.format(ctx.author.mention)
209            message = await ctx.send(embed=no_perms_embed)
210            await asyncio.sleep(15)
211            await message.delete()
212
213    except GoldyBot.errors.GuildNotRegistered:
214        if hidden == False:
215            guild_not_registered_embed.description = GoldyBot.utility.msgs.bot.CommandGuildNotRegistered.Embed.des.format(ctx.author.mention)
216            message = await ctx.send(embed=guild_not_registered_embed)
217            await asyncio.sleep(15)
218            await message.delete()
219
220    except Exception as e:
221        GoldyBot.logging.log("error", e)
222            """, 
223            
224            {"func":self.func, "client":GoldyBot.cache.main_cache_dict["client"], "command_name":self.command_name, "help_des":self.get_help_des(), "self":self,
225            "Interaction": GoldyBot.nextcord.Interaction, "GoldyBot": GoldyBot, "asyncio":asyncio, "nextcord":nextcord, "no_perms_embed":self.no_perms_embed, 
226            "guild_not_registered_embed":self.guild_not_registered_embed, "hidden":self.is_hidden, "guilds_allowed_in":self.guilds_allowed_in, 
227            "default_member_permissions":default_member_permissions}, return_data)
228
229        GoldyBot.logging.log(f"[{MODULE_NAME}] [{self.command_name.upper()}] Slash command created!")
230
231        self.command = return_data["slash_command_"]
232        return return_data["slash_command_"]
233
234    def remove(self):
235        """Removes command from nextcord."""
236        command_application_object = self.command
237
238        # Remove command from extension in cache.
239        if self.in_extension:
240            if self.module.is_internal_module:
241                GoldyBot.cache.main_cache_dict["internal_modules"][f"{self.module_name}"]["extensions"][f"{self.extension_name}"]["commands"].remove(self)
242            else:
243                GoldyBot.cache.main_cache_dict["modules"][f"{self.module_name}"]["extensions"][f"{self.extension_name}"]["commands"].remove(self)
244        else:
245            GoldyBot.cache.main_cache_dict["internal_modules"]["goldy"]["extensions"]["core"]["commands"].remove(self)
246
247        # Remove from nextcord.
248        client = GoldyBot.cache.client()
249        client.remove_command(name=self.code_name)
250
251        for guild_id in self.guilds_allowed_in:
252            print(command_application_object.command_ids) #TODO: Problem here!
253            GoldyBot.async_loop.run_until_complete(client.delete_application_commands(command_application_object, guild_id=guild_id))
254            
255            GoldyBot.cache.main_cache_dict["client"] = client
256
257        GoldyBot.logging.log("info_5", f"[{MODULE_NAME}] Removed the command '{self.code_name}'!")
258        return True
259
260    def any_args_missing(self, command_executers_args:tuple) -> bool:
261        """Checks if the args given by the command executer matches what parameters the command needs."""
262        if len(command_executers_args) == len(self.params[1:]):
263            return True
264        else:
265            return False
266
267    def slash_commands_params_generator(self):
268        """Generates a string of params for slash commands. This is more of an in-house thing."""
269        params_amount = len(self.params[1:])
270        slash_command_params = ""
271        slash_command_args = ""
272
273        if params_amount >= 1:
274            slash_command_params = ", "
275            slash_command_args = ", "
276            count = 0
277            for param in self.params[1:]:
278                count += 1
279
280                try:
281                    # String
282                    if isinstance(self.slash_options_[param.lower()], str):
283                        default_value = f"='{self.slash_options_[param.lower()]}'"
284
285                    # Slash Option
286                    if isinstance(self.slash_options_[param.lower()], nextcord.SlashOption):
287                        slash_option:nextcord.SlashOption = self.slash_options_[param.lower()]
288
289                        if isinstance(slash_option.name, str):
290                            name = f"'{slash_option.name}'"
291                        else:
292                            name = None
293
294                        if isinstance(slash_option.description, str):
295                            description = f"'{slash_option.description}'"
296                        else:
297                            description = None
298
299                        if isinstance(slash_option.required, nextcord.utils._MissingSentinel):
300                            required = None
301                        else:
302                            required = slash_option.required
303
304                        if isinstance(slash_option.choices, nextcord.utils._MissingSentinel):
305                            choices = None
306                        else:
307                            choices = slash_option.choices
308
309                        """
310                        if isinstance(slash_option.min_value, nextcord.utils._MissingSentinel):
311                            min_value = None
312                        else:
313                            min_value = slash_option.min_value
314                            
315                        if isinstance(slash_option.max_value, nextcord.utils._MissingSentinel):
316                            max_value = None
317                        else:
318                            max_value = slash_option.max_value
319                        """
320
321                        if isinstance(slash_option.autocomplete, nextcord.utils._MissingSentinel):
322                            autocomplete = None
323                        else:
324                            autocomplete = slash_option.autocomplete
325
326                        if isinstance(slash_option.default, str):
327                            default = f"'{slash_option.default}'"
328                        else:
329                            default = None
330                        
331                        default_value = f"""=nextcord.SlashOption(name={name}, description={description}, required={required}, 
332                        choices={choices}, autocomplete={autocomplete}, default={default}, verify={slash_option._verify})"""
333                    
334                    else:
335                        default_value = f"={self.slash_options_[param.lower()]}"
336
337                except KeyError:
338                    default_value = ""
339
340                if count >= params_amount:
341                    slash_command_params += f"{param}{default_value}"
342                    slash_command_args += f"{param}"
343                else:
344                    slash_command_params += f"{param}{default_value}, "
345                    slash_command_args += f"{param}, "
346
347        return (slash_command_params, slash_command_args)
348
349    def update_command_object(self, command_object:commands.Command):
350        """Adds/updates this command object to the class."""
351        self.command = command_object
352
353    def sub_command(self, command_name:str=None, required_roles:list=[], help_des:str=None, slash_options:Dict[str, nextcord.SlashOption]={}, also_run_parent_CMD:bool=True):
354        """Create a lovely sub command from this slash command. 😀 (Only works with slash commands.)"""
355
356        def decorate(func):
357            def inner(func, command_name, required_roles, help_des, slash_options):
358                parent_command = self.command
359
360                return_data = {}
361
362                goldy_sub_command = Command(func, command_name=command_name, required_roles=required_roles, slash_options=slash_options, help_des=help_des, parent_cmd=self)
363                slash_command_params = goldy_sub_command.slash_commands_params_generator()
364                parent_slash_command_params = self.slash_commands_params_generator()
365
366                if self.in_extension == True: # Run in EXTENSION!
367                    exec(f"""
368@parent_command.subcommand(name=command_name, description=help_des)
369async def slash_command_(interaction: Interaction{slash_command_params[0]}):
370    ctx = GoldyBot.objects.slash.InteractionToCtx(interaction)
371    try:
372        if self.allowed_to_run(ctx):
373            continue_onto_subcommand = None
374            if also_run_parent_CMD == True: continue_onto_subcommand = await goldy_parent_command.func(class_, ctx{parent_slash_command_params[1]})
375            if not continue_onto_subcommand == False:
376                await func(class_, ctx{slash_command_params[1]})
377                GoldyBot.logging.log(f"[{MODULE_NAME}] The slash subcommand '{goldy_sub_command.code_name}' was executed.")
378            else:
379                GoldyBot.logging.log(f"[{MODULE_NAME}] The slash subcommand '{goldy_sub_command.code_name}' never executed because parent command returned 'False'.")
380
381    except GoldyBot.errors.MemberHasNoPermsForCommand:
382        if hidden == False:
383            no_perms_embed.description = GoldyBot.utility.msgs.bot.CommandNoPerms.Embed.des.format(ctx.author.mention)
384            message = await ctx.send(embed=no_perms_embed)
385            await asyncio.sleep(6)
386            await message.delete()
387
388    except GoldyBot.errors.GuildNotRegistered:
389        if hidden == False:
390            guild_not_registered_embed.description = GoldyBot.utility.msgs.bot.CommandGuildNotRegistered.Embed.des.format(ctx.author.mention)
391            message = await ctx.send(embed=guild_not_registered_embed)
392            await asyncio.sleep(15)
393            message.delete()
394
395    except Exception as e:
396        GoldyBot.logging.log("error", e)
397                    """, 
398                                                                        # Lambda expression: Returns nc_co
399                    {"func":goldy_sub_command.func, "parent_command": parent_command, "command_name":goldy_sub_command.command_name, "help_des":goldy_sub_command.get_help_des(), 
400                    "self":goldy_sub_command, "Interaction": GoldyBot.nextcord.Interaction, "GoldyBot": GoldyBot, "asyncio":asyncio, "nextcord":nextcord, 
401                    "class_":goldy_sub_command.extension, "no_perms_embed":self.no_perms_embed, "guild_not_registered_embed":self.guild_not_registered_embed, 
402                    "hidden":goldy_sub_command.is_hidden, "also_run_parent_CMD":also_run_parent_CMD, "goldy_parent_command": self}, return_data)
403                    
404                else: # Run as NORMAL command!
405                    exec(f"""
406@parent_command.subcommand(name=command_name, description=help_des)
407async def slash_command_(interaction: Interaction{slash_command_params[0]}):
408    ctx = GoldyBot.objects.slash.InteractionToCtx(interaction)
409    try:
410        if self.allowed_to_run(ctx):
411            if also_run_parent_CMD == True: await goldy_parent_command.func(ctx{parent_slash_command_params[1]})
412            await func(ctx{slash_command_params[1]})
413            GoldyBot.logging.log(f"[{MODULE_NAME}] The slash command '{goldy_sub_command.code_name}' was executed.")
414
415    except GoldyBot.errors.MemberHasNoPermsForCommand:
416        if hidden == False:
417            no_perms_embed.description = GoldyBot.utility.msgs.bot.CommandNoPerms.Embed.des.format(ctx.author.mention)
418            message = await ctx.send(embed=no_perms_embed)
419            await asyncio.sleep(15)
420            await message.delete()
421
422    except GoldyBot.errors.GuildNotRegistered:
423        if hidden == False:
424            guild_not_registered_embed.description = GoldyBot.utility.msgs.bot.CommandGuildNotRegistered.Embed.des.format(ctx.author.mention)
425            message = await ctx.send(embed=guild_not_registered_embed)
426            await asyncio.sleep(15)
427            await message.delete()
428
429    except Exception as e:
430        GoldyBot.logging.log("error", e)
431                    """, 
432                    
433                    {"func":goldy_sub_command.func, "parent_command": parent_command, "command_name":goldy_sub_command.command_name, "help_des":goldy_sub_command.get_help_des(), 
434                    "self":goldy_sub_command, "Interaction": GoldyBot.nextcord.Interaction, "GoldyBot": GoldyBot, "asyncio":asyncio, "nextcord":nextcord, 
435                    "no_perms_embed":self.no_perms_embed, "guild_not_registered_embed":self.guild_not_registered_embed, "hidden":goldy_sub_command.is_hidden, 
436                    "also_run_parent_CMD":also_run_parent_CMD, "goldy_parent_command": self}, return_data)
437
438                goldy_sub_command.update_command_object(return_data["slash_command_"])
439
440                GoldyBot.logging.log("info_5", f"[{MODULE_NAME}] Sub Command '{goldy_sub_command.command_name}' of '{parent_command.name}' has been loaded.")
441                return goldy_sub_command
442
443            return inner(func, command_name, required_roles, help_des, slash_options)
444
445        return decorate
446
447    def allowed_to_run(self, ctx):
448        """Checks if the command is allowed to run with current circumstances."""
449        goldy_config = GoldyBot.config.Config(GoldyBot.files.File(GoldyBot.paths.GOLDY_CONFIG_JSON))
450        
451        # Check if guild is registered.
452        #--------------------------------
453        if str(ctx.guild.id) in goldy_config.read("allowed_guilds"):
454            guild_code_name = GoldyBot.cache.FindGuilds(goldy_config).find_object_by_id(ctx.guild.id).code_name
455            guild_config = GoldyBot.utility.guilds.config.GuildConfig(GoldyBot.config.Config(GoldyBot.files.File(GoldyBot.paths.CONFIG + f"/{guild_code_name}/config.json")))
456            
457            if guild_config.is_extension_allowed(self.extension_name):
458
459                if not self.required_roles_ == []:
460                    # If the required roles contain 'bot_dev' and the bot dev is running the command allow the command to execute.
461                    #----------------------------------------------------------------------------------------------------------------
462                    if "bot_dev" in self.required_roles_:
463                        if str(ctx.author.id) in GoldyBot.settings.BOT_DEVS:
464                            return True
465
466                    # If the required roles contain 'bot_admin' and a bot admin is running the command allow the command to execute. (NEW)
467                    #----------------------------------------------------------------------------------------------------------------
468                    if "bot_admin" in self.required_roles_:
469                        if str(ctx.author.id) in goldy_config.read("admin_users"):
470                            return True
471
472                    # Check if member has any of the required roles.
473                    #----------------------------------------------------
474                    for role_code_name in self.required_roles_:
475                        if not role_code_name in ["bot_dev", "bot_admin"]:
476                            role = guild_config.get_role(ctx, role_code_name)
477                            if GoldyBot.objects.member.Member(ctx).has_role(role):
478                                return True
479
480                    raise GoldyBot.errors.MemberHasNoPermsForCommand(f"The member '{ctx.author.name}' does not have the right permissions to use this command.")
481
482                else:
483                    return True
484                
485        else:
486            raise GoldyBot.errors.GuildNotRegistered(f"The guild '{ctx.guild.name}' has not been registered.")
487
488    @property
489    def guilds_allowed_in(self) -> List[int]:
490        """Returns the ids of the guilds this command is allowed to function in."""
491        goldy_config = GoldyBot.config.Config(GoldyBot.files.File(GoldyBot.paths.GOLDY_CONFIG_JSON))
492        allowed_guilds = goldy_config.read("allowed_guilds")
493
494        guilds_command_is_allowed_in:List[int] = []
495
496        for guild_id in allowed_guilds:
497            try:
498                guild_config = GoldyBot.utility.guilds.config.GuildConfig(GoldyBot.config.Config(GoldyBot.files.File(GoldyBot.paths.CONFIG + f"/{allowed_guilds[guild_id]}/config.json")))
499                
500                if guild_config.is_extension_allowed(self.extension_name):
501                    guilds_command_is_allowed_in.append(int(guild_id))
502            except FileNotFoundError:
503                pass
504            
505        if guilds_command_is_allowed_in == []: guilds_command_is_allowed_in = [123]
506
507        print(guilds_command_is_allowed_in)
508
509        return guilds_command_is_allowed_in
510
511    def get_help_des(self) -> str:
512        """Returns the command's help description."""
513        if self.help_des_ == None:
514            try:
515                return (importlib.import_module(f'.{self.command_name}', package="GoldyBot.utility.msgs")).help_des
516
517            except ImportError:
518                GoldyBot.logging.log("info", f"[{MODULE_NAME}] The command '{self.command_name}' does not have a 'msg' module, so the help command will not display a help description for it.")
519                return "None"
520
521            except AttributeError:
522                GoldyBot.logging.log("info", f"[{MODULE_NAME}] The command '{self.command_name}' does not contain 'help_des' variable in it's 'msg' module, so the help command will not display a help description.")
523                return "None"
524        else:
525            return self.help_des_
Command( func, command_object: nextcord.application_command.BaseApplicationCommand | nextcord.ext.commands.core.Command = None, command_name=None, required_roles: list = [], slash_options: dict = {}, help_des: str = None, hidden: bool = False, parent_cmd: GoldyBot.objects.Command = None)
31    def __init__(self, func, command_object:nextcord.BaseApplicationCommand | commands.Command=None, command_name=None, 
32        required_roles:list=[], slash_options:dict={}, help_des:str=None, hidden:bool=False, 
33        parent_cmd:Command=None
34    ):
35        """Generates goldy bot command object with command function object."""
36        self.func:function = func
37        self.command = command_object
38        """Nextcord command object."""
39
40        if command_name == None:
41            self.command_name = self.func.__name__
42        else:
43            self.command_name = command_name
44        self.required_roles_ = required_roles
45        self.slash_options_ = slash_options
46        self.params_ = list(self.func.__code__.co_varnames)
47        self.params_amount_ = self.func.__code__.co_argcount
48        self.help_des_ = help_des
49        self.is_hidden_ = hidden
50
51        self.parent_cmd_ = parent_cmd
52        
53        self.in_extension_ = False
54
55        if self.params[0] == "self":
56            self.in_extension_ = True
57            self.params_.pop(0)
58
59        # Add command to extension in cache.
60        if self.in_extension:
61            if self.module.is_internal_module:
62                GoldyBot.cache.main_cache_dict["internal_modules"][f"{self.module_name}"]["extensions"][f"{self.extension_name}"]["commands"].append(self)
63            else:
64                GoldyBot.cache.main_cache_dict["modules"][f"{self.module_name}"]["extensions"][f"{self.extension_name}"]["commands"].append(self)
65        else:
66            GoldyBot.cache.main_cache_dict["internal_modules"]["goldy"]["extensions"]["core"]["commands"].append(self)
67
68        super().__init__()

Generates goldy bot command object with command function object.

command

Nextcord command object.

code_name: str

Returns code name of command.

params: list

Returns list of function parameters.

extension_name: str | None

Returns extension's code name.

Finds and returns the object of the command's extension.

in_extension: bool

Returns true/false if the command is in a extension.

module_name: str

Returns name of module the command is located in.

is_hidden

Is the command hidden.

parent_cmd: GoldyBot.objects.Command | None

Returns the command object of the parent command if command has parent.

is_child

Returns if command is child or not.

def mention(self) -> str:
136    def mention(self) -> str:
137        """Returns mention of slash command, if registered as a slash command."""
138        #TODO: Perhaps have this return codeblock if this command is not a slash command.
139        try:
140            if self.is_child == False:
141                return f"</{self.code_name}:{self.command.command_ids[0]}>"
142            else:
143                return f"</{self.parent_cmd.code_name} {self.code_name}:{self.command.command_ids[0]}>"
144        except (TypeError, AttributeError):
145            GoldyBot.log("warn", f"[{MODULE_NAME}] Tried to mention slash command '{self.code_name}' but could not find it's command id so I'm returning the mention without it.")
146            
147            if self.is_child == False: return f"</{self.code_name}:0>"
148            else: return f"</{self.parent_cmd.code_name} {self.code_name}:0>"

Returns mention of slash command, if registered as a slash command.

def create_slash(self) -> nextcord.application_command.BaseApplicationCommand:
150    def create_slash(self) -> nextcord.BaseApplicationCommand:
151        """Creates slash command."""
152
153        GoldyBot.logging.log(f"[{MODULE_NAME}] [{self.command_name.upper()}] Creating slash command...")
154        slash_command_params = self.slash_commands_params_generator()
155
156        return_data = {}
157
158        #  Make slash command only visible to admins if it is hidden.
159        default_member_permissions = None
160        if self.is_hidden: default_member_permissions = nextcord.Permissions(permissions=8)
161        
162
163        if self.in_extension == True: # Run in EXTENSION!
164            exec(f"""
165@client.slash_command(name=command_name, description=help_des, guild_ids=guilds_allowed_in, default_member_permissions=default_member_permissions)
166async def slash_command_(interaction: Interaction{slash_command_params[0]}):
167    ctx = GoldyBot.objects.slash.InteractionToCtx(interaction)
168    try:
169        if self.allowed_to_run(ctx):
170            await func(class_, ctx{slash_command_params[1]})
171            GoldyBot.logging.log(f"[{MODULE_NAME}] The slash command '{self.code_name}' was executed.")
172
173    except GoldyBot.errors.MemberHasNoPermsForCommand:
174        if hidden == False:
175            no_perms_embed.description = GoldyBot.utility.msgs.bot.CommandNoPerms.Embed.des.format(ctx.author.mention)
176            message = await ctx.send(embed=no_perms_embed)
177            await asyncio.sleep(6)
178            await message.delete()
179
180    except GoldyBot.errors.GuildNotRegistered:
181        if hidden == False:
182            guild_not_registered_embed.description = GoldyBot.utility.msgs.bot.CommandGuildNotRegistered.Embed.des.format(ctx.author.mention)
183            message = await ctx.send(embed=guild_not_registered_embed)
184            await asyncio.sleep(15)
185            message.delete()
186
187    except Exception as e:
188        GoldyBot.logging.log("error", e)
189            """, 
190            
191            {"func":self.func, "client":GoldyBot.cache.main_cache_dict["client"], "command_name":self.command_name, "help_des":self.get_help_des(), "self":self,
192            "Interaction": GoldyBot.nextcord.Interaction, "GoldyBot": GoldyBot, "asyncio":asyncio, "nextcord":nextcord, "class_":self.extension, "no_perms_embed":self.no_perms_embed, 
193            "guild_not_registered_embed":self.guild_not_registered_embed, "hidden":self.is_hidden, "guilds_allowed_in":self.guilds_allowed_in, 
194            "default_member_permissions":default_member_permissions}, return_data)
195            
196        else: # Run as NORMAL command!
197            exec(f"""
198@client.slash_command(name=command_name, description=help_des, guild_ids=guilds_allowed_in, default_member_permissions=default_member_permissions)
199async def slash_command_(interaction: Interaction{slash_command_params[0]}):
200    ctx = GoldyBot.objects.slash.InteractionToCtx(interaction)
201    try:
202        if self.allowed_to_run(ctx):
203            await func(ctx{slash_command_params[1]})
204            GoldyBot.logging.log(f"[{MODULE_NAME}] The slash command '{self.code_name}' was executed.")
205
206    except GoldyBot.errors.MemberHasNoPermsForCommand:
207        if hidden == False:
208            no_perms_embed.description = GoldyBot.utility.msgs.bot.CommandNoPerms.Embed.des.format(ctx.author.mention)
209            message = await ctx.send(embed=no_perms_embed)
210            await asyncio.sleep(15)
211            await message.delete()
212
213    except GoldyBot.errors.GuildNotRegistered:
214        if hidden == False:
215            guild_not_registered_embed.description = GoldyBot.utility.msgs.bot.CommandGuildNotRegistered.Embed.des.format(ctx.author.mention)
216            message = await ctx.send(embed=guild_not_registered_embed)
217            await asyncio.sleep(15)
218            await message.delete()
219
220    except Exception as e:
221        GoldyBot.logging.log("error", e)
222            """, 
223            
224            {"func":self.func, "client":GoldyBot.cache.main_cache_dict["client"], "command_name":self.command_name, "help_des":self.get_help_des(), "self":self,
225            "Interaction": GoldyBot.nextcord.Interaction, "GoldyBot": GoldyBot, "asyncio":asyncio, "nextcord":nextcord, "no_perms_embed":self.no_perms_embed, 
226            "guild_not_registered_embed":self.guild_not_registered_embed, "hidden":self.is_hidden, "guilds_allowed_in":self.guilds_allowed_in, 
227            "default_member_permissions":default_member_permissions}, return_data)
228
229        GoldyBot.logging.log(f"[{MODULE_NAME}] [{self.command_name.upper()}] Slash command created!")
230
231        self.command = return_data["slash_command_"]
232        return return_data["slash_command_"]

Creates slash command.

def remove(self):
234    def remove(self):
235        """Removes command from nextcord."""
236        command_application_object = self.command
237
238        # Remove command from extension in cache.
239        if self.in_extension:
240            if self.module.is_internal_module:
241                GoldyBot.cache.main_cache_dict["internal_modules"][f"{self.module_name}"]["extensions"][f"{self.extension_name}"]["commands"].remove(self)
242            else:
243                GoldyBot.cache.main_cache_dict["modules"][f"{self.module_name}"]["extensions"][f"{self.extension_name}"]["commands"].remove(self)
244        else:
245            GoldyBot.cache.main_cache_dict["internal_modules"]["goldy"]["extensions"]["core"]["commands"].remove(self)
246
247        # Remove from nextcord.
248        client = GoldyBot.cache.client()
249        client.remove_command(name=self.code_name)
250
251        for guild_id in self.guilds_allowed_in:
252            print(command_application_object.command_ids) #TODO: Problem here!
253            GoldyBot.async_loop.run_until_complete(client.delete_application_commands(command_application_object, guild_id=guild_id))
254            
255            GoldyBot.cache.main_cache_dict["client"] = client
256
257        GoldyBot.logging.log("info_5", f"[{MODULE_NAME}] Removed the command '{self.code_name}'!")
258        return True

Removes command from nextcord.

def any_args_missing(self, command_executers_args: tuple) -> bool:
260    def any_args_missing(self, command_executers_args:tuple) -> bool:
261        """Checks if the args given by the command executer matches what parameters the command needs."""
262        if len(command_executers_args) == len(self.params[1:]):
263            return True
264        else:
265            return False

Checks if the args given by the command executer matches what parameters the command needs.

def slash_commands_params_generator(self):
267    def slash_commands_params_generator(self):
268        """Generates a string of params for slash commands. This is more of an in-house thing."""
269        params_amount = len(self.params[1:])
270        slash_command_params = ""
271        slash_command_args = ""
272
273        if params_amount >= 1:
274            slash_command_params = ", "
275            slash_command_args = ", "
276            count = 0
277            for param in self.params[1:]:
278                count += 1
279
280                try:
281                    # String
282                    if isinstance(self.slash_options_[param.lower()], str):
283                        default_value = f"='{self.slash_options_[param.lower()]}'"
284
285                    # Slash Option
286                    if isinstance(self.slash_options_[param.lower()], nextcord.SlashOption):
287                        slash_option:nextcord.SlashOption = self.slash_options_[param.lower()]
288
289                        if isinstance(slash_option.name, str):
290                            name = f"'{slash_option.name}'"
291                        else:
292                            name = None
293
294                        if isinstance(slash_option.description, str):
295                            description = f"'{slash_option.description}'"
296                        else:
297                            description = None
298
299                        if isinstance(slash_option.required, nextcord.utils._MissingSentinel):
300                            required = None
301                        else:
302                            required = slash_option.required
303
304                        if isinstance(slash_option.choices, nextcord.utils._MissingSentinel):
305                            choices = None
306                        else:
307                            choices = slash_option.choices
308
309                        """
310                        if isinstance(slash_option.min_value, nextcord.utils._MissingSentinel):
311                            min_value = None
312                        else:
313                            min_value = slash_option.min_value
314                            
315                        if isinstance(slash_option.max_value, nextcord.utils._MissingSentinel):
316                            max_value = None
317                        else:
318                            max_value = slash_option.max_value
319                        """
320
321                        if isinstance(slash_option.autocomplete, nextcord.utils._MissingSentinel):
322                            autocomplete = None
323                        else:
324                            autocomplete = slash_option.autocomplete
325
326                        if isinstance(slash_option.default, str):
327                            default = f"'{slash_option.default}'"
328                        else:
329                            default = None
330                        
331                        default_value = f"""=nextcord.SlashOption(name={name}, description={description}, required={required}, 
332                        choices={choices}, autocomplete={autocomplete}, default={default}, verify={slash_option._verify})"""
333                    
334                    else:
335                        default_value = f"={self.slash_options_[param.lower()]}"
336
337                except KeyError:
338                    default_value = ""
339
340                if count >= params_amount:
341                    slash_command_params += f"{param}{default_value}"
342                    slash_command_args += f"{param}"
343                else:
344                    slash_command_params += f"{param}{default_value}, "
345                    slash_command_args += f"{param}, "
346
347        return (slash_command_params, slash_command_args)

Generates a string of params for slash commands. This is more of an in-house thing.

def update_command_object(self, command_object: nextcord.ext.commands.core.Command):
349    def update_command_object(self, command_object:commands.Command):
350        """Adds/updates this command object to the class."""
351        self.command = command_object

Adds/updates this command object to the class.

def sub_command( self, command_name: str = None, required_roles: list = [], help_des: str = None, slash_options: Dict[str, nextcord.application_command.SlashOption] = {}, also_run_parent_CMD: bool = True):
353    def sub_command(self, command_name:str=None, required_roles:list=[], help_des:str=None, slash_options:Dict[str, nextcord.SlashOption]={}, also_run_parent_CMD:bool=True):
354        """Create a lovely sub command from this slash command. 😀 (Only works with slash commands.)"""
355
356        def decorate(func):
357            def inner(func, command_name, required_roles, help_des, slash_options):
358                parent_command = self.command
359
360                return_data = {}
361
362                goldy_sub_command = Command(func, command_name=command_name, required_roles=required_roles, slash_options=slash_options, help_des=help_des, parent_cmd=self)
363                slash_command_params = goldy_sub_command.slash_commands_params_generator()
364                parent_slash_command_params = self.slash_commands_params_generator()
365
366                if self.in_extension == True: # Run in EXTENSION!
367                    exec(f"""
368@parent_command.subcommand(name=command_name, description=help_des)
369async def slash_command_(interaction: Interaction{slash_command_params[0]}):
370    ctx = GoldyBot.objects.slash.InteractionToCtx(interaction)
371    try:
372        if self.allowed_to_run(ctx):
373            continue_onto_subcommand = None
374            if also_run_parent_CMD == True: continue_onto_subcommand = await goldy_parent_command.func(class_, ctx{parent_slash_command_params[1]})
375            if not continue_onto_subcommand == False:
376                await func(class_, ctx{slash_command_params[1]})
377                GoldyBot.logging.log(f"[{MODULE_NAME}] The slash subcommand '{goldy_sub_command.code_name}' was executed.")
378            else:
379                GoldyBot.logging.log(f"[{MODULE_NAME}] The slash subcommand '{goldy_sub_command.code_name}' never executed because parent command returned 'False'.")
380
381    except GoldyBot.errors.MemberHasNoPermsForCommand:
382        if hidden == False:
383            no_perms_embed.description = GoldyBot.utility.msgs.bot.CommandNoPerms.Embed.des.format(ctx.author.mention)
384            message = await ctx.send(embed=no_perms_embed)
385            await asyncio.sleep(6)
386            await message.delete()
387
388    except GoldyBot.errors.GuildNotRegistered:
389        if hidden == False:
390            guild_not_registered_embed.description = GoldyBot.utility.msgs.bot.CommandGuildNotRegistered.Embed.des.format(ctx.author.mention)
391            message = await ctx.send(embed=guild_not_registered_embed)
392            await asyncio.sleep(15)
393            message.delete()
394
395    except Exception as e:
396        GoldyBot.logging.log("error", e)
397                    """, 
398                                                                        # Lambda expression: Returns nc_co
399                    {"func":goldy_sub_command.func, "parent_command": parent_command, "command_name":goldy_sub_command.command_name, "help_des":goldy_sub_command.get_help_des(), 
400                    "self":goldy_sub_command, "Interaction": GoldyBot.nextcord.Interaction, "GoldyBot": GoldyBot, "asyncio":asyncio, "nextcord":nextcord, 
401                    "class_":goldy_sub_command.extension, "no_perms_embed":self.no_perms_embed, "guild_not_registered_embed":self.guild_not_registered_embed, 
402                    "hidden":goldy_sub_command.is_hidden, "also_run_parent_CMD":also_run_parent_CMD, "goldy_parent_command": self}, return_data)
403                    
404                else: # Run as NORMAL command!
405                    exec(f"""
406@parent_command.subcommand(name=command_name, description=help_des)
407async def slash_command_(interaction: Interaction{slash_command_params[0]}):
408    ctx = GoldyBot.objects.slash.InteractionToCtx(interaction)
409    try:
410        if self.allowed_to_run(ctx):
411            if also_run_parent_CMD == True: await goldy_parent_command.func(ctx{parent_slash_command_params[1]})
412            await func(ctx{slash_command_params[1]})
413            GoldyBot.logging.log(f"[{MODULE_NAME}] The slash command '{goldy_sub_command.code_name}' was executed.")
414
415    except GoldyBot.errors.MemberHasNoPermsForCommand:
416        if hidden == False:
417            no_perms_embed.description = GoldyBot.utility.msgs.bot.CommandNoPerms.Embed.des.format(ctx.author.mention)
418            message = await ctx.send(embed=no_perms_embed)
419            await asyncio.sleep(15)
420            await message.delete()
421
422    except GoldyBot.errors.GuildNotRegistered:
423        if hidden == False:
424            guild_not_registered_embed.description = GoldyBot.utility.msgs.bot.CommandGuildNotRegistered.Embed.des.format(ctx.author.mention)
425            message = await ctx.send(embed=guild_not_registered_embed)
426            await asyncio.sleep(15)
427            await message.delete()
428
429    except Exception as e:
430        GoldyBot.logging.log("error", e)
431                    """, 
432                    
433                    {"func":goldy_sub_command.func, "parent_command": parent_command, "command_name":goldy_sub_command.command_name, "help_des":goldy_sub_command.get_help_des(), 
434                    "self":goldy_sub_command, "Interaction": GoldyBot.nextcord.Interaction, "GoldyBot": GoldyBot, "asyncio":asyncio, "nextcord":nextcord, 
435                    "no_perms_embed":self.no_perms_embed, "guild_not_registered_embed":self.guild_not_registered_embed, "hidden":goldy_sub_command.is_hidden, 
436                    "also_run_parent_CMD":also_run_parent_CMD, "goldy_parent_command": self}, return_data)
437
438                goldy_sub_command.update_command_object(return_data["slash_command_"])
439
440                GoldyBot.logging.log("info_5", f"[{MODULE_NAME}] Sub Command '{goldy_sub_command.command_name}' of '{parent_command.name}' has been loaded.")
441                return goldy_sub_command
442
443            return inner(func, command_name, required_roles, help_des, slash_options)
444
445        return decorate

Create a lovely sub command from this slash command. 😀 (Only works with slash commands.)

def allowed_to_run(self, ctx):
447    def allowed_to_run(self, ctx):
448        """Checks if the command is allowed to run with current circumstances."""
449        goldy_config = GoldyBot.config.Config(GoldyBot.files.File(GoldyBot.paths.GOLDY_CONFIG_JSON))
450        
451        # Check if guild is registered.
452        #--------------------------------
453        if str(ctx.guild.id) in goldy_config.read("allowed_guilds"):
454            guild_code_name = GoldyBot.cache.FindGuilds(goldy_config).find_object_by_id(ctx.guild.id).code_name
455            guild_config = GoldyBot.utility.guilds.config.GuildConfig(GoldyBot.config.Config(GoldyBot.files.File(GoldyBot.paths.CONFIG + f"/{guild_code_name}/config.json")))
456            
457            if guild_config.is_extension_allowed(self.extension_name):
458
459                if not self.required_roles_ == []:
460                    # If the required roles contain 'bot_dev' and the bot dev is running the command allow the command to execute.
461                    #----------------------------------------------------------------------------------------------------------------
462                    if "bot_dev" in self.required_roles_:
463                        if str(ctx.author.id) in GoldyBot.settings.BOT_DEVS:
464                            return True
465
466                    # If the required roles contain 'bot_admin' and a bot admin is running the command allow the command to execute. (NEW)
467                    #----------------------------------------------------------------------------------------------------------------
468                    if "bot_admin" in self.required_roles_:
469                        if str(ctx.author.id) in goldy_config.read("admin_users"):
470                            return True
471
472                    # Check if member has any of the required roles.
473                    #----------------------------------------------------
474                    for role_code_name in self.required_roles_:
475                        if not role_code_name in ["bot_dev", "bot_admin"]:
476                            role = guild_config.get_role(ctx, role_code_name)
477                            if GoldyBot.objects.member.Member(ctx).has_role(role):
478                                return True
479
480                    raise GoldyBot.errors.MemberHasNoPermsForCommand(f"The member '{ctx.author.name}' does not have the right permissions to use this command.")
481
482                else:
483                    return True
484                
485        else:
486            raise GoldyBot.errors.GuildNotRegistered(f"The guild '{ctx.guild.name}' has not been registered.")

Checks if the command is allowed to run with current circumstances.

guilds_allowed_in: List[int]

Returns the ids of the guilds this command is allowed to function in.

def get_help_des(self) -> str:
511    def get_help_des(self) -> str:
512        """Returns the command's help description."""
513        if self.help_des_ == None:
514            try:
515                return (importlib.import_module(f'.{self.command_name}', package="GoldyBot.utility.msgs")).help_des
516
517            except ImportError:
518                GoldyBot.logging.log("info", f"[{MODULE_NAME}] The command '{self.command_name}' does not have a 'msg' module, so the help command will not display a help description for it.")
519                return "None"
520
521            except AttributeError:
522                GoldyBot.logging.log("info", f"[{MODULE_NAME}] The command '{self.command_name}' does not contain 'help_des' variable in it's 'msg' module, so the help command will not display a help description.")
523                return "None"
524        else:
525            return self.help_des_

Returns the command's help description.

class Member(GoldyBot.database.member.Member):
11class Member(database.member.Member):
12    """A class representing a discord member in Goldy Bot."""
13    def __init__(self, ctx, member_id:str|int=None, mention_str:str=None, member_object:nextcord.Member=None):
14        self.ctx = ctx
15        self.member_id_ = member_id
16        self.mention_str_ = mention_str
17        self.member_object_ = member_object
18
19        if self.member_object_ == None:
20            # Find the member.
21            self.member = self.find_member(self.member_id)
22        else:
23            self.member = self.member_object_
24
25        super().__init__(ctx, self)
26        
27    @property
28    def member_id(self) -> str:
29        """Returns id of discord member. Defaults to ctx author if ``member_id``, ``mention_str`` and ``member_user_object`` are None."""
30        if not self.member_id_ == None: return str(self.member_id_)
31        if not self.mention_str_ == None: return self.mention_str_[self.mention_str_.index("@") + 1: self.mention_str_.index(">")] # Getting id from mention (e.g. <@332592361307897856>).
32        if not self.member_object_ == None: return str(self.member_object_.id)
33        else:
34            if isinstance(self.ctx, Interaction):
35                return str(InteractionToCtx(self.ctx).author.id)
36            else:
37                return str(self.ctx.author.id)
38                
39    @property
40    def name(self):
41        """Returns the discord name of member including tag. Does not return server nickname!"""
42        return self.member.name
43
44    @property
45    def display_name(self):
46        """Returns display name of member, so server nickname."""
47        return self.member.display_name
48
49    # Roles
50    #---------
51    def has_role(self, role:role.Role):
52        """Checks if the member has a certain role."""
53        if role.role in self.member.roles:
54            return True
55        else:
56            return False
57
58    async def add_role(self, role:role.Role):
59        """This method adds the specified role to this member."""
60        if not self.has_role(role):
61            await self.member.add_roles(role)
62            return True
63        else:
64            return True
65
66    async def remove_role(self, role:role.Role):
67        """This method removes the specified role from this member."""
68        if self.has_role(role):
69            await self.member.remove_roles(role)
70            return True
71        else:
72            return None
73
74    def find_member(self, member_id:int|str) -> nextcord.Member | None:
75        """Finds the damn member!"""
76
77        if not member_id == None:
78            member = nextcord.utils.get(self.ctx.guild.members, id=int(member_id))
79            
80            if member is None: raise GoldyBot.errors.FailedToFindMember()
81
82            return member
83        else:
84            return None
85
86    # Utils
87    async def send(self, **args):
88        args.pop("ephemeral")
89        await self.member.send(**args)

A class representing a discord member in Goldy Bot.

Member( ctx, member_id: str | int = None, mention_str: str = None, member_object: nextcord.member.Member = None)
13    def __init__(self, ctx, member_id:str|int=None, mention_str:str=None, member_object:nextcord.Member=None):
14        self.ctx = ctx
15        self.member_id_ = member_id
16        self.mention_str_ = mention_str
17        self.member_object_ = member_object
18
19        if self.member_object_ == None:
20            # Find the member.
21            self.member = self.find_member(self.member_id)
22        else:
23            self.member = self.member_object_
24
25        super().__init__(ctx, self)
member_id: str

Returns id of discord member. Defaults to ctx author if member_id, mention_str and member_user_object are None.

name

Returns the discord name of member including tag. Does not return server nickname!

display_name

Returns display name of member, so server nickname.

def has_role(self, role: GoldyBot.objects.Role):
51    def has_role(self, role:role.Role):
52        """Checks if the member has a certain role."""
53        if role.role in self.member.roles:
54            return True
55        else:
56            return False

Checks if the member has a certain role.

async def add_role(self, role: GoldyBot.objects.Role):
58    async def add_role(self, role:role.Role):
59        """This method adds the specified role to this member."""
60        if not self.has_role(role):
61            await self.member.add_roles(role)
62            return True
63        else:
64            return True

This method adds the specified role to this member.

async def remove_role(self, role: GoldyBot.objects.Role):
66    async def remove_role(self, role:role.Role):
67        """This method removes the specified role from this member."""
68        if self.has_role(role):
69            await self.member.remove_roles(role)
70            return True
71        else:
72            return None

This method removes the specified role from this member.

def find_member(self, member_id: int | str) -> nextcord.member.Member | None:
74    def find_member(self, member_id:int|str) -> nextcord.Member | None:
75        """Finds the damn member!"""
76
77        if not member_id == None:
78            member = nextcord.utils.get(self.ctx.guild.members, id=int(member_id))
79            
80            if member is None: raise GoldyBot.errors.FailedToFindMember()
81
82            return member
83        else:
84            return None

Finds the damn member!

async def send(self, **args):
87    async def send(self, **args):
88        args.pop("ephemeral")
89        await self.member.send(**args)
class Role:
 9class Role():
10    """
11    A class representing a discord role in Goldy Bot. Either 'role_id', 'role_name', 'mention_str' or 'role_object' has to be passed in the 'Role()'.
12    
13    Raises FailedToFindRole() when role is not found.
14    """
15    def __init__(self, ctx, role_id:str=None, role_name:str=None, role_object:nextcord.Role=None, mention_str:str=None):
16        self.ctx = ctx
17        self.role_id_ = role_id
18        self.role_name_ = role_name
19        self.mention_str_ = mention_str
20        self.role_object_ = role_object
21
22        self.role_ = None
23
24        if self.role_object_ == None:
25            self.role_ = self.find_role(self.role_id, self.role_name_)
26        else:
27            self.role_ = self.role_object_
28
29    @property
30    def role(self) -> nextcord.Role:
31        """Returns the actual representation of the role in nextcord."""
32        return self.role_
33
34    @property
35    def role_id(self) -> str|None:
36        """Returns id of discord role. Returns ``None`` if ``role_id``, ``role_name``, ``mention_str`` and ``role_object`` are left blank."""
37        if not self.role_id_ == None: return str(self.role_id_)
38        if not self.mention_str_ == None: return self.mention_str_[3:-1]
39        if not self.role_object_ == None: return str(self.role_object_.id)
40
41        return None
42
43    @property
44    def role_name(self) -> str:
45        """Returns the name of the role."""
46        return self.role.name
47
48    def find_role(self, role_id:int|str, role_name:str=None) -> nextcord.Role:
49        role:nextcord.Role
50
51        if role_name == None:
52            if not role_id == None:
53                role = self.ctx.guild.get_role(int(role_id))
54            else:
55                role = None
56
57            if role == None:
58                raise FailedToFindRole(option_used="id", option_value=role_id)
59            else:
60                GoldyBot.logging.log(f"Found the role '{role.name}' by id.")
61                return role
62            
63        else:
64            role = nextcord.utils.get(self.ctx.guild.roles, name=role_name)
65
66            if role == None: 
67                raise FailedToFindRole(option_used="role name", option_value=role_name)
68            else:
69                GoldyBot.logging.log(f"Found the role '{role.name}' by name.")
70                return role

A class representing a discord role in Goldy Bot. Either 'role_id', 'role_name', 'mention_str' or 'role_object' has to be passed in the 'Role()'.

Raises FailedToFindRole() when role is not found.

Role( ctx, role_id: str = None, role_name: str = None, role_object: nextcord.role.Role = None, mention_str: str = None)
15    def __init__(self, ctx, role_id:str=None, role_name:str=None, role_object:nextcord.Role=None, mention_str:str=None):
16        self.ctx = ctx
17        self.role_id_ = role_id
18        self.role_name_ = role_name
19        self.mention_str_ = mention_str
20        self.role_object_ = role_object
21
22        self.role_ = None
23
24        if self.role_object_ == None:
25            self.role_ = self.find_role(self.role_id, self.role_name_)
26        else:
27            self.role_ = self.role_object_
role: nextcord.role.Role

Returns the actual representation of the role in nextcord.

role_id: str | None

Returns id of discord role. Returns None if role_id, role_name, mention_str and role_object are left blank.

role_name: str

Returns the name of the role.

def find_role(self, role_id: int | str, role_name: str = None) -> nextcord.role.Role:
48    def find_role(self, role_id:int|str, role_name:str=None) -> nextcord.Role:
49        role:nextcord.Role
50
51        if role_name == None:
52            if not role_id == None:
53                role = self.ctx.guild.get_role(int(role_id))
54            else:
55                role = None
56
57            if role == None:
58                raise FailedToFindRole(option_used="id", option_value=role_id)
59            else:
60                GoldyBot.logging.log(f"Found the role '{role.name}' by id.")
61                return role
62            
63        else:
64            role = nextcord.utils.get(self.ctx.guild.roles, name=role_name)
65
66            if role == None: 
67                raise FailedToFindRole(option_used="role name", option_value=role_name)
68            else:
69                GoldyBot.logging.log(f"Found the role '{role.name}' by name.")
70                return role
class InteractionToCtx:
13class InteractionToCtx():
14    """This Goldy Bot class is used to convert interactions to ctx."""
15    def __init__(self, interaction: Interaction):
16        self.interaction = interaction
17
18    @property
19    def guild(self) -> Interaction.guild:
20        return self.interaction.guild
21
22    @property
23    def author(self):
24        return self.interaction.user
25
26    @property
27    def channel(self):
28        return self.interaction.channel
29
30    @property
31    def response(self) -> InteractionResponse:
32        return self.interaction.response
33
34    async def send(self, text:str=None, **kwargs):
35        if not text == None:
36            await self.interaction.send(text)
37        else:
38            await self.interaction.send(**kwargs)
39        
40        return Message(self.interaction)
41
42    async def send_modal(self, modal:nextcord.ui.Modal):
43        """Sends modal."""
44        await self.interaction.response.send_modal(modal)
45
46        return Message(self.interaction)

This Goldy Bot class is used to convert interactions to ctx.

InteractionToCtx(interaction: nextcord.interactions.Interaction)
15    def __init__(self, interaction: Interaction):
16        self.interaction = interaction
guild: <property object at 0x000001B473CA9EE0>
author
channel
response: nextcord.interactions.InteractionResponse
async def send(self, text: str = None, **kwargs):
34    async def send(self, text:str=None, **kwargs):
35        if not text == None:
36            await self.interaction.send(text)
37        else:
38            await self.interaction.send(**kwargs)
39        
40        return Message(self.interaction)
async def send_modal(self, modal: nextcord.ui.modal.Modal):
42    async def send_modal(self, modal:nextcord.ui.Modal):
43        """Sends modal."""
44        await self.interaction.response.send_modal(modal)
45
46        return Message(self.interaction)

Sends modal.

class Channel:
10class Channel():
11    """A class representing a discord channel in Goldy Bot."""
12    def __init__(self, ctx, channel_id:str|int=None, mention_str:str=None, channel_object:nextcord.abc.GuildChannel=None):
13
14        self.ctx = ctx
15        self.channel_id_ = channel_id
16        self.mention_str_ = mention_str
17        self.channel_object_ = channel_object
18
19        self.channel:nextcord.abc.GuildChannel|None
20
21        if self.channel_object_ == None:
22            # Find the channel.
23            self.channel = self.find_channel(self.channel_id)
24        else:
25            self.channel = self.channel_object_
26        
27    @property
28    def channel_id(self) -> str:
29        """Returns id of discord channel. Defaults to ctx channel if ``channel_id``, ``mention_str`` and ``channel_object`` are None."""
30        if not self.channel_id_ == None: return str(self.channel_id_)
31        if not self.mention_str_ == None: return self.mention_str_[3:-1]
32        if not self.channel_object_ == None: return str(self.channel_object_.id)
33        else:
34            if isinstance(self.ctx, Interaction):
35                return str(InteractionToCtx(self.ctx).channel.id)
36            else:
37                return str(self.ctx.channel.id)
38                
39    @property
40    def name(self):
41        """Returns the discord channel name."""
42        return self.channel.name
43
44    @property
45    def display_name(self):
46        """Alias of ``Channel().name``"""
47        return self.name
48
49    async def purge(self, amount:int|None):
50        """Deletes specified number of messages in this channel. (Only works if this channel is a text channel.)"""
51        if isinstance(self.channel, nextcord.TextChannel):
52            channel:nextcord.TextChannel = self.channel
53
54            deleted = None
55            try:
56                deleted = await channel.purge(limit=amount)
57                GoldyBot.logging.log("info_5", f"[{MODULE_NAME}] Deleted '{len(deleted)}' messages from the channel '{self.name}'.")
58            except Exception as e:
59                GoldyBot.logging.log("warn", f"[{MODULE_NAME}] Couldn't delete from '{self.name}' because '{e}'.")
60                
61            return deleted
62        else:
63            GoldyBot.logging.log("warn", f"[{MODULE_NAME}] Can't purge messages because this channel isn't a text channel!")
64
65
66    def find_channel(self, channel_id:int|str) -> nextcord.abc.GuildChannel | None:
67        """Finds the damn channel!"""
68
69        if not channel_id == None:
70            return nextcord.utils.get(self.ctx.guild.channels, id=int(channel_id))
71        else:
72            return None

A class representing a discord channel in Goldy Bot.

Channel( ctx, channel_id: str | int = None, mention_str: str = None, channel_object: nextcord.abc.GuildChannel = None)
12    def __init__(self, ctx, channel_id:str|int=None, mention_str:str=None, channel_object:nextcord.abc.GuildChannel=None):
13
14        self.ctx = ctx
15        self.channel_id_ = channel_id
16        self.mention_str_ = mention_str
17        self.channel_object_ = channel_object
18
19        self.channel:nextcord.abc.GuildChannel|None
20
21        if self.channel_object_ == None:
22            # Find the channel.
23            self.channel = self.find_channel(self.channel_id)
24        else:
25            self.channel = self.channel_object_
channel_id: str

Returns id of discord channel. Defaults to ctx channel if channel_id, mention_str and channel_object are None.

name

Returns the discord channel name.

display_name

Alias of Channel().name

async def purge(self, amount: int | None):
49    async def purge(self, amount:int|None):
50        """Deletes specified number of messages in this channel. (Only works if this channel is a text channel.)"""
51        if isinstance(self.channel, nextcord.TextChannel):
52            channel:nextcord.TextChannel = self.channel
53
54            deleted = None
55            try:
56                deleted = await channel.purge(limit=amount)
57                GoldyBot.logging.log("info_5", f"[{MODULE_NAME}] Deleted '{len(deleted)}' messages from the channel '{self.name}'.")
58            except Exception as e:
59                GoldyBot.logging.log("warn", f"[{MODULE_NAME}] Couldn't delete from '{self.name}' because '{e}'.")
60                
61            return deleted
62        else:
63            GoldyBot.logging.log("warn", f"[{MODULE_NAME}] Can't purge messages because this channel isn't a text channel!")

Deletes specified number of messages in this channel. (Only works if this channel is a text channel.)

def find_channel(self, channel_id: int | str) -> nextcord.abc.GuildChannel | None:
66    def find_channel(self, channel_id:int|str) -> nextcord.abc.GuildChannel | None:
67        """Finds the damn channel!"""
68
69        if not channel_id == None:
70            return nextcord.utils.get(self.ctx.guild.channels, id=int(channel_id))
71        else:
72            return None

Finds the damn channel!

class Currency:
 2class Currency():
 3    """
 4    Base class for a currency in Goldy Bot. Use this to create you own custom currency.
 5        
 6    ---------------
 7    ### ***``Example:``***
 8
 9    Hello, want to make your own custom currency? Well anyways you came to the right place.
10    Below I show you an example on how to create your very own currency in Goldy Bot using the currency base class.
11
12    ```python
13    class GBP(GoldyBot.Currency):
14        def __init__(self):
15            super().__init__("GBP", "British Pounds", "💷", 600)
16    ```
17    - This is how a custom currency is implemented. The code name is ``GBP``, the display name is ``British Pounds``, the currency icon/emoji is a ``pound banknote`` (💷) emoji and the default balance for this currency is 600.
18
19    ```python
20    class UwUCoin(GoldyBot.Currency):
21        def __init__(self):
22            super().__init__("uwu_coin", "UwU Coin", "🟡", 0)
23    ```
24    - Here's another example for fun. 😁
25    """
26
27    def __init__(self, code_name:str, display_name:str, display_emoji:str="💷", default_bal:int=600):
28        self.code_name_ = code_name
29        self.display_name_ = display_name
30        self.display_emoji_ = display_emoji
31        self.default_bal_ = default_bal
32
33    @property
34    def code_name(self):
35        """Returns code name of currency."""
36        return self.code_name_
37
38    @property
39    def display_name(self):
40        """Returns display name of currency."""
41        return self.display_name_
42
43    @property
44    def display_emoji(self):
45        """Returns some sort of emoji or icon that is used to identify this currency."""
46        return self.display_emoji_
47
48    @property
49    def default_bal(self):
50        """Returns the default balance for this currency."""
51        return self.default_bal_

Base class for a currency in Goldy Bot. Use this to create you own custom currency.


Example:

Hello, want to make your own custom currency? Well anyways you came to the right place. Below I show you an example on how to create your very own currency in Goldy Bot using the currency base class.

class GBP(GoldyBot.Currency):
    def __init__(self):
        super().__init__("GBP", "British Pounds", "💷", 600)
  • This is how a custom currency is implemented. The code name is GBP, the display name is British Pounds, the currency icon/emoji is a pound banknote (💷) emoji and the default balance for this currency is 600.
class UwUCoin(GoldyBot.Currency):
    def __init__(self):
        super().__init__("uwu_coin", "UwU Coin", "🟡", 0)
  • Here's another example for fun. 😁
Currency( code_name: str, display_name: str, display_emoji: str = '💷', default_bal: int = 600)
27    def __init__(self, code_name:str, display_name:str, display_emoji:str="💷", default_bal:int=600):
28        self.code_name_ = code_name
29        self.display_name_ = display_name
30        self.display_emoji_ = display_emoji
31        self.default_bal_ = default_bal
code_name

Returns code name of currency.

display_name

Returns display name of currency.

display_emoji

Returns some sort of emoji or icon that is used to identify this currency.

default_bal

Returns the default balance for this currency.