Module: OnyxCord::Commands::CommandContainer

Includes:
RateLimiter
Included in:
Bot
Defined in:
lib/onyxcord/commands/container.rb

Overview

This module holds a collection of commands that can be easily added to by calling the #command function. Other containers can be included into it as well. This allows for modularization of command bots.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from RateLimiter

#bucket, #clean, #include_buckets, #rate_limited?

Instance Attribute Details

#commandsHash<Symbol, Command, CommandAlias> (readonly)

Returns hash of command names and commands this container has.

Returns:

  • (Hash<Symbol, Command, CommandAlias>)

    hash of command names and commands this container has.



13
14
15
# File 'lib/onyxcord/commands/container.rb', line 13

def commands
  @commands
end

Instance Method Details

#command(name, attributes = {}) {|event| ... } ⇒ Command

Note:

LocalJumpErrors are rescued from internally, giving bots the opportunity to use return or break in their blocks without propagating an exception.

Adds a new command to the container.

Parameters:

  • name (Symbol)

    The name of the command to add.

  • attributes (Hash) (defaults to: {})

    The attributes to initialize the command with.

Options Hash (attributes):

  • :aliases (Array<Symbol>)

    A list of additional names for this command. This in effect creates OnyxCord::Commands::CommandAlias objects in the container (#commands) that refer to the newly created command. Additionally, the default help command will identify these command names as an alias where applicable.

  • :permission_level (Integer)

    The minimum permission level that can use this command, inclusive. See Commands::Bot#set_user_permission and Commands::Bot#set_role_permission.

  • :permission_message (String, false)

    Message to display when a user does not have sufficient permissions to execute a command. %name% in the message will be replaced with the name of the command. Disable the message by setting this option to false.

  • :required_permissions (Array<Symbol>)

    Discord action permissions (e.g. :kick_members) that should be required to use this command. See Permissions::FLAGS for a list.

  • :required_roles (Array<Role>, Array<String, Integer>)

    Roles, or their IDs, that user must have to use this command (user must have all of them).

  • :allowed_roles (Array<Role>, Array<String, Integer>)

    Roles, or their IDs, that user should have to use this command (user should have at least one of them).

  • :channels (Array<String, Integer, Channel>)

    The channels that this command can be used on. An empty array indicates it can be used on any channel. Supersedes the command bot attribute.

  • :chain_usable (true, false)

    Whether this command is able to be used inside of a command chain or sub-chain. Typically used for administrative commands that shouldn't be done carelessly.

  • :help_available (true, false)

    Whether this command is visible in the help command. See the :help_command attribute of Bot#initialize.

  • :description (String)

    A short description of what this command does. Will be shown in the help command if the user asks for it.

  • :usage (String)

    A short description of how this command should be used. Will be displayed in the help command or if the user uses it wrong.

  • :arg_types (Array<Class>)

    An array of argument classes which will be used for type-checking. Hard-coded for some native classes, but can be used with any class that implements static method from_argument.

  • :min_args (Integer)

    The minimum number of arguments this command should have. If a user attempts to call the command with fewer arguments, the usage information will be displayed, if it exists.

  • :max_args (Integer)

    The maximum number of arguments the command should have.

  • :rate_limit_message (String)

    The message that should be displayed if the command hits a rate limit. None if unspecified or nil. %time% in the message will be replaced with the time in seconds when the command will be available again.

  • :bucket (Symbol)

    The rate limit bucket that should be used for rate limiting. No rate limiting will be done if unspecified or nil.

  • :rescue (String, #call)

    A string to respond with, or a block to be called in the event an exception is raised internally. If given a String, %exception% will be substituted with the exception's #message. If given a Proc, it will be passed the CommandEvent along with the Exception.

Yields:

  • The block is executed when the command is executed.

Yield Parameters:

  • event (CommandEvent)

    The event of the message that contained the command.

Returns:

  • (Command)

    The command that was added.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/onyxcord/commands/container.rb', line 61

def command(name, attributes = {}, &block)
  @commands ||= {}

  # TODO: Remove in 4.0
  if name.is_a?(Array)
    name, *aliases = name
    attributes[:aliases] = aliases if attributes[:aliases].nil?
    OnyxCord::LOGGER.warn("While registering command #{name.inspect}")
    OnyxCord::LOGGER.warn('Arrays for command aliases is removed. Please use `aliases` argument instead.')
  end

  new_command = Command.new(name, attributes, &block)
  new_command.attributes[:aliases].each do |aliased_name|
    @commands[aliased_name] = CommandAlias.new(aliased_name, new_command)
  end
  @commands[name] = new_command
end

#group(group_name, attributes = {}) { ... } ⇒ self

Creates a command group. Commands defined inside the block will be prefixed with the group name.

Examples:

group :admin do
  command(:ban) { |event, *args| "Banned #{args.first}" }
  command(:kick) { |event, *args| "Kicked #{args.first}" }
end
# Creates :admin_ban and :admin_kick commands

Parameters:

  • group_name (Symbol)

    The group prefix.

  • attributes (Hash) (defaults to: {})

    Shared attributes applied to all commands in the group.

Yields:

  • The block defines commands within the group.

Returns:

  • (self)

Raises:

  • (ArgumentError)


99
100
101
102
103
104
105
# File 'lib/onyxcord/commands/container.rb', line 99

def group(group_name, attributes = {}, &block)
  raise ArgumentError, 'Block required for group' unless block_given?

  proxy = GroupProxy.new(self, group_name, attributes)
  proxy.instance_exec(&block)
  self
end

#include!(container) ⇒ Object

Includes another container into this one.

Parameters:

  • container (Module)

    An EventContainer or CommandContainer that will be included if it can.



153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/onyxcord/commands/container.rb', line 153

def include!(container)
  container_modules = container.singleton_class.included_modules

  # If the container is an EventContainer and we can include it, then do that
  include_events(container) if container_modules.include?(OnyxCord::EventContainer) && respond_to?(:include_events)

  if container_modules.include? OnyxCord::Commands::CommandContainer
    include_commands(container)
    include_buckets(container)
  elsif !container_modules.include? OnyxCord::EventContainer
    raise "Could not include! this particular container - ancestors: #{container_modules}"
  end
end

#include_commands(container) ⇒ Object

Adds all commands from another container into this one. Existing commands will be overwritten.

Parameters:



109
110
111
112
113
114
115
# File 'lib/onyxcord/commands/container.rb', line 109

def include_commands(container)
  handlers = container.instance_variable_get :@commands
  return unless handlers

  @commands ||= {}
  @commands.merge! handlers
end

#middleware(command_name, type = :before) {|event, args, result| ... } ⇒ self

Registers a before or after hook on an existing command.

Parameters:

  • command_name (Symbol)

    The name of the command to hook.

  • type (:before, :after) (defaults to: :before)

    The hook type.

Yield Parameters:

  • event (CommandEvent)

    The event.

  • args (Array<String>)

    The command arguments.

  • result (Object)

    The command result (after hooks only).

Returns:

  • (self)


139
140
141
142
143
144
145
146
147
148
149
# File 'lib/onyxcord/commands/container.rb', line 139

def middleware(command_name, type = :before, &hook)
  cmd = @commands&.fetch(command_name, nil)
  cmd = cmd.aliased_command if cmd.is_a?(CommandAlias)
  return self unless cmd.is_a?(Command)

  case type
  when :before then cmd.before(&hook)
  when :after then cmd.after(&hook)
  end
  self
end

#remove_command(name) ⇒ Object

Removes a specific command from this container.

Parameters:

  • name (Symbol)

    The command to remove.



81
82
83
84
# File 'lib/onyxcord/commands/container.rb', line 81

def remove_command(name)
  @commands ||= {}
  @commands.delete name
end

#walk_commands {|name, cmd| ... } ⇒ self

Yields each command in this container, flattening subcommands.

Yield Parameters:

  • name (Symbol)

    The command name.

  • cmd (Command)

    The command object.

Returns:

  • (self)


121
122
123
124
125
126
127
128
129
130
# File 'lib/onyxcord/commands/container.rb', line 121

def walk_commands
  return self unless block_given?

  @commands&.each do |name, cmd|
    next if cmd.is_a?(CommandAlias)

    yield name, cmd
  end
  self
end