discordrb 3.1.1 → 3.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.

Files changed (91) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +126 -0
  3. data/.codeclimate.yml +16 -0
  4. data/.github/CONTRIBUTING.md +13 -0
  5. data/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
  6. data/.github/ISSUE_TEMPLATE/feature_request.md +25 -0
  7. data/.github/pull_request_template.md +37 -0
  8. data/.gitignore +5 -0
  9. data/.rubocop.yml +39 -33
  10. data/.travis.yml +27 -2
  11. data/.yardopts +1 -1
  12. data/CHANGELOG.md +808 -208
  13. data/Gemfile +4 -1
  14. data/LICENSE.txt +1 -1
  15. data/README.md +108 -53
  16. data/Rakefile +14 -1
  17. data/bin/console +1 -0
  18. data/bin/travis_build_docs.sh +17 -0
  19. data/discordrb-webhooks.gemspec +26 -0
  20. data/discordrb.gemspec +24 -15
  21. data/lib/discordrb.rb +75 -2
  22. data/lib/discordrb/allowed_mentions.rb +36 -0
  23. data/lib/discordrb/api.rb +126 -27
  24. data/lib/discordrb/api/channel.rb +165 -43
  25. data/lib/discordrb/api/invite.rb +10 -7
  26. data/lib/discordrb/api/server.rb +240 -61
  27. data/lib/discordrb/api/user.rb +26 -24
  28. data/lib/discordrb/api/webhook.rb +83 -0
  29. data/lib/discordrb/await.rb +1 -2
  30. data/lib/discordrb/bot.rb +417 -149
  31. data/lib/discordrb/cache.rb +42 -10
  32. data/lib/discordrb/colour_rgb.rb +43 -0
  33. data/lib/discordrb/commands/command_bot.rb +186 -31
  34. data/lib/discordrb/commands/container.rb +30 -16
  35. data/lib/discordrb/commands/parser.rb +102 -47
  36. data/lib/discordrb/commands/rate_limiter.rb +18 -17
  37. data/lib/discordrb/container.rb +245 -41
  38. data/lib/discordrb/data.rb +27 -2511
  39. data/lib/discordrb/data/activity.rb +264 -0
  40. data/lib/discordrb/data/application.rb +50 -0
  41. data/lib/discordrb/data/attachment.rb +56 -0
  42. data/lib/discordrb/data/audit_logs.rb +345 -0
  43. data/lib/discordrb/data/channel.rb +849 -0
  44. data/lib/discordrb/data/embed.rb +251 -0
  45. data/lib/discordrb/data/emoji.rb +82 -0
  46. data/lib/discordrb/data/integration.rb +83 -0
  47. data/lib/discordrb/data/invite.rb +137 -0
  48. data/lib/discordrb/data/member.rb +297 -0
  49. data/lib/discordrb/data/message.rb +334 -0
  50. data/lib/discordrb/data/overwrite.rb +102 -0
  51. data/lib/discordrb/data/profile.rb +91 -0
  52. data/lib/discordrb/data/reaction.rb +33 -0
  53. data/lib/discordrb/data/recipient.rb +34 -0
  54. data/lib/discordrb/data/role.rb +191 -0
  55. data/lib/discordrb/data/server.rb +1002 -0
  56. data/lib/discordrb/data/user.rb +204 -0
  57. data/lib/discordrb/data/voice_region.rb +45 -0
  58. data/lib/discordrb/data/voice_state.rb +41 -0
  59. data/lib/discordrb/data/webhook.rb +145 -0
  60. data/lib/discordrb/errors.rb +36 -2
  61. data/lib/discordrb/events/bans.rb +7 -5
  62. data/lib/discordrb/events/channels.rb +2 -0
  63. data/lib/discordrb/events/generic.rb +19 -3
  64. data/lib/discordrb/events/guilds.rb +129 -6
  65. data/lib/discordrb/events/invites.rb +125 -0
  66. data/lib/discordrb/events/members.rb +6 -2
  67. data/lib/discordrb/events/message.rb +86 -36
  68. data/lib/discordrb/events/presence.rb +23 -16
  69. data/lib/discordrb/events/raw.rb +47 -0
  70. data/lib/discordrb/events/reactions.rb +159 -0
  71. data/lib/discordrb/events/roles.rb +7 -6
  72. data/lib/discordrb/events/typing.rb +9 -5
  73. data/lib/discordrb/events/voice_server_update.rb +47 -0
  74. data/lib/discordrb/events/voice_state_update.rb +29 -9
  75. data/lib/discordrb/events/webhooks.rb +64 -0
  76. data/lib/discordrb/gateway.rb +219 -88
  77. data/lib/discordrb/id_object.rb +39 -0
  78. data/lib/discordrb/light.rb +1 -1
  79. data/lib/discordrb/light/integrations.rb +1 -1
  80. data/lib/discordrb/light/light_bot.rb +1 -1
  81. data/lib/discordrb/logger.rb +12 -11
  82. data/lib/discordrb/paginator.rb +57 -0
  83. data/lib/discordrb/permissions.rb +148 -14
  84. data/lib/discordrb/version.rb +1 -1
  85. data/lib/discordrb/voice/encoder.rb +14 -15
  86. data/lib/discordrb/voice/network.rb +86 -45
  87. data/lib/discordrb/voice/sodium.rb +96 -0
  88. data/lib/discordrb/voice/voice_bot.rb +52 -40
  89. data/lib/discordrb/webhooks.rb +12 -0
  90. data/lib/discordrb/websocket.rb +2 -2
  91. metadata +137 -34
@@ -1,2523 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # These classes hold relevant Discord data, such as messages or channels.
4
-
5
- require 'ostruct'
3
+ require 'discordrb/allowed_mentions'
6
4
  require 'discordrb/permissions'
5
+ require 'discordrb/id_object'
6
+ require 'discordrb/colour_rgb'
7
7
  require 'discordrb/errors'
8
8
  require 'discordrb/api'
9
9
  require 'discordrb/api/channel'
10
10
  require 'discordrb/api/server'
11
11
  require 'discordrb/api/invite'
12
12
  require 'discordrb/api/user'
13
+ require 'discordrb/api/webhook'
14
+ require 'discordrb/webhooks/embeds'
15
+ require 'discordrb/paginator'
13
16
  require 'time'
14
17
  require 'base64'
15
18
 
16
- # Discordrb module
17
- module Discordrb
18
- # The unix timestamp Discord IDs are based on
19
- DISCORD_EPOCH = 1_420_070_400_000
20
-
21
- # Compares two objects based on IDs - either the objects' IDs are equal, or one object is equal to the other's ID.
22
- def self.id_compare(one_id, other)
23
- other.respond_to?(:resolve_id) ? (one_id.resolve_id == other.resolve_id) : (one_id == other)
24
- end
25
-
26
- # The maximum length a Discord message can have
27
- CHARACTER_LIMIT = 2000
28
-
29
- # Splits a message into chunks of 2000 characters. Attempts to split by lines if possible.
30
- # @param msg [String] The message to split.
31
- # @return [Array<String>] the message split into chunks
32
- def self.split_message(msg)
33
- # If the messages is empty, return an empty array
34
- return [] if msg.empty?
35
-
36
- # Split the message into lines
37
- lines = msg.lines
38
-
39
- # Turn the message into a "triangle" of consecutively longer slices, for example the array [1,2,3,4] would become
40
- # [
41
- # [1],
42
- # [1, 2],
43
- # [1, 2, 3],
44
- # [1, 2, 3, 4]
45
- # ]
46
- tri = [*0..(lines.length - 1)].map { |i| lines.combination(i + 1).first }
47
-
48
- # Join the individual elements together to get an array of strings with consecutively more lines
49
- joined = tri.map(&:join)
50
-
51
- # Find the largest element that is still below the character limit, or if none such element exists return the first
52
- ideal = joined.max_by { |e| e.length > CHARACTER_LIMIT ? -1 : e.length }
53
-
54
- # If it's still larger than the character limit (none was smaller than it) split it into slices with the length
55
- # being the character limit, otherwise just return an array with one element
56
- ideal_ary = ideal.length > CHARACTER_LIMIT ? ideal.chars.each_slice(CHARACTER_LIMIT).map(&:join) : [ideal]
57
-
58
- # Slice off the ideal part and strip newlines
59
- rest = msg[ideal.length..-1].strip
60
-
61
- # If none remains, return an empty array -> we're done
62
- return [] unless rest
63
-
64
- # Otherwise, call the method recursively to split the rest of the string and add it onto the ideal array
65
- ideal_ary + split_message(rest)
66
- end
67
-
68
- # Mixin for objects that have IDs
69
- module IDObject
70
- # @return [Integer] the ID which uniquely identifies this object across Discord.
71
- attr_reader :id
72
- alias_method :resolve_id, :id
73
-
74
- # ID based comparison
75
- def ==(other)
76
- Discordrb.id_compare(@id, other)
77
- end
78
-
79
- # Estimates the time this object was generated on based on the beginning of the ID. This is fairly accurate but
80
- # shouldn't be relied on as Discord might change its algorithm at any time
81
- # @return [Time] when this object was created at
82
- def creation_time
83
- # Milliseconds
84
- ms = (@id >> 22) + DISCORD_EPOCH
85
- Time.at(ms / 1000.0)
86
- end
87
- end
88
-
89
- # Mixin for the attributes users should have
90
- module UserAttributes
91
- # @return [String] this user's username
92
- attr_reader :username
93
- alias_method :name, :username
94
-
95
- # @return [String] this user's discriminator which is used internally to identify users with identical usernames.
96
- attr_reader :discriminator
97
- alias_method :discrim, :discriminator
98
- alias_method :tag, :discriminator
99
- alias_method :discord_tag, :discriminator
100
-
101
- # @return [true, false] whether this user is a Discord bot account
102
- attr_reader :bot_account
103
- alias_method :bot_account?, :bot_account
104
-
105
- # @return [String] the ID of this user's current avatar, can be used to generate an avatar URL.
106
- # @see #avatar_url
107
- attr_reader :avatar_id
108
-
109
- # Utility function to mention users in messages
110
- # @return [String] the mention code in the form of <@id>
111
- def mention
112
- "<@#{@id}>"
113
- end
114
-
115
- # Utility function to get Discord's distinct representation of a user, i. e. username + discriminator
116
- # @return [String] distinct representation of user
117
- def distinct
118
- "#{@username}##{@discriminator}"
119
- end
120
-
121
- # Utility function to get a user's avatar URL.
122
- # @return [String] the URL to the avatar image.
123
- def avatar_url
124
- API::User.avatar_url(@id, @avatar_id)
125
- end
126
- end
127
-
128
- # User on Discord, including internal data like discriminators
129
- class User
130
- include IDObject
131
- include UserAttributes
132
-
133
- # @!attribute [r] status
134
- # @return [Symbol] the current online status of the user (`:online`, `:offline` or `:idle`)
135
- attr_accessor :status
136
-
137
- # @!attribute [r] game
138
- # @return [String, nil] the game the user is currently playing, or `nil` if none is being played.
139
- attr_accessor :game
140
-
141
- def initialize(data, bot)
142
- @bot = bot
143
-
144
- @username = data['username']
145
- @id = data['id'].to_i
146
- @discriminator = data['discriminator']
147
- @avatar_id = data['avatar']
148
- @roles = {}
149
-
150
- @bot_account = false
151
- @bot_account = true if data['bot']
152
-
153
- @status = :offline
154
- end
155
-
156
- # Get a user's PM channel or send them a PM
157
- # @overload pm
158
- # Creates a private message channel for this user or returns an existing one if it already exists
159
- # @return [Channel] the PM channel to this user.
160
- # @overload pm(content)
161
- # Sends a private to this user.
162
- # @param content [String] The content to send.
163
- # @return [Message] the message sent to this user.
164
- def pm(content = nil)
165
- if content
166
- # Recursively call pm to get the channel, then send a message to it
167
- channel = pm
168
- channel.send_message(content)
169
- else
170
- # If no message was specified, return the PM channel
171
- @bot.pm_channel(@id)
172
- end
173
- end
174
-
175
- alias_method :dm, :pm
176
-
177
- # Send the user a file.
178
- # @param file [File] The file to send to the user
179
- # @param caption [String] The caption of the file being sent
180
- # @return [Message] the message sent to this user.
181
- def send_file(file, caption = nil)
182
- pm.send_file(file, caption: caption)
183
- end
184
-
185
- # Set the user's name
186
- # @note for internal use only
187
- # @!visibility private
188
- def update_username(username)
189
- @username = username
190
- end
191
-
192
- # Add an await for a message from this user. Specifically, this adds a global await for a MessageEvent with this
193
- # user's ID as a :from attribute.
194
- # @see Bot#add_await
195
- def await(key, attributes = {}, &block)
196
- @bot.add_await(key, Discordrb::Events::MessageEvent, { from: @id }.merge(attributes), &block)
197
- end
198
-
199
- # Gets the member this user is on a server
200
- # @param server [Server] The server to get the member for
201
- # @return [Member] this user as a member on a particular server
202
- def on(server)
203
- id = server.resolve_id
204
- @bot.server(id).member(@id)
205
- end
206
-
207
- # Is the user the bot?
208
- # @return [true, false] whether this user is the bot
209
- def current_bot?
210
- @bot.profile.id == @id
211
- end
212
-
213
- # @return [true, false] whether this user is a fake user for a webhook message
214
- def webhook?
215
- @discriminator == Message::ZERO_DISCRIM
216
- end
217
-
218
- [:offline, :idle, :online].each do |e|
219
- define_method(e.to_s + '?') do
220
- @status.to_sym == e
221
- end
222
- end
223
-
224
- # The inspect method is overwritten to give more useful output
225
- def inspect
226
- "<User username=#{@username} id=#{@id} discriminator=#{@discriminator}>"
227
- end
228
- end
229
-
230
- # OAuth Application information
231
- class Application
232
- include IDObject
233
-
234
- # @return [String] the application name
235
- attr_reader :name
236
-
237
- # @return [String] the application description
238
- attr_reader :description
239
-
240
- # @return [Array<String>] the applications origins permitted to use RPC
241
- attr_reader :rpc_origins
242
-
243
- # @return [Integer]
244
- attr_reader :flags
245
-
246
- # Gets the user object of the owner. May be limited to username, discriminator,
247
- # ID and avatar if the bot cannot reach the owner.
248
- # @return [User] the user object of the owner
249
- attr_reader :owner
250
-
251
- def initialize(data, bot)
252
- @bot = bot
253
-
254
- @name = data['name']
255
- @id = data['id'].to_i
256
- @description = data['description']
257
- @icon_id = data['icon']
258
- @rpc_origins = data['rpc_origins']
259
- @flags = data['flags']
260
- @owner = @bot.ensure_user(data['owner'])
261
- end
262
-
263
- # Utility function to get a application's icon URL.
264
- # @return [String, nil] the URL to the icon image (nil if no image is set).
265
- def icon_url
266
- return nil if @icon_id.nil?
267
- API.app_icon_url(@id, @icon_id)
268
- end
269
-
270
- # The inspect method is overwritten to give more useful output
271
- def inspect
272
- "<Application name=#{@name} id=#{@id}>"
273
- end
274
- end
275
-
276
- # Mixin for the attributes members and private members should have
277
- module MemberAttributes
278
- # @return [Time] when this member joined the server.
279
- attr_reader :joined_at
280
-
281
- # @return [String, nil] the nickname this member has, or nil if it has none.
282
- attr_reader :nick
283
- alias_method :nickname, :nick
284
-
285
- # @return [Array<Role>] the roles this member has.
286
- attr_reader :roles
287
-
288
- # @return [Server] the server this member is on.
289
- attr_reader :server
290
- end
291
-
292
- # Mixin to calculate resulting permissions from overrides etc.
293
- module PermissionCalculator
294
- # Checks whether this user can do the particular action, regardless of whether it has the permission defined,
295
- # through for example being the server owner or having the Manage Roles permission
296
- # @param action [Symbol] The permission that should be checked. See also {Permissions::Flags} for a list.
297
- # @param channel [Channel, nil] If channel overrides should be checked too, this channel specifies where the overrides should be checked.
298
- # @example Check if the bot can send messages to a specific channel in a server.
299
- # bot_profile = bot.profile.on(event.server)
300
- # can_send_messages = bot_profile.permission?(:send_messages, channel)
301
- # @return [true, false] whether or not this user has the permission.
302
- def permission?(action, channel = nil)
303
- # If the member is the server owner, it irrevocably has all permissions.
304
- return true if owner?
305
-
306
- # First, check whether the user has Manage Roles defined.
307
- # (Coincidentally, Manage Permissions is the same permission as Manage Roles, and a
308
- # Manage Permissions deny overwrite will override Manage Roles, so we can just check for
309
- # Manage Roles once and call it a day.)
310
- return true if defined_permission?(:administrator, channel)
311
-
312
- # Otherwise, defer to defined_permission
313
- defined_permission?(action, channel)
314
- end
315
-
316
- # Checks whether this user has a particular permission defined (i. e. not implicit, through for example
317
- # Manage Roles)
318
- # @param action [Symbol] The permission that should be checked. See also {Permissions::Flags} for a list.
319
- # @param channel [Channel, nil] If channel overrides should be checked too, this channel specifies where the overrides should be checked.
320
- # @example Check if a member has the Manage Channels permission defined in the server.
321
- # has_manage_channels = member.defined_permission?(:manage_channels)
322
- # @return [true, false] whether or not this user has the permission defined.
323
- def defined_permission?(action, channel = nil)
324
- # Get the permission the user's roles have
325
- role_permission = defined_role_permission?(action, channel)
326
-
327
- # Once we have checked the role permission, we have to check the channel overrides for the
328
- # specific user
329
- user_specific_override = permission_overwrite(action, channel, id) # Use the ID reader as members have no ID instance variable
330
-
331
- # Merge the two permissions - if an override is defined, it has to be allow, otherwise we only care about the role
332
- return role_permission unless user_specific_override
333
- user_specific_override == :allow
334
- end
335
-
336
- # Define methods for querying permissions
337
- Discordrb::Permissions::Flags.each_value do |flag|
338
- define_method "can_#{flag}?" do |channel = nil|
339
- permission? flag, channel
340
- end
341
- end
342
-
343
- alias_method :can_administrate?, :can_administrator?
344
-
345
- private
346
-
347
- def defined_role_permission?(action, channel)
348
- # For each role, check if
349
- # (1) the channel explicitly allows or permits an action for the role and
350
- # (2) if the user is allowed to do the action if the channel doesn't specify
351
- @roles.reduce(false) do |can_act, role|
352
- # Get the override defined for the role on the channel
353
- channel_allow = permission_overwrite(action, channel, role.id)
354
- can_act = if channel_allow
355
- # If the channel has an override, check whether it is an allow - if yes,
356
- # the user can act, if not, it can't
357
- channel_allow == :allow
358
- else
359
- # Otherwise defer to the role
360
- role.permissions.instance_variable_get("@#{action}") || can_act
361
- end
362
- can_act
363
- end
364
- end
365
-
366
- def permission_overwrite(action, channel, id)
367
- # If no overwrites are defined, or no channel is set, no overwrite will be present
368
- return nil unless channel && channel.permission_overwrites[id]
369
-
370
- # Otherwise, check the allow and deny objects
371
- allow = channel.permission_overwrites[id].allow
372
- deny = channel.permission_overwrites[id].deny
373
- if allow.instance_variable_get("@#{action}")
374
- :allow
375
- elsif deny.instance_variable_get("@#{action}")
376
- :deny
377
- end
378
-
379
- # If there's no variable defined, nil will implicitly be returned
380
- end
381
- end
382
-
383
- # A voice state represents the state of a member's connection to a voice channel. It includes data like the voice
384
- # channel the member is connected to and mute/deaf flags.
385
- class VoiceState
386
- # @return [Integer] the ID of the user whose voice state is represented by this object.
387
- attr_reader :user_id
388
-
389
- # @return [true, false] whether this voice state's member is muted server-wide.
390
- attr_reader :mute
391
-
392
- # @return [true, false] whether this voice state's member is deafened server-wide.
393
- attr_reader :deaf
394
-
395
- # @return [true, false] whether this voice state's member has muted themselves.
396
- attr_reader :self_mute
397
-
398
- # @return [true, false] whether this voice state's member has deafened themselves.
399
- attr_reader :self_deaf
400
-
401
- # @return [Channel] the voice channel this voice state's member is in.
402
- attr_reader :voice_channel
403
-
404
- # @!visibility private
405
- def initialize(user_id)
406
- @user_id = user_id
407
- end
408
-
409
- # Update this voice state with new data from Discord
410
- # @note For internal use only.
411
- # @!visibility private
412
- def update(channel, mute, deaf, self_mute, self_deaf)
413
- @voice_channel = channel
414
- @mute = mute
415
- @deaf = deaf
416
- @self_mute = self_mute
417
- @self_deaf = self_deaf
418
- end
419
- end
420
-
421
- # A member is a user on a server. It differs from regular users in that it has roles, voice statuses and things like
422
- # that.
423
- class Member < DelegateClass(User)
424
- # @return [true, false] whether this member is muted server-wide.
425
- def mute
426
- voice_state_attribute(:mute)
427
- end
428
-
429
- # @return [true, false] whether this member is deafened server-wide.
430
- def deaf
431
- voice_state_attribute(:deaf)
432
- end
433
-
434
- # @return [true, false] whether this member has muted themselves.
435
- def self_mute
436
- voice_state_attribute(:self_mute)
437
- end
438
-
439
- # @return [true, false] whether this member has deafened themselves.
440
- def self_deaf
441
- voice_state_attribute(:self_deaf)
442
- end
443
-
444
- # @return [Channel] the voice channel this member is in.
445
- def voice_channel
446
- voice_state_attribute(:voice_channel)
447
- end
448
-
449
- alias_method :muted?, :mute
450
- alias_method :deafened?, :deaf
451
- alias_method :self_muted?, :self_mute
452
- alias_method :self_deafened?, :self_deaf
453
-
454
- include MemberAttributes
455
-
456
- # @!visibility private
457
- def initialize(data, server, bot)
458
- @bot = bot
459
-
460
- @user = bot.ensure_user(data['user'])
461
- super @user # Initialize the delegate class
462
-
463
- # Somehow, Discord doesn't send the server ID in the standard member format...
464
- raise ArgumentError, 'Cannot create a member without any information about the server!' if server.nil? && data['guild_id'].nil?
465
- @server = server || bot.server(data['guild_id'].to_i)
466
-
467
- # Initialize the roles by getting the roles from the server one-by-one
468
- update_roles(data['roles'])
469
-
470
- @nick = data['nick']
471
- @joined_at = data['joined_at'] ? Time.parse(data['joined_at']) : nil
472
- end
473
-
474
- # @return [true, false] whether this member is the server owner.
475
- def owner?
476
- @server.owner == self
477
- end
478
-
479
- # @param role [Role, Integer, #resolve_id] the role to check or its ID.
480
- # @return [true, false] whether this member has the specified role.
481
- def role?(role)
482
- role = role.resolve_id
483
- @roles.any? { |e| e.id == role }
484
- end
485
-
486
- # Bulk sets a member's roles.
487
- # @param role [Role, Array<Role>] The role(s) to set.
488
- def roles=(role)
489
- role_ids = role_id_array(role)
490
- API::Server.update_member(@bot.token, @server.id, @user.id, roles: role_ids)
491
- end
492
-
493
- # Adds and removes roles from a member.
494
- # @param add [Role, Array<Role>] The role(s) to add.
495
- # @param remove [Role, Array<Role>] The role(s) to remove.
496
- # @example Remove the 'Member' role from a user, and add the 'Muted' role to them.
497
- # to_add = server.roles.find {|role| role.name == 'Muted'}
498
- # to_remove = server.roles.find {|role| role.name == 'Member'}
499
- # member.modify_roles(to_add, to_remove)
500
- def modify_roles(add, remove)
501
- add_role_ids = role_id_array(add)
502
- remove_role_ids = role_id_array(remove)
503
- old_role_ids = @roles.map(&:id)
504
- new_role_ids = (old_role_ids - remove_role_ids + add_role_ids).uniq
505
-
506
- API::Server.update_member(@bot.token, @server.id, @user.id, roles: new_role_ids)
507
- end
508
-
509
- # Adds one or more roles to this member.
510
- # @param role [Role, Array<Role>] The role(s) to add.
511
- def add_role(role)
512
- role_ids = role_id_array(role)
513
- old_role_ids = @roles.map(&:id)
514
- new_role_ids = (old_role_ids + role_ids).uniq
515
-
516
- API::Server.update_member(@bot.token, @server.id, @user.id, roles: new_role_ids)
517
- end
518
-
519
- # Removes one or more roles from this member.
520
- # @param role [Role, Array<Role>] The role(s) to remove.
521
- def remove_role(role)
522
- old_role_ids = @roles.map(&:id)
523
- role_ids = role_id_array(role)
524
- new_role_ids = old_role_ids.reject { |i| role_ids.include?(i) }
525
-
526
- API::Server.update_member(@bot.token, @server.id, @user.id, roles: new_role_ids)
527
- end
528
-
529
- # Server deafens this member.
530
- def server_deafen
531
- API::Server.update_member(@bot.token, @server.id, @user.id, deaf: true)
532
- end
533
-
534
- # Server undeafens this member.
535
- def server_undeafen
536
- API::Server.update_member(@bot.token, @server.id, @user.id, deaf: false)
537
- end
538
-
539
- # Server mutes this member.
540
- def server_mute
541
- API::Server.update_member(@bot.token, @server.id, @user.id, mute: true)
542
- end
543
-
544
- # Server unmutes this member.
545
- def server_unmute
546
- API::Server.update_member(@bot.token, @server.id, @user.id, mute: false)
547
- end
548
-
549
- # Sets or resets this member's nickname. Requires the Change Nickname permission for the bot itself and Manage
550
- # Nicknames for other users.
551
- # @param nick [String, nil] The string to set the nickname to, or nil if it should be reset.
552
- def nick=(nick)
553
- # Discord uses the empty string to signify 'no nickname' so we convert nil into that
554
- nick ||= ''
555
-
556
- if @user.current_bot?
557
- API::User.change_own_nickname(@bot.token, @server.id, nick)
558
- else
559
- API::Server.update_member(@bot.token, @server.id, @user.id, nick: nick)
560
- end
561
- end
562
-
563
- alias_method :nickname=, :nick=
564
-
565
- # @return [String] the name the user displays as (nickname if they have one, username otherwise)
566
- def display_name
567
- nickname || username
568
- end
569
-
570
- # Update this member's roles
571
- # @note For internal use only.
572
- # @!visibility private
573
- def update_roles(roles)
574
- @roles = roles.map do |role|
575
- role.is_a?(Role) ? role : @server.role(role.to_i)
576
- end
577
- end
578
-
579
- # Update this member's nick
580
- # @note For internal use only.
581
- # @!visibility private
582
- def update_nick(nick)
583
- @nick = nick
584
- end
585
-
586
- include PermissionCalculator
587
-
588
- # Overwriting inspect for debug purposes
589
- def inspect
590
- "<Member user=#{@user.inspect} server=#{@server.inspect} joined_at=#{@joined_at} roles=#{@roles.inspect} voice_channel=#{@voice_channel.inspect} mute=#{@mute} deaf=#{@deaf} self_mute=#{@self_mute} self_deaf=#{@self_deaf}>"
591
- end
592
-
593
- private
594
-
595
- # Utility method to get a list of role IDs from one role or an array of roles
596
- def role_id_array(role)
597
- if role.is_a? Array
598
- role.map(&:resolve_id)
599
- else
600
- [role.resolve_id]
601
- end
602
- end
603
-
604
- # Utility method to get data out of this member's voice state
605
- def voice_state_attribute(name)
606
- voice_state = @server.voice_states[@user.id]
607
- voice_state.send name if voice_state
608
- end
609
- end
610
-
611
- # Recipients are members on private channels - they exist for completeness purposes, but all
612
- # the attributes will be empty.
613
- class Recipient < DelegateClass(User)
614
- include MemberAttributes
615
-
616
- # @return [Channel] the private channel this recipient is the recipient of.
617
- attr_reader :channel
618
-
619
- # @!visibility private
620
- def initialize(user, channel, bot)
621
- @bot = bot
622
- @channel = channel
623
- raise ArgumentError, 'Tried to create a recipient for a public channel!' unless @channel.private?
624
-
625
- @user = user
626
- super @user
627
-
628
- # Member attributes
629
- @mute = @deaf = @self_mute = @self_deaf = false
630
- @voice_channel = nil
631
- @server = nil
632
- @roles = []
633
- @joined_at = @channel.creation_time
634
- end
635
-
636
- # Overwriting inspect for debug purposes
637
- def inspect
638
- "<Recipient user=#{@user.inspect} channel=#{@channel.inspect}>"
639
- end
640
- end
641
-
642
- # This class is a special variant of User that represents the bot's user profile (things like own username and the avatar).
643
- # It can be accessed using {Bot#profile}.
644
- class Profile < User
645
- def initialize(data, bot)
646
- super(data, bot)
647
- end
648
-
649
- # Whether or not the user is the bot. The Profile can only ever be the bot user, so this always returns true.
650
- # @return [true]
651
- def current_bot?
652
- true
653
- end
654
-
655
- # Sets the bot's username.
656
- # @param username [String] The new username.
657
- def username=(username)
658
- update_profile_data(username: username)
659
- end
660
-
661
- alias_method :name=, :username=
662
-
663
- # Changes the bot's avatar.
664
- # @param avatar [String, #read] A JPG file to be used as the avatar, either
665
- # something readable (e. g. File Object) or as a data URL.
666
- def avatar=(avatar)
667
- if avatar.respond_to? :read
668
- # Set the file to binary mode if supported, so we don't get problems with Windows
669
- avatar.binmode if avatar.respond_to?(:binmode)
670
-
671
- avatar_string = 'data:image/jpg;base64,'
672
- avatar_string += Base64.strict_encode64(avatar.read)
673
- update_profile_data(avatar: avatar_string)
674
- else
675
- update_profile_data(avatar: avatar)
676
- end
677
- end
678
-
679
- # Updates the cached profile data with the new one.
680
- # @note For internal use only.
681
- # @!visibility private
682
- def update_data(new_data)
683
- @username = new_data[:username] || @username
684
- @avatar_id = new_data[:avatar_id] || @avatar_id
685
- end
686
-
687
- # Sets the user status setting to Online.
688
- # @note Only usable on User accounts.
689
- def online
690
- update_profile_status_setting('online')
691
- end
692
-
693
- # Sets the user status setting to Idle.
694
- # @note Only usable on User accounts.
695
- def idle
696
- update_profile_status_setting('idle')
697
- end
698
-
699
- # Sets the user status setting to Do Not Disturb.
700
- # @note Only usable on User accounts.
701
- def dnd
702
- update_profile_status_setting('dnd')
703
- end
704
-
705
- alias_method(:busy, :dnd)
706
-
707
- # Sets the user status setting to Invisible.
708
- # @note Only usable on User accounts.
709
- def invisible
710
- update_profile_status_setting('invisible')
711
- end
712
-
713
- # The inspect method is overwritten to give more useful output
714
- def inspect
715
- "<Profile user=#{super}>"
716
- end
717
-
718
- private
719
-
720
- # Internal handler for updating the user's status setting
721
- def update_profile_status_setting(status)
722
- API::User.change_status_setting(@bot.token, status)
723
- end
724
-
725
- def update_profile_data(new_data)
726
- API::User.update_profile(@bot.token,
727
- nil, nil,
728
- new_data[:username] || @username,
729
- new_data.key?(:avatar) ? new_data[:avatar] : @avatar_id)
730
- update_data(new_data)
731
- end
732
- end
733
-
734
- # A Discord role that contains permissions and applies to certain users
735
- class Role
736
- include IDObject
737
-
738
- # @return [Permissions] this role's permissions.
739
- attr_reader :permissions
740
-
741
- # @return [String] this role's name ("new role" if it hasn't been changed)
742
- attr_reader :name
743
-
744
- # @return [true, false] whether or not this role should be displayed separately from other users
745
- attr_reader :hoist
746
-
747
- # @return [true, false] whether this role can be mentioned using a role mention
748
- attr_reader :mentionable
749
- alias_method :mentionable?, :mentionable
750
-
751
- # @return [ColourRGB] the role colour
752
- attr_reader :colour
753
- alias_method :color, :colour
754
-
755
- # @return [Integer] the position of this role in the hierarchy
756
- attr_reader :position
757
-
758
- # This class is used internally as a wrapper to a Role object that allows easy writing of permission data.
759
- class RoleWriter
760
- # @!visibility private
761
- def initialize(role, token)
762
- @role = role
763
- @token = token
764
- end
765
-
766
- # Write the specified permission data to the role, without updating the permission cache
767
- # @param bits [Integer] The packed permissions to write.
768
- def write(bits)
769
- @role.send(:packed=, bits, false)
770
- end
771
-
772
- # The inspect method is overridden, in this case to prevent the token being leaked
773
- def inspect
774
- "<RoleWriter role=#{@role} token=...>"
775
- end
776
- end
777
-
778
- # @!visibility private
779
- def initialize(data, bot, server = nil)
780
- @bot = bot
781
- @server = server
782
- @permissions = Permissions.new(data['permissions'], RoleWriter.new(self, @bot.token))
783
- @name = data['name']
784
- @id = data['id'].to_i
785
-
786
- @position = data['position']
787
-
788
- @hoist = data['hoist']
789
- @mentionable = data['mentionable']
790
-
791
- @colour = ColourRGB.new(data['color'])
792
- end
793
-
794
- # @return [String] a string that will mention this role, if it is mentionable.
795
- def mention
796
- "<@&#{@id}>"
797
- end
798
-
799
- # @return [Array<Member>] an array of members who have this role.
800
- # @note This requests a member chunk if it hasn't for the server before, which may be slow initially
801
- def members
802
- @server.members.select { |m| m.role? role }
803
- end
804
-
805
- alias_method :users, :members
806
-
807
- # Updates the data cache from another Role object
808
- # @note For internal use only
809
- # @!visibility private
810
- def update_from(other)
811
- @permissions = other.permissions
812
- @name = other.name
813
- @hoist = other.hoist
814
- @colour = other.colour
815
- @position = other.position
816
- end
817
-
818
- # Updates the data cache from a hash containing data
819
- # @note For internal use only
820
- # @!visibility private
821
- def update_data(new_data)
822
- @name = new_data[:name] || new_data['name'] || @name
823
- @hoist = new_data['hoist'] unless new_data['hoist'].nil?
824
- @hoist = new_data[:hoist] unless new_data[:hoist].nil?
825
- @colour = new_data[:colour] || (new_data['color'] ? ColourRGB.new(new_data['color']) : @colour)
826
- end
827
-
828
- # Sets the role name to something new
829
- # @param name [String] The name that should be set
830
- def name=(name)
831
- update_role_data(name: name)
832
- end
833
-
834
- # Changes whether or not this role is displayed at the top of the user list
835
- # @param hoist [true, false] The value it should be changed to
836
- def hoist=(hoist)
837
- update_role_data(hoist: hoist)
838
- end
839
-
840
- # Changes whether or not this role can be mentioned
841
- # @param mentionable [true, false] The value it should be changed to
842
- def mentionable=(mentionable)
843
- update_role_data(mentionable: mentionable)
844
- end
845
-
846
- # Sets the role colour to something new
847
- # @param colour [ColourRGB] The new colour
848
- def colour=(colour)
849
- update_role_data(colour: colour)
850
- end
851
-
852
- alias_method :color=, :colour=
853
-
854
- # Changes this role's permissions to a fixed bitfield. This allows setting multiple permissions at once with just
855
- # one API call.
856
- #
857
- # Information on how this bitfield is structured can be found at
858
- # https://discordapp.com/developers/docs/topics/permissions.
859
- # @example Remove all permissions from a role
860
- # role.packed = 0
861
- # @param packed [Integer] A bitfield with the desired permissions value.
862
- # @param update_perms [true, false] Whether the internal data should also be updated. This should always be true
863
- # when calling externally.
864
- def packed=(packed, update_perms = true)
865
- update_role_data(permissions: packed)
866
- @permissions.bits = packed if update_perms
867
- end
868
-
869
- # Deletes this role. This cannot be undone without recreating the role!
870
- def delete
871
- API::Server.delete_role(@bot.token, @server.id, @id)
872
- @server.delete_role(@id)
873
- end
874
-
875
- # The inspect method is overwritten to give more useful output
876
- def inspect
877
- "<Role name=#{@name} permissions=#{@permissions.inspect} hoist=#{@hoist} colour=#{@colour.inspect} server=#{@server.inspect}>"
878
- end
879
-
880
- private
881
-
882
- def update_role_data(new_data)
883
- API::Server.update_role(@bot.token, @server.id, @id,
884
- new_data[:name] || @name,
885
- (new_data[:colour] || @colour).combined,
886
- new_data[:hoist].nil? ? @hoist : new_data[:hoist],
887
- new_data[:mentionable].nil? ? @mentionable : new_data[:mentionable],
888
- new_data[:permissions] || @permissions.bits)
889
- update_data(new_data)
890
- end
891
- end
892
-
893
- # A channel referenced by an invite. It has less data than regular channels, so it's a separate class
894
- class InviteChannel
895
- include IDObject
896
-
897
- # @return [String] this channel's name.
898
- attr_reader :name
899
-
900
- # @return [Integer] this channel's type (0: text, 1: private, 2: voice, 3: group).
901
- attr_reader :type
902
-
903
- # @!visibility private
904
- def initialize(data, bot)
905
- @bot = bot
906
-
907
- @id = data['id'].to_i
908
- @name = data['name']
909
- @type = data['type']
910
- end
911
- end
912
-
913
- # A server referenced to by an invite
914
- class InviteServer
915
- include IDObject
916
-
917
- # @return [String] this server's name.
918
- attr_reader :name
919
-
920
- # @return [String, nil] the hash of the server's invite splash screen (for partnered servers) or nil if none is
921
- # present
922
- attr_reader :splash_hash
923
-
924
- # @!visibility private
925
- def initialize(data, bot)
926
- @bot = bot
927
-
928
- @id = data['id'].to_i
929
- @name = data['name']
930
- @splash_hash = data['splash_hash']
931
- end
932
- end
933
-
934
- # A Discord invite to a channel
935
- class Invite
936
- # @return [InviteChannel] the channel this invite references.
937
- attr_reader :channel
938
-
939
- # @return [InviteServer] the server this invite references.
940
- attr_reader :server
941
-
942
- # @return [Integer] the amount of uses left on this invite.
943
- attr_reader :uses
944
- alias_method :max_uses, :uses
945
-
946
- # @return [User, nil] the user that made this invite. May also be nil if the user can't be determined.
947
- attr_reader :inviter
948
- alias_method :user, :inviter
949
-
950
- # @return [true, false] whether or not this invite is temporary.
951
- attr_reader :temporary
952
- alias_method :temporary?, :temporary
953
-
954
- # @return [true, false] whether this invite is still valid.
955
- attr_reader :revoked
956
- alias_method :revoked?, :revoked
957
-
958
- # @return [String] this invite's code
959
- attr_reader :code
960
-
961
- # @!visibility private
962
- def initialize(data, bot)
963
- @bot = bot
964
-
965
- @channel = InviteChannel.new(data['channel'], bot)
966
- @server = InviteServer.new(data['guild'], bot)
967
- @uses = data['uses']
968
- @inviter = data['inviter'] ? (@bot.user(data['inviter']['id'].to_i) || User.new(data['inviter'], bot)) : nil
969
- @temporary = data['temporary']
970
- @revoked = data['revoked']
971
-
972
- @code = data['code']
973
- end
974
-
975
- # Code based comparison
976
- def ==(other)
977
- other.respond_to?(:code) ? (@code == other.code) : (@code == other)
978
- end
979
-
980
- # Deletes this invite
981
- def delete
982
- API::Invite.delete(@bot.token, @code)
983
- end
984
-
985
- alias_method :revoke, :delete
986
-
987
- # The inspect method is overwritten to give more useful output
988
- def inspect
989
- "<Invite code=#{@code} channel=#{@channel} uses=#{@uses} temporary=#{@temporary} revoked=#{@revoked}>"
990
- end
991
-
992
- # Creates an invite URL.
993
- def url
994
- "https://discord.gg/#{@code}"
995
- end
996
- end
997
-
998
- # A Discord channel, including data like the topic
999
- class Channel
1000
- include IDObject
1001
-
1002
- # @return [String] this channel's name.
1003
- attr_reader :name
1004
-
1005
- # @return [Server, nil] the server this channel is on. If this channel is a PM channel, it will be nil.
1006
- attr_reader :server
1007
-
1008
- # @return [Integer] the type of this channel (0: text, 1: private, 2: voice, 3: group)
1009
- attr_reader :type
1010
-
1011
- # @return [Integer, nil] the id of the owner of the group channel or nil if this is not a group channel.
1012
- attr_reader :owner_id
1013
-
1014
- # @return [Array<Recipient>, nil] the array of recipients of the private messages, or nil if this is not a Private channel
1015
- attr_reader :recipients
1016
-
1017
- # @return [String] the channel's topic
1018
- attr_reader :topic
1019
-
1020
- # @return [Integer] the bitrate (in bps) of the channel
1021
- attr_reader :bitrate
1022
-
1023
- # @return [Integer] the amount of users that can be in the channel. `0` means it is unlimited.
1024
- attr_reader :user_limit
1025
- alias_method :limit, :user_limit
1026
-
1027
- # @return [Integer] the channel's position on the channel list
1028
- attr_reader :position
1029
-
1030
- # This channel's permission overwrites, represented as a hash of role/user ID to an OpenStruct which has the
1031
- # `allow` and `deny` properties which are {Permissions} objects respectively.
1032
- # @return [Hash<Integer => OpenStruct>] the channel's permission overwrites
1033
- attr_reader :permission_overwrites
1034
-
1035
- # @return [true, false] whether or not this channel is a PM or group channel.
1036
- def private?
1037
- pm? || group?
1038
- end
1039
-
1040
- # @return [String] a string that will mention the channel as a clickable link on Discord.
1041
- def mention
1042
- "<##{@id}>"
1043
- end
1044
-
1045
- # @return [Recipient, nil] the recipient of the private messages, or nil if this is not a PM channel
1046
- def recipient
1047
- @recipients.first if pm?
1048
- end
1049
-
1050
- # @!visibility private
1051
- def initialize(data, bot, server = nil)
1052
- @bot = bot
1053
- # data is a sometimes a Hash and other times an array of Hashes, you only want the last one if it's an array
1054
- data = data[-1] if data.is_a?(Array)
1055
-
1056
- @id = data['id'].to_i
1057
- @type = data['type'] || 0
1058
- @topic = data['topic']
1059
- @bitrate = data['bitrate']
1060
- @user_limit = data['user_limit']
1061
- @position = data['position']
1062
-
1063
- if private?
1064
- @recipients = []
1065
- if data['recipients']
1066
- data['recipients'].each do |recipient|
1067
- recipient_user = bot.ensure_user(recipient)
1068
- @recipients << Recipient.new(recipient_user, self, bot)
1069
- end
1070
- end
1071
- if pm?
1072
- @name = @recipients.first.username
1073
- else
1074
- @name = data['name']
1075
- @owner_id = data['owner_id']
1076
- end
1077
- else
1078
- @name = data['name']
1079
- @server = if server
1080
- server
1081
- else
1082
- bot.server(data['guild_id'].to_i)
1083
- end
1084
- end
1085
-
1086
- # Populate permission overwrites
1087
- @permission_overwrites = {}
1088
- return unless data['permission_overwrites']
1089
- data['permission_overwrites'].each do |element|
1090
- role_id = element['id'].to_i
1091
- deny = Permissions.new(element['deny'])
1092
- allow = Permissions.new(element['allow'])
1093
- @permission_overwrites[role_id] = OpenStruct.new
1094
- @permission_overwrites[role_id].deny = deny
1095
- @permission_overwrites[role_id].allow = allow
1096
- end
1097
- end
1098
-
1099
- # @return [true, false] whether or not this channel is a text channel
1100
- def text?
1101
- @type.zero?
1102
- end
1103
-
1104
- # @return [true, false] whether or not this channel is a PM channel.
1105
- def pm?
1106
- @type == 1
1107
- end
1108
-
1109
- # @return [true, false] whether or not this channel is a voice channel.
1110
- def voice?
1111
- @type == 2
1112
- end
1113
-
1114
- # @return [true, false] whether or not this channel is a group channel.
1115
- def group?
1116
- @type == 3
1117
- end
1118
-
1119
- # Sends a message to this channel.
1120
- # @param content [String] The content to send. Should not be longer than 2000 characters or it will result in an error.
1121
- # @param tts [true, false] Whether or not this message should be sent using Discord text-to-speech.
1122
- # @return [Message] the message that was sent.
1123
- def send_message(content, tts = false)
1124
- @bot.send_message(@id, content, tts, @server && @server.id)
1125
- end
1126
-
1127
- alias_method :send, :send_message
1128
-
1129
- # Sends a temporary message to this channel.
1130
- # @param content [String] The content to send. Should not be longer than 2000 characters or it will result in an error.
1131
- # @param timeout [Float] The amount of time in seconds after which the message sent will be deleted.
1132
- # @param tts [true, false] Whether or not this message should be sent using Discord text-to-speech.
1133
- def send_temporary_message(content, timeout, tts = false)
1134
- @bot.send_temporary_message(@id, content, timeout, tts, @server && @server.id)
1135
- end
1136
-
1137
- # Sends multiple messages to a channel
1138
- # @param content [Array<String>] The messages to send.
1139
- def send_multiple(content)
1140
- content.each { |e| send_message(e) }
1141
- end
1142
-
1143
- # Splits a message into chunks whose length is at most the Discord character limit, then sends them individually.
1144
- # Useful for sending long messages, but be wary of rate limits!
1145
- def split_send(content)
1146
- send_multiple(Discordrb.split_message(content))
1147
- end
1148
-
1149
- # Sends a file to this channel. If it is an image, it will be embedded.
1150
- # @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)
1151
- # @param caption [string] The caption for the file.
1152
- # @param tts [true, false] Whether or not this file's caption should be sent using Discord text-to-speech.
1153
- def send_file(file, caption: nil, tts: false)
1154
- @bot.send_file(@id, file, caption: caption, tts: tts)
1155
- end
1156
-
1157
- # Permanently deletes this channel
1158
- def delete
1159
- API::Channel.delete(@bot.token, @id)
1160
- end
1161
-
1162
- # Sets this channel's name. The name must be alphanumeric with dashes, unless this is a voice channel (then there are no limitations)
1163
- # @param name [String] The new name.
1164
- def name=(name)
1165
- @name = name
1166
- update_channel_data
1167
- end
1168
-
1169
- # Sets this channel's topic.
1170
- # @param topic [String] The new topic.
1171
- def topic=(topic)
1172
- raise 'Tried to set topic on voice channel' if voice?
1173
- @topic = topic
1174
- update_channel_data
1175
- end
1176
-
1177
- # Sets this channel's bitrate.
1178
- # @param bitrate [Integer] The new bitrate (in bps). Number has to be between 8000-96000 (128000 for VIP servers)
1179
- def bitrate=(bitrate)
1180
- raise 'Tried to set bitrate on text channel' if text?
1181
- @bitrate = bitrate
1182
- update_channel_data
1183
- end
1184
-
1185
- # Sets this channel's user limit.
1186
- # @param limit [Integer] The new user limit. `0` for unlimited, has to be a number between 0-99
1187
- def user_limit=(limit)
1188
- raise 'Tried to set user_limit on text channel' if text?
1189
- @user_limit = limit
1190
- update_channel_data
1191
- end
1192
-
1193
- alias_method :limit=, :user_limit=
1194
-
1195
- # Sets this channel's position in the list.
1196
- # @param position [Integer] The new position.
1197
- def position=(position)
1198
- @position = position
1199
- update_channel_data
1200
- end
1201
-
1202
- # Defines a permission overwrite for this channel that sets the specified thing to the specified allow and deny
1203
- # permission sets, or change an existing one.
1204
- # @param thing [User, Role] What to define an overwrite for.
1205
- # @param allow [#bits, Permissions, Integer] The permission sets that should receive an `allow` override (i. e. a
1206
- # green checkmark on Discord)
1207
- # @param deny [#bits, Permissions, Integer] The permission sets that should receive a `deny` override (i. e. a red
1208
- # cross on Discord)
1209
- # @example Define a permission overwrite for a user that can then mention everyone and use TTS, but not create any invites
1210
- # allow = Discordrb::Permissions.new
1211
- # allow.can_mention_everyone = true
1212
- # allow.can_send_tts_messages = true
1213
- #
1214
- # deny = Discordrb::Permissions.new
1215
- # deny.can_create_instant_invite = true
1216
- #
1217
- # channel.define_overwrite(user, allow, deny)
1218
- def define_overwrite(thing, allow, deny)
1219
- allow_bits = allow.respond_to?(:bits) ? allow.bits : allow
1220
- deny_bits = deny.respond_to?(:bits) ? deny.bits : deny
1221
-
1222
- type = if thing.is_a?(User) || thing.is_a?(Member) || thing.is_a?(Recipient) || thing.is_a?(Profile)
1223
- :member
1224
- elsif thing.is_a? Role
1225
- :role
1226
- else
1227
- raise ArgumentError, '`thing` in define_overwrite needs to be a kind of User (User, Member, Recipient, Profile) or a Role!'
1228
- end
1229
-
1230
- API::Channel.update_permission(@bot.token, @id, thing.id, allow_bits, deny_bits, type)
1231
- end
1232
-
1233
- # Updates the cached data from another channel.
1234
- # @note For internal use only
1235
- # @!visibility private
1236
- def update_from(other)
1237
- @topic = other.topic
1238
- @name = other.name
1239
- @permission_overwrites = other.permission_overwrites
1240
- end
1241
-
1242
- # The list of users currently in this channel. For a voice channel, it will return all the members currently
1243
- # in that channel. For a text channel, it will return all online members that have permission to read it.
1244
- # @return [Array<Member>] the users in this channel
1245
- def users
1246
- if text?
1247
- @server.online_members(include_idle: true).select { |u| u.can_read_messages? self }
1248
- elsif voice?
1249
- @server.voice_states.map { |id, voice_state| @server.member(id) if !voice_state.voice_channel.nil? && voice_state.voice_channel.id == @id }.compact
1250
- end
1251
- end
1252
-
1253
- # Retrieves some of this channel's message history.
1254
- # @param amount [Integer] How many messages to retrieve. This must be less than or equal to 100, if it is higher
1255
- # than 100 it will be treated as 100 on Discord's side.
1256
- # @param before_id [Integer] The ID of the most recent message the retrieval should start at, or nil if it should
1257
- # start at the current message.
1258
- # @param after_id [Integer] The ID of the oldest message the retrieval should start at, or nil if it should start
1259
- # as soon as possible with the specified amount.
1260
- # @example Count the number of messages in the last 50 messages that contain the letter 'e'.
1261
- # message_count = channel.history(50).count {|message| message.content.include? "e"}
1262
- # @return [Array<Message>] the retrieved messages.
1263
- def history(amount, before_id = nil, after_id = nil)
1264
- logs = API::Channel.messages(@bot.token, @id, amount, before_id, after_id)
1265
- JSON.parse(logs).map { |message| Message.new(message, @bot) }
1266
- end
1267
-
1268
- # Retrieves message history, but only message IDs for use with prune
1269
- # @note For internal use only
1270
- # @!visibility private
1271
- def history_ids(amount, before_id = nil, after_id = nil)
1272
- logs = API::Channel.messages(@bot.token, @id, amount, before_id, after_id)
1273
- JSON.parse(logs).map { |message| message['id'] }
1274
- end
1275
-
1276
- # Returns a single message from this channel's history by ID.
1277
- # @param message_id [Integer] The ID of the message to retrieve.
1278
- # @return [Message] the retrieved message.
1279
- def load_message(message_id)
1280
- response = API::Channel.message(@bot.token, @id, message_id)
1281
- return Message.new(JSON.parse(response), @bot)
1282
- rescue RestClient::ResourceNotFound
1283
- return nil
1284
- end
1285
-
1286
- alias_method :message, :load_message
1287
-
1288
- # Requests all pinned messages of a channel.
1289
- # @return [Array<Message>] the received messages.
1290
- def pins
1291
- msgs = API::Channel.pinned_messages(@bot.token, @id)
1292
- JSON.parse(msgs).map { |msg| Message.new(msg, @bot) }
1293
- end
1294
-
1295
- # Delete the last N messages on this channel.
1296
- # @param amount [Integer] How many messages to delete. Must be a value between 2 and 100 (Discord limitation)
1297
- # @raise [ArgumentError] if the amount of messages is not a value between 2 and 100
1298
- def prune(amount)
1299
- raise ArgumentError, 'Can only prune between 2 and 100 messages!' unless amount.between?(2, 100)
1300
-
1301
- messages = history_ids(amount)
1302
- API::Channel.bulk_delete_messages(@bot.token, @id, messages)
1303
- end
1304
-
1305
- # Deletes a collection of messages
1306
- # @param messages [Array<Message, Integer>] the messages (or message IDs) to delete. Total must be an amount between 2 and 100 (Discord limitation)
1307
- # @raise [ArgumentError] if the amount of messages is not a value between 2 and 100
1308
- def delete_messages(messages)
1309
- raise ArgumentError, 'Can only delete between 2 and 100 messages!' unless messages.count.between?(2, 100)
1310
-
1311
- messages.map!(&:resolve_id)
1312
- API::Channel.bulk_delete_messages(@bot.token, @id, messages)
1313
- end
1314
-
1315
- # Updates the cached permission overwrites
1316
- # @note For internal use only
1317
- # @!visibility private
1318
- def update_overwrites(overwrites)
1319
- @permission_overwrites = overwrites
1320
- end
1321
-
1322
- # Add an {Await} for a message in this channel. This is identical in functionality to adding a
1323
- # {Discordrb::Events::MessageEvent} await with the `in` attribute as this channel.
1324
- # @see Bot#add_await
1325
- def await(key, attributes = {}, &block)
1326
- @bot.add_await(key, Discordrb::Events::MessageEvent, { in: @id }.merge(attributes), &block)
1327
- end
1328
-
1329
- # Creates a new invite to this channel.
1330
- # @param max_age [Integer] How many seconds this invite should last.
1331
- # @param max_uses [Integer] How many times this invite should be able to be used.
1332
- # @param temporary [true, false] Whether membership should be temporary (kicked after going offline).
1333
- # @return [Invite] the created invite.
1334
- def make_invite(max_age = 0, max_uses = 0, temporary = false)
1335
- response = API::Channel.create_invite(@bot.token, @id, max_age, max_uses, temporary)
1336
- Invite.new(JSON.parse(response), @bot)
1337
- end
1338
-
1339
- alias_method :invite, :make_invite
1340
-
1341
- # Starts typing, which displays the typing indicator on the client for five seconds.
1342
- # If you want to keep typing you'll have to resend this every five seconds. (An abstraction
1343
- # for this will eventually be coming)
1344
- def start_typing
1345
- API::Channel.start_typing(@bot.token, @id)
1346
- end
1347
-
1348
- # Creates a Group channel
1349
- # @param user_ids [Array<Integer>] Array of user IDs to add to the new group channel (Excluding
1350
- # the recipient of the PM channel).
1351
- # @return [Channel] the created channel.
1352
- def create_group(user_ids)
1353
- raise 'Attempted to create group channel on a non-pm channel!' unless pm?
1354
- response = API::Channel.create_group(@bot.token, @id, user_ids.shift)
1355
- channel = Channel.new(JSON.parse(response), @bot)
1356
- channel.add_group_users(user_ids)
1357
- end
1358
-
1359
- # Adds a user to a Group channel
1360
- # @param user_ids [Array<#resolve_id>, #resolve_id] User ID or array of user IDs to add to the group channel.
1361
- # @return [Channel] the group channel.
1362
- def add_group_users(user_ids)
1363
- raise 'Attempted to add a user to a non-group channel!' unless group?
1364
- user_ids = [user_ids] unless user_ids.is_a? Array
1365
- user_ids.each do |user_id|
1366
- API::Channel.add_group_user(@bot.token, @id, user_id.resolve_id)
1367
- end
1368
- self
1369
- end
1370
-
1371
- alias_method :add_group_user, :add_group_users
1372
-
1373
- # Removes a user from a group channel.
1374
- # @param user_ids [Array<#resolve_id>, #resolve_id] User ID or array of user IDs to remove from the group channel.
1375
- # @return [Channel] the group channel.
1376
- def remove_group_users(user_ids)
1377
- raise 'Attempted to remove a user from a non-group channel!' unless group?
1378
- user_ids = [user_ids] unless user_ids.is_a? Array
1379
- user_ids.each do |user_id|
1380
- API::Channel.remove_group_user(@bot.token, @id, user_id.resolve_id)
1381
- end
1382
- self
1383
- end
1384
-
1385
- alias_method :remove_group_user, :remove_group_users
1386
-
1387
- # Leaves the group
1388
- def leave_group
1389
- raise 'Attempted to leave a non-group channel!' unless group?
1390
- API::Channel.leave_group(@bot.token, @id)
1391
- end
1392
-
1393
- alias_method :leave, :leave_group
1394
-
1395
- # The inspect method is overwritten to give more useful output
1396
- def inspect
1397
- "<Channel name=#{@name} id=#{@id} topic=\"#{@topic}\" type=#{@type} position=#{@position} server=#{@server}>"
1398
- end
1399
-
1400
- # Adds a recipient to a group channel.
1401
- # @param recipient [Recipient] the recipient to add to the group
1402
- # @raise [ArgumentError] if tried to add a non-recipient
1403
- # @note For internal use only
1404
- # @!visibility private
1405
- def add_recipient(recipient)
1406
- raise 'Tried to add recipient to a non-group channel' unless group?
1407
- raise ArgumentError, 'Tried to add a non-recipient to a group' unless recipient.is_a?(Recipient)
1408
- @recipients << recipient
1409
- end
1410
-
1411
- # Removes a recipient from a group channel.
1412
- # @param recipient [Recipient] the recipient to remove from the group
1413
- # @raise [ArgumentError] if tried to remove a non-recipient
1414
- # @note For internal use only
1415
- # @!visibility private
1416
- def remove_recipient(recipient)
1417
- raise 'Tried to add recipient to a non-group channel' unless group?
1418
- raise ArgumentError, 'Tried to remove a non-recipient from a group' unless recipient.is_a?(Recipient)
1419
- @recipients.delete(recipient)
1420
- end
1421
-
1422
- private
1423
-
1424
- def update_channel_data
1425
- API::Channel.update(@bot.token, @id, @name, @topic, @position, @bitrate, @user_limit)
1426
- end
1427
- end
1428
-
1429
- # An Embed object that is contained in a message
1430
- # A freshly generated embed object will not appear in a message object
1431
- # unless grabbed from its ID in a channel.
1432
- class Embed
1433
- # @return [Message] the message this embed object is contained in.
1434
- attr_reader :message
1435
-
1436
- # @return [String] the URL this embed object is based on.
1437
- attr_reader :url
1438
-
1439
- # @return [String, nil] the title of the embed object. `nil` if there is not a title
1440
- attr_reader :title
1441
-
1442
- # @return [String, nil] the description of the embed object. `nil` if there is not a description
1443
- attr_reader :description
1444
-
1445
- # @return [Symbol] the type of the embed object. Possible types are:
1446
- #
1447
- # * `:link`
1448
- # * `:video`
1449
- # * `:image`
1450
- attr_reader :type
1451
-
1452
- # @return [EmbedProvider, nil] the provider of the embed object. `nil` is there is not a provider
1453
- attr_reader :provider
1454
-
1455
- # @return [EmbedThumbnail, nil] the thumbnail of the embed object. `nil` is there is not a thumbnail
1456
- attr_reader :thumbnail
1457
-
1458
- # @return [EmbedAuthor, nil] the author of the embed object. `nil` is there is not an author
1459
- attr_reader :author
1460
-
1461
- # @!visibility private
1462
- def initialize(data, message)
1463
- @message = message
1464
-
1465
- @url = data['url']
1466
- @title = data['title']
1467
- @type = data['type'].to_sym
1468
- @description = data['description']
1469
- @provider = data['provider'].nil? ? nil : EmbedProvider.new(data['provider'], self)
1470
- @thumbnail = data['thumbnail'].nil? ? nil : EmbedThumbnail.new(data['thumbnail'], self)
1471
- @author = data['author'].nil? ? nil : EmbedAuthor.new(data['author'], self)
1472
- end
1473
- end
1474
-
1475
- # An Embed thumbnail for the embed object
1476
- class EmbedThumbnail
1477
- # @return [Embed] the embed object this is based on.
1478
- attr_reader :embed
1479
-
1480
- # @return [String] the CDN URL this thumbnail can be downloaded at.
1481
- attr_reader :url
1482
-
1483
- # @return [String] the thumbnail's proxy URL - I'm not sure what exactly this does, but I think it has something to
1484
- # do with CDNs
1485
- attr_reader :proxy_url
1486
-
1487
- # @return [Integer] the width of this thumbnail file, in pixels.
1488
- attr_reader :width
1489
-
1490
- # @return [Integer] the height of this thumbnail file, in pixels.
1491
- attr_reader :height
1492
-
1493
- # @!visibility private
1494
- def initialize(data, embed)
1495
- @embed = embed
1496
-
1497
- @url = data['url']
1498
- @proxy_url = data['proxy_url']
1499
- @width = data['width']
1500
- @height = data['height']
1501
- end
1502
- end
1503
-
1504
- # An Embed provider for the embed object
1505
- class EmbedProvider
1506
- # @return [Embed] the embed object this is based on.
1507
- attr_reader :embed
1508
-
1509
- # @return [String] the provider's name.
1510
- attr_reader :name
1511
-
1512
- # @return [String, nil] the URL of the provider. `nil` is there is no URL
1513
- attr_reader :url
1514
-
1515
- # @!visibility private
1516
- def initialize(data, embed)
1517
- @embed = embed
1518
-
1519
- @name = data['name']
1520
- @url = data['url']
1521
- end
1522
- end
1523
-
1524
- # An Embed author for the embed object
1525
- class EmbedAuthor
1526
- # @return [Embed] the embed object this is based on.
1527
- attr_reader :embed
1528
-
1529
- # @return [String] the author's name.
1530
- attr_reader :name
1531
-
1532
- # @return [String, nil] the URL of the author's website. `nil` is there is no URL
1533
- attr_reader :url
1534
-
1535
- # @!visibility private
1536
- def initialize(data, embed)
1537
- @embed = embed
1538
-
1539
- @name = data['name']
1540
- @url = data['url']
1541
- end
1542
- end
1543
-
1544
- # An attachment to a message
1545
- class Attachment
1546
- include IDObject
1547
-
1548
- # @return [Message] the message this attachment belongs to.
1549
- attr_reader :message
1550
-
1551
- # @return [String] the CDN URL this attachment can be downloaded at.
1552
- attr_reader :url
1553
-
1554
- # @return [String] the attachment's proxy URL - I'm not sure what exactly this does, but I think it has something to
1555
- # do with CDNs
1556
- attr_reader :proxy_url
1557
-
1558
- # @return [String] the attachment's filename.
1559
- attr_reader :filename
1560
-
1561
- # @return [Integer] the attachment's file size in bytes.
1562
- attr_reader :size
1563
-
1564
- # @return [Integer, nil] the width of an image file, in pixels, or nil if the file is not an image.
1565
- attr_reader :width
1566
-
1567
- # @return [Integer, nil] the height of an image file, in pixels, or nil if the file is not an image.
1568
- attr_reader :height
1569
-
1570
- # @!visibility private
1571
- def initialize(data, message, bot)
1572
- @bot = bot
1573
- @message = message
1574
-
1575
- @url = data['url']
1576
- @proxy_url = data['proxy_url']
1577
- @filename = data['filename']
1578
-
1579
- @size = data['size']
1580
-
1581
- @width = data['width']
1582
- @height = data['height']
1583
- end
1584
-
1585
- # @return [true, false] whether this file is an image file.
1586
- def image?
1587
- !(@width.nil? || @height.nil?)
1588
- end
1589
- end
1590
-
1591
- # A message on Discord that was sent to a text channel
1592
- class Message
1593
- include IDObject
1594
-
1595
- # @return [String] the content of this message.
1596
- attr_reader :content
1597
- alias_method :text, :content
1598
- alias_method :to_s, :content
1599
-
1600
- # @return [Member] the user that sent this message.
1601
- attr_reader :author
1602
- alias_method :user, :author
1603
- alias_method :writer, :author
1604
-
1605
- # @return [Channel] the channel in which this message was sent.
1606
- attr_reader :channel
1607
-
1608
- # @return [Time] the timestamp at which this message was sent.
1609
- attr_reader :timestamp
1610
-
1611
- # @return [Time] the timestamp at which this message was edited. `nil` if the message was never edited.
1612
- attr_reader :edited_timestamp
1613
- alias_method :edit_timestamp, :edited_timestamp
1614
-
1615
- # @return [Array<User>] the users that were mentioned in this message.
1616
- attr_reader :mentions
1617
-
1618
- # @return [Array<Role>] the roles that were mentioned in this message.
1619
- attr_reader :role_mentions
1620
-
1621
- # @return [Array<Attachment>] the files attached to this message.
1622
- attr_reader :attachments
1623
-
1624
- # @return [Array<Embed>] the embed objects contained in this message.
1625
- attr_reader :embeds
1626
-
1627
- # @return [true, false] whether the message used Text-To-Speech (TTS) or not.
1628
- attr_reader :tts
1629
- alias_method :tts?, :tts
1630
-
1631
- # @return [String] used for validating a message was sent
1632
- attr_reader :nonce
1633
-
1634
- # @return [true, false] whether the message was edited or not.
1635
- attr_reader :edited
1636
- alias_method :edited?, :edited
1637
-
1638
- # @return [true, false] whether the message mentioned everyone or not.
1639
- attr_reader :mention_everyone
1640
- alias_method :mention_everyone?, :mention_everyone
1641
- alias_method :mentions_everyone?, :mention_everyone
1642
-
1643
- # @return [true, false] whether the message is pinned or not.
1644
- attr_reader :pinned
1645
- alias_method :pinned?, :pinned
1646
-
1647
- # @return [Integer, nil] the webhook ID that sent this message, or nil if it wasn't sent through a webhook.
1648
- attr_reader :webhook_id
1649
-
1650
- # The discriminator that webhook user accounts have.
1651
- ZERO_DISCRIM = '0000'.freeze
1652
-
1653
- # @!visibility private
1654
- def initialize(data, bot)
1655
- @bot = bot
1656
- @content = data['content']
1657
- @channel = bot.channel(data['channel_id'].to_i)
1658
- @pinned = data['pinned']
1659
- @tts = data['tts']
1660
- @nonce = data['nonce']
1661
- @mention_everyone = data['mention_everyone']
1662
-
1663
- @author = if data['author']
1664
- if data['author']['discriminator'] == ZERO_DISCRIM
1665
- # This is a webhook user! It would be pointless to try to resolve a member here, so we just create
1666
- # a User and return that instead.
1667
- Discordrb::LOGGER.debug("Webhook user: #{data['author']['id']}")
1668
- User.new(data['author'], @bot)
1669
- elsif @channel.private?
1670
- # Turn the message user into a recipient - we can't use the channel recipient
1671
- # directly because the bot may also send messages to the channel
1672
- Recipient.new(bot.user(data['author']['id'].to_i), @channel, bot)
1673
- else
1674
- member = @channel.server.member(data['author']['id'].to_i)
1675
- Discordrb::LOGGER.warn("Member with ID #{data['author']['id']} not cached even though it should be.") unless member
1676
- member
1677
- end
1678
- end
1679
-
1680
- @webhook_id = data['webhook_id'].to_i if data['webhook_id']
1681
-
1682
- @timestamp = Time.parse(data['timestamp']) if data['timestamp']
1683
- @edited_timestamp = data['edited_timestamp'].nil? ? nil : Time.parse(data['edited_timestamp'])
1684
- @edited = !@edited_timestamp.nil?
1685
- @id = data['id'].to_i
1686
-
1687
- @emoji = []
1688
-
1689
- @mentions = []
1690
-
1691
- data['mentions'].each do |element|
1692
- @mentions << bot.ensure_user(element)
1693
- end if data['mentions']
1694
-
1695
- @role_mentions = []
1696
-
1697
- # Role mentions can only happen on public servers so make sure we only parse them there
1698
- if @channel.text?
1699
- data['mention_roles'].each do |element|
1700
- @role_mentions << @channel.server.role(element.to_i)
1701
- end if data['mention_roles']
1702
- end
1703
-
1704
- @attachments = []
1705
- @attachments = data['attachments'].map { |e| Attachment.new(e, self, @bot) } if data['attachments']
1706
-
1707
- @embeds = []
1708
- @embeds = data['embeds'].map { |e| Embed.new(e, self) } if data['embeds']
1709
- end
1710
-
1711
- # Replies to this message with the specified content.
1712
- # @see Channel#send_message
1713
- def reply(content)
1714
- @channel.send_message(content)
1715
- end
1716
-
1717
- # Edits this message to have the specified content instead.
1718
- # You can only edit your own messages.
1719
- # @param new_content [String] the new content the message should have.
1720
- # @return [Message] the resulting message.
1721
- def edit(new_content)
1722
- response = API::Channel.edit_message(@bot.token, @channel.id, @id, new_content)
1723
- Message.new(JSON.parse(response), @bot)
1724
- end
1725
-
1726
- # Deletes this message.
1727
- def delete
1728
- API::Channel.delete_message(@bot.token, @channel.id, @id)
1729
- nil
1730
- end
1731
-
1732
- # Pins this message
1733
- def pin
1734
- API::Channel.pin_message(@bot.token, @channel.id, @id)
1735
- @pinned = true
1736
- nil
1737
- end
1738
-
1739
- # Unpins this message
1740
- def unpin
1741
- API::Channel.unpin_message(@bot.token, @channel.id, @id)
1742
- @pinned = false
1743
- nil
1744
- end
1745
-
1746
- # Add an {Await} for a message with the same user and channel.
1747
- # @see Bot#add_await
1748
- def await(key, attributes = {}, &block)
1749
- @bot.add_await(key, Discordrb::Events::MessageEvent, { from: @author.id, in: @channel.id }.merge(attributes), &block)
1750
- end
1751
-
1752
- # @return [true, false] whether this message was sent by the current {Bot}.
1753
- def from_bot?
1754
- @author && @author.current_bot?
1755
- end
1756
-
1757
- # @return [true, false] whether this message has been sent over a webhook.
1758
- def webhook?
1759
- !@webhook_id.nil?
1760
- end
1761
-
1762
- # @!visibility private
1763
- # @return [Array<String>] the emoji mentions found in the message
1764
- def scan_for_emoji
1765
- emoji = @content.split
1766
- emoji = emoji.grep(/<:(?<name>\w+):(?<id>\d+)>?/)
1767
- emoji
1768
- end
1769
-
1770
- # @return [Array<Emoji>] the emotes that were used/mentioned in this message (Only returns Emoji the bot has access to, else nil).
1771
- def emoji
1772
- return if @content.nil?
1773
-
1774
- emoji = scan_for_emoji
1775
- emoji.each do |element|
1776
- @emoji << @bot.parse_mention(element)
1777
- end
1778
- @emoji
1779
- end
1780
-
1781
- # Check if any emoji got used in this message
1782
- # @return [true, false] whether or not any emoji got used
1783
- def emoji?
1784
- emoji = scan_for_emoji
1785
- return true unless emoji.empty?
1786
- end
1787
-
1788
- # The inspect method is overwritten to give more useful output
1789
- def inspect
1790
- "<Message content=\"#{@content}\" id=#{@id} timestamp=#{@timestamp} author=#{@author} channel=#{@channel}>"
1791
- end
1792
- end
1793
-
1794
- # Server emoji
1795
- class Emoji
1796
- include IDObject
1797
-
1798
- # @return [String] the emoji name
1799
- attr_reader :name
1800
-
1801
- # @return [Server] the server of this emoji
1802
- attr_reader :server
1803
-
1804
- # @return [Array<Role>] roles this emoji is active for
1805
- attr_reader :roles
1806
-
1807
- def initialize(data, bot, server)
1808
- @bot = bot
1809
- @roles = nil
1810
-
1811
- @name = data['name']
1812
- @server = server
1813
- @id = data['id'].to_i
1814
-
1815
- process_roles(data['roles']) if server
1816
- end
1817
-
1818
- # @return [String] the layout to mention it (or have it used) in a message
1819
- def mention
1820
- "<:#{@name}:#{@id}>"
1821
- end
1822
-
1823
- alias_method :use, :mention
1824
- alias_method :to_s, :mention
1825
-
1826
- # @return [String] the icon URL of the emoji
1827
- def icon_url
1828
- API.emoji_icon_url(@id)
1829
- end
1830
-
1831
- # The inspect method is overwritten to give more useful output
1832
- def inspect
1833
- "<Emoji name=#{@name} id=#{@id}>"
1834
- end
1835
-
1836
- # @!visibility private
1837
- def process_roles(roles)
1838
- @roles = []
1839
- return unless roles
1840
- roles.each do |role_id|
1841
- role = server.role(role_id)
1842
- @roles << role
1843
- end
1844
- end
1845
- end
1846
-
1847
- # Emoji that is not tailored to a server
1848
- class GlobalEmoji
1849
- include IDObject
1850
-
1851
- # @return [String] the emoji name
1852
- attr_reader :name
1853
-
1854
- # @return [Hash<Integer => Array<Role>>] roles this emoji is active for in every server
1855
- attr_reader :role_associations
1856
-
1857
- def initialize(data, bot)
1858
- @bot = bot
1859
- @roles = nil
1860
-
1861
- @name = data.name
1862
- @id = data.id
1863
- @role_associations = Hash.new([])
1864
- @role_associations[data.server.id] = data.roles
1865
- end
1866
-
1867
- # @return [String] the layout to mention it (or have it used) in a message
1868
- def mention
1869
- "<:#{@name}:#{@id}>"
1870
- end
1871
-
1872
- alias_method :use, :mention
1873
- alias_method :to_s, :mention
1874
-
1875
- # @return [String] the icon URL of the emoji
1876
- def icon_url
1877
- API.emoji_icon_url(@id)
1878
- end
1879
-
1880
- # The inspect method is overwritten to give more useful output
1881
- def inspect
1882
- "<GlobalEmoji name=#{@name} id=#{@id}>"
1883
- end
1884
-
1885
- # @!visibility private
1886
- def process_roles(roles)
1887
- new_roles = []
1888
- return unless roles
1889
- roles.each do
1890
- role = server.role(role_id)
1891
- new_roles << role
1892
- end
1893
- new_roles
1894
- end
1895
- end
1896
-
1897
- # Basic attributes a server should have
1898
- module ServerAttributes
1899
- # @return [String] this server's name.
1900
- attr_reader :name
1901
-
1902
- # @return [String] the hexadecimal ID used to identify this server's icon.
1903
- attr_reader :icon_id
1904
-
1905
- # Utility function to get the URL for the icon image
1906
- # @return [String] the URL to the icon image
1907
- def icon_url
1908
- return nil unless @icon_id
1909
- API.icon_url(@id, @icon_id)
1910
- end
1911
- end
1912
-
1913
- # Integration Account
1914
- class IntegrationAccount
1915
- # @return [String] this account's name.
1916
- attr_reader :name
1917
-
1918
- # @return [Integer] this account's ID.
1919
- attr_reader :id
1920
-
1921
- def initialize(data)
1922
- @name = data['name']
1923
- @id = data['id'].to_i
1924
- end
1925
- end
1926
-
1927
- # Server integration
1928
- class Integration
1929
- include IDObject
1930
-
1931
- # @return [String] the integration name
1932
- attr_reader :name
1933
-
1934
- # @return [Server] the server the integration is linked to
1935
- attr_reader :server
1936
-
1937
- # @return [User] the user the integration is linked to
1938
- attr_reader :user
1939
-
1940
- # @return [Role, nil] the role that this integration uses for "subscribers"
1941
- attr_reader :role
1942
-
1943
- # @return [true, false] whether emoticons are enabled
1944
- attr_reader :emoticon
1945
- alias_method :emoticon?, :emoticon
1946
-
1947
- # @return [String] the integration type (Youtube, Twitch, etc.)
1948
- attr_reader :type
1949
-
1950
- # @return [true, false] whether the integration is enabled
1951
- attr_reader :enabled
1952
-
1953
- # @return [true, false] whether the integration is syncing
1954
- attr_reader :syncing
1955
-
1956
- # @return [IntegrationAccount] the integration account information
1957
- attr_reader :account
1958
-
1959
- # @return [Time] the time the integration was synced at
1960
- attr_reader :synced_at
1961
-
1962
- # @return [Symbol] the behaviour of expiring subscribers (:remove = Remove User from role; :kick = Kick User from server)
1963
- attr_reader :expire_behaviour
1964
- alias_method :expire_behavior, :expire_behaviour
1965
-
1966
- # @return [Integer] the grace period before subscribers expire (in days)
1967
- attr_reader :expire_grace_period
1968
-
1969
- def initialize(data, bot, server)
1970
- @bot = bot
1971
-
1972
- @name = data['name']
1973
- @server = server
1974
- @id = data['id'].to_i
1975
- @enabled = data['enabled']
1976
- @syncing = data['syncing']
1977
- @type = data['type']
1978
- @account = IntegrationAccount.new(data['account'])
1979
- @synced_at = Time.parse(data['synced_at'])
1980
- @expire_behaviour = [:remove, :kick][data['expire_behavior']]
1981
- @expire_grace_period = data['expire_grace_period']
1982
- @user = @bot.ensure_user(data['user'])
1983
- @role = server.role(data['role_id']) || nil
1984
- @emoticon = data['enable_emoticons']
1985
- end
1986
-
1987
- # The inspect method is overwritten to give more useful output
1988
- def inspect
1989
- "<Integration name=#{@name} id=#{@id} type=#{@type} enabled=#{@enabled}>"
1990
- end
1991
- end
1992
-
1993
- # A server on Discord
1994
- class Server
1995
- include IDObject
1996
- include ServerAttributes
1997
-
1998
- # @return [String] the region the server is on (e. g. `amsterdam`).
1999
- attr_reader :region
2000
-
2001
- # @return [Member] The server owner.
2002
- attr_reader :owner
2003
-
2004
- # @return [Array<Channel>] an array of all the channels (text and voice) on this server.
2005
- attr_reader :channels
2006
-
2007
- # @return [Array<Role>] an array of all the roles created on this server.
2008
- attr_reader :roles
2009
-
2010
- # @return [Array<Emoji>] an array of all the emoji available on this server.
2011
- attr_reader :emoji
2012
- alias_method :emojis, :emoji
2013
-
2014
- # @return [true, false] whether or not this server is large (members > 100). If it is,
2015
- # it means the members list may be inaccurate for a couple seconds after starting up the bot.
2016
- attr_reader :large
2017
- alias_method :large?, :large
2018
-
2019
- # @return [Array<Symbol>] the features of the server (eg. "INVITE_SPLASH")
2020
- attr_reader :features
2021
-
2022
- # @return [Integer] the absolute number of members on this server, offline or not.
2023
- attr_reader :member_count
2024
-
2025
- # @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').
2026
- attr_reader :verification_level
2027
-
2028
- # @return [Integer] the amount of time after which a voice user gets moved into the AFK channel, in seconds.
2029
- attr_reader :afk_timeout
2030
-
2031
- # @return [Channel, nil] the AFK voice channel of this server, or nil if none is set
2032
- attr_reader :afk_channel
2033
-
2034
- # @return [Hash<Integer => VoiceState>] the hash (user ID => voice state) of voice states of members on this server
2035
- attr_reader :voice_states
2036
-
2037
- # @!visibility private
2038
- def initialize(data, bot, exists = true)
2039
- @bot = bot
2040
- @owner_id = data['owner_id'].to_i
2041
- @id = data['id'].to_i
2042
- update_data(data)
2043
-
2044
- @large = data['large']
2045
- @member_count = data['member_count']
2046
- @verification_level = [:none, :low, :medium, :high][data['verification_level']]
2047
- @splash_id = nil
2048
- @embed = nil
2049
- @features = data['features'].map { |element| element.downcase.to_sym }
2050
- @members = {}
2051
- @voice_states = {}
2052
- @emoji = {}
2053
-
2054
- process_roles(data['roles'])
2055
- process_emoji(data['emojis'])
2056
- process_members(data['members'])
2057
- process_presences(data['presences'])
2058
- process_channels(data['channels'])
2059
- process_voice_states(data['voice_states'])
2060
-
2061
- # Whether this server's members have been chunked (resolved using op 8 and GUILD_MEMBERS_CHUNK) yet
2062
- @chunked = false
2063
- @processed_chunk_members = 0
2064
-
2065
- # Only get the owner of the server actually exists (i. e. not for ServerDeleteEvent)
2066
- @owner = member(@owner_id) if exists
2067
- end
2068
-
2069
- # @return [Channel] The default channel on this server (usually called #general)
2070
- def default_channel
2071
- @bot.channel(@id)
2072
- end
2073
-
2074
- alias_method :general_channel, :default_channel
2075
-
2076
- # Gets a role on this server based on its ID.
2077
- # @param id [Integer] The role ID to look for.
2078
- def role(id)
2079
- @roles.find { |e| e.id == id }
2080
- end
2081
-
2082
- # Gets a member on this server based on user ID
2083
- # @param id [Integer] The user ID to look for
2084
- # @param request [true, false] Whether the member should be requested from Discord if it's not cached
2085
- def member(id, request = true)
2086
- id = id.resolve_id
2087
- return @members[id] if member_cached?(id)
2088
- return nil unless request
2089
-
2090
- member = @bot.member(self, id)
2091
- @members[id] = member
2092
- rescue
2093
- nil
2094
- end
2095
-
2096
- # @return [Array<Member>] an array of all the members on this server.
2097
- def members
2098
- return @members.values if @chunked
2099
-
2100
- @bot.debug("Members for server #{@id} not chunked yet - initiating")
2101
- @bot.request_chunks(@id)
2102
- sleep 0.05 until @chunked
2103
- @members.values
2104
- end
2105
-
2106
- alias_method :users, :members
2107
-
2108
- # @return [Array<Integration>] an array of all the integrations connected to this server.
2109
- def integrations
2110
- integration = JSON.parse(API.server_integrations(@bot.token, @id))
2111
- integration.map { |element| Integration.new(element, @bot, self) }
2112
- end
2113
-
2114
- # Cache @embed
2115
- # @note For internal use only
2116
- # @!visibility private
2117
- def cache_embed
2118
- @embed = JSON.parse(API.server(@bot.token, @id))['embed_enabled'] if @embed.nil?
2119
- end
2120
-
2121
- # @return [true, false] whether or not the server has widget enabled
2122
- def embed?
2123
- cache_embed if @embed.nil?
2124
- @embed
2125
- end
2126
-
2127
- # @param include_idle [true, false] Whether to count idle members as online.
2128
- # @param include_bots [true, false] Whether to include bot accounts in the count.
2129
- # @return [Array<Member>] an array of online members on this server.
2130
- def online_members(include_idle: false, include_bots: true)
2131
- @members.values.select do |e|
2132
- ((include_idle ? e.idle? : false) || e.online?) && (include_bots ? true : !e.bot_account?)
2133
- end
2134
- end
2135
-
2136
- alias_method :online_users, :online_members
2137
-
2138
- # @return [Array<Channel>] an array of text channels on this server
2139
- def text_channels
2140
- @channels.select(&:text?)
2141
- end
2142
-
2143
- # @return [Array<Channel>] an array of voice channels on this server
2144
- def voice_channels
2145
- @channels.select(&:voice?)
2146
- end
2147
-
2148
- # @return [String, nil] the widget URL to the server that displays the amount of online members in a
2149
- # stylish way. `nil` if the widget is not enabled.
2150
- def widget_url
2151
- cache_embed if @embed.nil?
2152
- return nil unless @embed
2153
- API.widget_url(@id)
2154
- end
2155
-
2156
- # @param style [Symbol] The style the picture should have. Possible styles are:
2157
- # * `: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.
2158
- # * `: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.
2159
- # * `: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.
2160
- # * `: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.
2161
- # * `: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.
2162
- # @return [String, nil] the widget banner URL to the server that displays the amount of online members,
2163
- # server icon and server name in a stylish way. `nil` if the widget is not enabled.
2164
- def widget_banner_url(style)
2165
- return nil unless @embed
2166
- cache_embed if @embed.nil?
2167
- API.widget_url(@id, style)
2168
- end
2169
-
2170
- # @return [String] the hexadecimal ID used to identify this server's splash image for their VIP invite page.
2171
- def splash_id
2172
- @splash_id = JSON.parse(API.server(@bot.token, @id))['splash'] if @splash_id.nil?
2173
- @splash_id
2174
- end
2175
-
2176
- # @return [String, nil] the splash image URL for the server's VIP invite page.
2177
- # `nil` if there is no splash image.
2178
- def splash_url
2179
- splash_id if @splash_id.nil?
2180
- return nil unless @splash_id
2181
- API.splash_url(@id, @splash_id)
2182
- end
2183
-
2184
- # Adds a role to the role cache
2185
- # @note For internal use only
2186
- # @!visibility private
2187
- def add_role(role)
2188
- @roles << role
2189
- end
2190
-
2191
- # Removes a role from the role cache
2192
- # @note For internal use only
2193
- # @!visibility private
2194
- def delete_role(role_id)
2195
- @roles.reject! { |r| r.id == role_id }
2196
- @members.each do |_, member|
2197
- new_roles = member.roles.reject { |r| r.id == role_id }
2198
- member.update_roles(new_roles)
2199
- end
2200
- @channels.each do |channel|
2201
- overwrites = channel.permission_overwrites.reject { |id, _| id == role_id }
2202
- channel.update_overwrites(overwrites)
2203
- end
2204
- end
2205
-
2206
- # Adds a member to the member cache.
2207
- # @note For internal use only
2208
- # @!visibility private
2209
- def add_member(member)
2210
- @members[member.id] = member
2211
- @member_count += 1
2212
- end
2213
-
2214
- # Removes a member from the member cache.
2215
- # @note For internal use only
2216
- # @!visibility private
2217
- def delete_member(user_id)
2218
- @members.delete(user_id)
2219
- @member_count -= 1
2220
- end
2221
-
2222
- # Checks whether a member is cached
2223
- # @note For internal use only
2224
- # @!visibility private
2225
- def member_cached?(user_id)
2226
- @members.include?(user_id)
2227
- end
2228
-
2229
- # Adds a member to the cache
2230
- # @note For internal use only
2231
- # @!visibility private
2232
- def cache_member(member)
2233
- @members[member.id] = member
2234
- end
2235
-
2236
- # Updates a member's voice state
2237
- # @note For internal use only
2238
- # @!visibility private
2239
- def update_voice_state(data)
2240
- user_id = data['user_id'].to_i
2241
-
2242
- if data['channel_id']
2243
- unless @voice_states[user_id]
2244
- # Create a new voice state for the user
2245
- @voice_states[user_id] = VoiceState.new(user_id)
2246
- end
2247
-
2248
- # Update the existing voice state (or the one we just created)
2249
- channel = @channels_by_id[data['channel_id'].to_i]
2250
- @voice_states[user_id].update(
2251
- channel,
2252
- data['mute'],
2253
- data['deaf'],
2254
- data['self_mute'],
2255
- data['self_deaf']
2256
- )
2257
- else
2258
- # The user is not in a voice channel anymore, so delete its voice state
2259
- @voice_states.delete(user_id)
2260
- end
2261
- end
2262
-
2263
- # Creates a channel on this server with the given name.
2264
- # @param name [String] Name of the channel to create
2265
- # @param type [Integer] Type of channel to create (0: text, 2: voice)
2266
- # @return [Channel] the created channel.
2267
- # @raise [ArgumentError] if type is not 0 or 2
2268
- def create_channel(name, type = 0)
2269
- raise ArgumentError, 'Channel type must be either 0 (text) or 2 (voice)!' unless [0, 2].include?(type)
2270
- response = API::Server.create_channel(@bot.token, @id, name, type)
2271
- Channel.new(JSON.parse(response), @bot)
2272
- end
2273
-
2274
- # Creates a role on this server which can then be modified. It will be initialized (on Discord's side)
2275
- # with the regular role defaults the client uses, i. e. name is "new role", permissions are the default,
2276
- # colour is the default etc.
2277
- # @return [Role] the created role.
2278
- def create_role
2279
- response = API::Server.create_role(@bot.token, @id)
2280
- role = Role.new(JSON.parse(response), @bot, self)
2281
- @roles << role
2282
- role
2283
- end
2284
-
2285
- # @return [Array<User>] a list of banned users on this server.
2286
- def bans
2287
- users = JSON.parse(API::Server.bans(@bot.token, @id))
2288
- users.map { |e| User.new(e['user'], @bot) }
2289
- end
2290
-
2291
- # Bans a user from this server.
2292
- # @param user [User, #resolve_id] The user to ban.
2293
- # @param message_days [Integer] How many days worth of messages sent by the user should be deleted.
2294
- def ban(user, message_days = 0)
2295
- API::Server.ban_user(@bot.token, @id, user.resolve_id, message_days)
2296
- end
2297
-
2298
- # Unbans a previously banned user from this server.
2299
- # @param user [User, #resolve_id] The user to unban.
2300
- def unban(user)
2301
- API::Server.unban_user(@bot.token, @id, user.resolve_id)
2302
- end
2303
-
2304
- # Kicks a user from this server.
2305
- # @param user [User, #resolve_id] The user to kick.
2306
- def kick(user)
2307
- API::Server.remove_member(@bot.token, @id, user.resolve_id)
2308
- end
2309
-
2310
- # Forcibly moves a user into a different voice channel. Only works if the bot has the permission needed.
2311
- # @param user [User] The user to move.
2312
- # @param channel [Channel] The voice channel to move into.
2313
- def move(user, channel)
2314
- API::Server.update_member(@bot.token, @id, user.id, channel_id: channel.id)
2315
- end
2316
-
2317
- # Deletes this server. Be aware that this is permanent and impossible to undo, so be careful!
2318
- def delete
2319
- API::Server.delete(@bot.token, @id)
2320
- end
2321
-
2322
- # Leave the server
2323
- def leave
2324
- API::User.leave_server(@bot.token, @id)
2325
- end
2326
-
2327
- # Transfers server ownership to another user.
2328
- # @param user [User] The user who should become the new owner.
2329
- def owner=(user)
2330
- API::Server.transfer_ownership(@bot.token, @id, user.id)
2331
- end
2332
-
2333
- # Sets the server's name.
2334
- # @param name [String] The new server name.
2335
- def name=(name)
2336
- update_server_data(name: name)
2337
- end
2338
-
2339
- # Moves the server to another region. This will cause a voice interruption of at most a second.
2340
- # @param region [String] The new region the server should be in.
2341
- def region=(region)
2342
- update_server_data(region: region.to_s)
2343
- end
2344
-
2345
- # Sets the server's icon.
2346
- # @param icon [String, #read] The new icon, in base64-encoded JPG format.
2347
- def icon=(icon)
2348
- if icon.respond_to? :read
2349
- icon_string = 'data:image/jpg;base64,'
2350
- icon_string += Base64.strict_encode64(icon.read)
2351
- update_server_data(icon: icon_string)
2352
- else
2353
- update_server_data(icon: icon)
2354
- end
2355
- end
2356
-
2357
- # Sets the server's AFK channel.
2358
- # @param afk_channel [Channel, nil] The new AFK channel, or `nil` if there should be none set.
2359
- def afk_channel=(afk_channel)
2360
- update_server_data(afk_channel_id: afk_channel.resolve_id)
2361
- end
2362
-
2363
- # Sets the amount of time after which a user gets moved into the AFK channel.
2364
- # @param afk_timeout [Integer] The AFK timeout, in seconds.
2365
- def afk_timeout=(afk_timeout)
2366
- update_server_data(afk_timeout: afk_timeout)
2367
- end
2368
-
2369
- # @return [true, false] whether this server has any emoji or not.
2370
- def any_emoji?
2371
- @emoji.any?
2372
- end
2373
-
2374
- alias_method :has_emoji?, :any_emoji?
2375
- alias_method :emoji?, :any_emoji?
2376
-
2377
- # Processes a GUILD_MEMBERS_CHUNK packet, specifically the members field
2378
- # @note For internal use only
2379
- # @!visibility private
2380
- def process_chunk(members)
2381
- process_members(members)
2382
- @processed_chunk_members += members.length
2383
- LOGGER.debug("Processed one chunk on server #{@id} - length #{members.length}")
2384
-
2385
- # Don't bother with the rest of the method if it's not truly the last packet
2386
- return unless @processed_chunk_members == @member_count
2387
-
2388
- LOGGER.debug("Finished chunking server #{@id}")
2389
-
2390
- # Reset everything to normal
2391
- @chunked = true
2392
- @processed_chunk_members = 0
2393
- end
2394
-
2395
- # Updates the cached data with new data
2396
- # @note For internal use only
2397
- # @!visibility private
2398
- def update_data(new_data)
2399
- @name = new_data[:name] || new_data['name'] || @name
2400
- @region = new_data[:region] || new_data['region'] || @region
2401
- @icon_id = new_data[:icon] || new_data['icon'] || @icon_id
2402
- @afk_timeout = new_data[:afk_timeout] || new_data['afk_timeout'].to_i || @afk_timeout
2403
-
2404
- @afk_channel_id = new_data[:afk_channel_id] || new_data['afk_channel_id'].to_i || @afk_channel.id
2405
-
2406
- begin
2407
- @afk_channel = @bot.channel(@afk_channel_id, self) if @afk_channel_id.nonzero? && (!@afk_channel || @afk_channel_id != @afk_channel.id)
2408
- rescue Discordrb::Errors::NoPermission
2409
- LOGGER.debug("AFK channel #{@afk_channel_id} on server #{@id} is unreachable, setting to nil even though one exists")
2410
- @afk_channel = nil
2411
- end
2412
- end
2413
-
2414
- # The inspect method is overwritten to give more useful output
2415
- def inspect
2416
- "<Server name=#{@name} id=#{@id} large=#{@large} region=#{@region} owner=#{@owner} afk_channel_id=#{@afk_channel_id} afk_timeout=#{@afk_timeout}>"
2417
- end
2418
-
2419
- private
2420
-
2421
- def update_server_data(new_data)
2422
- API::Server.update(@bot.token, @id,
2423
- new_data[:name] || @name,
2424
- new_data[:region] || @region,
2425
- new_data[:icon_id] || @icon_id,
2426
- new_data[:afk_channel_id] || @afk_channel_id,
2427
- new_data[:afk_timeout] || @afk_timeout)
2428
- update_data(new_data)
2429
- end
2430
-
2431
- def process_roles(roles)
2432
- # Create roles
2433
- @roles = []
2434
- @roles_by_id = {}
2435
-
2436
- return unless roles
2437
- roles.each do |element|
2438
- role = Role.new(element, @bot, self)
2439
- @roles << role
2440
- @roles_by_id[role.id] = role
2441
- end
2442
- end
2443
-
2444
- def process_emoji(emoji)
2445
- return if emoji.empty?
2446
- emoji.each do |element|
2447
- new_emoji = Emoji.new(element, @bot, self)
2448
- @emoji[new_emoji.id] = new_emoji
2449
- end
2450
- end
2451
-
2452
- def process_members(members)
2453
- return unless members
2454
- members.each do |element|
2455
- member = Member.new(element, self, @bot)
2456
- @members[member.id] = member
2457
- end
2458
- end
2459
-
2460
- def process_presences(presences)
2461
- # Update user statuses with presence info
2462
- return unless presences
2463
- presences.each do |element|
2464
- next unless element['user']
2465
- user_id = element['user']['id'].to_i
2466
- user = @members[user_id]
2467
- if user
2468
- user.status = element['status'].to_sym
2469
- user.game = element['game'] ? element['game']['name'] : nil
2470
- else
2471
- LOGGER.warn "Rogue presence update! #{element['user']['id']} on #{@id}"
2472
- end
2473
- end
2474
- end
2475
-
2476
- def process_channels(channels)
2477
- @channels = []
2478
- @channels_by_id = {}
2479
-
2480
- return unless channels
2481
- channels.each do |element|
2482
- channel = @bot.ensure_channel(element, self)
2483
- @channels << channel
2484
- @channels_by_id[channel.id] = channel
2485
- end
2486
- end
2487
-
2488
- def process_voice_states(voice_states)
2489
- return unless voice_states
2490
- voice_states.each do |element|
2491
- update_voice_state(element)
2492
- end
2493
- end
2494
- end
2495
-
2496
- # A colour (red, green and blue values). Used for role colours. If you prefer the American spelling, the alias
2497
- # {ColorRGB} is also available.
2498
- class ColourRGB
2499
- # @return [Integer] the red part of this colour (0-255).
2500
- attr_reader :red
2501
-
2502
- # @return [Integer] the green part of this colour (0-255).
2503
- attr_reader :green
2504
-
2505
- # @return [Integer] the blue part of this colour (0-255).
2506
- attr_reader :blue
2507
-
2508
- # @return [Integer] the colour's RGB values combined into one integer.
2509
- attr_reader :combined
2510
-
2511
- # Make a new colour from the combined value.
2512
- # @param combined [Integer] The colour's RGB values combined into one integer
2513
- def initialize(combined)
2514
- @combined = combined
2515
- @red = (combined >> 16) & 0xFF
2516
- @green = (combined >> 8) & 0xFF
2517
- @blue = combined & 0xFF
2518
- end
2519
- end
2520
-
2521
- # Alias for the class {ColourRGB}
2522
- ColorRGB = ColourRGB
2523
- end
19
+ require 'discordrb/data/activity'
20
+ require 'discordrb/data/application'
21
+ require 'discordrb/data/user'
22
+ require 'discordrb/data/voice_state'
23
+ require 'discordrb/data/voice_region'
24
+ require 'discordrb/data/member'
25
+ require 'discordrb/data/recipient'
26
+ require 'discordrb/data/profile'
27
+ require 'discordrb/data/role'
28
+ require 'discordrb/data/invite'
29
+ require 'discordrb/data/overwrite'
30
+ require 'discordrb/data/channel'
31
+ require 'discordrb/data/embed'
32
+ require 'discordrb/data/attachment'
33
+ require 'discordrb/data/message'
34
+ require 'discordrb/data/reaction'
35
+ require 'discordrb/data/emoji'
36
+ require 'discordrb/data/integration'
37
+ require 'discordrb/data/server'
38
+ require 'discordrb/data/webhook'
39
+ require 'discordrb/data/audit_logs'