discordrb 2.1.3 → 3.0.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +76 -0
- data/README.md +4 -2
- data/discordrb.gemspec +1 -1
- data/examples/commands.rb +2 -0
- data/examples/data/music.dca +0 -0
- data/examples/data/music.mp3 +0 -0
- data/examples/eval.rb +6 -3
- data/examples/ping.rb +14 -1
- data/examples/ping_with_respond_time.rb +6 -4
- data/examples/pm_send.rb +3 -0
- data/examples/shutdown.rb +7 -2
- data/examples/voice_send.rb +51 -0
- data/lib/discordrb/api.rb +66 -460
- data/lib/discordrb/api/channel.rb +306 -0
- data/lib/discordrb/api/invite.rb +41 -0
- data/lib/discordrb/api/server.rb +357 -0
- data/lib/discordrb/api/user.rb +134 -0
- data/lib/discordrb/bot.rb +266 -576
- data/lib/discordrb/cache.rb +27 -28
- data/lib/discordrb/commands/command_bot.rb +44 -15
- data/lib/discordrb/commands/container.rb +3 -2
- data/lib/discordrb/commands/parser.rb +14 -6
- data/lib/discordrb/container.rb +30 -3
- data/lib/discordrb/data.rb +823 -189
- data/lib/discordrb/errors.rb +145 -0
- data/lib/discordrb/events/channels.rb +63 -3
- data/lib/discordrb/events/members.rb +1 -2
- data/lib/discordrb/events/message.rb +96 -17
- data/lib/discordrb/events/presence.rb +15 -0
- data/lib/discordrb/events/typing.rb +7 -1
- data/lib/discordrb/gateway.rb +724 -0
- data/lib/discordrb/light/light_bot.rb +6 -4
- data/lib/discordrb/logger.rb +26 -9
- data/lib/discordrb/permissions.rb +6 -3
- data/lib/discordrb/version.rb +1 -1
- data/lib/discordrb/voice/voice_bot.rb +29 -6
- metadata +12 -5
- data/lib/discordrb/token_cache.rb +0 -181
data/lib/discordrb/data.rb
CHANGED
@@ -4,7 +4,12 @@
|
|
4
4
|
|
5
5
|
require 'ostruct'
|
6
6
|
require 'discordrb/permissions'
|
7
|
+
require 'discordrb/errors'
|
7
8
|
require 'discordrb/api'
|
9
|
+
require 'discordrb/api/channel'
|
10
|
+
require 'discordrb/api/server'
|
11
|
+
require 'discordrb/api/invite'
|
12
|
+
require 'discordrb/api/user'
|
8
13
|
require 'discordrb/events/message'
|
9
14
|
require 'time'
|
10
15
|
require 'base64'
|
@@ -49,7 +54,7 @@ module Discordrb
|
|
49
54
|
|
50
55
|
# If it's still larger than the character limit (none was smaller than it) split it into slices with the length
|
51
56
|
# being the character limit, otherwise just return an array with one element
|
52
|
-
ideal_ary =
|
57
|
+
ideal_ary = ideal.length > CHARACTER_LIMIT ? ideal.chars.each_slice(CHARACTER_LIMIT).map(&:join) : [ideal]
|
53
58
|
|
54
59
|
# Slice off the ideal part and strip newlines
|
55
60
|
rest = msg[ideal.length..-1].strip
|
@@ -117,7 +122,7 @@ module Discordrb
|
|
117
122
|
# Utility function to get a user's avatar URL.
|
118
123
|
# @return [String] the URL to the avatar image.
|
119
124
|
def avatar_url
|
120
|
-
API.avatar_url(@id, @avatar_id)
|
125
|
+
API::User.avatar_url(@id, @avatar_id)
|
121
126
|
end
|
122
127
|
end
|
123
128
|
|
@@ -164,10 +169,20 @@ module Discordrb
|
|
164
169
|
channel.send_message(content)
|
165
170
|
else
|
166
171
|
# If no message was specified, return the PM channel
|
167
|
-
@bot.
|
172
|
+
@bot.pm_channel(@id)
|
168
173
|
end
|
169
174
|
end
|
170
175
|
|
176
|
+
alias_method :dm, :pm
|
177
|
+
|
178
|
+
# Send the user a file.
|
179
|
+
# @param file [File] The file to send to the user
|
180
|
+
# @param caption [String] The caption of the file being sent
|
181
|
+
# @return [Message] the message sent to this user.
|
182
|
+
def send_file(file, caption = nil)
|
183
|
+
pm.send_file(file, caption: caption)
|
184
|
+
end
|
185
|
+
|
171
186
|
# Set the user's name
|
172
187
|
# @note for internal use only
|
173
188
|
# @!visibility private
|
@@ -208,24 +223,54 @@ module Discordrb
|
|
208
223
|
end
|
209
224
|
end
|
210
225
|
|
211
|
-
#
|
212
|
-
|
213
|
-
|
214
|
-
attr_reader :mute
|
215
|
-
alias_method :muted?, :mute
|
226
|
+
# OAuth Application information
|
227
|
+
class Application
|
228
|
+
include IDObject
|
216
229
|
|
217
|
-
# @return [
|
218
|
-
attr_reader :
|
219
|
-
alias_method :deafened?, :deaf
|
230
|
+
# @return [String] the application name
|
231
|
+
attr_reader :name
|
220
232
|
|
221
|
-
# @return [
|
222
|
-
attr_reader :
|
223
|
-
alias_method :self_muted?, :self_mute
|
233
|
+
# @return [String] the application description
|
234
|
+
attr_reader :description
|
224
235
|
|
225
|
-
# @return [
|
226
|
-
attr_reader :
|
227
|
-
|
236
|
+
# @return [Array<String>] the applications origins permitted to use RPC
|
237
|
+
attr_reader :rpc_origins
|
238
|
+
|
239
|
+
# @return [Integer]
|
240
|
+
attr_reader :flags
|
241
|
+
|
242
|
+
# Gets the user object of the owner. May be limited to username, discriminator,
|
243
|
+
# ID and avatar if the bot cannot reach the owner.
|
244
|
+
# @return [User] the user object of the owner
|
245
|
+
attr_reader :owner
|
246
|
+
|
247
|
+
def initialize(data, bot)
|
248
|
+
@bot = bot
|
249
|
+
|
250
|
+
@name = data['name']
|
251
|
+
@id = data['id'].to_i
|
252
|
+
@description = data['description']
|
253
|
+
@icon_id = data['icon']
|
254
|
+
@rpc_origins = data['rpc_origins']
|
255
|
+
@flags = data['flags']
|
256
|
+
@owner = @bot.ensure_user(data['owner'])
|
257
|
+
end
|
228
258
|
|
259
|
+
# Utility function to get a application's icon URL.
|
260
|
+
# @return [String, nil] the URL to the icon image (nil if no iamge is set).
|
261
|
+
def icon_url
|
262
|
+
return nil if @icon_id.nil?
|
263
|
+
API.app_icon_url(@id, @icon_id)
|
264
|
+
end
|
265
|
+
|
266
|
+
# The inspect method is overwritten to give more useful output
|
267
|
+
def inspect
|
268
|
+
"<Application name=#{@name} id=#{@id}>"
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
# Mixin for the attributes members and private members should have
|
273
|
+
module MemberAttributes
|
229
274
|
# @return [Time] when this member joined the server.
|
230
275
|
attr_reader :joined_at
|
231
276
|
|
@@ -238,9 +283,6 @@ module Discordrb
|
|
238
283
|
|
239
284
|
# @return [Server] the server this member is on.
|
240
285
|
attr_reader :server
|
241
|
-
|
242
|
-
# @return [Channel] the voice channel the user is in.
|
243
|
-
attr_reader :voice_channel
|
244
286
|
end
|
245
287
|
|
246
288
|
# Mixin to calculate resulting permissions from overrides etc.
|
@@ -258,7 +300,7 @@ module Discordrb
|
|
258
300
|
# (Coincidentally, Manage Permissions is the same permission as Manage Roles, and a
|
259
301
|
# Manage Permissions deny overwrite will override Manage Roles, so we can just check for
|
260
302
|
# Manage Roles once and call it a day.)
|
261
|
-
return true if defined_permission?(:
|
303
|
+
return true if defined_permission?(:administrator, channel)
|
262
304
|
|
263
305
|
# Otherwise, defer to defined_permission
|
264
306
|
defined_permission?(action, channel)
|
@@ -289,6 +331,8 @@ module Discordrb
|
|
289
331
|
end
|
290
332
|
end
|
291
333
|
|
334
|
+
alias_method :can_administrate?, :can_administrator?
|
335
|
+
|
292
336
|
private
|
293
337
|
|
294
338
|
def defined_role_permission?(action, channel)
|
@@ -327,9 +371,77 @@ module Discordrb
|
|
327
371
|
end
|
328
372
|
end
|
329
373
|
|
374
|
+
# A voice state represents the state of a member's connection to a voice channel. It includes data like the voice
|
375
|
+
# channel the member is connected to and mute/deaf flags.
|
376
|
+
class VoiceState
|
377
|
+
# @return [Integer] the ID of the user whose voice state is represented by this object.
|
378
|
+
attr_reader :user_id
|
379
|
+
|
380
|
+
# @return [true, false] whether this voice state's member is muted server-wide.
|
381
|
+
attr_reader :mute
|
382
|
+
|
383
|
+
# @return [true, false] whether this voice state's member is deafened server-wide.
|
384
|
+
attr_reader :deaf
|
385
|
+
|
386
|
+
# @return [true, false] whether this voice state's member has muted themselves.
|
387
|
+
attr_reader :self_mute
|
388
|
+
|
389
|
+
# @return [true, false] whether this voice state's member has deafened themselves.
|
390
|
+
attr_reader :self_deaf
|
391
|
+
|
392
|
+
# @return [Channel] the voice channel this voice state's member is in.
|
393
|
+
attr_reader :voice_channel
|
394
|
+
|
395
|
+
# @!visibility private
|
396
|
+
def initialize(user_id)
|
397
|
+
@user_id = user_id
|
398
|
+
end
|
399
|
+
|
400
|
+
# Update this voice state with new data from Discord
|
401
|
+
# @note For internal use only.
|
402
|
+
# @!visibility private
|
403
|
+
def update(channel, mute, deaf, self_mute, self_deaf)
|
404
|
+
@voice_channel = channel
|
405
|
+
@mute = mute
|
406
|
+
@deaf = deaf
|
407
|
+
@self_mute = self_mute
|
408
|
+
@self_deaf = self_deaf
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
330
412
|
# A member is a user on a server. It differs from regular users in that it has roles, voice statuses and things like
|
331
413
|
# that.
|
332
414
|
class Member < DelegateClass(User)
|
415
|
+
# @return [true, false] whether this member is muted server-wide.
|
416
|
+
def mute
|
417
|
+
voice_state_attribute(:mute)
|
418
|
+
end
|
419
|
+
|
420
|
+
# @return [true, false] whether this member is deafened server-wide.
|
421
|
+
def deaf
|
422
|
+
voice_state_attribute(:deaf)
|
423
|
+
end
|
424
|
+
|
425
|
+
# @return [true, false] whether this member has muted themselves.
|
426
|
+
def self_mute
|
427
|
+
voice_state_attribute(:self_mute)
|
428
|
+
end
|
429
|
+
|
430
|
+
# @return [true, false] whether this member has deafened themselves.
|
431
|
+
def self_deaf
|
432
|
+
voice_state_attribute(:self_deaf)
|
433
|
+
end
|
434
|
+
|
435
|
+
# @return [Channel] the voice channel this member is in.
|
436
|
+
def voice_channel
|
437
|
+
voice_state_attribute(:voice_channel)
|
438
|
+
end
|
439
|
+
|
440
|
+
alias_method :muted?, :mute
|
441
|
+
alias_method :deafened?, :deaf
|
442
|
+
alias_method :self_muted?, :self_mute
|
443
|
+
alias_method :self_deafened?, :self_deaf
|
444
|
+
|
333
445
|
include MemberAttributes
|
334
446
|
|
335
447
|
# @!visibility private
|
@@ -347,9 +459,6 @@ module Discordrb
|
|
347
459
|
update_roles(data['roles'])
|
348
460
|
|
349
461
|
@nick = data['nick']
|
350
|
-
|
351
|
-
@deaf = data['deaf']
|
352
|
-
@mute = data['mute']
|
353
462
|
@joined_at = data['joined_at'] ? Time.parse(data['joined_at']) : nil
|
354
463
|
end
|
355
464
|
|
@@ -365,6 +474,25 @@ module Discordrb
|
|
365
474
|
@roles.any? { |e| e.id == role }
|
366
475
|
end
|
367
476
|
|
477
|
+
# Bulk sets a member's roles.
|
478
|
+
# @param role [Role, Array<Role>] The role(s) to set.
|
479
|
+
def roles=(role)
|
480
|
+
role_ids = role_id_array(role)
|
481
|
+
API::Server.update_member(@bot.token, @server.id, @user.id, roles: role_ids)
|
482
|
+
end
|
483
|
+
|
484
|
+
# Adds and removes roles from a member.
|
485
|
+
# @param add [Role, Array<Role>] The role(s) to add.
|
486
|
+
# @param remove [Role, Array<Role>] The role(s) to remove.
|
487
|
+
def modify_roles(add, remove)
|
488
|
+
add_role_ids = role_id_array(add)
|
489
|
+
remove_role_ids = role_id_array(remove)
|
490
|
+
old_role_ids = @roles.map(&:id)
|
491
|
+
new_role_ids = (old_role_ids - remove_role_ids + add_role_ids).uniq
|
492
|
+
|
493
|
+
API::Server.update_member(@bot.token, @server.id, @user.id, roles: new_role_ids)
|
494
|
+
end
|
495
|
+
|
368
496
|
# Adds one or more roles to this member.
|
369
497
|
# @param role [Role, Array<Role>] The role(s) to add.
|
370
498
|
def add_role(role)
|
@@ -372,7 +500,7 @@ module Discordrb
|
|
372
500
|
old_role_ids = @roles.map(&:id)
|
373
501
|
new_role_ids = (old_role_ids + role_ids).uniq
|
374
502
|
|
375
|
-
API.
|
503
|
+
API::Server.update_member(@bot.token, @server.id, @user.id, roles: new_role_ids)
|
376
504
|
end
|
377
505
|
|
378
506
|
# Removes one or more roles from this member.
|
@@ -382,7 +510,27 @@ module Discordrb
|
|
382
510
|
role_ids = role_id_array(role)
|
383
511
|
new_role_ids = old_role_ids.reject { |i| role_ids.include?(i) }
|
384
512
|
|
385
|
-
API.
|
513
|
+
API::Server.update_member(@bot.token, @server.id, @user.id, roles: new_role_ids)
|
514
|
+
end
|
515
|
+
|
516
|
+
# Server deafens this member.
|
517
|
+
def server_deafen
|
518
|
+
API::Server.update_member(@bot.token, @server.id, @user.id, deaf: true)
|
519
|
+
end
|
520
|
+
|
521
|
+
# Server undeafens this member.
|
522
|
+
def server_undeafen
|
523
|
+
API::Server.update_member(@bot.token, @server.id, @user.id, deaf: false)
|
524
|
+
end
|
525
|
+
|
526
|
+
# Server mutes this member.
|
527
|
+
def server_mute
|
528
|
+
API::Server.update_member(@bot.token, @server.id, @user.id, mute: true)
|
529
|
+
end
|
530
|
+
|
531
|
+
# Server unmutes this member.
|
532
|
+
def server_unmute
|
533
|
+
API::Server.update_member(@bot.token, @server.id, @user.id, mute: false)
|
386
534
|
end
|
387
535
|
|
388
536
|
# Sets or resets this member's nickname. Requires the Change Nickname permission for the bot itself and Manage
|
@@ -392,7 +540,11 @@ module Discordrb
|
|
392
540
|
# Discord uses the empty string to signify 'no nickname' so we convert nil into that
|
393
541
|
nick ||= ''
|
394
542
|
|
395
|
-
|
543
|
+
if @user.current_bot?
|
544
|
+
API::User.change_own_nickname(@bot.token, @server.id, nick)
|
545
|
+
else
|
546
|
+
API.change_nickname(@bot.token, @server.id, @user.id, nick)
|
547
|
+
end
|
396
548
|
end
|
397
549
|
|
398
550
|
alias_method :nickname=, :nick=
|
@@ -418,17 +570,6 @@ module Discordrb
|
|
418
570
|
@nick = nick
|
419
571
|
end
|
420
572
|
|
421
|
-
# Update this member's voice state
|
422
|
-
# @note For internal use only.
|
423
|
-
# @!visibility private
|
424
|
-
def update_voice_state(channel, mute, deaf, self_mute, self_deaf)
|
425
|
-
@voice_channel = channel
|
426
|
-
@mute = mute
|
427
|
-
@deaf = deaf
|
428
|
-
@self_mute = self_mute
|
429
|
-
@self_deaf = self_deaf
|
430
|
-
end
|
431
|
-
|
432
573
|
include PermissionCalculator
|
433
574
|
|
434
575
|
# Overwriting inspect for debug purposes
|
@@ -446,6 +587,12 @@ module Discordrb
|
|
446
587
|
[role.resolve_id]
|
447
588
|
end
|
448
589
|
end
|
590
|
+
|
591
|
+
# Utility method to get data out of this member's voice state
|
592
|
+
def voice_state_attribute(name)
|
593
|
+
voice_state = @server.voice_states[@user.id]
|
594
|
+
voice_state.send name if voice_state
|
595
|
+
end
|
449
596
|
end
|
450
597
|
|
451
598
|
# Recipients are members on private channels - they exist for completeness purposes, but all
|
@@ -479,13 +626,11 @@ module Discordrb
|
|
479
626
|
end
|
480
627
|
end
|
481
628
|
|
482
|
-
# This class is a special variant of User that represents the bot's user profile (things like
|
629
|
+
# This class is a special variant of User that represents the bot's user profile (things like own username and the avatar).
|
483
630
|
# It can be accessed using {Bot#profile}.
|
484
631
|
class Profile < User
|
485
|
-
def initialize(data, bot
|
632
|
+
def initialize(data, bot)
|
486
633
|
super(data, bot)
|
487
|
-
@email = email
|
488
|
-
@password = password
|
489
634
|
end
|
490
635
|
|
491
636
|
# Whether or not the user is the bot. The Profile can only ever be the bot user, so this always returns true.
|
@@ -500,22 +645,11 @@ module Discordrb
|
|
500
645
|
update_profile_data(username: username)
|
501
646
|
end
|
502
647
|
|
503
|
-
|
504
|
-
# one afterwards, so the bot doesn't have any trouble logging in in the future.
|
505
|
-
# @param email [String] The new email address.
|
506
|
-
def email=(email)
|
507
|
-
update_profile_data(email: email)
|
508
|
-
end
|
509
|
-
|
510
|
-
# Changes the bot's password. This will invalidate all tokens so you will have to relog the bot.
|
511
|
-
# @param password [String] The new password.
|
512
|
-
def password=(password)
|
513
|
-
update_profile_data(new_password: password)
|
514
|
-
end
|
648
|
+
alias_method :name=, :username=
|
515
649
|
|
516
650
|
# Changes the bot's avatar.
|
517
651
|
# @param avatar [String, #read] A JPG file to be used as the avatar, either
|
518
|
-
# something readable (e. g. File) or as a data URL.
|
652
|
+
# something readable (e. g. File Object) or as a data URL.
|
519
653
|
def avatar=(avatar)
|
520
654
|
if avatar.respond_to? :read
|
521
655
|
# Set the file to binary mode if supported, so we don't get problems with Windows
|
@@ -533,26 +667,22 @@ module Discordrb
|
|
533
667
|
# @note For internal use only.
|
534
668
|
# @!visibility private
|
535
669
|
def update_data(new_data)
|
536
|
-
@email = new_data[:email] || @email
|
537
|
-
@password = new_data[:new_password] || @password
|
538
670
|
@username = new_data[:username] || @username
|
539
671
|
@avatar_id = new_data[:avatar_id] || @avatar_id
|
540
672
|
end
|
541
673
|
|
542
674
|
# The inspect method is overwritten to give more useful output
|
543
675
|
def inspect
|
544
|
-
"<Profile
|
676
|
+
"<Profile user=#{super}>"
|
545
677
|
end
|
546
678
|
|
547
679
|
private
|
548
680
|
|
549
681
|
def update_profile_data(new_data)
|
550
|
-
API.
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
new_data[:avatar],
|
555
|
-
new_data[:new_password] || nil)
|
682
|
+
API::User.update_profile(@bot.token,
|
683
|
+
nil, nil,
|
684
|
+
new_data[:username] || @username,
|
685
|
+
new_data.key?(:avatar) ? new_data[:avatar] : @avatar_id)
|
556
686
|
update_data(new_data)
|
557
687
|
end
|
558
688
|
end
|
@@ -576,9 +706,11 @@ module Discordrb
|
|
576
706
|
|
577
707
|
# @return [ColourRGB] the role colour
|
578
708
|
attr_reader :colour
|
579
|
-
|
580
709
|
alias_method :color, :colour
|
581
710
|
|
711
|
+
# @return [Integer] the position of this role in the hierarchy
|
712
|
+
attr_reader :position
|
713
|
+
|
582
714
|
# This class is used internally as a wrapper to a Role object that allows easy writing of permission data.
|
583
715
|
class RoleWriter
|
584
716
|
# @!visibility private
|
@@ -602,6 +734,8 @@ module Discordrb
|
|
602
734
|
@name = data['name']
|
603
735
|
@id = data['id'].to_i
|
604
736
|
|
737
|
+
@position = data['position']
|
738
|
+
|
605
739
|
@hoist = data['hoist']
|
606
740
|
@mentionable = data['mentionable']
|
607
741
|
|
@@ -613,6 +747,14 @@ module Discordrb
|
|
613
747
|
"<@&#{@id}>"
|
614
748
|
end
|
615
749
|
|
750
|
+
# @return [Array<Member>] an array of members who have this role.
|
751
|
+
# @note This requests a member chunk if it hasn't for the server before, which may be slow initially
|
752
|
+
def members
|
753
|
+
@server.members.select { |m| m.role? role }
|
754
|
+
end
|
755
|
+
|
756
|
+
alias_method :users, :members
|
757
|
+
|
616
758
|
# Updates the data cache from another Role object
|
617
759
|
# @note For internal use only
|
618
760
|
# @!visibility private
|
@@ -621,6 +763,7 @@ module Discordrb
|
|
621
763
|
@name = other.name
|
622
764
|
@hoist = other.hoist
|
623
765
|
@colour = other.colour
|
766
|
+
@position = other.position
|
624
767
|
end
|
625
768
|
|
626
769
|
# Updates the data cache from a hash containing data
|
@@ -645,6 +788,12 @@ module Discordrb
|
|
645
788
|
update_role_data(hoist: hoist)
|
646
789
|
end
|
647
790
|
|
791
|
+
# Changes whether or not this role can be mentioned
|
792
|
+
# @param mentionable [true, false] The value it should be changed to
|
793
|
+
def mentionable=(mentionable)
|
794
|
+
update_role_data(mentionable: mentionable)
|
795
|
+
end
|
796
|
+
|
648
797
|
# Sets the role colour to something new
|
649
798
|
# @param colour [ColourRGB] The new colour
|
650
799
|
def colour=(colour)
|
@@ -653,9 +802,16 @@ module Discordrb
|
|
653
802
|
|
654
803
|
alias_method :color=, :colour=
|
655
804
|
|
656
|
-
# Changes
|
657
|
-
#
|
658
|
-
#
|
805
|
+
# Changes this role's permissions to a fixed bitfield. This allows setting multiple permissions at once with just
|
806
|
+
# one API call.
|
807
|
+
#
|
808
|
+
# Information on how this bitfield is structured can be found at
|
809
|
+
# https://discordapp.com/developers/docs/topics/permissions.
|
810
|
+
# @example Remove all permissions from a role
|
811
|
+
# role.packed = 0
|
812
|
+
# @param packed [Integer] A bitfield with the desired permissions value.
|
813
|
+
# @param update_perms [true, false] Whether the internal data should also be updated. This should always be true
|
814
|
+
# when calling externally.
|
659
815
|
def packed=(packed, update_perms = true)
|
660
816
|
update_role_data(permissions: packed)
|
661
817
|
@permissions.bits = packed if update_perms
|
@@ -663,7 +819,7 @@ module Discordrb
|
|
663
819
|
|
664
820
|
# Delets this role. This cannot be undone without recreating the role!
|
665
821
|
def delete
|
666
|
-
API.delete_role(@bot.token, @server.id, @id)
|
822
|
+
API::Server.delete_role(@bot.token, @server.id, @id)
|
667
823
|
@server.delete_role(@id)
|
668
824
|
end
|
669
825
|
|
@@ -675,11 +831,12 @@ module Discordrb
|
|
675
831
|
private
|
676
832
|
|
677
833
|
def update_role_data(new_data)
|
678
|
-
API.update_role(@bot.token, @server.id, @id,
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
834
|
+
API::Server.update_role(@bot.token, @server.id, @id,
|
835
|
+
new_data[:name] || @name,
|
836
|
+
(new_data[:colour] || @colour).combined,
|
837
|
+
new_data[:hoist].nil? ? @hoist : new_data[:hoist],
|
838
|
+
new_data[:mentionable].nil? ? @mentionable : new_data[:mentionable],
|
839
|
+
new_data[:permissions] || @permissions.bits)
|
683
840
|
update_data(new_data)
|
684
841
|
end
|
685
842
|
end
|
@@ -691,7 +848,7 @@ module Discordrb
|
|
691
848
|
# @return [String] this channel's name.
|
692
849
|
attr_reader :name
|
693
850
|
|
694
|
-
# @return [
|
851
|
+
# @return [Integer] this channel's type (0: text, 1: private, 2: voice, 3: group).
|
695
852
|
attr_reader :type
|
696
853
|
|
697
854
|
# @!visibility private
|
@@ -735,29 +892,23 @@ module Discordrb
|
|
735
892
|
|
736
893
|
# @return [Integer] the amount of uses left on this invite.
|
737
894
|
attr_reader :uses
|
895
|
+
alias_method :max_uses, :uses
|
738
896
|
|
739
897
|
# @return [User, nil] the user that made this invite. May also be nil if the user can't be determined.
|
740
898
|
attr_reader :inviter
|
899
|
+
alias_method :user, :inviter
|
741
900
|
|
742
901
|
# @return [true, false] whether or not this invite is temporary.
|
743
902
|
attr_reader :temporary
|
903
|
+
alias_method :temporary?, :temporary
|
744
904
|
|
745
905
|
# @return [true, false] whether this invite is still valid.
|
746
906
|
attr_reader :revoked
|
747
|
-
|
748
|
-
# @return [true, false] whether this invite is in xkcd format (i. e. "Human readable" in the invite settings)
|
749
|
-
attr_reader :xkcd
|
907
|
+
alias_method :revoked?, :revoked
|
750
908
|
|
751
909
|
# @return [String] this invite's code
|
752
910
|
attr_reader :code
|
753
911
|
|
754
|
-
alias_method :max_uses, :uses
|
755
|
-
alias_method :user, :inviter
|
756
|
-
|
757
|
-
alias_method :temporary?, :temporary
|
758
|
-
alias_method :revoked?, :revoked
|
759
|
-
alias_method :xkcd?, :xkcd
|
760
|
-
|
761
912
|
# @!visibility private
|
762
913
|
def initialize(data, bot)
|
763
914
|
@bot = bot
|
@@ -768,7 +919,6 @@ module Discordrb
|
|
768
919
|
@inviter = data['inviter'] ? (@bot.user(data['inviter']['id'].to_i) || User.new(data['inviter'], bot)) : nil
|
769
920
|
@temporary = data['temporary']
|
770
921
|
@revoked = data['revoked']
|
771
|
-
@xkcd = data['xkcdpass']
|
772
922
|
|
773
923
|
@code = data['code']
|
774
924
|
end
|
@@ -780,14 +930,14 @@ module Discordrb
|
|
780
930
|
|
781
931
|
# Deletes this invite
|
782
932
|
def delete
|
783
|
-
API.
|
933
|
+
API::Invite.delete(@bot.token, @code)
|
784
934
|
end
|
785
935
|
|
786
936
|
alias_method :revoke, :delete
|
787
937
|
|
788
938
|
# The inspect method is overwritten to give more useful output
|
789
939
|
def inspect
|
790
|
-
"<Invite code=#{@code} channel=#{@channel} uses=#{@uses} temporary=#{@temporary} revoked=#{@revoked}
|
940
|
+
"<Invite code=#{@code} channel=#{@channel} uses=#{@uses} temporary=#{@temporary} revoked=#{@revoked}>"
|
791
941
|
end
|
792
942
|
|
793
943
|
# Creates an invite URL.
|
@@ -798,14 +948,6 @@ module Discordrb
|
|
798
948
|
|
799
949
|
# A Discord channel, including data like the topic
|
800
950
|
class Channel
|
801
|
-
# The type string that stands for a text channel
|
802
|
-
# @see Channel#type
|
803
|
-
TEXT_TYPE = 'text'.freeze
|
804
|
-
|
805
|
-
# The type string that stands for a voice channel
|
806
|
-
# @see Channel#type
|
807
|
-
VOICE_TYPE = 'voice'.freeze
|
808
|
-
|
809
951
|
include IDObject
|
810
952
|
|
811
953
|
# @return [String] this channel's name.
|
@@ -814,15 +956,25 @@ module Discordrb
|
|
814
956
|
# @return [Server, nil] the server this channel is on. If this channel is a PM channel, it will be nil.
|
815
957
|
attr_reader :server
|
816
958
|
|
817
|
-
# @return [
|
959
|
+
# @return [Integer] the type of this channel (0: text, 1: private, 2: voice, 3: group)
|
818
960
|
attr_reader :type
|
819
961
|
|
820
|
-
# @return [
|
821
|
-
attr_reader :
|
962
|
+
# @return [Integer, nil] the id of the owner of the group channel or nil if this is not a group channel.
|
963
|
+
attr_reader :owner_id
|
964
|
+
|
965
|
+
# @return [Array<Recipient>, nil] the array of recipients of the private messages, or nil if this is not a Private channel
|
966
|
+
attr_reader :recipients
|
822
967
|
|
823
968
|
# @return [String] the channel's topic
|
824
969
|
attr_reader :topic
|
825
970
|
|
971
|
+
# @return [Integer] the bitrate (in bps) of the channel
|
972
|
+
attr_reader :bitrate
|
973
|
+
|
974
|
+
# @return [Integer] the amount of users that can be in the channel. `0` means it is unlimited.
|
975
|
+
attr_reader :user_limit
|
976
|
+
alias_method :limit, :user_limit
|
977
|
+
|
826
978
|
# @return [Integer] the channel's position on the channel list
|
827
979
|
attr_reader :position
|
828
980
|
|
@@ -831,9 +983,9 @@ module Discordrb
|
|
831
983
|
# @return [Hash<Integer => OpenStruct>] the channel's permission overwrites
|
832
984
|
attr_reader :permission_overwrites
|
833
985
|
|
834
|
-
# @return [true, false] whether or not this channel is a PM channel.
|
986
|
+
# @return [true, false] whether or not this channel is a PM or group channel.
|
835
987
|
def private?
|
836
|
-
|
988
|
+
pm? || group?
|
837
989
|
end
|
838
990
|
|
839
991
|
# @return [String] a string that will mention the channel as a clickable link on Discord.
|
@@ -841,23 +993,38 @@ module Discordrb
|
|
841
993
|
"<##{@id}>"
|
842
994
|
end
|
843
995
|
|
996
|
+
# @return [Recipient, nil] the recipient of the private messages, or nil if this is not a PM channel
|
997
|
+
def recipient
|
998
|
+
@recipients.first if pm?
|
999
|
+
end
|
1000
|
+
|
844
1001
|
# @!visibility private
|
845
1002
|
def initialize(data, bot, server = nil)
|
846
1003
|
@bot = bot
|
847
|
-
|
848
|
-
# data is a sometimes a Hash and othertimes an array of Hashes, you only want the last one if it's an array
|
1004
|
+
# data is a sometimes a Hash and other times an array of Hashes, you only want the last one if it's an array
|
849
1005
|
data = data[-1] if data.is_a?(Array)
|
850
1006
|
|
851
1007
|
@id = data['id'].to_i
|
852
|
-
@type = data['type'] ||
|
1008
|
+
@type = data['type'] || 0
|
853
1009
|
@topic = data['topic']
|
1010
|
+
@bitrate = data['bitrate']
|
1011
|
+
@user_limit = data['user_limit']
|
854
1012
|
@position = data['position']
|
855
1013
|
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
1014
|
+
if private?
|
1015
|
+
@recipients = []
|
1016
|
+
if data['recipients']
|
1017
|
+
data['recipients'].each do |recipient|
|
1018
|
+
recipient_user = bot.ensure_user(recipient)
|
1019
|
+
@recipients << Recipient.new(recipient_user, self, bot)
|
1020
|
+
end
|
1021
|
+
end
|
1022
|
+
if pm?
|
1023
|
+
@name = @recipients.first.username
|
1024
|
+
else
|
1025
|
+
@name = data['name']
|
1026
|
+
@owner_id = data['owner_id']
|
1027
|
+
end
|
861
1028
|
else
|
862
1029
|
@name = data['name']
|
863
1030
|
@server = if server
|
@@ -882,12 +1049,22 @@ module Discordrb
|
|
882
1049
|
|
883
1050
|
# @return [true, false] whether or not this channel is a text channel
|
884
1051
|
def text?
|
885
|
-
@type
|
1052
|
+
@type.zero?
|
886
1053
|
end
|
887
1054
|
|
888
|
-
# @return [true, false] whether or not this channel is a
|
1055
|
+
# @return [true, false] whether or not this channel is a PM channel.
|
1056
|
+
def pm?
|
1057
|
+
@type == 1
|
1058
|
+
end
|
1059
|
+
|
1060
|
+
# @return [true, false] whether or not this channel is a voice channel.
|
889
1061
|
def voice?
|
890
|
-
@type ==
|
1062
|
+
@type == 2
|
1063
|
+
end
|
1064
|
+
|
1065
|
+
# @return [true, false] whether or not this channel is a group channel.
|
1066
|
+
def group?
|
1067
|
+
@type == 3
|
891
1068
|
end
|
892
1069
|
|
893
1070
|
# Sends a message to this channel.
|
@@ -898,6 +1075,16 @@ module Discordrb
|
|
898
1075
|
@bot.send_message(@id, content, tts, @server && @server.id)
|
899
1076
|
end
|
900
1077
|
|
1078
|
+
alias_method :send, :send_message
|
1079
|
+
|
1080
|
+
# Sends a temporary message to this channel.
|
1081
|
+
# @param content [String] The content to send. Should not be longer than 2000 characters or it will result in an error.
|
1082
|
+
# @param timeout [Float] The amount of time in seconds after which the message sent will be deleted.
|
1083
|
+
# @param tts [true, false] Whether or not this message should be sent using Discord text-to-speech.
|
1084
|
+
def send_temporary_message(content, timeout, tts = false)
|
1085
|
+
@bot.send_temporary_message(@id, content, timeout, tts, @server && @server.id)
|
1086
|
+
end
|
1087
|
+
|
901
1088
|
# Sends multiple messages to a channel
|
902
1089
|
# @param content [Array<String>] The messages to send.
|
903
1090
|
def send_multiple(content)
|
@@ -912,13 +1099,15 @@ module Discordrb
|
|
912
1099
|
|
913
1100
|
# Sends a file to this channel. If it is an image, it will be embedded.
|
914
1101
|
# @param file [File] The file to send. There's no clear size limit for this, you'll have to attempt it for yourself (most non-image files are fine, large images may fail to embed)
|
915
|
-
|
916
|
-
|
1102
|
+
# @param caption [string] The caption for the file.
|
1103
|
+
# @param tts [true, false] Whether or not this file's caption should be sent using Discord text-to-speech.
|
1104
|
+
def send_file(file, caption: nil, tts: false)
|
1105
|
+
@bot.send_file(@id, file, caption: caption, tts: tts)
|
917
1106
|
end
|
918
1107
|
|
919
1108
|
# Permanently deletes this channel
|
920
1109
|
def delete
|
921
|
-
API.
|
1110
|
+
API::Channel.delete(@bot.token, @id)
|
922
1111
|
end
|
923
1112
|
|
924
1113
|
# Sets this channel's name. The name must be alphanumeric with dashes, unless this is a voice channel (then there are no limitations)
|
@@ -931,10 +1120,29 @@ module Discordrb
|
|
931
1120
|
# Sets this channel's topic.
|
932
1121
|
# @param topic [String] The new topic.
|
933
1122
|
def topic=(topic)
|
1123
|
+
raise 'Tried to set topic on voice channel' if voice?
|
934
1124
|
@topic = topic
|
935
1125
|
update_channel_data
|
936
1126
|
end
|
937
1127
|
|
1128
|
+
# Sets this channel's bitrate.
|
1129
|
+
# @param bitrate [Integer] The new bitrate (in bps). Number has to be between 8000-96000 (128000 for VIP servers)
|
1130
|
+
def bitrate=(bitrate)
|
1131
|
+
raise 'Tried to set bitrate on text channel' if text?
|
1132
|
+
@bitrate = bitrate
|
1133
|
+
update_channel_data
|
1134
|
+
end
|
1135
|
+
|
1136
|
+
# Sets this channel's user limit.
|
1137
|
+
# @param limit [Integer] The new user limit. `0` for unlimited, has to be a number between 0-99
|
1138
|
+
def user_limit=(limit)
|
1139
|
+
raise 'Tried to set user_limit on text channel' if text?
|
1140
|
+
@user_limit = limit
|
1141
|
+
update_channel_data
|
1142
|
+
end
|
1143
|
+
|
1144
|
+
alias_method :limit=, :user_limit=
|
1145
|
+
|
938
1146
|
# Sets this channel's position in the list.
|
939
1147
|
# @param position [Integer] The new position.
|
940
1148
|
def position=(position)
|
@@ -962,11 +1170,15 @@ module Discordrb
|
|
962
1170
|
allow_bits = allow.respond_to?(:bits) ? allow.bits : allow
|
963
1171
|
deny_bits = deny.respond_to?(:bits) ? deny.bits : deny
|
964
1172
|
|
965
|
-
if thing.is_a?
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
1173
|
+
type = if thing.is_a?(User) || thing.is_a?(Member) || thing.is_a?(Recipient) || thing.is_a?(Profile)
|
1174
|
+
:member
|
1175
|
+
elsif thing.is_a? Role
|
1176
|
+
:role
|
1177
|
+
else
|
1178
|
+
raise ArgumentError, '`thing` in define_overwrite needs to be a kind of User (User, Member, Recipient, Profile) or a Role!'
|
1179
|
+
end
|
1180
|
+
|
1181
|
+
API::Channel.update_permission(@bot.token, @id, thing.id, allow_bits, deny_bits, type)
|
970
1182
|
end
|
971
1183
|
|
972
1184
|
# Updates the cached data from another channel.
|
@@ -975,20 +1187,17 @@ module Discordrb
|
|
975
1187
|
def update_from(other)
|
976
1188
|
@topic = other.topic
|
977
1189
|
@name = other.name
|
978
|
-
@recipient = other.recipient
|
979
1190
|
@permission_overwrites = other.permission_overwrites
|
980
1191
|
end
|
981
1192
|
|
982
|
-
# The list of users currently in this channel.
|
983
|
-
#
|
1193
|
+
# The list of users currently in this channel. For a voice channel, it will return all the members currently
|
1194
|
+
# in that channel. For a text channel, it will return all online members that have permission to read it.
|
984
1195
|
# @return [Array<Member>] the users in this channel
|
985
1196
|
def users
|
986
|
-
if
|
987
|
-
@server.
|
988
|
-
|
989
|
-
@server.
|
990
|
-
user.voice_channel.id == @id if user.voice_channel
|
991
|
-
end
|
1197
|
+
if text?
|
1198
|
+
@server.online_members(include_idle: true).select { |u| u.can_read_messages? self }
|
1199
|
+
elsif voice?
|
1200
|
+
@server.voice_states.map { |id, voice_state| @server.member(id) if !voice_state.voice_channel.nil? && voice_state.voice_channel.id == @id }.compact
|
992
1201
|
end
|
993
1202
|
end
|
994
1203
|
|
@@ -1001,18 +1210,45 @@ module Discordrb
|
|
1001
1210
|
# as soon as possible with the specified amount.
|
1002
1211
|
# @return [Array<Message>] the retrieved messages.
|
1003
1212
|
def history(amount, before_id = nil, after_id = nil)
|
1004
|
-
logs = API.
|
1213
|
+
logs = API::Channel.messages(@bot.token, @id, amount, before_id, after_id)
|
1005
1214
|
JSON.parse(logs).map { |message| Message.new(message, @bot) }
|
1006
1215
|
end
|
1007
1216
|
|
1217
|
+
# Retrieves message history, but only message IDs for use with prune
|
1218
|
+
# @note For internal use only
|
1219
|
+
# @!visibility private
|
1220
|
+
def history_ids(amount, before_id = nil, after_id = nil)
|
1221
|
+
logs = API::Channel.messages(@bot.token, @id, amount, before_id, after_id)
|
1222
|
+
JSON.parse(logs).map { |message| message['id'] }
|
1223
|
+
end
|
1224
|
+
|
1225
|
+
# Returns a single message from this channel's history by ID.
|
1226
|
+
# @param message_id [Integer] The ID of the message to retrieve.
|
1227
|
+
# @return [Message] the retrieved message.
|
1228
|
+
def load_message(message_id)
|
1229
|
+
response = API::Channel.message(@bot.token, @id, message_id)
|
1230
|
+
return Message.new(JSON.parse(response), @bot)
|
1231
|
+
rescue RestClient::ResourceNotFound
|
1232
|
+
return nil
|
1233
|
+
end
|
1234
|
+
|
1235
|
+
alias_method :message, :load_message
|
1236
|
+
|
1237
|
+
# Requests all pinned messages of a channel.
|
1238
|
+
# @return [Array<Message>] the received messages.
|
1239
|
+
def pins
|
1240
|
+
msgs = API::Channel.pinned_messages(@bot.token, @id)
|
1241
|
+
JSON.parse(msgs).map { |msg| Message.new(msg, @bot) }
|
1242
|
+
end
|
1243
|
+
|
1008
1244
|
# Delete the last N messages on this channel.
|
1009
1245
|
# @param amount [Integer] How many messages to delete. Must be a value between 2 and 100 (Discord limitation)
|
1010
1246
|
# @raise [ArgumentError] if the amount of messages is not a value between 2 and 100
|
1011
1247
|
def prune(amount)
|
1012
1248
|
raise ArgumentError, 'Can only prune between 2 and 100 messages!' unless amount.between?(2, 100)
|
1013
1249
|
|
1014
|
-
messages =
|
1015
|
-
API.
|
1250
|
+
messages = history_ids(amount)
|
1251
|
+
API::Channel.bulk_delete_messages(@bot.token, @id, messages)
|
1016
1252
|
end
|
1017
1253
|
|
1018
1254
|
# Updates the cached permission overwrites
|
@@ -1033,33 +1269,214 @@ module Discordrb
|
|
1033
1269
|
# @param max_age [Integer] How many seconds this invite should last.
|
1034
1270
|
# @param max_uses [Integer] How many times this invite should be able to be used.
|
1035
1271
|
# @param temporary [true, false] Whether membership should be temporary (kicked after going offline).
|
1036
|
-
# @param xkcd [true, false] Whether or not the invite should be human-readable.
|
1037
1272
|
# @return [Invite] the created invite.
|
1038
|
-
def make_invite(max_age = 0, max_uses = 0, temporary = false
|
1039
|
-
response = API.create_invite(@bot.token, @id, max_age, max_uses, temporary
|
1273
|
+
def make_invite(max_age = 0, max_uses = 0, temporary = false)
|
1274
|
+
response = API::Channel.create_invite(@bot.token, @id, max_age, max_uses, temporary)
|
1040
1275
|
Invite.new(JSON.parse(response), @bot)
|
1041
1276
|
end
|
1042
1277
|
|
1278
|
+
alias_method :invite, :make_invite
|
1279
|
+
|
1043
1280
|
# Starts typing, which displays the typing indicator on the client for five seconds.
|
1044
1281
|
# If you want to keep typing you'll have to resend this every five seconds. (An abstraction
|
1045
1282
|
# for this will eventually be coming)
|
1046
1283
|
def start_typing
|
1047
|
-
API.start_typing(@bot.token, @id)
|
1284
|
+
API::Channel.start_typing(@bot.token, @id)
|
1048
1285
|
end
|
1049
1286
|
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1287
|
+
# Creates a Group channel
|
1288
|
+
# @param user_ids [Array<Integer>] Array of user IDs to add to the new group channel (Excluding
|
1289
|
+
# the recipient of the PM channel).
|
1290
|
+
# @return [Channel] the created channel.
|
1291
|
+
def create_group(user_ids)
|
1292
|
+
raise 'Attempted to create group channel on a non-pm channel!' unless pm?
|
1293
|
+
response = API::Channel.create_group(@bot.token, @id, user_ids.shift)
|
1294
|
+
channel = Channel.new(JSON.parse(response), @bot)
|
1295
|
+
channel.add_group_users(user_ids)
|
1296
|
+
end
|
1297
|
+
|
1298
|
+
# Adds a user to a Group channel
|
1299
|
+
# @param user_ids [Array<#resolve_id>, #resolve_id] User ID or array of user IDs to add to the group channel.
|
1300
|
+
# @return [Channel] the group channel.
|
1301
|
+
def add_group_users(user_ids)
|
1302
|
+
raise 'Attempted to add a user to a non-group channel!' unless group?
|
1303
|
+
user_ids = [user_ids] unless user_ids.is_a? Array
|
1304
|
+
user_ids.each do |user_id|
|
1305
|
+
API::Channel.add_group_user(@bot.token, @id, user_id.resolve_id)
|
1306
|
+
end
|
1307
|
+
self
|
1308
|
+
end
|
1309
|
+
|
1310
|
+
alias_method :add_group_user, :add_group_users
|
1311
|
+
|
1312
|
+
# Removes a user from a group channel.
|
1313
|
+
# @param user_ids [Array<#resolve_id>, #resolve_id] User ID or array of user IDs to remove from the group channel.
|
1314
|
+
# @return [Channel] the group channel.
|
1315
|
+
def remove_group_users(user_ids)
|
1316
|
+
raise 'Attempted to remove a user from a non-group channel!' unless group?
|
1317
|
+
user_ids = [user_ids] unless user_ids.is_a? Array
|
1318
|
+
user_ids.each do |user_id|
|
1319
|
+
API::Channel.remove_group_user(@bot.token, @id, user_id.resolve_id)
|
1320
|
+
end
|
1321
|
+
self
|
1322
|
+
end
|
1323
|
+
|
1324
|
+
alias_method :remove_group_user, :remove_group_users
|
1325
|
+
|
1326
|
+
# Leaves the group
|
1327
|
+
def leave_group
|
1328
|
+
raise 'Attempted to leave a non-group channel!' unless group?
|
1329
|
+
API::Channel.leave_group(@bot.token, @id)
|
1330
|
+
end
|
1331
|
+
|
1332
|
+
alias_method :leave, :leave_group
|
1053
1333
|
|
1054
1334
|
# The inspect method is overwritten to give more useful output
|
1055
1335
|
def inspect
|
1056
1336
|
"<Channel name=#{@name} id=#{@id} topic=\"#{@topic}\" type=#{@type} position=#{@position} server=#{@server}>"
|
1057
1337
|
end
|
1058
1338
|
|
1339
|
+
# Adds a recipient to a group channel.
|
1340
|
+
# @param recipient [Recipient] the recipient to add to the group
|
1341
|
+
# @raise [ArgumentError] if tried to add a non-recipient
|
1342
|
+
# @note For internal use only
|
1343
|
+
# @!visibility private
|
1344
|
+
def add_recipient(recipient)
|
1345
|
+
raise 'Tried to add recipient to a non-group channel' unless group?
|
1346
|
+
raise ArgumentError, 'Tried to add a non-recipient to a group' unless recipient.is_a?(Recipient)
|
1347
|
+
@recipients << recipient
|
1348
|
+
end
|
1349
|
+
|
1350
|
+
# Removes a recipient from a group channel.
|
1351
|
+
# @param recipient [Recipient] the recipient to remove from the group
|
1352
|
+
# @raise [ArgumentError] if tried to remove a non-recipient
|
1353
|
+
# @note For internal use only
|
1354
|
+
# @!visibility private
|
1355
|
+
def remove_recipient(recipient)
|
1356
|
+
raise 'Tried to add recipient to a non-group channel' unless group?
|
1357
|
+
raise ArgumentError, 'Tried to remove a non-recipient from a group' unless recipient.is_a?(Recipient)
|
1358
|
+
@recipients.delete(recipient)
|
1359
|
+
end
|
1360
|
+
|
1059
1361
|
private
|
1060
1362
|
|
1061
1363
|
def update_channel_data
|
1062
|
-
API.update_channel(@bot.token, @id, @name, @topic, @position)
|
1364
|
+
API.update_channel(@bot.token, @id, @name, @topic, @position, @bitrate, @user_limit)
|
1365
|
+
end
|
1366
|
+
end
|
1367
|
+
|
1368
|
+
# An Embed object that is contained in a message
|
1369
|
+
# A freshly generated embed object will not appear in a message object
|
1370
|
+
# unless grabbed from its ID in a channel.
|
1371
|
+
class Embed
|
1372
|
+
# @return [Message] the message this embed object is contained in.
|
1373
|
+
attr_reader :message
|
1374
|
+
|
1375
|
+
# @return [String] the URL this embed object is based on.
|
1376
|
+
attr_reader :url
|
1377
|
+
|
1378
|
+
# @return [String, nil] the title of the embed object. `nil` if there is not a title
|
1379
|
+
attr_reader :title
|
1380
|
+
|
1381
|
+
# @return [String, nil] the description of the embed object. `nil` if there is not a description
|
1382
|
+
attr_reader :description
|
1383
|
+
|
1384
|
+
# @return [Symbol] the type of the embed object. Possible types are:
|
1385
|
+
#
|
1386
|
+
# * `:link`
|
1387
|
+
# * `:video`
|
1388
|
+
# * `:image`
|
1389
|
+
attr_reader :type
|
1390
|
+
|
1391
|
+
# @return [EmbedProvider, nil] the provider of the embed object. `nil` is there is not a provider
|
1392
|
+
attr_reader :provider
|
1393
|
+
|
1394
|
+
# @return [EmbedThumbnail, nil] the thumbnail of the embed object. `nil` is there is not a thumbnail
|
1395
|
+
attr_reader :thumbnail
|
1396
|
+
|
1397
|
+
# @return [EmbedAuthor, nil] the author of the embed object. `nil` is there is not an author
|
1398
|
+
attr_reader :author
|
1399
|
+
|
1400
|
+
# @!visibility private
|
1401
|
+
def initialize(data, message)
|
1402
|
+
@message = message
|
1403
|
+
|
1404
|
+
@url = data['url']
|
1405
|
+
@title = data['title']
|
1406
|
+
@type = data['type'].to_sym
|
1407
|
+
@description = data['description']
|
1408
|
+
@provider = data['provider'].nil? ? nil : EmbedProvider.new(data['provider'], self)
|
1409
|
+
@thumbnail = data['thumbnail'].nil? ? nil : EmbedThumbnail.new(data['thumbnail'], self)
|
1410
|
+
@author = data['author'].nil? ? nil : EmbedAuthor.new(data['author'], self)
|
1411
|
+
end
|
1412
|
+
end
|
1413
|
+
|
1414
|
+
# An Embed thumbnail for the embed object
|
1415
|
+
class EmbedThumbnail
|
1416
|
+
# @return [Embed] the embed object this is based on.
|
1417
|
+
attr_reader :embed
|
1418
|
+
|
1419
|
+
# @return [String] the CDN URL this thumbnail can be downloaded at.
|
1420
|
+
attr_reader :url
|
1421
|
+
|
1422
|
+
# @return [String] the thumbnail's proxy URL - I'm not sure what exactly this does, but I think it has something to
|
1423
|
+
# do with CDNs
|
1424
|
+
attr_reader :proxy_url
|
1425
|
+
|
1426
|
+
# @return [Integer] the width of this thumbnail file, in pixels.
|
1427
|
+
attr_reader :width
|
1428
|
+
|
1429
|
+
# @return [Integer] the height of this thumbnail file, in pixels.
|
1430
|
+
attr_reader :height
|
1431
|
+
|
1432
|
+
# @!visibility private
|
1433
|
+
def initialize(data, embed)
|
1434
|
+
@embed = embed
|
1435
|
+
|
1436
|
+
@url = data['url']
|
1437
|
+
@proxy_url = data['proxy_url']
|
1438
|
+
@width = data['width']
|
1439
|
+
@height = data['height']
|
1440
|
+
end
|
1441
|
+
end
|
1442
|
+
|
1443
|
+
# An Embed provider for the embed object
|
1444
|
+
class EmbedProvider
|
1445
|
+
# @return [Embed] the embed object this is based on.
|
1446
|
+
attr_reader :embed
|
1447
|
+
|
1448
|
+
# @return [String] the provider's name.
|
1449
|
+
attr_reader :name
|
1450
|
+
|
1451
|
+
# @return [String, nil] the URL of the provider. `nil` is there is no URL
|
1452
|
+
attr_reader :url
|
1453
|
+
|
1454
|
+
# @!visibility private
|
1455
|
+
def initialize(data, embed)
|
1456
|
+
@embed = embed
|
1457
|
+
|
1458
|
+
@name = data['name']
|
1459
|
+
@url = data['url']
|
1460
|
+
end
|
1461
|
+
end
|
1462
|
+
|
1463
|
+
# An Embed author for the embed object
|
1464
|
+
class EmbedAuthor
|
1465
|
+
# @return [Embed] the embed object this is based on.
|
1466
|
+
attr_reader :embed
|
1467
|
+
|
1468
|
+
# @return [String] the author's name.
|
1469
|
+
attr_reader :name
|
1470
|
+
|
1471
|
+
# @return [String, nil] the URL of the author's website. `nil` is there is no URL
|
1472
|
+
attr_reader :url
|
1473
|
+
|
1474
|
+
# @!visibility private
|
1475
|
+
def initialize(data, embed)
|
1476
|
+
@embed = embed
|
1477
|
+
|
1478
|
+
@name = data['name']
|
1479
|
+
@url = data['url']
|
1063
1480
|
end
|
1064
1481
|
end
|
1065
1482
|
|
@@ -1116,9 +1533,13 @@ module Discordrb
|
|
1116
1533
|
|
1117
1534
|
# @return [String] the content of this message.
|
1118
1535
|
attr_reader :content
|
1536
|
+
alias_method :text, :content
|
1537
|
+
alias_method :to_s, :content
|
1119
1538
|
|
1120
1539
|
# @return [Member] the user that sent this message.
|
1121
1540
|
attr_reader :author
|
1541
|
+
alias_method :user, :author
|
1542
|
+
alias_method :writer, :author
|
1122
1543
|
|
1123
1544
|
# @return [Channel] the channel in which this message was sent.
|
1124
1545
|
attr_reader :channel
|
@@ -1126,6 +1547,10 @@ module Discordrb
|
|
1126
1547
|
# @return [Time] the timestamp at which this message was sent.
|
1127
1548
|
attr_reader :timestamp
|
1128
1549
|
|
1550
|
+
# @return [Time] the timestamp at which this message was edited. `nil` if the message was never edited.
|
1551
|
+
attr_reader :edited_timestamp
|
1552
|
+
alias_method :edit_timestamp, :edited_timestamp
|
1553
|
+
|
1129
1554
|
# @return [Array<User>] the users that were mentioned in this message.
|
1130
1555
|
attr_reader :mentions
|
1131
1556
|
|
@@ -1135,15 +1560,38 @@ module Discordrb
|
|
1135
1560
|
# @return [Array<Attachment>] the files attached to this message.
|
1136
1561
|
attr_reader :attachments
|
1137
1562
|
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1563
|
+
# @return [Array<Embed>] the embed objects contained in this message.
|
1564
|
+
attr_reader :embeds
|
1565
|
+
|
1566
|
+
# @return [true, false] whether the message used Text-To-Speech (TTS) or not.
|
1567
|
+
attr_reader :tts
|
1568
|
+
alias_method :tts?, :tts
|
1569
|
+
|
1570
|
+
# @return [String] used for validating a message was sent
|
1571
|
+
attr_reader :nonce
|
1572
|
+
|
1573
|
+
# @return [true, false] whether the message was edited or not.
|
1574
|
+
attr_reader :edited
|
1575
|
+
alias_method :edited?, :edited
|
1576
|
+
|
1577
|
+
# @return [true, false] whether the message mentioned everyone or not.
|
1578
|
+
attr_reader :mention_everyone
|
1579
|
+
alias_method :mention_everyone?, :mention_everyone
|
1580
|
+
alias_method :mentions_everyone?, :mention_everyone
|
1581
|
+
|
1582
|
+
# @return [true, false] whether the message is pinned or not.
|
1583
|
+
attr_reader :pinned
|
1584
|
+
alias_method :pinned?, :pinned
|
1141
1585
|
|
1142
1586
|
# @!visibility private
|
1143
1587
|
def initialize(data, bot)
|
1144
1588
|
@bot = bot
|
1145
1589
|
@content = data['content']
|
1146
1590
|
@channel = bot.channel(data['channel_id'].to_i)
|
1591
|
+
@pinned = data['pinned']
|
1592
|
+
@tts = data['tts']
|
1593
|
+
@nonce = data['nonce']
|
1594
|
+
@mention_everyone = data['mention_everyone']
|
1147
1595
|
|
1148
1596
|
@author = if data['author']
|
1149
1597
|
if @channel.private?
|
@@ -1151,13 +1599,15 @@ module Discordrb
|
|
1151
1599
|
# directly because the bot may also send messages to the channel
|
1152
1600
|
Recipient.new(bot.user(data['author']['id'].to_i), @channel, bot)
|
1153
1601
|
else
|
1154
|
-
member = @channel.server.member(data['author']['id'].to_i
|
1602
|
+
member = @channel.server.member(data['author']['id'].to_i)
|
1155
1603
|
Discordrb::LOGGER.warn("Member with ID #{data['author']['id']} not cached even though it should be.") unless member
|
1156
1604
|
member
|
1157
1605
|
end
|
1158
1606
|
end
|
1159
1607
|
|
1160
1608
|
@timestamp = Time.parse(data['timestamp']) if data['timestamp']
|
1609
|
+
@edited_timestamp = data['edited_timestamp'].nil? ? nil : Time.parse(data['edited_timestamp'])
|
1610
|
+
@edited = !@edited_timestamp.nil?
|
1161
1611
|
@id = data['id'].to_i
|
1162
1612
|
|
1163
1613
|
@mentions = []
|
@@ -1169,7 +1619,7 @@ module Discordrb
|
|
1169
1619
|
@role_mentions = []
|
1170
1620
|
|
1171
1621
|
# Role mentions can only happen on public servers so make sure we only parse them there
|
1172
|
-
|
1622
|
+
if @channel.text?
|
1173
1623
|
data['mention_roles'].each do |element|
|
1174
1624
|
@role_mentions << @channel.server.role(element.to_i)
|
1175
1625
|
end if data['mention_roles']
|
@@ -1177,6 +1627,9 @@ module Discordrb
|
|
1177
1627
|
|
1178
1628
|
@attachments = []
|
1179
1629
|
@attachments = data['attachments'].map { |e| Attachment.new(e, self, @bot) } if data['attachments']
|
1630
|
+
|
1631
|
+
@embeds = []
|
1632
|
+
@embeds = data['embeds'].map { |e| Embed.new(e, self) } if data['embeds']
|
1180
1633
|
end
|
1181
1634
|
|
1182
1635
|
# Replies to this message with the specified content.
|
@@ -1189,13 +1642,27 @@ module Discordrb
|
|
1189
1642
|
# @param new_content [String] the new content the message should have.
|
1190
1643
|
# @return [Message] the resulting message.
|
1191
1644
|
def edit(new_content)
|
1192
|
-
response = API.edit_message(@bot.token, @channel.id, @id, new_content)
|
1645
|
+
response = API::Channel.edit_message(@bot.token, @channel.id, @id, new_content)
|
1193
1646
|
Message.new(JSON.parse(response), @bot)
|
1194
1647
|
end
|
1195
1648
|
|
1196
1649
|
# Deletes this message.
|
1197
1650
|
def delete
|
1198
|
-
API.delete_message(@bot.token, @channel.id, @id)
|
1651
|
+
API::Channel.delete_message(@bot.token, @channel.id, @id)
|
1652
|
+
nil
|
1653
|
+
end
|
1654
|
+
|
1655
|
+
# Pins this message
|
1656
|
+
def pin
|
1657
|
+
API::Channel.pin_message(@bot.token, @channel.id, @id)
|
1658
|
+
@pinned = true
|
1659
|
+
nil
|
1660
|
+
end
|
1661
|
+
|
1662
|
+
# Unpins this message
|
1663
|
+
def unpin
|
1664
|
+
API::Channel.unpin_message(@bot.token, @channel.id, @id)
|
1665
|
+
@pinned = false
|
1199
1666
|
nil
|
1200
1667
|
end
|
1201
1668
|
|
@@ -1227,10 +1694,91 @@ module Discordrb
|
|
1227
1694
|
# Utility function to get the URL for the icon image
|
1228
1695
|
# @return [String] the URL to the icon image
|
1229
1696
|
def icon_url
|
1697
|
+
return nil unless @icon_id
|
1230
1698
|
API.icon_url(@id, @icon_id)
|
1231
1699
|
end
|
1232
1700
|
end
|
1233
1701
|
|
1702
|
+
# Integration Account
|
1703
|
+
class IntegrationAccount
|
1704
|
+
# @return [String] this accounts's name.
|
1705
|
+
attr_reader :name
|
1706
|
+
|
1707
|
+
# @return [Integer] this account's ID.
|
1708
|
+
attr_reader :id
|
1709
|
+
|
1710
|
+
def initialize(data)
|
1711
|
+
@name = data['name']
|
1712
|
+
@id = data['id'].to_i
|
1713
|
+
end
|
1714
|
+
end
|
1715
|
+
|
1716
|
+
# Server integration
|
1717
|
+
class Integration
|
1718
|
+
include IDObject
|
1719
|
+
|
1720
|
+
# @return [String] the integration name
|
1721
|
+
attr_reader :name
|
1722
|
+
|
1723
|
+
# @return [Server] the server the integration is linked to
|
1724
|
+
attr_reader :server
|
1725
|
+
|
1726
|
+
# @return [User] the user the integration is linked to
|
1727
|
+
attr_reader :user
|
1728
|
+
|
1729
|
+
# @return [Role, nil] the role that this integration uses for "subscribers"
|
1730
|
+
attr_reader :role
|
1731
|
+
|
1732
|
+
# @return [true, false] whether emoticons are enabled
|
1733
|
+
attr_reader :emoticon
|
1734
|
+
alias_method :emoticon?, :emoticon
|
1735
|
+
|
1736
|
+
# @return [String] the integration type (Youtube, Twitch, etc.)
|
1737
|
+
attr_reader :type
|
1738
|
+
|
1739
|
+
# @return [true, false] whether the integration is enabled
|
1740
|
+
attr_reader :enabled
|
1741
|
+
|
1742
|
+
# @return [true, false] whether the integration is syncing
|
1743
|
+
attr_reader :syncing
|
1744
|
+
|
1745
|
+
# @return [IntegrationAccount] the integration account information
|
1746
|
+
attr_reader :account
|
1747
|
+
|
1748
|
+
# @return [Time] the time the integration was synced at
|
1749
|
+
attr_reader :synced_at
|
1750
|
+
|
1751
|
+
# @return [Symbol] the behaviour of expiring subscribers (:remove = Remove User from role; :kick = Kick User from server)
|
1752
|
+
attr_reader :expire_behaviour
|
1753
|
+
alias_method :expire_behavior, :expire_behaviour
|
1754
|
+
|
1755
|
+
# @return [Integer] the grace period before subscribers expire (in days)
|
1756
|
+
attr_reader :expire_grace_period
|
1757
|
+
|
1758
|
+
def initialize(data, bot, server)
|
1759
|
+
@bot = bot
|
1760
|
+
|
1761
|
+
@name = data['name']
|
1762
|
+
@server = server
|
1763
|
+
@id = data['id'].to_i
|
1764
|
+
@enabled = data['enabled']
|
1765
|
+
@syncing = data['syncing']
|
1766
|
+
@type = data['type']
|
1767
|
+
@account = IntegrationAccount.new(data['account'])
|
1768
|
+
@synced_at = Time.parse(data['synced_at'])
|
1769
|
+
@expire_behaviour = [:remove, :kick][data['expire_behavior']]
|
1770
|
+
@expire_grace_period = data['expire_grace_period']
|
1771
|
+
@user = @bot.ensure_user(data['user'])
|
1772
|
+
@role = server.role(data['role_id']) || nil
|
1773
|
+
@emoticon = data['enable_emoticons']
|
1774
|
+
end
|
1775
|
+
|
1776
|
+
# The inspect method is overwritten to give more useful output
|
1777
|
+
def inspect
|
1778
|
+
"<Integration name=#{@name} id=#{@id} type=#{@type} enabled=#{@enabled}>"
|
1779
|
+
end
|
1780
|
+
end
|
1781
|
+
|
1234
1782
|
# A server on Discord
|
1235
1783
|
class Server
|
1236
1784
|
include IDObject
|
@@ -1253,15 +1801,24 @@ module Discordrb
|
|
1253
1801
|
attr_reader :large
|
1254
1802
|
alias_method :large?, :large
|
1255
1803
|
|
1804
|
+
# @return [Array<Symbol>] the features of the server (eg. "INVITE_SPLASH")
|
1805
|
+
attr_reader :features
|
1806
|
+
|
1256
1807
|
# @return [Integer] the absolute number of members on this server, offline or not.
|
1257
1808
|
attr_reader :member_count
|
1258
1809
|
|
1810
|
+
# @return [Symbol] the verification level of the server (:none = none, :low = 'Must have a verified email on their Discord account', :medium = 'Has to be registered with Discord for at least 5 minutes', :high = 'Has to be a member of this server for at least 10 minutes').
|
1811
|
+
attr_reader :verification_level
|
1812
|
+
|
1259
1813
|
# @return [Integer] the amount of time after which a voice user gets moved into the AFK channel, in seconds.
|
1260
1814
|
attr_reader :afk_timeout
|
1261
1815
|
|
1262
1816
|
# @return [Channel, nil] the AFK voice channel of this server, or nil if none is set
|
1263
1817
|
attr_reader :afk_channel
|
1264
1818
|
|
1819
|
+
# @return [Hash<Integer => VoiceState>] the hash (user ID => voice state) of voice states of members on this server
|
1820
|
+
attr_reader :voice_states
|
1821
|
+
|
1265
1822
|
# @!visibility private
|
1266
1823
|
def initialize(data, bot, exists = true)
|
1267
1824
|
@bot = bot
|
@@ -1271,7 +1828,12 @@ module Discordrb
|
|
1271
1828
|
|
1272
1829
|
@large = data['large']
|
1273
1830
|
@member_count = data['member_count']
|
1831
|
+
@verification_level = [:none, :low, :medium, :high][data['verification_level']]
|
1832
|
+
@splash_id = nil
|
1833
|
+
@embed = nil
|
1834
|
+
@features = data['features'].map { |element| element.downcase.to_sym }
|
1274
1835
|
@members = {}
|
1836
|
+
@voice_states = {}
|
1275
1837
|
|
1276
1838
|
process_roles(data['roles'])
|
1277
1839
|
process_members(data['members'])
|
@@ -1308,7 +1870,7 @@ module Discordrb
|
|
1308
1870
|
return @members[id] if member_cached?(id)
|
1309
1871
|
return nil unless request
|
1310
1872
|
|
1311
|
-
member = @bot.member(
|
1873
|
+
member = @bot.member(self, id)
|
1312
1874
|
@members[id] = member
|
1313
1875
|
rescue
|
1314
1876
|
nil
|
@@ -1326,6 +1888,25 @@ module Discordrb
|
|
1326
1888
|
|
1327
1889
|
alias_method :users, :members
|
1328
1890
|
|
1891
|
+
# @return [Array<Integration>] an array of all the integrations connected to this server.
|
1892
|
+
def integrations
|
1893
|
+
integration = JSON.parse(API.server_integrations(@bot.token, @id))
|
1894
|
+
integration.map { |element| Integration.new(element, @bot, self) }
|
1895
|
+
end
|
1896
|
+
|
1897
|
+
# Cache @embed
|
1898
|
+
# @note For internal use only
|
1899
|
+
# @!visibility private
|
1900
|
+
def cache_embed
|
1901
|
+
@embed = JSON.parse(API.server(@bot.token, @id))['embed_enabled'] if @embed.nil?
|
1902
|
+
end
|
1903
|
+
|
1904
|
+
# @return [true, false] whether or not the server has widget enabled
|
1905
|
+
def embed?
|
1906
|
+
cache_embed if @embed.nil?
|
1907
|
+
@embed
|
1908
|
+
end
|
1909
|
+
|
1329
1910
|
# @param include_idle [true, false] Whether to count idle members as online.
|
1330
1911
|
# @param include_bots [true, false] Whether to include bot accounts in the count.
|
1331
1912
|
# @return [Array<Member>] an array of online members on this server.
|
@@ -1347,6 +1928,42 @@ module Discordrb
|
|
1347
1928
|
@channels.select(&:voice?)
|
1348
1929
|
end
|
1349
1930
|
|
1931
|
+
# @return [String, nil] the widget URL to the server that displays the amount of online members in a
|
1932
|
+
# stylish way. `nil` if the widget is not enabled.
|
1933
|
+
def widget_url
|
1934
|
+
cache_embed if @embed.nil?
|
1935
|
+
return nil unless @embed
|
1936
|
+
API.widget_url(@id)
|
1937
|
+
end
|
1938
|
+
|
1939
|
+
# @param style [Symbol] The style the picture should have. Possible styles are:
|
1940
|
+
# * `:banner1` creates a rectangular image with the server name, member count and icon, a "Powered by Discord" message on the bottom and an arrow on the right.
|
1941
|
+
# * `:banner2` creates a less tall rectangular image that has the same information as `banner1`, but the Discord logo on the right - together with the arrow and separated by a diagonal separator.
|
1942
|
+
# * `:banner3` creates an image similar in size to `banner1`, but it has the arrow in the bottom part, next to the Discord logo and with a "Chat now" text.
|
1943
|
+
# * `:banner4` creates a tall, almost square, image that prominently features the Discord logo at the top and has a "Join my server" in a pill-style button on the bottom. The information about the server is in the same format as the other three `banner` styles.
|
1944
|
+
# * `:shield` creates a very small, long rectangle, of the style you'd find at the top of GitHub `README.md` files. It features a small version of the Discord logo at the left and the member count at the right.
|
1945
|
+
# @return [String, nil] the widget banner URL to the server that displays the amount of online members,
|
1946
|
+
# server icon and server name in a stylish way. `nil` if the widget is not enabled.
|
1947
|
+
def widget_banner_url(style)
|
1948
|
+
return nil unless @embed
|
1949
|
+
cache_embed if @embed.nil?
|
1950
|
+
API.widget_url(@id, style)
|
1951
|
+
end
|
1952
|
+
|
1953
|
+
# @return [String] the hexadecimal ID used to identify this server's splash image for their VIP invite page.
|
1954
|
+
def splash_id
|
1955
|
+
@splash_id = JSON.parse(API.server(@bot.token, @id))['splash'] if @splash_id.nil?
|
1956
|
+
@splash_id
|
1957
|
+
end
|
1958
|
+
|
1959
|
+
# @return [String, nil] the splash image URL for the server's VIP invite page.
|
1960
|
+
# `nil` if there is no splash image.
|
1961
|
+
def splash_url
|
1962
|
+
splash_id if @splash_id.nil?
|
1963
|
+
return nil unless @splash_id
|
1964
|
+
API.splash_url(@id, @splash_id)
|
1965
|
+
end
|
1966
|
+
|
1350
1967
|
# Adds a role to the role cache
|
1351
1968
|
# @note For internal use only
|
1352
1969
|
# @!visibility private
|
@@ -1399,10 +2016,41 @@ module Discordrb
|
|
1399
2016
|
@members[member.id] = member
|
1400
2017
|
end
|
1401
2018
|
|
2019
|
+
# Updates a member's voice state
|
2020
|
+
# @note For internal use only
|
2021
|
+
# @!visibility private
|
2022
|
+
def update_voice_state(data)
|
2023
|
+
user_id = data['user_id'].to_i
|
2024
|
+
|
2025
|
+
if data['channel_id']
|
2026
|
+
unless @voice_states[user_id]
|
2027
|
+
# Create a new voice state for the user
|
2028
|
+
@voice_states[user_id] = VoiceState.new(user_id)
|
2029
|
+
end
|
2030
|
+
|
2031
|
+
# Update the existing voice state (or the one we just created)
|
2032
|
+
channel = @channels_by_id[data['channel_id'].to_i]
|
2033
|
+
@voice_states[user_id].update(
|
2034
|
+
channel,
|
2035
|
+
data['mute'],
|
2036
|
+
data['deaf'],
|
2037
|
+
data['self_mute'],
|
2038
|
+
data['self_deaf']
|
2039
|
+
)
|
2040
|
+
else
|
2041
|
+
# The user is not in a voice channel anymore, so delete its voice state
|
2042
|
+
@voice_states.delete(user_id)
|
2043
|
+
end
|
2044
|
+
end
|
2045
|
+
|
1402
2046
|
# Creates a channel on this server with the given name.
|
2047
|
+
# @param name [String] Name of the channel to create
|
2048
|
+
# @param type [Integer] Type of channel to create (0: text, 2: voice)
|
1403
2049
|
# @return [Channel] the created channel.
|
1404
|
-
|
1405
|
-
|
2050
|
+
# @raise [ArgumentError] if type is not 0 or 2
|
2051
|
+
def create_channel(name, type = 0)
|
2052
|
+
raise ArgumentError, 'Channel type must be either 0 (text) or 2 (voice)!' unless [0, 2].include?(type)
|
2053
|
+
response = API::Server.create_channel(@bot.token, @id, name, type)
|
1406
2054
|
Channel.new(JSON.parse(response), @bot)
|
1407
2055
|
end
|
1408
2056
|
|
@@ -1411,7 +2059,7 @@ module Discordrb
|
|
1411
2059
|
# colour is the default etc.
|
1412
2060
|
# @return [Role] the created role.
|
1413
2061
|
def create_role
|
1414
|
-
response = API.create_role(@bot.token, @id)
|
2062
|
+
response = API::Server.create_role(@bot.token, @id)
|
1415
2063
|
role = Role.new(JSON.parse(response), @bot, self)
|
1416
2064
|
@roles << role
|
1417
2065
|
role
|
@@ -1419,7 +2067,7 @@ module Discordrb
|
|
1419
2067
|
|
1420
2068
|
# @return [Array<User>] a list of banned users on this server.
|
1421
2069
|
def bans
|
1422
|
-
users = JSON.parse(API.bans(@bot.token, @id))
|
2070
|
+
users = JSON.parse(API::Server.bans(@bot.token, @id))
|
1423
2071
|
users.map { |e| User.new(e['user'], @bot) }
|
1424
2072
|
end
|
1425
2073
|
|
@@ -1427,42 +2075,42 @@ module Discordrb
|
|
1427
2075
|
# @param user [User, #resolve_id] The user to ban.
|
1428
2076
|
# @param message_days [Integer] How many days worth of messages sent by the user should be deleted.
|
1429
2077
|
def ban(user, message_days = 0)
|
1430
|
-
API.ban_user(@bot.token, @id, user.resolve_id, message_days)
|
2078
|
+
API::Server.ban_user(@bot.token, @id, user.resolve_id, message_days)
|
1431
2079
|
end
|
1432
2080
|
|
1433
2081
|
# Unbans a previously banned user from this server.
|
1434
2082
|
# @param user [User, #resolve_id] The user to unban.
|
1435
2083
|
def unban(user)
|
1436
|
-
API.unban_user(@bot.token, @id, user.resolve_id)
|
2084
|
+
API::Server.unban_user(@bot.token, @id, user.resolve_id)
|
1437
2085
|
end
|
1438
2086
|
|
1439
2087
|
# Kicks a user from this server.
|
1440
2088
|
# @param user [User, #resolve_id] The user to kick.
|
1441
2089
|
def kick(user)
|
1442
|
-
API.
|
2090
|
+
API::Server.remove_member(@bot.token, @id, user.resolve_id)
|
1443
2091
|
end
|
1444
2092
|
|
1445
2093
|
# Forcibly moves a user into a different voice channel. Only works if the bot has the permission needed.
|
1446
2094
|
# @param user [User] The user to move.
|
1447
2095
|
# @param channel [Channel] The voice channel to move into.
|
1448
2096
|
def move(user, channel)
|
1449
|
-
API.
|
2097
|
+
API::Server.update_member(@bot.token, @id, user.id, channel_id: channel.id)
|
1450
2098
|
end
|
1451
2099
|
|
1452
2100
|
# Deletes this server. Be aware that this is permanent and impossible to undo, so be careful!
|
1453
2101
|
def delete
|
1454
|
-
API.
|
2102
|
+
API::Server.delete(@bot.token, @id)
|
1455
2103
|
end
|
1456
2104
|
|
1457
2105
|
# Leave the server
|
1458
2106
|
def leave
|
1459
|
-
API.leave_server(@bot.token, @id)
|
2107
|
+
API::User.leave_server(@bot.token, @id)
|
1460
2108
|
end
|
1461
2109
|
|
1462
2110
|
# Transfers server ownership to another user.
|
1463
2111
|
# @param user [User] The user who should become the new owner.
|
1464
2112
|
def owner=(user)
|
1465
|
-
API.transfer_ownership(@bot.token, @id, user.id)
|
2113
|
+
API::Server.transfer_ownership(@bot.token, @id, user.id)
|
1466
2114
|
end
|
1467
2115
|
|
1468
2116
|
# Sets the server's name.
|
@@ -1529,7 +2177,13 @@ module Discordrb
|
|
1529
2177
|
@afk_timeout = new_data[:afk_timeout] || new_data['afk_timeout'].to_i || @afk_timeout
|
1530
2178
|
|
1531
2179
|
@afk_channel_id = new_data[:afk_channel_id] || new_data['afk_channel_id'].to_i || @afk_channel.id
|
1532
|
-
|
2180
|
+
|
2181
|
+
begin
|
2182
|
+
@afk_channel = @bot.channel(@afk_channel_id, self) if @afk_channel_id.nonzero? && (!@afk_channel || @afk_channel_id != @afk_channel.id)
|
2183
|
+
rescue Discordrb::Errors::NoPermission
|
2184
|
+
LOGGER.debug("AFK channel #{@afk_channel_id} on server #{@id} is unreachable, setting to nil even though one exists")
|
2185
|
+
@afk_channel = nil
|
2186
|
+
end
|
1533
2187
|
end
|
1534
2188
|
|
1535
2189
|
# The inspect method is overwritten to give more useful output
|
@@ -1540,12 +2194,12 @@ module Discordrb
|
|
1540
2194
|
private
|
1541
2195
|
|
1542
2196
|
def update_server_data(new_data)
|
1543
|
-
API.
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
2197
|
+
API::Server.update(@bot.token, @id,
|
2198
|
+
new_data[:name] || @name,
|
2199
|
+
new_data[:region] || @region,
|
2200
|
+
new_data[:icon_id] || @icon_id,
|
2201
|
+
new_data[:afk_channel_id] || @afk_channel_id,
|
2202
|
+
new_data[:afk_timeout] || @afk_timeout)
|
1549
2203
|
update_data(new_data)
|
1550
2204
|
end
|
1551
2205
|
|
@@ -1566,17 +2220,6 @@ module Discordrb
|
|
1566
2220
|
return unless members
|
1567
2221
|
members.each do |element|
|
1568
2222
|
member = Member.new(element, self, @bot)
|
1569
|
-
if @members[member.id] && @members[member.id].voice_channel
|
1570
|
-
@bot.debug("Preserving voice state of member #{member.id} while chunking")
|
1571
|
-
old_member = @members[member.id]
|
1572
|
-
member.update_voice_state(
|
1573
|
-
old_member.voice_channel,
|
1574
|
-
old_member.mute,
|
1575
|
-
old_member.deaf,
|
1576
|
-
old_member.self_mute,
|
1577
|
-
old_member.self_deaf
|
1578
|
-
)
|
1579
|
-
end
|
1580
2223
|
@members[member.id] = member
|
1581
2224
|
end
|
1582
2225
|
end
|
@@ -1591,6 +2234,8 @@ module Discordrb
|
|
1591
2234
|
if user
|
1592
2235
|
user.status = element['status'].to_sym
|
1593
2236
|
user.game = element['game'] ? element['game']['name'] : nil
|
2237
|
+
else
|
2238
|
+
LOGGER.warn "Rogue presence update! #{element['user']['id']} on #{@id}"
|
1594
2239
|
end
|
1595
2240
|
end
|
1596
2241
|
end
|
@@ -1610,18 +2255,7 @@ module Discordrb
|
|
1610
2255
|
def process_voice_states(voice_states)
|
1611
2256
|
return unless voice_states
|
1612
2257
|
voice_states.each do |element|
|
1613
|
-
|
1614
|
-
member = @members[user_id]
|
1615
|
-
next unless member
|
1616
|
-
channel_id = element['channel_id'].to_i
|
1617
|
-
channel = channel_id ? @channels_by_id[channel_id] : nil
|
1618
|
-
|
1619
|
-
member.update_voice_state(
|
1620
|
-
channel,
|
1621
|
-
element['mute'],
|
1622
|
-
element['deaf'],
|
1623
|
-
element['self_mute'],
|
1624
|
-
element['self_deaf'])
|
2258
|
+
update_voice_state(element)
|
1625
2259
|
end
|
1626
2260
|
end
|
1627
2261
|
end
|