Documentation ¶
Overview ¶
Package drc is an early alpha command router and middleware for discordgo its primary function is handling certain tasks like permissions checks, argument parsing, and finding and executing command functions
Index ¶
- Constants
- func BitwiseDescriptionGen(n map[int64]string, b int64) []string
- func DisableSubcommands(s ...string) map[string]trit.Trit
- func FindFlag(args []string, name string) (pos int, addition string)
- func GetErrorType(err error) (bool, string)
- func IsDenied(err error) bool
- func IsFailure(err error) bool
- func IsParsingError(err error) bool
- func NewDenied(payload error, message string, details ...interface{}) error
- func NewFailure(payload error, message string, details ...interface{}) error
- func NewParseError(payload error, message string, details ...interface{}) error
- func ParseArgflags(args []string, flags map[string]string) (remainder []string, out map[string]Argument, err error)
- func ParseBoolflags(args []string, flags map[string]bool) (remainder []string, out map[string]bool, err error)
- func ParseChannel(s *discordgo.Session, channel, guild string) (*discordgo.Channel, error)
- func ParseMember(s *discordgo.Session, member, guild string) (*discordgo.Member, error)
- func ParseRole(s *discordgo.Session, role, guild string) (*discordgo.Role, error)
- func PermissionCheck(perms, required int64) int64
- func PermissionCheckChannel(s *discordgo.Session, userID, channelID string, permissions int64) (bool, int64, error)
- func PermissionCheckGuild(s *discordgo.Session, userID, guildID string, permissions int64) (bool, int64, error)
- func PermissionsGetGuild(s *discordgo.Session, guildID, userID string) (perms int64, err error)
- func RemDash(args []string) []string
- type ActOn
- type ActionReactions
- type Argument
- func (a Argument) Bool() (bool, error)
- func (a Argument) Channel(ctx *Context) (*discordgo.Channel, bool, error)
- func (a Argument) Duration() (time.Duration, error)
- func (a Argument) Float64() (float64, error)
- func (a Argument) Int() (int, error)
- func (a Argument) Int64() (int64, error)
- func (a Argument) Member(ctx *Context) (*discordgo.Member, bool, error)
- func (a Argument) Role(ctx *Context) (*discordgo.Role, bool, error)
- func (a Argument) String() (string, error)
- func (a Argument) Uint() (uint, error)
- func (a Argument) Uint64() (uint64, error)
- type BotAllowState
- type CfgCommand
- type CfgHandler
- type Command
- type CommandDMConfig
- type CommandListStructure
- type CommandMap
- func (cm *CommandMap) Add(cmd *Command) *Command
- func (cm *CommandMap) AddAliasPointer(name string, to *Command) *Command
- func (cm *CommandMap) AddAliasString(name string, to ...string) *Command
- func (cm *CommandMap) AddBulk(cmds []*Command)
- func (cm *CommandMap) List(listAll bool) []string
- func (cm *CommandMap) ListRecursive(listAll bool, maxDepth int, prefix bool) []string
- func (cm *CommandMap) ListRecursiveStructured(listAll bool, maxDepth int) []ListStructure
- func (cm *CommandMap) ListStructured(listAll bool, maxDepth int) []CommandListStructure
- type Context
- func (c Context) DumpReply(title string, text ...interface{}) (err error)
- func (c Context) DumpReplyf(title, layout string, text ...interface{}) error
- func (c Context) Print(txt ...interface{}) error
- func (c Context) Reply(txt ...interface{}) error
- func (c Context) ReplyEmbed(embed *discordgo.MessageEmbed) error
- func (c Context) Replyf(layout string, txt ...interface{}) error
- func (c Context) XPrint(txt ...interface{}) (*discordgo.Message, error)
- func (c Context) XReply(txt ...interface{}) (*discordgo.Message, error)
- func (c Context) XReplyEmbed(embed *discordgo.MessageEmbed) (*discordgo.Message, error)
- func (c Context) XReplyf(layout string, txt ...interface{}) (*discordgo.Message, error)
- type DefaultLogger
- type FetcherData
- type Handler
- func (h *Handler) BotPermissionCheck(s *discordgo.Session, channelID string, permissions int64) (bool, int64, error)
- func (h *Handler) CheckAlias(cmd *Command) (*Command, FetcherData)
- func (h *Handler) CheckPrefix(content, guild string) (length int)
- func (h *Handler) CommandPermissionCheck(s *discordgo.Session, m *discordgo.MessageCreate, p Permissions) (bool, int64, error)
- func (h *Handler) FetchCommand(List CommandMap, data FetcherData) (*Command, FetcherData)
- func (h *Handler) IsReady() bool
- func (h *Handler) IsUserBotAdmin(userID string) bool
- func (h *Handler) OnMessage(s *discordgo.Session, m *discordgo.MessageCreate) (err error)
- func (h *Handler) OnMessageWithCheck(s *discordgo.Session, m *discordgo.MessageCreate) (ok bool, err error)
- func (h *Handler) PermissionDescriptionGen(p int64) []string
- func (h *Handler) Ready() (err error)
- func (h *Handler) ServerPrefixesAdd(server, prefix string)
- func (h *Handler) ServerPrefixesExists(server string) bool
- func (h *Handler) ServerPrefixesGet(server string) []string
- func (h *Handler) ServerPrefixesGetAll(server string) (prefixes map[string][]string)
- func (h *Handler) ServerPrefixesInit(server string)
- func (h *Handler) ServerPrefixesRemove(server, prefix string)
- func (h *Handler) ServerPrefixesSet(server string, prefixes []string)
- func (h *Handler) ServerPrefixesSetBulk(list map[string][]string)
- type ListStructure
- type Logging
- type PanicLog
- type Permissions
- Bugs
Constants ¶
const ( ErrorUnknown d2ErrTypes = iota ErrorDenied ErrorFailure ErrorParsing )
Const values / enum containing internal error types
const DMPermissions = 0 | discordgo.PermissionAddReactions | discordgo.PermissionSendMessages | discordgo.PermissionSendTTSMessages | discordgo.PermissionAttachFiles | discordgo.PermissionReadMessages | discordgo.PermissionReadMessageHistory | discordgo.PermissionEmbedLinks
const Library = "drc.go"
Library is the name of the library
const Version = "v0.5.4 alpha"
Version is the version of the library
Variables ¶
This section is empty.
Functions ¶
func BitwiseDescriptionGen ¶
BitwiseDescriptionGen takes a map containing the names to go with each bitwise permission, and an int containing a set of bits, and it outputs a string array containing each entry of n that is located in b (using a bitwise AND comparison)
func DisableSubcommands ¶
DisableSubcommands takes a list of any amount of subcommands and generates a map of trits containing them To be used as an alterative to using map[string]trit.Trit{"command1": 1, "command2": 1} in Command.SubcommandToggle
func FindFlag ¶
FindFlag finds if the flag signaled by name is located in args using a syntax where a flag is prefixed with either - or -- if it comes across an entry in args that is solely "--" it will halt returning -2, if the flag contains : or = it will return an additional argument containing the contents after that
func GetErrorType ¶
GetErrorType returns whether or not the error is a d2cmd error, as well as its d2cmd type
func IsParsingError ¶
IsParsingError tells you if an error is a parsing error type
func NewFailure ¶
NewFailure returns a new error with a 'failure' designation
func NewParseError ¶
NewParseError returns a new error with a 'parsing error' designation
func ParseArgflags ¶
func ParseArgflags(args []string, flags map[string]string) (remainder []string, out map[string]Argument, err error)
ParseArgflags works similarly to ParseBoolflags except instead of booleans it returns a map of arguments (strings with the parsing methods from parse)
func ParseBoolflags ¶
func ParseBoolflags(args []string, flags map[string]bool) (remainder []string, out map[string]bool, err error)
ParseBoolflags takes a list of arguments, and a list of flags with a default state and searches through the args to find all flags which are specified it returns a remainder that no longer contains those flags, and a map containing all the flag states
func ParseChannel ¶
ParseChannel takes a string and attempts to find a channel that matches that string
func ParseMember ¶
ParseMember takes a string and attempts to find a member that matches that string
func PermissionCheck ¶
PermissionCheck determines if a user has the specified permissions if all required permissions are present it will return 0, else it will return the bits of the missing permissions
func PermissionCheckChannel ¶
func PermissionCheckChannel(s *discordgo.Session, userID, channelID string, permissions int64) (bool, int64, error)
PermissionCheckChannel checks to make sure a user has the required permissions to do an action in a specific channel
func PermissionCheckGuild ¶
func PermissionCheckGuild(s *discordgo.Session, userID, guildID string, permissions int64) (bool, int64, error)
PermissionCheckGuild is used for checking a user has required guild level permissions
func PermissionsGetGuild ¶
PermissionsGetGuild grabs the permission bits from all of a users roles
Types ¶
type ActOn ¶
type ActOn struct { Error trit.Trit // Act if a command or the handler runs into an error Denied trit.Trit // Act if a user is lacking permissions to run a command, or a command returns a permission denied error Failure trit.Trit // Act if a command returns an error type stating that the command failed for some reason Success trit.Trit // Act if a command succeeds // SendRawErrorContent Is ignored for ReactOn // This determines if it should send the raw error data SendRawErrorContent trit.Trit }
ActOn is a type containing some configuration for whether it should act or react on a certain event
type ActionReactions ¶
type ActionReactions struct { Error string Parser string Denied string Failure string Success string }
ActionReactions is a type containing the emotes to use for the ReactOn cases Must be set with a discord API ready emote string
type Argument ¶
type Argument struct { Raw string // currently only used for flags, determines if a flag is set or not IsSet bool }
Argument specified a type used for command arguments containing a raw string and some various parsing methods
func (Argument) Bool ¶
Bool parses the argument into int64 form, returns an error if an error occours
func (Argument) Channel ¶
Channel attempts to locate a channel using the data specified in the argument the boolean argument specifies if its marked as set for flags, this can be ignored for arguments but is important for flags as defaults may not be able to be relied on for dynamic data
func (Argument) Duration ¶
Duration parses the argument into int64 form, returns an error if an error occours
func (Argument) Float64 ¶
Float64 parses the argument into int64 form, returns an error if an error occours
func (Argument) Int64 ¶
Int64 parses the argument into int64 form, returns an error if an error occours
func (Argument) Member ¶
Member attempts to locate a member using the data specified in the argument the boolean argument specifies if its marked as set for flags, this can be ignored for arguments but is important for flags as defaults may not be able to be relied on for dynamic data
func (Argument) Role ¶
Role attempts to locate a role using the data specified in the argument the boolean argument specifies if its marked as set for flags, this can be ignored for arguments but is important for flags as defaults may not be able to be relied on for dynamic data
type BotAllowState ¶
type BotAllowState uint8
BotAllowState is a setting type for noting whether or not bots should be able to run commands
const ( BotAllowNone BotAllowState = iota // BotAllowLetList // TODO BotAllowAllExceptWebhooks BotAllowAll BotAllowOnlyExceptWebhooks BotAllowOnly )
The various states of whether or not
type CfgCommand ¶
type CfgCommand struct { // Whether or not the command should be listed in the command list Listable bool // Whether or not bots can run this command AllowBots BotAllowState // Whether or not the command should be DMs or Guild Only DMSettings CommandDMConfig // Whether or not to React on or Reply on certain events such as errors ReactOn ActOn ReplyOn ActOn // whether or not to enable the definable automatically added subcommands SubcommandToggle map[string]trit.Trit // boolean flags are used for toggles are parsed in advance and they only take up the flag itself // bool flags are configured with a default state, if used in a command it will be the inverse of the default // however you may also specify the value when calling them via doing -b=true or -bol:true (anything after = or : must be valid to be parsed by strconv.ParseBool() ) BoolFlags map[string]bool // Data flags function more like arguments, they are read and removed from the arguments on parsetime and can be found in context.Flags // however they are not typed and must be parsed in command time similar to arguments, like with boolflags you can give it a default to use if it is not added into a command DataFlags map[string]string // The minimum number of arguments that must be passed in order for the command to be executed MinimumArgs int }
CfgCommand is a type containing the various command specific settings
type CfgHandler ¶
type CfgHandler struct { Prefixes []string Manual []string Admins []string Name string // disable the ability to use an @mention as a command prefix for the bot DisableMentionAsPrefix bool // Whether or not to React on or Reply on certain events such as errors // These can be overrided on a per command level ReactOn ActOn ReplyOn ActOn // The Emotes to use for ReactOn Events ReactionEmotes ActionReactions // Default permissions to apply to *all* commands DefaultPermissions Permissions // PanicLog as an optional addition for logging panics (it will always log to stderr regardless) PanicLogger PanicLog // Logger is used for setting the interface which to log internal events to Logger Logging // LogDebug is whether or not to also log debug and trace stuff LogDebug bool // Add subcommands which will by default be added to all commands by default // Which then can be disabled on a command by command bases via Command.SubcommandToggle DefaultSubcommands []Command // The templates to send error messages with per the specifications of the stdlib text/template package. // {{.Error}} for the embeded payload error if applicable or the raw error if not applicable, // {{.RawError}} for the Raw error message, // {{.Details}} for extra details (such as the exact permissions missing in a permission error), // {{.Description}} for the embedded error message if applicable or the same as error if not applicable, // {{.HasExtras}} contains whether or not it has the extras from a d2cmd error, // {{.Msg}} is a substruct containing the full message create event, // {{.Msg.Author.String}} for a representation of the users username, // {{if .Cfg.SendRawErrorContent.Bool}} can be used to add an if to include the full raw error content ErrorTemplates struct { ParserError string Denied string Failure string Error string } // The names the permission name generator will use for each permission, the key is the bitwise bit of the permission, see discordgo docs for the list of all permission bits PermissionNames map[int64]string // Use custom implementations of the built in ctx.Reply methods GenericReply func(session *discordgo.Session, targetChannel string, message string) (*discordgo.Message, error) }
CfgHandler is a type containing some configuration and settings for the handler
type Command ¶
type Command struct { Name string // Command name Manual []string // Command Help / documentation Description string // (**DEPRECATED** use page 0 of Manual instead) A small description of a commands purpose Config CfgCommand // Config Settings Permissions Permissions // Permission Settings for what settings it will expect users to have CommandPerms int64 // The perms the bot requires itself to have in order to execute AliasPointer *Command // Pointer based alias AliasText []string // Text based alias, can add arguments via this method Subcommands CommandMap // The list of subcommands Exec func(*Context) error // The function to be executed Parent *Command // The parent command if this is a subcommand (note that this primarily exists for the "help" commands and should not be relied on otherwise) // contains filtered or unexported fields }
Command is a struct containing all the various thingies for commands
func (Command) Perms ¶
func (c Command) Perms() Permissions
Perms returns the modified state of the permissions after initialisation
func (Command) Settings ¶
func (c Command) Settings() CfgCommand
Settings Returns the Modified state of the config after initialisation
type CommandDMConfig ¶
type CommandDMConfig uint8
CommandDMConfig is a setting type for if commands should be able to be used in DMs
const ( // CommandDMsAndGuild : Allow in both DMs and guilds, Default CommandDMsAndGuild CommandDMConfig = iota // CommandDMsBlock : Only allow in guilds, disabled in DMs CommandDMsBlock // CommandDMsOnly : Only allow in DMs, disabled in guilds CommandDMsOnly )
type CommandListStructure ¶
type CommandListStructure struct { Name string Description string Permissions Permissions SubLists []CommandListStructure }
CommandListStructure describes a type that contains a name, some extra properties and a list of subentries, used by CommandMap.ListRecursiveStructured()
type CommandMap ¶
CommandMap is the central type used for storing commands
func (*CommandMap) Add ¶
func (cm *CommandMap) Add(cmd *Command) *Command
Add adds a command to the map
func (*CommandMap) AddAliasPointer ¶
func (cm *CommandMap) AddAliasPointer(name string, to *Command) *Command
AddAliasPointer adds an alias command which aliases to a pointer
func (*CommandMap) AddAliasString ¶
func (cm *CommandMap) AddAliasString(name string, to ...string) *Command
AddAliasString adds an alias command which aliases to a string
func (*CommandMap) AddBulk ¶
func (cm *CommandMap) AddBulk(cmds []*Command)
AddBulk adds an array of commands onto the current command
func (*CommandMap) List ¶
func (cm *CommandMap) List(listAll bool) []string
List lists all commands on this commandmap, 1st argument defines whether or not it should ignore commands not set to be listable
func (*CommandMap) ListRecursive ¶
func (cm *CommandMap) ListRecursive(listAll bool, maxDepth int, prefix bool) []string
ListRecursive lists all commands and subcommands on this commandmap 1st argument defines whether or not it should ignore commands not set to be listable, 2nd argument specifies the max layers of depth (if set below 1 it'll go forever until an int overflow eventually brings it to 0) 3rd argument tells it what to prefix with, false will have it prefixed with a variable amount of "- "s, true will have it prefixed by the command names
func (*CommandMap) ListRecursiveStructured ¶
func (cm *CommandMap) ListRecursiveStructured(listAll bool, maxDepth int) []ListStructure
ListRecursiveStructured is like ListStructured but without any of the extra details, note that this may not stick around in later releases, and just exists as a lazy way to fetch a command list to throw into a formatter function
func (*CommandMap) ListStructured ¶
func (cm *CommandMap) ListStructured(listAll bool, maxDepth int) []CommandListStructure
ListStructured lists all commands and subcommands on this commandmap returning the data in a structured fromat 1st argument defines whether or not it should ignore commands not set to be listable, 2nd argument specifies the max layers of depth (if set below 1 it'll go forever until an int overflow eventually brings it to 0)
type Context ¶
type Context struct { Args []Argument // Args contains the arguments passed after the command RawArgs []string // Args contains all arguments passed after the command but in raw string form AllArgs []string // RawArgs contains all arguments, including the commands that would be stripped away in Context.Args BoolFlags map[string]bool // Boolean toggle flags Flags map[string]Argument // Data flags that function similarly to arguments CommandPath []string // The path to the command which was just executed Ses *discordgo.Session Mes *discordgo.MessageCreate Han *Handler Com *Command }
Context is a struct that contains many helper functions and data for use in commands
func (Context) DumpReply ¶
DumpReply is used for dumping a large amount of text, usually for debug purposes, it encases the content in a discord code block and if its length is greater than 2000 it splits it into multiple messages at linebreaks, NOTE that if a single line is greater than 2000 characters it will still error from being too long
func (Context) DumpReplyf ¶
DumpReplyf is like DumpReply except it uses fmt.Sprintf logic instead of fmt.Sprint logic
func (Context) ReplyEmbed ¶
func (c Context) ReplyEmbed(embed *discordgo.MessageEmbed) error
ReplyEmbed creates an embed reply in the channel which spawned this context
func (Context) Replyf ¶
Replyf creates a reply in the channel which spawned this context using the same logic as fmt.Sprintf for formatting
func (Context) XPrint ¶
XPrint creates a simple reply in the channel which spawned this context and returns the message object of the sent message
func (Context) XReply ¶
XReply creates a reply in the channel which spawned this context and returns the message object of the sent message
func (Context) XReplyEmbed ¶
XReplyEmbed creates an embed reply in the channel which spawned this context and returns the message object of the sent message
type DefaultLogger ¶
type DefaultLogger struct {
// contains filtered or unexported fields
}
DefaultLogger is a default implementation for the logger To be rewritten with a better logger in the future
func NewDefaultLogger ¶
func NewDefaultLogger(timeformat string) *DefaultLogger
NewDefaultLogger returns an instance of the default logger
func (DefaultLogger) Error ¶
func (l DefaultLogger) Error(in ...interface{})
Error logs info of type error to stderr
func (DefaultLogger) Info ¶
func (l DefaultLogger) Info(in ...interface{})
Info logs info of type info to stdout
type FetcherData ¶
type FetcherData struct { Args []string // Normal command arguments PreArg []string // Arguments that come before a command in cases like ( !command argument subcommand ) Path []string // The full path to a command // contains filtered or unexported fields }
FetcherData contains the various argument types to be returned by the fetcher
type Handler ¶
type Handler struct { Config CfgHandler ServerPrefixes map[string]*[]string Commands CommandMap // contains filtered or unexported fields }
Handler is the central type that encompasses everything
func NewHandler ¶
func NewHandler(config CfgHandler, s *discordgo.Session) *Handler
NewHandler returns a new handler for you to use
func (*Handler) BotPermissionCheck ¶
func (h *Handler) BotPermissionCheck(s *discordgo.Session, channelID string, permissions int64) (bool, int64, error)
BotPermissionCheck checks if the bot has the required permissions in a certain channel
func (*Handler) CheckAlias ¶
func (h *Handler) CheckAlias(cmd *Command) (*Command, FetcherData)
CheckAlias checks if a command is an alias to another command, returning the command object if so, returning nil if not
func (*Handler) CheckPrefix ¶
CheckPrefix checks whether or not a string of text contains any of the known/set prefixes on a specified guild, returning the length of the prefix if so, and returning -1 if it does not contain any prefix
func (*Handler) CommandPermissionCheck ¶
func (h *Handler) CommandPermissionCheck(s *discordgo.Session, m *discordgo.MessageCreate, p Permissions) (bool, int64, error)
CommandPermissionCheck checks if a user in a message create event has the required permissions to run a command
func (*Handler) FetchCommand ¶
func (h *Handler) FetchCommand(List CommandMap, data FetcherData) (*Command, FetcherData)
FetchCommand recursively checks down the list of arguments to figure out which command is referenced in the chain of arguments It returns the furthest down valid command in the chain, and the remainder arguments, doupper if set to true will make it case sentitive (by default it ToLowers the key when it checks it) this is used internally in the alias handler so that commands defined with uppercase symbols are only accessable via aliases
func (*Handler) IsUserBotAdmin ¶
IsUserBotAdmin Determines if a user is in the bots whitelisted list of 'bot admins'
func (*Handler) OnMessage ¶
OnMessage is the primary entry point function for the message and command routing functionality This should be placed somewhere in the MessageCreate handler for discordgo
func (*Handler) OnMessageWithCheck ¶
func (h *Handler) OnMessageWithCheck(s *discordgo.Session, m *discordgo.MessageCreate) (ok bool, err error)
OnMessageWithCheck is the same as OnMessage, except it also returns if a command has been ran
func (*Handler) PermissionDescriptionGen ¶
PermissionDescriptionGen generates a string array containing all the permissions given in p using the names in handler.Config.PermissionNames
func (*Handler) Ready ¶
Ready finalises the settings for operation. This method must be called after everything is added but before the connection to discord
func (*Handler) ServerPrefixesAdd ¶
ServerPrefixesAdd appends a new server prefix
func (*Handler) ServerPrefixesExists ¶
ServerPrefixesExists checks if a custom prefixes list has been initialised for a server
func (*Handler) ServerPrefixesGet ¶
ServerPrefixesGet returns the list of prefixes on a specified server
func (*Handler) ServerPrefixesGetAll ¶
ServerPrefixesGetAll returns all set server prefixes
func (*Handler) ServerPrefixesInit ¶
ServerPrefixesInit initialises custom prefixes on a server, making it use a copy of the defaults instead of the defaults
func (*Handler) ServerPrefixesRemove ¶
ServerPrefixesRemove removes a prefix from a server prefixes list
func (*Handler) ServerPrefixesSet ¶
ServerPrefixesSet sets the server prefixes to a custom list of prefixes Note that you will need to implement a method of storing and loading custom prefixes yourself
func (*Handler) ServerPrefixesSetBulk ¶
ServerPrefixesSetBulk allows you to set server prefixes in bulk
type ListStructure ¶
type ListStructure struct { Name string SubLists []ListStructure }
ListStructure is like CommandListStructure but without any of the extra details, note that this may not stick around in later releases
type Logging ¶
type Logging interface { Info(...interface{}) Error(...interface{}) }
Logging is the interface used for the handler logging
type PanicLog ¶
type PanicLog interface {
Print(stack string, msg interface{})
}
PanicLog as an optional addition for logging panics (it will always log to stderr regardless)
type Permissions ¶
type Permissions struct { BotAdmin trit.Trit // Whether or not to require a user being in the configured admin letlist Discord int64 // Discord permissions to require the user to *globally* have (channel overrides excluded) DiscordChannel int64 // Discord permissions to require the user have within the channel that command was run in }
Permissions is a type defining some various permission requirements
Notes ¶
Bugs ¶
custom server prefixes are currently untested TODO? Replace custom prefix system with an interface as to allow the bot to handle managing them instead of having an internal list that has to be saved and loaded in bulk
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package subpresets contains some presets and premade 'default' subcommands for DRC 0.X These can be added to the handler.Config.DefaultSubcommands array where they'll be automatically added to all commands at init time They can also be excluded from being added from certain commands via Command.SubcommandToggle
|
Package subpresets contains some presets and premade 'default' subcommands for DRC 0.X These can be added to the handler.Config.DefaultSubcommands array where they'll be automatically added to all commands at init time They can also be excluded from being added from certain commands via Command.SubcommandToggle |