discordrb 1.3.4 → 1.3.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of discordrb might be problematic. Click here for more details.

@@ -6,6 +6,7 @@ require 'discordrb/commands/events'
6
6
  # Specialized bot to run commands
7
7
 
8
8
  module Discordrb::Commands
9
+ # Bot that supports commands and command chains
9
10
  class CommandBot < Discordrb::Bot
10
11
  attr_reader :attributes, :prefix
11
12
 
@@ -51,34 +52,29 @@ module Discordrb::Commands
51
52
  users: {}
52
53
  }
53
54
 
54
- if @attributes[:help_command]
55
- 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|
56
- if command_name
57
- command = @commands[command_name.to_sym]
58
- unless command
59
- return "The command `#{command_name}` does not exist!"
55
+ return unless @attributes[:help_command]
56
+ 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|
57
+ if command_name
58
+ command = @commands[command_name.to_sym]
59
+ return "The command `#{command_name}` does not exist!" unless command
60
+ desc = command.attributes[:description] || '*No description available*'
61
+ usage = command.attributes[:usage]
62
+ result = "**`#{command_name}`**: #{desc}"
63
+ result << "\nUsage: `#{usage}`" if usage
64
+ else
65
+ available_commands = @commands.values.reject { |c| !c.attributes[:help_available] }
66
+ case available_commands.length
67
+ when 0..5
68
+ available_commands.reduce "**List of commands:**\n" do |memo, c|
69
+ memo + "**`#{c.name}`**: #{c.attributes[:description] || '*No description available*'}\n"
60
70
  end
61
- desc = command.attributes[:description] || '*No description available*'
62
- usage = command.attributes[:usage]
63
- result = "**`#{command_name}`**: #{desc}"
64
- result << "\nUsage: `#{usage}`" if usage
71
+ when 5..50
72
+ (available_commands.reduce "**List of commands:**\n" do |memo, c|
73
+ memo + "`#{c.name}`, "
74
+ end)[0..-3]
65
75
  else
66
- available_commands = @commands.values.reject { |command| !command.attributes[:help_available] }
67
- case available_commands.length
68
- when 0..5
69
- available_commands.reduce "**List of commands:**\n" do |memo, command|
70
- memo + "**`#{command.name}`**: #{command.attributes[:description] || '*No description available*'}\n"
71
- end
72
- when 5..50
73
- (available_commands.reduce "**List of commands:**\n" do |memo, command|
74
- memo + "`#{command.name}`, "
75
- end)[0..-3]
76
- else
77
- event.user.pm (available_commands.reduce "**List of commands:**\n" do |memo, command|
78
- memo + "`#{command.name}`, "
79
- end)[0..-3]
80
- "Sending list in PM!"
81
- end
76
+ event.user.pm(available_commands.reduce("**List of commands:**\n") { |a, e| a + "`#{e.name}`, " })[0..-3]
77
+ 'Sending list in PM!'
82
78
  end
83
79
  end
84
80
  end
@@ -114,19 +110,18 @@ module Discordrb::Commands
114
110
  message = Discordrb::Message.new(data, self)
115
111
  event = CommandEvent.new(message, self)
116
112
 
117
- if message.content.start_with? @prefix
118
- chain = message.content[@prefix.length..-1]
119
-
120
- if chain.strip.empty?
121
- debug("Chain is empty")
122
- return
123
- end
113
+ return unless message.content.start_with? @prefix
114
+ chain = message.content[@prefix.length..-1]
124
115
 
125
- debug("Parsing command chain #{chain}")
126
- result = (@attributes[:advanced_functionality]) ? CommandChain.new(chain, self).execute(event) : simple_execute(chain, event)
127
- result = event.saved_message + (result || '')
128
- event.respond result if result
116
+ if chain.strip.empty?
117
+ debug('Chain is empty')
118
+ return
129
119
  end
120
+
121
+ debug("Parsing command chain #{chain}")
122
+ result = (@attributes[:advanced_functionality]) ? CommandChain.new(chain, self).execute(event) : simple_execute(chain, event)
123
+ result = event.saved_message + (result || '')
124
+ event.respond result if result
130
125
  end
131
126
 
132
127
  def set_user_permission(id, level)
@@ -1,6 +1,7 @@
1
1
  require 'discordrb/events/message'
2
2
 
3
3
  module Discordrb::Commands
4
+ # Extension of MessageEvent for commands that contains the command called, makes the bot readable and adds a message to be saved
4
5
  class CommandEvent < Discordrb::Events::MessageEvent
5
6
  attr_reader :bot, :saved_message
6
7
  attr_accessor :command
@@ -1,4 +1,5 @@
1
1
  module Discordrb::Commands
2
+ # Command that can be called in a chain
2
3
  class Command
3
4
  attr_reader :attributes, :name
4
5
 
@@ -51,6 +52,7 @@ module Discordrb::Commands
51
52
  end
52
53
  end
53
54
 
55
+ # Command chain, may have multiple commands, nested and commands
54
56
  class CommandChain
55
57
  def initialize(chain, bot, subchain = false)
56
58
  @attributes = bot.attributes
@@ -60,7 +62,8 @@ module Discordrb::Commands
60
62
  end
61
63
 
62
64
  def execute_bare(event)
63
- b_start, b_level = -1, 0
65
+ b_start = -1
66
+ b_level = 0
64
67
  result = ''
65
68
  quoted = false
66
69
  hacky_delim, hacky_space, hacky_prev = [0xe001, 0xe002, 0xe003].pack('U*').chars
@@ -100,14 +103,12 @@ module Discordrb::Commands
100
103
 
101
104
  result << char if b_level <= 0
102
105
 
103
- if char == @attributes[:sub_chain_end] && !quoted
104
- b_level -= 1
105
- if b_level == 0
106
- nested = @chain[b_start + 1 .. index - 1]
107
- subchain = CommandChain.new(nested, @bot, true)
108
- result << subchain.execute(event)
109
- end
110
- end
106
+ next unless char == @attributes[:sub_chain_end] && !quoted
107
+ b_level -= 1
108
+ next unless b_level == 0
109
+ nested = @chain[b_start + 1..index - 1]
110
+ subchain = CommandChain.new(nested, @bot, true)
111
+ result << subchain.execute(event)
111
112
  end
112
113
 
113
114
  event.respond("Your subchains are mismatched! Make sure you don't have any extra #{@attributes[:sub_chain_start]}'s or #{@attributes[:sub_chain_end]}'s") unless b_level == 0
@@ -135,8 +136,8 @@ module Discordrb::Commands
135
136
  command.gsub! hacky_delim, @attributes[:chain_delimiter]
136
137
 
137
138
  first_space = command.index ' '
138
- command_name = first_space ? command[0..first_space-1] : command
139
- arguments = first_space ? command[first_space+1..-1] : ''
139
+ command_name = first_space ? command[0..first_space - 1] : command
140
+ arguments = first_space ? command[first_space + 1..-1] : ''
140
141
 
141
142
  # Append a previous sign if none is present
142
143
  arguments << @attributes[:previous] unless arguments.include? @attributes[:previous]
@@ -161,7 +162,7 @@ module Discordrb::Commands
161
162
 
162
163
  def execute(event)
163
164
  old_chain = @chain
164
- @bot.debug "Executing bare chain"
165
+ @bot.debug 'Executing bare chain'
165
166
  result = execute_bare(event)
166
167
 
167
168
  @chain_args ||= []
@@ -179,7 +180,7 @@ module Discordrb::Commands
179
180
  end
180
181
 
181
182
  result = new_result
182
- # TODO: more chain arguments
183
+ # TODO: more chain arguments
183
184
  end
184
185
  end
185
186
 
@@ -201,7 +202,7 @@ module Discordrb::Commands
201
202
  arg.split ' '
202
203
  end
203
204
 
204
- chain = chain[chain_args_index+1..-1]
205
+ chain = chain[chain_args_index + 1..-1]
205
206
  end
206
207
 
207
208
  [chain_args, chain]
@@ -6,6 +6,7 @@ require 'discordrb/api'
6
6
  require 'discordrb/games'
7
7
 
8
8
  module Discordrb
9
+ # User on Discord, including internal data like discriminators
9
10
  class User
10
11
  attr_reader :username, :id, :discriminator, :avatar
11
12
 
@@ -76,11 +77,11 @@ module Discordrb
76
77
  # Determine if the user has permission to do an action
77
78
  # action is a permission from Permissions::Flags.
78
79
  # channel is the channel in which the action takes place (not applicable for server-wide actions).
79
- def has_permission?(action, server, channel = nil)
80
+ def permission?(action, server, channel = nil)
80
81
  # For each role, check if
81
82
  # (1) the channel explicitly allows or permits an action for the role and
82
83
  # (2) if the user is allowed to do the action if the channel doesn't specify
83
- return false if !@roles[server.id]
84
+ return false unless @roles[server.id]
84
85
 
85
86
  @roles[server.id].reduce(false) do |can_act, role|
86
87
  channel_allow = nil
@@ -91,28 +92,29 @@ module Discordrb
91
92
  channel_allow = true
92
93
  elsif deny.instance_variable_get("@#{action}")
93
94
  channel_allow = false
94
- # else
95
- # If the channel has nothing to say on the matter, we can defer to the role itself
96
95
  end
96
+ # If the channel has nothing to say on the matter, we can defer to the role itself
97
97
  end
98
98
  if channel_allow == false
99
- can_act = can_act || false
99
+ can_act = false
100
100
  elsif channel_allow == true
101
101
  can_act = true
102
102
  else # channel_allow == nil
103
103
  can_act = role.permissions.instance_variable_get("@#{action}") || can_act
104
104
  end
105
+ can_act
105
106
  end
106
107
  end
107
108
 
108
109
  # Define methods for querying permissions
109
110
  Discordrb::Permissions::Flags.each_value do |flag|
110
111
  define_method "can_#{flag}?" do |server, channel = nil|
111
- has_permission? flag, server, channel
112
+ permission? flag, server, channel
112
113
  end
113
114
  end
114
115
  end
115
116
 
117
+ # A Discord role that contains permissions and applies to certain users
116
118
  class Role
117
119
  attr_reader :permissions
118
120
  attr_reader :name
@@ -121,6 +123,8 @@ module Discordrb
121
123
  attr_reader :color
122
124
 
123
125
  def initialize(data, bot, server = nil)
126
+ @bot = bot
127
+ @server = server
124
128
  @permissions = Permissions.new(data['permissions'])
125
129
  @name = data['name']
126
130
  @id = data['id'].to_i
@@ -136,6 +140,7 @@ module Discordrb
136
140
  end
137
141
  end
138
142
 
143
+ # A Discord channel, including data like the topic
139
144
  class Channel
140
145
  attr_reader :name, :server, :type, :id, :is_private, :recipient, :topic, :position
141
146
 
@@ -144,7 +149,7 @@ module Discordrb
144
149
  def initialize(data, bot, server = nil)
145
150
  @bot = bot
146
151
 
147
- #data is a sometimes a Hash and othertimes an array of Hashes, you only want the last one if it's an array
152
+ # data is a sometimes a Hash and othertimes an array of Hashes, you only want the last one if it's an array
148
153
  data = data[-1] if data.is_a?(Array)
149
154
 
150
155
  @id = data['id'].to_i
@@ -159,20 +164,19 @@ module Discordrb
159
164
  else
160
165
  @name = data['name']
161
166
  @server = bot.server(data['guild_id'].to_i)
162
- @server = server if !@server
167
+ @server ||= server
163
168
  end
164
169
 
165
170
  # Populate permission overwrites
166
171
  @permission_overwrites = {}
167
- if data['permission_overwrites']
168
- data['permission_overwrites'].each do |element|
169
- role_id = element['id'].to_i
170
- deny = Permissions.new(element['deny'])
171
- allow = Permissions.new(element['allow'])
172
- @permission_overwrites[role_id] = OpenStruct.new
173
- @permission_overwrites[role_id].deny = deny
174
- @permission_overwrites[role_id].allow = allow
175
- end
172
+ return unless data['permission_overwrites']
173
+ data['permission_overwrites'].each do |element|
174
+ role_id = element['id'].to_i
175
+ deny = Permissions.new(element['deny'])
176
+ allow = Permissions.new(element['allow'])
177
+ @permission_overwrites[role_id] = OpenStruct.new
178
+ @permission_overwrites[role_id].deny = deny
179
+ @permission_overwrites[role_id].allow = allow
176
180
  end
177
181
  end
178
182
 
@@ -214,12 +218,10 @@ module Discordrb
214
218
  # List of users currently in a channel
215
219
  def users
216
220
  if @type == 'text'
217
- @server.members.select {|u| u.status != :offline }
221
+ @server.members.select { |u| u.status != :offline }
218
222
  else
219
223
  @server.members.select do |user|
220
- if user.voice_channel
221
- user.voice_channel.id == @id
222
- end
224
+ user.voice_channel.id == @id if user.voice_channel
223
225
  end
224
226
  end
225
227
  end
@@ -238,6 +240,7 @@ module Discordrb
238
240
  end
239
241
  end
240
242
 
243
+ # A message on Discord that was sent to a text channel
241
244
  class Message
242
245
  attr_reader :content, :author, :channel, :timestamp, :id, :mentions
243
246
  alias_method :user, :author
@@ -271,6 +274,7 @@ module Discordrb
271
274
  end
272
275
  end
273
276
 
277
+ # A server on Discord
274
278
  class Server
275
279
  attr_reader :region, :name, :owner_id, :id, :members
276
280
 
@@ -304,8 +308,8 @@ module Discordrb
304
308
  @members << user
305
309
  members_by_id[user.id] = user
306
310
  user_roles = []
307
- element['roles'].each do |element|
308
- role_id = element.to_i
311
+ element['roles'].each do |e|
312
+ role_id = e.to_i
309
313
  user_roles << roles_by_id[role_id]
310
314
  end
311
315
  user.update_roles(self, user_roles)
@@ -314,13 +318,12 @@ module Discordrb
314
318
  # Update user statuses with presence info
315
319
  if data['presences']
316
320
  data['presences'].each do |element|
317
- if element['user']
318
- user_id = element['user']['id'].to_i
319
- user = members_by_id[user_id]
320
- if user
321
- user.status = element['status'].to_sym
322
- user.game = Discordrb::Games.find_game(element['game_id'])
323
- end
321
+ next unless element['user']
322
+ user_id = element['user']['id'].to_i
323
+ user = members_by_id[user_id]
324
+ if user
325
+ user.status = element['status'].to_sym
326
+ user.game = Discordrb::Games.find_game(element['game_id'])
324
327
  end
325
328
  end
326
329
  end
@@ -336,23 +339,18 @@ module Discordrb
336
339
  end
337
340
  end
338
341
 
339
- if data['voice_states']
340
- data['voice_states'].each do |element|
341
- user_id = element['user_id'].to_i
342
- user = members_by_id[user_id]
343
- if user
344
- user.server_mute = element['mute']
345
- user.server_deaf = element['deaf']
346
- user.self_mute = element['self_mute']
347
- user.self_mute = element['self_mute']
348
- channel_id = element['channel_id']
349
- channel = nil
350
- if channel_id
351
- channel = channels_by_id[channel_id]
352
- end
353
- user.move(channel)
354
- end
355
- end
342
+ return unless data['voice_states']
343
+ data['voice_states'].each do |element|
344
+ user_id = element['user_id'].to_i
345
+ user = members_by_id[user_id]
346
+ next unless user
347
+ user.server_mute = element['mute']
348
+ user.server_deaf = element['deaf']
349
+ user.self_mute = element['self_mute']
350
+ user.self_mute = element['self_mute']
351
+ channel_id = element['channel_id']
352
+ channel = channel_id ? channels_by_id[channel_id] : nil
353
+ user.move(channel)
356
354
  end
357
355
  end
358
356
 
@@ -361,13 +359,13 @@ module Discordrb
361
359
  end
362
360
 
363
361
  def delete_role(role_id)
364
- @roles.reject! {|r| r.id == role_id}
362
+ @roles.reject! { |r| r.id == role_id }
365
363
  @members.each do |user|
366
- new_roles = user.roles.reject {|r| r.id == role_id}
364
+ new_roles = user.roles.reject { |r| r.id == role_id }
367
365
  user.update_roles(self, new_roles)
368
366
  end
369
367
  @channels.each do |channel|
370
- overwrites = channel.permission_overwrites.reject {|id, perm| id == role_id}
368
+ overwrites = channel.permission_overwrites.reject { |id, _| id == role_id }
371
369
  channel.update_overwrites(overwrites)
372
370
  end
373
371
  end
@@ -378,6 +376,7 @@ module Discordrb
378
376
  end
379
377
  end
380
378
 
379
+ # A colour (red, green and blue values). Used for role colours
381
380
  class ColorRGB
382
381
  attr_reader :red, :green, :blue
383
382
 
@@ -1,48 +1,50 @@
1
- require 'discordrb/events/generic'
2
- require 'discordrb/data'
3
-
4
- module Discordrb::Events
5
- class ChannelCreateEvent
6
- attr_reader :type
7
- attr_reader :topic
8
- attr_reader :position
9
- attr_reader :name
10
- attr_reader :is_private
11
- attr_reader :id
12
- attr_reader :server
13
-
14
- def initialize(data, bot)
15
- @type = data['type']
16
- @topic = data['topic']
17
- @position = data['position']
18
- @name = data['name']
19
- @is_private = data['is_private']
20
- @id = data['id']
21
- @server = bot.server(data['guild_id'].to_i)
22
- end
23
- end
24
-
25
- class ChannelCreateEventHandler < EventHandler
26
- def matches?(event)
27
- # Check for the proper event type
28
- return false unless event.is_a? ChannelCreateEvent
29
-
30
- return [
31
- matches_all(@attributes[:type], event.type) do |a,e|
32
- if a.is_a? String
33
- a == e.name
34
- else
35
- a == e
36
- end
37
- end,
38
- matches_all(@attributes[:name], event.name) do |a,e|
39
- if a.is_a? String
40
- a == e.to_s
41
- else
42
- a == e
43
- end
44
- end
45
- ].reduce(true, &:&)
46
- end
47
- end
48
- end
1
+ require 'discordrb/events/generic'
2
+ require 'discordrb/data'
3
+
4
+ module Discordrb::Events
5
+ # Raised when a channel is created
6
+ class ChannelCreateEvent
7
+ attr_reader :type
8
+ attr_reader :topic
9
+ attr_reader :position
10
+ attr_reader :name
11
+ attr_reader :is_private
12
+ attr_reader :id
13
+ attr_reader :server
14
+
15
+ def initialize(data, bot)
16
+ @type = data['type']
17
+ @topic = data['topic']
18
+ @position = data['position']
19
+ @name = data['name']
20
+ @is_private = data['is_private']
21
+ @id = data['id']
22
+ @server = bot.server(data['guild_id'].to_i)
23
+ end
24
+ end
25
+
26
+ # Event handler for ChannelCreateEvent
27
+ class ChannelCreateEventHandler < EventHandler
28
+ def matches?(event)
29
+ # Check for the proper event type
30
+ return false unless event.is_a? ChannelCreateEvent
31
+
32
+ [
33
+ matches_all(@attributes[:type], event.type) do |a, e|
34
+ if a.is_a? String
35
+ a == e.name
36
+ else
37
+ a == e
38
+ end
39
+ end,
40
+ matches_all(@attributes[:name], event.name) do |a, e|
41
+ if a.is_a? String
42
+ a == e.to_s
43
+ else
44
+ a == e
45
+ end
46
+ end
47
+ ].reduce(true, &:&)
48
+ end
49
+ end
50
+ end