Class: Discordrb::Commands::CommandBot

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

Overview

Bot that supports commands and command chains

Instance Attribute Summary collapse

Attributes inherited from Bot

#bot_user, #debug, #token

Instance Method Summary collapse

Methods inherited from Bot

#add_handler, #channel, #channel_create, #channel_delete, #channel_update, #disconnected, #game=, #join, #mention, #message, #presence, #private_channel, #ready, #remove_handler, #run, #run_async, #send_file, #send_message, #server, #stop, #sync, #typing, #user, #voice_state_update

Methods included from Events

matches_all

Constructor Details

#initialize(email, password, prefix, attributes = {}, debug = false) ⇒ CommandBot

Returns a new instance of CommandBot.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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
# File 'lib/discordrb/commands/command_bot.rb', line 13

def initialize(email, password, prefix, attributes = {}, debug = false)
  super(email, password, debug)
  @prefix = prefix
  @commands = {}
  @attributes = {
    # Whether advanced functionality such as command chains are enabled
    advanced_functionality: attributes[:advanced_functionality].nil? ? true : attributes[:advanced_functionality],

    # The name of the help command (that displays information to other commands). Nil if none should exist
    help_command: 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
    command_doesnt_exist_message: attributes[:command_doesnt_exist_message] || "The command `%command%` doesn't exist!",

    # 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
    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

#attributesObject (readonly)

Returns the value of attribute attributes.



11
12
13
# File 'lib/discordrb/commands/command_bot.rb', line 11

def attributes
  @attributes
end

#prefixObject (readonly)

Returns the value of attribute prefix.



11
12
13
# File 'lib/discordrb/commands/command_bot.rb', line 11

def prefix
  @prefix
end

Instance Method Details

#command(name, attributes = {}, &block) ⇒ Object



83
84
85
# File 'lib/discordrb/commands/command_bot.rb', line 83

def command(name, attributes = {}, &block)
  @commands[name] = Command.new(name, attributes, &block)
end

#create_message(data) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/discordrb/commands/command_bot.rb', line 109

def create_message(data)
  message = Discordrb::Message.new(data, self)
  event = CommandEvent.new(message, self)

  return unless message.content.start_with? @prefix
  chain = message.content[@prefix.length..-1]

  if chain.strip.empty?
    debug('Chain is empty')
    return
  end

  debug("Parsing command chain #{chain}")
  result = (@attributes[:advanced_functionality]) ? CommandChain.new(chain, self).execute(event) : simple_execute(chain, event)
  result = event.saved_message + (result || '')
  event.respond result if result
end

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



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/discordrb/commands/command_bot.rb', line 87

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) if @attributes[:command_doesnt_exist_message]
    return
  end
  if permission?(user(event.user.id), command.attributes[:permission_level], event.server.id)
    event.command = command
    command.call(event, arguments, chained)
  else
    event.respond "You don't have permission to execute command `#{name}`!"
    return
  end
end

#permission?(user, level, server_id) ⇒ Boolean

Returns:

  • (Boolean)


135
136
137
138
139
140
# File 'lib/discordrb/commands/command_bot.rb', line 135

def permission?(user, level, server_id)
  determined_level = user.roles[server_id].each.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



131
132
133
# File 'lib/discordrb/commands/command_bot.rb', line 131

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

#set_user_permission(id, level) ⇒ Object



127
128
129
# File 'lib/discordrb/commands/command_bot.rb', line 127

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

#simple_execute(chain, event) ⇒ Object



103
104
105
106
107
# File 'lib/discordrb/commands/command_bot.rb', line 103

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