discordrb 1.3.12 → 1.4.0

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.

@@ -88,7 +88,7 @@ module Discordrb::Commands
88
88
  debug("Executing command #{name} with arguments #{arguments}")
89
89
  command = @commands[name]
90
90
  unless command
91
- event.respond @attributes[:command_doesnt_exist_message].gsub('%command%', name) if @attributes[:command_doesnt_exist_message]
91
+ event.respond @attributes[:command_doesnt_exist_message].gsub('%command%', name.to_s) if @attributes[:command_doesnt_exist_message]
92
92
  return
93
93
  end
94
94
  if permission?(user(event.user.id), command.attributes[:permission_level], event.server)
@@ -118,10 +118,24 @@ module Discordrb::Commands
118
118
  return
119
119
  end
120
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
121
+ execute_chain(chain, event)
122
+ end
123
+
124
+ def execute_chain(chain, event)
125
+ t = Thread.new do
126
+ @event_threads << t
127
+ Thread.current[:discordrb_name] = "ct-#{@current_thread += 1}"
128
+ begin
129
+ debug("Parsing command chain #{chain}")
130
+ result = (@attributes[:advanced_functionality]) ? CommandChain.new(chain, self).execute(event) : simple_execute(chain, event)
131
+ result = event.saved_message + (result || '')
132
+ event.respond result if result
133
+ rescue => e
134
+ log_exception(e)
135
+ ensure
136
+ @event_threads.delete(t)
137
+ end
138
+ end
125
139
  end
126
140
 
127
141
  def set_user_permission(id, level)
@@ -4,7 +4,9 @@ require 'ostruct'
4
4
  require 'discordrb/permissions'
5
5
  require 'discordrb/api'
6
6
  require 'discordrb/games'
7
+ require 'base64'
7
8
 
9
+ # Discordrb module
8
10
  module Discordrb
9
11
  # User on Discord, including internal data like discriminators
10
12
  class User
@@ -121,25 +123,164 @@ module Discordrb
121
123
  end
122
124
  end
123
125
 
126
+ # A class that represents the bot user itself and has methods to change stuff
127
+ class Profile < User
128
+ def initialize(data, bot, email, password)
129
+ super(data, bot)
130
+ @email = email
131
+ @password = password
132
+ end
133
+
134
+ def bot?
135
+ true
136
+ end
137
+
138
+ def username=(username)
139
+ update_server_data(username: username)
140
+ end
141
+
142
+ def email=(email)
143
+ update_server_data(email: email)
144
+ end
145
+
146
+ def password=(password)
147
+ update_server_data(new_password: password)
148
+ end
149
+
150
+ def avatar=(avatar)
151
+ if avatar.is_a? File
152
+ avatar_string = 'data:image/jpg;base64,'
153
+ avatar_string += Base64.strict_encode64(avatar.read)
154
+ update_server_data(avatar: avatar_string)
155
+ else
156
+ update_server_data(avatar: avatar)
157
+ end
158
+ end
159
+
160
+ def update_data(new_data)
161
+ @email = new_data[:email] || @email
162
+ @password = new_data[:new_password] || @password
163
+ @username = new_data[:username] || @username
164
+ @avatar = new_data[:avatar] || @avatar
165
+ end
166
+
167
+ private
168
+
169
+ def update_server_data(new_data)
170
+ API.update_user(@bot.token,
171
+ new_data[:email] || @email,
172
+ @password,
173
+ new_data[:username] || @username,
174
+ new_data[:avatar] || @avatar,
175
+ new_data[:new_password] || nil)
176
+ update_data(new_data)
177
+ end
178
+ end
179
+
124
180
  # A Discord role that contains permissions and applies to certain users
125
181
  class Role
126
- attr_reader :permissions, :name, :id, :hoist, :color
182
+ attr_reader :permissions, :name, :id, :hoist, :colour
183
+ alias_method :color, :colour
184
+
185
+ # Class that writes data for a Permissions object
186
+ class RoleWriter
187
+ def initialize(role, token)
188
+ @role = role
189
+ @token = token
190
+ end
191
+
192
+ def write(bits)
193
+ @role.send(:packed=, bits, false)
194
+ end
195
+ end
127
196
 
128
197
  def initialize(data, bot, server = nil)
129
198
  @bot = bot
130
199
  @server = server
131
- @permissions = Permissions.new(data['permissions'])
200
+ @permissions = Permissions.new(data['permissions'], RoleWriter.new(self, @bot.token))
132
201
  @name = data['name']
133
202
  @id = data['id'].to_i
134
203
  @hoist = data['hoist']
135
- @color = ColorRGB.new(data['color'])
204
+ @colour = ColourRGB.new(data['color'])
136
205
  end
137
206
 
138
207
  def update_from(other)
139
208
  @permissions = other.permissions
140
209
  @name = other.name
141
210
  @hoist = other.hoist
142
- @color = other.color
211
+ @colour = other.colour
212
+ end
213
+
214
+ def update_data(new_data)
215
+ @name = new_data[:name] || new_data['name'] || @name
216
+ @hoist = new_data['hoist'] unless new_data['hoist'].nil?
217
+ @hoist = new_data[:hoist] unless new_data[:hoist].nil?
218
+ @colour = new_data[:colour] || (new_data['color'] ? ColourRGB.new(new_data['color']) : @colour)
219
+ end
220
+
221
+ def name=(name)
222
+ update_role_data(name: name)
223
+ end
224
+
225
+ def hoist=(hoist)
226
+ update_role_data(hoist: hoist)
227
+ end
228
+
229
+ def colour=(colour)
230
+ update_role_data(colour: colour)
231
+ end
232
+
233
+ alias_method :color=, :colour=
234
+
235
+ def packed=(packed, update_perms = true)
236
+ update_role_data(permissions: packed)
237
+ @permissions.bits = packed if update_perms
238
+ end
239
+
240
+ def delete
241
+ API.delete_role(@bot.token, @server.id, @id)
242
+ @server.delete_role(@id)
243
+ end
244
+
245
+ private
246
+
247
+ def update_role_data(new_data)
248
+ API.update_role(@bot.token, @server.id, @id,
249
+ new_data[:name] || @name,
250
+ (new_data[:colour] || @colour).combined,
251
+ !(!(new_data[:hoist].nil? ? new_data[:hoist] : @hoist)),
252
+ new_data[:permissions] || @permissions.bits)
253
+ update_data(new_data)
254
+ end
255
+ end
256
+
257
+ # A Discord invite to a channel
258
+ class Invite
259
+ attr_reader :channel, :uses, :inviter, :temporary, :revoked, :xkcd, :code
260
+ alias_method :max_uses, :uses
261
+ alias_method :user, :inviter
262
+
263
+ alias_method :temporary?, :temporary
264
+ alias_method :revoked?, :revoked
265
+ alias_method :xkcd?, :xkcd
266
+
267
+ delegate :server, to: :channel
268
+
269
+ def initialize(data, bot)
270
+ @bot = bot
271
+
272
+ @channel = Channel.new(data['channel'], bot)
273
+ @uses = data['uses']
274
+ @inviter = @bot.user(data['inviter']['id'].to_i) || User.new(data['inviter'], bot)
275
+ @temporary = data['temporary']
276
+ @revoked = data['revoked']
277
+ @xkcd = data['xkcdpass']
278
+
279
+ @code = data['code']
280
+ end
281
+
282
+ def delete
283
+ API.delete_invite(@bot.token, @code)
143
284
  end
144
285
  end
145
286
 
@@ -231,6 +372,11 @@ module Discordrb
231
372
  end
232
373
  end
233
374
 
375
+ def history(amount, before_id = nil, after_id = nil)
376
+ logs = API.channel_log(@bot.token, @id, amount, before_id, after_id)
377
+ JSON.parse(logs).map { |message| Message.new(message, @bot) }
378
+ end
379
+
234
380
  def update_overwrites(overwrites)
235
381
  @permission_overwrites = overwrites
236
382
  end
@@ -240,8 +386,21 @@ module Discordrb
240
386
  @bot.add_await(key, MessageEvent, { in: @id }.merge(attributes), &block)
241
387
  end
242
388
 
389
+ def make_invite(max_age = 0, max_uses = 0, temporary = false, xkcd = false)
390
+ response = API.create_invite(@bot.token, @id, max_age, max_uses, temporary, xkcd)
391
+ Invite.new(JSON.parse(response), @bot)
392
+ end
393
+
394
+ # Starts typing, which displays the typing indicator on the client for five seconds.
395
+ # If you want to keep typing you'll have to resend this every five seconds. (An abstraction
396
+ # for this will eventually be coming)
397
+ def start_typing
398
+ API.start_typing(@bot.token, @id)
399
+ end
400
+
243
401
  alias_method :send, :send_message
244
402
  alias_method :message, :send_message
403
+ alias_method :invite, :make_invite
245
404
 
246
405
  private
247
406
 
@@ -295,74 +454,88 @@ module Discordrb
295
454
 
296
455
  # A server on Discord
297
456
  class Server
298
- attr_reader :region, :name, :owner_id, :id, :members, :channels, :roles
457
+ attr_reader :region, :name, :owner_id, :id, :members, :channels, :roles, :icon, :afk_timeout, :afk_channel_id
299
458
 
300
459
  def initialize(data, bot)
301
460
  @bot = bot
302
- @region = data['region']
303
- @name = data['name']
304
461
  @owner_id = data['owner_id'].to_i
305
462
  @id = data['id'].to_i
463
+ update_data(data)
464
+
465
+ process_roles(data['roles'])
466
+ process_members(data['members'])
467
+ process_presences(data['presences'])
468
+ process_channels(data['channels'])
469
+ process_voice_states(data['voice_states'])
470
+ end
306
471
 
472
+ def process_roles(roles)
307
473
  # Create roles
308
474
  @roles = []
309
- roles_by_id = {}
310
- data['roles'].each do |element|
311
- role = Role.new(element, bot)
475
+ @roles_by_id = {}
476
+ roles.each do |element|
477
+ role = Role.new(element, @bot, self)
312
478
  @roles << role
313
- roles_by_id[role.id] = role
479
+ @roles_by_id[role.id] = role
314
480
  end
481
+ end
315
482
 
483
+ def process_members(members)
316
484
  @members = []
317
- members_by_id = {}
485
+ @members_by_id = {}
318
486
 
319
- data['members'].each do |element|
320
- user = User.new(element['user'], bot)
487
+ return unless members
488
+ members.each do |element|
489
+ user = User.new(element['user'], @bot)
321
490
  @members << user
322
- members_by_id[user.id] = user
491
+ @members_by_id[user.id] = user
323
492
  user_roles = []
324
493
  element['roles'].each do |e|
325
494
  role_id = e.to_i
326
- user_roles << roles_by_id[role_id]
495
+ user_roles << @roles_by_id[role_id]
327
496
  end
328
497
  user.update_roles(self, user_roles)
329
498
  end
499
+ end
330
500
 
501
+ def process_presences(presences)
331
502
  # Update user statuses with presence info
332
- if data['presences']
333
- data['presences'].each do |element|
334
- next unless element['user']
335
- user_id = element['user']['id'].to_i
336
- user = members_by_id[user_id]
337
- if user
338
- user.status = element['status'].to_sym
339
- user.game = Discordrb::Games.find_game(element['game_id'])
340
- end
503
+ return unless presences
504
+ presences.each do |element|
505
+ next unless element['user']
506
+ user_id = element['user']['id'].to_i
507
+ user = @members_by_id[user_id]
508
+ if user
509
+ user.status = element['status'].to_sym
510
+ user.game = Discordrb::Games.find_game(element['game_id'])
341
511
  end
342
512
  end
513
+ end
343
514
 
515
+ def process_channels(channels)
344
516
  @channels = []
345
- channels_by_id = {}
517
+ @channels_by_id = {}
346
518
 
347
- if data['channels']
348
- data['channels'].each do |element|
349
- channel = Channel.new(element, bot, self)
350
- @channels << channel
351
- channels_by_id[channel.id] = channel
352
- end
519
+ return unless channels
520
+ channels.each do |element|
521
+ channel = Channel.new(element, @bot, self)
522
+ @channels << channel
523
+ @channels_by_id[channel.id] = channel
353
524
  end
525
+ end
354
526
 
355
- return unless data['voice_states']
356
- data['voice_states'].each do |element|
527
+ def process_voice_states(voice_states)
528
+ return unless voice_states
529
+ voice_states.each do |element|
357
530
  user_id = element['user_id'].to_i
358
- user = members_by_id[user_id]
531
+ user = @members_by_id[user_id]
359
532
  next unless user
360
533
  user.server_mute = element['mute']
361
534
  user.server_deaf = element['deaf']
362
535
  user.self_mute = element['self_mute']
363
536
  user.self_mute = element['self_mute']
364
537
  channel_id = element['channel_id']
365
- channel = channel_id ? channels_by_id[channel_id] : nil
538
+ channel = channel_id ? @channels_by_id[channel_id] : nil
366
539
  user.move(channel)
367
540
  end
368
541
  end
@@ -374,7 +547,7 @@ module Discordrb
374
547
  def delete_role(role_id)
375
548
  @roles.reject! { |r| r.id == role_id }
376
549
  @members.each do |user|
377
- new_roles = user.roles.reject { |r| r.id == role_id }
550
+ new_roles = user.roles[@id].reject { |r| r.id == role_id }
378
551
  user.update_roles(self, new_roles)
379
552
  end
380
553
  @channels.each do |channel|
@@ -396,6 +569,13 @@ module Discordrb
396
569
  Channel.new(JSON.parse(response), @bot)
397
570
  end
398
571
 
572
+ def create_role
573
+ response = API.create_role(@bot.token, @id)
574
+ role = Role.new(JSON.parse(response), @bot)
575
+ @roles << role
576
+ role
577
+ end
578
+
399
579
  def ban(user, message_days = 0)
400
580
  API.ban_user(@bot.token, @id, user.id, message_days)
401
581
  end
@@ -407,16 +587,69 @@ module Discordrb
407
587
  def kick(user)
408
588
  API.kick_user(@bot.token, @id, user.id)
409
589
  end
590
+
591
+ def delete
592
+ API.delete_server(@bot.token, @id)
593
+ end
594
+
595
+ def name=(name)
596
+ update_server_data(name: name)
597
+ end
598
+
599
+ def region=(region)
600
+ update_server_data(region: region.to_s)
601
+ end
602
+
603
+ def icon=(icon)
604
+ update_server_data(icon: icon)
605
+ end
606
+
607
+ def afk_channel=(afk_channel)
608
+ update_server_data(afk_channel_id: afk_channel.id)
609
+ end
610
+
611
+ def afk_channel_id=(afk_channel_id)
612
+ update_server_data(afk_channel_id: afk_channel_id)
613
+ end
614
+
615
+ def afk_timeout=(afk_timeout)
616
+ update_server_data(afk_timeout: afk_timeout)
617
+ end
618
+
619
+ def update_data(new_data)
620
+ @name = new_data[:name] || new_data['name'] || @name
621
+ @region = new_data[:region] || new_data['region'] || @region
622
+ @icon = new_data[:icon] || new_data['icon'] || @icon
623
+ @afk_timeout = new_data[:afk_timeout] || new_data['afk_timeout'].to_i || @afk_timeout
624
+
625
+ afk_channel_id = new_data[:afk_channel_id] || new_data['afk_channel_id'].to_i || @afk_channel.id
626
+ @afk_channel = @bot.channel(afk_channel_id) if afk_channel_id != 0 && (!@afk_channel || afk_channel_id != @afk_channel.id)
627
+ end
628
+
629
+ private
630
+
631
+ def update_server_data(new_data)
632
+ API.update_server(@bot.token, @id,
633
+ new_data[:name] || @name,
634
+ new_data[:region] || @region,
635
+ new_data[:icon] || @icon,
636
+ new_data[:afk_channel_id] || @afk_channel_id,
637
+ new_data[:afk_timeout] || @afk_timeout)
638
+ update_data(new_data)
639
+ end
410
640
  end
411
641
 
412
642
  # A colour (red, green and blue values). Used for role colours
413
- class ColorRGB
414
- attr_reader :red, :green, :blue
643
+ class ColourRGB
644
+ attr_reader :red, :green, :blue, :combined
415
645
 
416
646
  def initialize(combined)
647
+ @combined = combined
417
648
  @red = (combined >> 16) & 0xFF
418
649
  @green = (combined >> 8) & 0xFF
419
650
  @blue = combined & 0xFF
420
651
  end
421
652
  end
653
+
654
+ ColorRGB = ColourRGB
422
655
  end