Class: Discordrb::Commands::CommandBot

Inherits:
Bot
  • Object
show all
Includes:
CommandContainer
Defined in:
lib/discordrb/commands/command_bot.rb

Overview

Bot that supports commands and command chains

Instance Attribute Summary collapse

Attributes inherited from Bot

#event_threads, #name, #profile, #servers, #should_parse_self, #users, #voices

Instance Method Summary collapse

Methods included from CommandContainer

#command, #include!, #include_commands, #remove_command

Methods included from RateLimiter

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

Methods inherited from Bot

#add_await, #create_oauth_application, #create_server, #debug, #debug=, #delete_invite, #game=, #ignore_user, #inject_reconnect, #inject_resume, #invite_url, #join, #log_exception, #mode=, #parse_mention, #raw_token, #run, #run_async, #send_file, #send_message, #stop, #suppress_ready_debug, #sync, #token, #unignore_user, #update_oauth_application, #voice, #voice_connect, #voice_destroy

Methods included from Discordrb::Cache

#channel, #ensure_channel, #ensure_server, #ensure_user, #find_channel, #find_user, #init_cache, #invite, #member, #private_channel, #request_chunks, #resolve_invite_code, #server, #user

Methods included from EventContainer

#add_handler, #await, #channel_create, #channel_delete, #channel_update, class_from_string, #clear!, #disconnected, event_class, handler_class, #include_events, #member_join, #member_leave, #member_update, #mention, #message, #message_delete, #message_edit, #playing, #pm, #presence, #ready, #remove_handler, #server_create, #server_delete, #server_update, #typing, #user_ban, #user_unban, #voice_state_update

Methods included from Events

matches_all

Constructor Details

#initialize(attributes = {}) ⇒ CommandBot

Creates a new CommandBot and logs in to Discord.

Parameters:

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

    The attributes to initialize the CommandBot with.

Options Hash (attributes):

  • :prefix (String)

    The prefix that should trigger this bot's commands. Can be any string (including the empty string), but note that it will be literal - if the prefix is "hi" then the corresponding trigger string for a command called "test" would be "hitest". Don't forget to put spaces in if you need them!

  • :advanced_functionality (true, false)

    Whether to enable advanced functionality (very powerful way to nest commands into chains, see https://github.com/meew0/discordrb/wiki/Commands#command-chain-syntax for info. Default is true.

  • :help_command (Symbol, Array<Symbol>, false)

    The name of the command that displays info for other commands. Use an array if you want to have aliases. Default is "help". If none should be created, use false as the value.

  • :command_doesnt_exist_message (String)

    The message that should be displayed if a user attempts to use a command that does not exist. If none is specified, no message will be displayed. In the message, you can use the string '%command%' that will be replaced with the name of the command.

  • :spaces_allowed (true, false)

    Whether spaces are allowed to occur between the prefix and the command. Default is false.

  • :previous (String)

    Character that should designate the result of the previous command in a command chain (see :advanced_functionality). Default is '~'.

  • :chain_delimiter (String)

    Character that should designate that a new command begins in the command chain (see :advanced_functionality). Default is '>'.

  • :chain_args_delim (String)

    Character that should separate the command chain arguments from the chain itself (see :advanced_functionality). Default is ':'.

  • :sub_chain_start (String)

    Character that should start a sub-chain (see :advanced_functionality). Default is '['.

  • :sub_chain_end (String)

    Character that should end a sub-chain (see :advanced_functionality). Default is ']'.

  • :quote_start (String)

    Character that should start a quoted string (see :advanced_functionality). Default is '"'.

  • :quote_end (String)

    Character that should end a quoted string (see :advanced_functionality). Default is '"'.

See Also:

  • for other attributes that should be used to create the underlying regular bot.


54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/discordrb/commands/command_bot.rb', line 54

def initialize(attributes = {})
  super(
    email: attributes[:email],
    password: attributes[:password],
    log_mode: attributes[:log_mode],
    token: attributes[:token],
    application_id: attributes[:application_id],
    type: attributes[:type],
    name: attributes[:name],
    fancy_log: attributes[:fancy_log],
    suppress_ready: attributes[:suppress_ready],
    parse_self: attributes[:parse_self])

  @prefix = attributes[:prefix]
  @attributes = {
    # Whether advanced functionality such as command chains are enabled
    advanced_functionality: attributes[:advanced_functionality].nil? ? false : attributes[:advanced_functionality],

    # The name of the help command (that displays information to other commands). False if none should exist
    help_command: (attributes[:help_command].is_a? FalseClass) ? nil : (attributes[:help_command] || :help),

    # The message to display for when a command doesn't exist, %command% to get the command name in question and nil for no message
    # No default value here because it may not be desired behaviour
    command_doesnt_exist_message: attributes[:command_doesnt_exist_message],

    # Spaces allowed between prefix and command
    spaces_allowed: attributes[:spaces_allowed].nil? ? false : attributes[:spaces_allowed],

    # All of the following need to be one character
    # String to designate previous result in command chain
    previous: attributes[:previous] || '~',

    # Command chain delimiter
    chain_delimiter: attributes[:chain_delimiter] || '>',

    # Chain argument delimiter
    chain_args_delim: attributes[:chain_args_delim] || ':',

    # Sub-chain starting character
    sub_chain_start: attributes[:sub_chain_start] || '[',

    # Sub-chain ending character
    sub_chain_end: attributes[:sub_chain_end] || ']',

    # Quoted mode starting character
    quote_start: attributes[:quote_start] || '"',

    # Quoted mode ending character
    quote_end: attributes[:quote_end] || '"'
  }

  @permissions = {
    roles: {},
    users: {}
  }

  return unless @attributes[:help_command]
  command(@attributes[:help_command], max_args: 1, description: 'Shows a list of all the commands available or displays help for a specific command.', usage: 'help [command name]') do |event, command_name|
    if command_name
      command = @commands[command_name.to_sym]
      return "The command `#{command_name}` does not exist!" unless command
      desc = command.attributes[:description] || '*No description available*'
      usage = command.attributes[:usage]
      result = "**`#{command_name}`**: #{desc}"
      result += "\nUsage: `#{usage}`" if usage
      result
    else
      available_commands = @commands.values.reject { |c| !c.attributes[:help_available] }
      case available_commands.length
      when 0..5
        available_commands.reduce "**List of commands:**\n" do |memo, c|
          memo + "**`#{c.name}`**: #{c.attributes[:description] || '*No description available*'}\n"
        end
      when 5..50
        (available_commands.reduce "**List of commands:**\n" do |memo, c|
          memo + "`#{c.name}`, "
        end)[0..-3]
      else
        event.user.pm(available_commands.reduce("**List of commands:**\n") { |a, e| a + "`#{e.name}`, " })[0..-3]
        'Sending list in PM!'
      end
    end
  end
end

Instance Attribute Details

#attributesHash (readonly)

Returns this bot's attributes.

Returns:

  • (Hash)

    this bot's attributes.



16
17
18
# File 'lib/discordrb/commands/command_bot.rb', line 16

def attributes
  @attributes
end

#prefixString (readonly)

Returns the prefix commands are triggered with.

Returns:

  • (String)

    the prefix commands are triggered with.



19
20
21
# File 'lib/discordrb/commands/command_bot.rb', line 19

def prefix
  @prefix
end

Instance Method Details

#execute_command(name, event, arguments, chained = false) ⇒ String?

Executes a particular command on the bot. Mostly useful for internal stuff, but one can never know.

Parameters:

  • name (Symbol)

    The command to execute.

  • event (CommandEvent)

    The event to pass to the command.

  • arguments (Array<String>)

    The arguments to pass to the command.

  • chained (true, false) (defaults to: false)

    Whether or not it should be executed as part of a command chain. If this is false, commands that have chain_usable set to false will not work.

Returns:

  • (String, nil)

    the command's result, if there is any.



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/discordrb/commands/command_bot.rb', line 146

def execute_command(name, event, arguments, chained = false)
  debug("Executing command #{name} with arguments #{arguments}")
  command = @commands[name]
  unless command
    event.respond @attributes[:command_doesnt_exist_message].gsub('%command%', name.to_s) if @attributes[:command_doesnt_exist_message]
    return
  end
  if permission?(event.user, command.attributes[:permission_level], event.server)
    event.command = command
    result = command.call(event, arguments, chained)
    stringify(result)
  else
    event.respond "You don't have permission to execute command `#{name}`!"
  end
end

#permission?(user, level, server) ⇒ true, false

Check if a user has permission to do something

Parameters:

  • user (User)

    The user to check

  • level (Integer)

    The minimum permission level the user should have (inclusive)

  • server (Server)

    The server on which to check

Returns:

  • (true, false)

    whether or not the user has the given permission



191
192
193
194
195
196
# File 'lib/discordrb/commands/command_bot.rb', line 191

def permission?(user, level, server)
  determined_level = server.nil? ? 0 : user.roles.reduce(0) do |memo, role|
    [@permissions[:roles][role.id] || 0, memo].max
  end
  [@permissions[:users][user.id] || 0, determined_level].max >= level
end

#set_role_permission(id, level) ⇒ Object

Sets the permission level of a role - this applies to all users in the role

Parameters:

  • id (Integer)

    the ID of the role whose level to set

  • level (Integer)

    the level to set the permission to



182
183
184
# File 'lib/discordrb/commands/command_bot.rb', line 182

def set_role_permission(id, level)
  @permissions[:roles][id] = level
end

#set_user_permission(id, level) ⇒ Object

Sets the permission level of a user

Parameters:

  • id (Integer)

    the ID of the user whose level to set

  • level (Integer)

    the level to set the permission to



175
176
177
# File 'lib/discordrb/commands/command_bot.rb', line 175

def set_user_permission(id, level)
  @permissions[:users][id] = level
end

#simple_execute(chain, event) ⇒ String?

Executes a command in a simple manner, without command chains or permissions.

Parameters:

  • chain (String)

    The command with its arguments separated by spaces.

  • event (CommandEvent)

    The event to pass to the command.

Returns:

  • (String, nil)

    the command's result, if there is any.



166
167
168
169
170
# File 'lib/discordrb/commands/command_bot.rb', line 166

def simple_execute(chain, event)
  return nil if chain.empty?
  args = chain.split(' ')
  execute_command(args[0].to_sym, event, args[1..-1])
end