class Discordrb::Commands::Command

Command that can be called in a chain

Attributes

attributes[R]

@return [Hash] the attributes the command was initialized with

name[R]

@return [Symbol] the name of this command

Public Class Methods

new(name, attributes = {}, &block) click to toggle source

@!visibility private

# File lib/discordrb/commands/parser.rb, line 13
def initialize(name, attributes = {}, &block)
  @name = name
  @attributes = {
    # The lowest permission level that can use the command
    permission_level: attributes[:permission_level] || 0,

    # Message to display when a user does not have sufficient permissions to execute a command
    permission_message: attributes[:permission_message].is_a?(FalseClass) ? nil : (attributes[:permission_message] || "You don't have permission to execute command %name%!"),

    # Discord action permissions required to use this command
    required_permissions: attributes[:required_permissions] || [],

    # Roles required to use this command (all? comparison)
    required_roles: attributes[:required_roles] || [],

    # Roles allowed to use this command (any? comparison)
    allowed_roles: attributes[:allowed_roles] || [],

    # Channels this command can be used on
    channels: attributes[:channels] || nil,

    # Whether this command is usable in a command chain
    chain_usable: attributes[:chain_usable].nil? ? true : attributes[:chain_usable],

    # Whether this command should show up in the help command
    help_available: attributes[:help_available].nil? ? true : attributes[:help_available],

    # Description (for help command)
    description: attributes[:description] || nil,

    # Usage description (for help command and error messages)
    usage: attributes[:usage] || nil,

    # Array of arguments (for type-checking)
    arg_types: attributes[:arg_types] || nil,

    # Parameter list (for help command and error messages)
    parameters: attributes[:parameters] || nil,

    # Minimum number of arguments
    min_args: attributes[:min_args] || 0,

    # Maximum number of arguments (-1 for no limit)
    max_args: attributes[:max_args] || -1,

    # Message to display upon rate limiting (%time% in the message for the remaining time until the next possible
    # request, nil for no message)
    rate_limit_message: attributes[:rate_limit_message],

    # Rate limiting bucket (nil for no rate limiting)
    bucket: attributes[:bucket],

    # Block for handling internal exceptions, or a string to respond with
    rescue: attributes[:rescue],

    # A list of aliases that reference this command
    aliases: attributes[:aliases] || []
  }

  @block = block
end

Public Instance Methods

call(event, arguments, chained = false, check_permissions = true) click to toggle source

Calls this command and executes the code inside. @param event [CommandEvent] The event to call the command with. @param arguments [Array<String>] The attributes for the command. @param chained [true, false] Whether or not this command is part of a command chain. @param check_permissions [true, false] Whether the user’s permission to execute the command (i.e. rate limits)

should be checked.

@return [String] the result of the execution.

# File lib/discordrb/commands/parser.rb, line 82
def call(event, arguments, chained = false, check_permissions = true)
  if arguments.length < @attributes[:min_args]
    response = "Too few arguments for command `#{name}`!"
    response += "\nUsage: `#{@attributes[:usage]}`" if @attributes[:usage]
    event.respond(response)
    return
  end
  if @attributes[:max_args] >= 0 && arguments.length > @attributes[:max_args]
    response = "Too many arguments for command `#{name}`!"
    response += "\nUsage: `#{@attributes[:usage]}`" if @attributes[:usage]
    event.respond(response)
    return
  end
  unless @attributes[:chain_usable] && !chained
    event.respond "Command `#{name}` cannot be used in a command chain!"
    return
  end

  if check_permissions
    rate_limited = event.bot.rate_limited?(@attributes[:bucket], event.author)
    if @attributes[:bucket] && rate_limited
      event.respond @attributes[:rate_limit_message].gsub('%time%', rate_limited.round(2).to_s) if @attributes[:rate_limit_message]
      return
    end
  end

  result = @block.call(event, *arguments)
  event.drain_into(result)
rescue LocalJumpError => e # occurs when breaking
  result = e.exit_value
  event.drain_into(result)
rescue StandardError => e # Something went wrong inside our @block!
  rescue_value = @attributes[:rescue] || event.bot.attributes[:rescue]
  if rescue_value
    event.respond(rescue_value.gsub('%exception%', e.message)) if rescue_value.is_a?(String)
    rescue_value.call(event, e) if rescue_value.respond_to?(:call)
  end

  raise e
end