discordrb 3.3.0 → 3.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +126 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +25 -0
  5. data/.github/pull_request_template.md +37 -0
  6. data/.rubocop.yml +34 -37
  7. data/.travis.yml +5 -6
  8. data/CHANGELOG.md +504 -347
  9. data/Gemfile +2 -0
  10. data/LICENSE.txt +1 -1
  11. data/README.md +61 -79
  12. data/Rakefile +2 -0
  13. data/bin/console +1 -0
  14. data/discordrb-webhooks.gemspec +6 -6
  15. data/discordrb.gemspec +18 -18
  16. data/lib/discordrb/allowed_mentions.rb +36 -0
  17. data/lib/discordrb/api/channel.rb +62 -39
  18. data/lib/discordrb/api/invite.rb +3 -3
  19. data/lib/discordrb/api/server.rb +57 -50
  20. data/lib/discordrb/api/user.rb +9 -8
  21. data/lib/discordrb/api/webhook.rb +6 -6
  22. data/lib/discordrb/api.rb +40 -15
  23. data/lib/discordrb/await.rb +0 -1
  24. data/lib/discordrb/bot.rb +175 -73
  25. data/lib/discordrb/cache.rb +4 -2
  26. data/lib/discordrb/colour_rgb.rb +43 -0
  27. data/lib/discordrb/commands/command_bot.rb +30 -9
  28. data/lib/discordrb/commands/container.rb +20 -23
  29. data/lib/discordrb/commands/parser.rb +18 -18
  30. data/lib/discordrb/commands/rate_limiter.rb +3 -2
  31. data/lib/discordrb/container.rb +77 -17
  32. data/lib/discordrb/data/activity.rb +271 -0
  33. data/lib/discordrb/data/application.rb +50 -0
  34. data/lib/discordrb/data/attachment.rb +56 -0
  35. data/lib/discordrb/data/audit_logs.rb +345 -0
  36. data/lib/discordrb/data/channel.rb +849 -0
  37. data/lib/discordrb/data/embed.rb +251 -0
  38. data/lib/discordrb/data/emoji.rb +82 -0
  39. data/lib/discordrb/data/integration.rb +83 -0
  40. data/lib/discordrb/data/invite.rb +137 -0
  41. data/lib/discordrb/data/member.rb +297 -0
  42. data/lib/discordrb/data/message.rb +334 -0
  43. data/lib/discordrb/data/overwrite.rb +102 -0
  44. data/lib/discordrb/data/profile.rb +91 -0
  45. data/lib/discordrb/data/reaction.rb +33 -0
  46. data/lib/discordrb/data/recipient.rb +34 -0
  47. data/lib/discordrb/data/role.rb +191 -0
  48. data/lib/discordrb/data/server.rb +1002 -0
  49. data/lib/discordrb/data/user.rb +204 -0
  50. data/lib/discordrb/data/voice_region.rb +45 -0
  51. data/lib/discordrb/data/voice_state.rb +41 -0
  52. data/lib/discordrb/data/webhook.rb +145 -0
  53. data/lib/discordrb/data.rb +25 -4180
  54. data/lib/discordrb/errors.rb +2 -1
  55. data/lib/discordrb/events/bans.rb +7 -5
  56. data/lib/discordrb/events/channels.rb +2 -0
  57. data/lib/discordrb/events/guilds.rb +16 -9
  58. data/lib/discordrb/events/invites.rb +125 -0
  59. data/lib/discordrb/events/members.rb +6 -2
  60. data/lib/discordrb/events/message.rb +69 -27
  61. data/lib/discordrb/events/presence.rb +14 -4
  62. data/lib/discordrb/events/raw.rb +1 -3
  63. data/lib/discordrb/events/reactions.rb +49 -3
  64. data/lib/discordrb/events/typing.rb +6 -4
  65. data/lib/discordrb/events/voice_server_update.rb +47 -0
  66. data/lib/discordrb/events/voice_state_update.rb +15 -10
  67. data/lib/discordrb/events/webhooks.rb +9 -6
  68. data/lib/discordrb/gateway.rb +72 -57
  69. data/lib/discordrb/id_object.rb +39 -0
  70. data/lib/discordrb/light/integrations.rb +1 -1
  71. data/lib/discordrb/light/light_bot.rb +1 -1
  72. data/lib/discordrb/logger.rb +4 -4
  73. data/lib/discordrb/paginator.rb +57 -0
  74. data/lib/discordrb/permissions.rb +103 -8
  75. data/lib/discordrb/version.rb +1 -1
  76. data/lib/discordrb/voice/encoder.rb +16 -7
  77. data/lib/discordrb/voice/network.rb +84 -43
  78. data/lib/discordrb/voice/sodium.rb +96 -0
  79. data/lib/discordrb/voice/voice_bot.rb +34 -26
  80. data/lib/discordrb.rb +73 -0
  81. metadata +98 -60
  82. /data/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +0 -0
@@ -0,0 +1,345 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discordrb
4
+ # A server's audit logs
5
+ class AuditLogs
6
+ # The numbers associated with the type of action.
7
+ ACTIONS = {
8
+ 1 => :server_update,
9
+ 10 => :channel_create,
10
+ 11 => :channel_update,
11
+ 12 => :channel_delete,
12
+ 13 => :channel_overwrite_create,
13
+ 14 => :channel_overwrite_update,
14
+ 15 => :channel_overwrite_delete,
15
+ 20 => :member_kick,
16
+ 21 => :member_prune,
17
+ 22 => :member_ban_add,
18
+ 23 => :member_ban_remove,
19
+ 24 => :member_update,
20
+ 25 => :member_role_update,
21
+ 26 => :member_move,
22
+ 27 => :member_disconnect,
23
+ 28 => :bot_add,
24
+ 30 => :role_create,
25
+ 31 => :role_update,
26
+ 32 => :role_delete,
27
+ 40 => :invite_create,
28
+ 41 => :invite_update,
29
+ 42 => :invite_delete,
30
+ 50 => :webhook_create,
31
+ 51 => :webhook_update,
32
+ 52 => :webhook_delete,
33
+ 60 => :emoji_create,
34
+ 61 => :emoji_update,
35
+ 62 => :emoji_delete,
36
+ # 70
37
+ # 71
38
+ 72 => :message_delete,
39
+ 73 => :message_bulk_delete,
40
+ 74 => :message_pin,
41
+ 75 => :message_unpin,
42
+ 80 => :integration_create,
43
+ 81 => :integration_update,
44
+ 82 => :integration_delete
45
+ }.freeze
46
+
47
+ # @!visibility private
48
+ CREATE_ACTIONS = %i[
49
+ channel_create channel_overwrite_create member_ban_add role_create
50
+ invite_create webhook_create emoji_create integration_create
51
+ ].freeze
52
+
53
+ # @!visibility private
54
+ DELETE_ACTIONS = %i[
55
+ channel_delete channel_overwrite_delete member_kick member_prune
56
+ member_ban_remove role_delete invite_delete webhook_delete
57
+ emoji_delete message_delete message_bulk_delete integration_delete
58
+ ].freeze
59
+
60
+ # @!visibility private
61
+ UPDATE_ACTIONS = %i[
62
+ server_update channel_update channel_overwrite_update member_update
63
+ member_role_update role_update invite_update webhook_update
64
+ emoji_update integration_update
65
+ ].freeze
66
+
67
+ # @return [Hash<String => User>] the users included in the audit logs.
68
+ attr_reader :users
69
+
70
+ # @return [Hash<String => Webhook>] the webhooks included in the audit logs.
71
+ attr_reader :webhooks
72
+
73
+ # @return [Array<Entry>] the entries listed in the audit logs.
74
+ attr_reader :entries
75
+
76
+ # @!visibility private
77
+ def initialize(server, bot, data)
78
+ @bot = bot
79
+ @server = server
80
+ @users = {}
81
+ @webhooks = {}
82
+ @entries = data['audit_log_entries'].map { |entry| Entry.new(self, @server, @bot, entry) }
83
+
84
+ process_users(data['users'])
85
+ process_webhooks(data['webhooks'])
86
+ end
87
+
88
+ # An entry in a server's audit logs.
89
+ class Entry
90
+ include IDObject
91
+
92
+ # @return [Symbol] the action that was performed.
93
+ attr_reader :action
94
+
95
+ # @return [Symbol] the type action that was performed. (:create, :delete, :update, :unknown)
96
+ attr_reader :action_type
97
+
98
+ # @return [Symbol] the type of target being performed on. (:server, :channel, :user, :role, :invite, :webhook, :emoji, :unknown)
99
+ attr_reader :target_type
100
+
101
+ # @return [Integer, nil] the amount of messages deleted. Only present if the action is `:message_delete`.
102
+ attr_reader :count
103
+ alias_method :amount, :count
104
+
105
+ # @return [Integer, nil] the amount of days the members were inactive for. Only present if the action is `:member_prune`.
106
+ attr_reader :days
107
+
108
+ # @return [Integer, nil] the amount of members removed. Only present if the action is `:member_prune`.
109
+ attr_reader :members_removed
110
+
111
+ # @return [String, nil] the reason for this action occurring.
112
+ attr_reader :reason
113
+
114
+ # @return [Hash<String => Change>, RoleChange, nil] the changes from this log, listing the key as the key changed. Will be a RoleChange object if the action is `:member_role_update`. Will be nil if the action is either `:message_delete` or `:member_prune`.
115
+ attr_reader :changes
116
+
117
+ # @!visibility private
118
+ def initialize(logs, server, bot, data)
119
+ @bot = bot
120
+ @id = data['id'].resolve_id
121
+ @logs = logs
122
+ @server = server
123
+ @data = data
124
+ @action = ACTIONS[data['action_type']]
125
+ @reason = data['reason']
126
+ @action_type = AuditLogs.action_type_for(data['action_type'])
127
+ @target_type = AuditLogs.target_type_for(data['action_type'])
128
+
129
+ # Sets the 'changes' variable to a empty hash if there are no special actions.
130
+ @changes = {} unless @action == :message_delete || @action == :member_prune || @action == :member_role_update
131
+
132
+ # Sets the 'changes' variable to a RoleChange class if there's a role update.
133
+ @changes = RoleChange.new(data['changes'][0], @server) if @action == :member_role_update
134
+
135
+ process_changes(data['changes']) unless @action == :member_role_update
136
+ return unless data.include?('options')
137
+
138
+ # Checks and sets variables for special action options.
139
+ @count = data['options']['count'].to_i unless data['options']['count'].nil?
140
+ @channel_id = data['options']['channel'].to_i unless data['options']['channel'].nil?
141
+ @days = data['options']['delete_member_days'].to_i unless data['options']['delete_member_days'].nil?
142
+ @members_removed = data['options']['members_removed'].to_i unless data['options']['members_removed'].nil?
143
+ end
144
+
145
+ # @return [Server, Channel, Member, User, Role, Invite, Webhook, Emoji, nil] the target being performed on.
146
+ def target
147
+ @target ||= process_target(@data['target_id'], @target_type)
148
+ end
149
+
150
+ # @return [Member, User] the user that authored this action. Can be a User object if the user no longer exists in the server.
151
+ def user
152
+ @user ||= @server.member(@data['user_id'].to_i) || @bot.user(@data['user_id'].to_i) || @logs.user(@data['user_id'].to_i)
153
+ end
154
+ alias_method :author, :user
155
+
156
+ # @return [Channel, nil] the amount of messages deleted. Won't be nil if the action is `:message_delete`.
157
+ def channel
158
+ return nil unless @channel_id
159
+
160
+ @channel ||= @bot.channel(@channel_id, @server, bot, self)
161
+ end
162
+
163
+ # @!visibility private
164
+ def process_target(id, type)
165
+ id = id.resolve_id unless id.nil?
166
+ case type
167
+ when :server then @server # Since it won't be anything else
168
+ when :channel then @bot.channel(id, @server)
169
+ when :user, :message then @server.member(id) || @bot.user(id) || @logs.user(id)
170
+ when :role then @server.role(id)
171
+ when :invite then @bot.invite(@data['changes'].find { |change| change['key'] == 'code' }.values.delete_if { |v| v == 'code' }.first)
172
+ when :webhook then @server.webhooks.find { |webhook| webhook.id == id } || @logs.webhook(id)
173
+ when :emoji then @server.emoji[id]
174
+ when :integration then @server.integrations.find { |integration| integration.id == id }
175
+ end
176
+ end
177
+
178
+ # The inspect method is overwritten to give more useful output
179
+ def inspect
180
+ "<AuditLogs::Entry id=#{@id} action=#{@action} reason=#{@reason} action_type=#{@action_type} target_type=#{@target_type} count=#{@count} days=#{@days} members_removed=#{@members_removed}>"
181
+ end
182
+
183
+ # Process action changes
184
+ # @note For internal use only
185
+ # @!visibility private
186
+ def process_changes(changes)
187
+ return unless changes
188
+
189
+ changes.each do |element|
190
+ change = Change.new(element, @server, @bot, self)
191
+ @changes[change.key] = change
192
+ end
193
+ end
194
+ end
195
+
196
+ # A change in a audit log entry.
197
+ class Change
198
+ # @return [String] the key that was changed.
199
+ # @note You should check with the Discord API Documentation on what key gives out what value.
200
+ attr_reader :key
201
+
202
+ # @return [String, Integer, true, false, Permissions, Overwrite, nil] the value that was changed from.
203
+ attr_reader :old
204
+ alias_method :old_value, :old
205
+
206
+ # @return [String, Integer, true, false, Permissions, Overwrite, nil] the value that was changed to.
207
+ attr_reader :new
208
+ alias_method :new_value, :new
209
+
210
+ # @!visibility private
211
+ def initialize(data, server, bot, logs)
212
+ @key = data['key']
213
+ @old = data['old_value']
214
+ @new = data['new_value']
215
+ @server = server
216
+ @bot = bot
217
+ @logs = logs
218
+
219
+ @old = Permissions.new(@old) if @old && @key == 'permissions'
220
+ @new = Permissions.new(@new) if @new && @key == 'permissions'
221
+
222
+ @old = @old.map { |o| Overwrite.new(o['id'], type: o['type'].to_sym, allow: o['allow'], deny: o['deny']) } if @old && @key == 'permission_overwrites'
223
+ @new = @new.map { |o| Overwrite.new(o['id'], type: o['type'].to_sym, allow: o['allow'], deny: o['deny']) } if @new && @key == 'permission_overwrites'
224
+ end
225
+
226
+ # @return [Channel, nil] the channel that was previously used in the server widget. Only present if the key for this change is `widget_channel_id`.
227
+ def old_widget_channel
228
+ @bot.channel(@old, @server) if @old && @key == 'widget_channel_id'
229
+ end
230
+
231
+ # @return [Channel, nil] the channel that is used in the server widget prior to this change. Only present if the key for this change is `widget_channel_id`.
232
+ def new_widget_channel
233
+ @bot.channel(@new, @server) if @new && @key == 'widget_channel_id'
234
+ end
235
+
236
+ # @return [Channel, nil] the channel that was previously used in the server as an AFK channel. Only present if the key for this change is `afk_channel_id`.
237
+ def old_afk_channel
238
+ @bot.channel(@old, @server) if @old && @key == 'afk_channel_id'
239
+ end
240
+
241
+ # @return [Channel, nil] the channel that is used in the server as an AFK channel prior to this change. Only present if the key for this change is `afk_channel_id`.
242
+ def new_afk_channel
243
+ @bot.channel(@new, @server) if @new && @key == 'afk_channel_id'
244
+ end
245
+
246
+ # @return [Member, User, nil] the member that used to be the owner of the server. Only present if the for key for this change is `owner_id`.
247
+ def old_owner
248
+ @server.member(@old) || @bot.user(@old) || @logs.user(@old) if @old && @key == 'owner_id'
249
+ end
250
+
251
+ # @return [Member, User, nil] the member that is now the owner of the server prior to this change. Only present if the key for this change is `owner_id`.
252
+ def new_owner
253
+ @server.member(@new) || @bot.user(@new) || @logs.user(@new) if @new && @key == 'owner_id'
254
+ end
255
+ end
256
+
257
+ # A change that includes roles.
258
+ class RoleChange
259
+ # @return [Symbol] what type of change this is: (:add, :remove)
260
+ attr_reader :type
261
+
262
+ # @!visibility private
263
+ def initialize(data, server)
264
+ @type = data['key'].delete('$').to_sym
265
+ @role_id = data['new_value'][0]['id'].to_i
266
+ @server = server
267
+ end
268
+
269
+ # @return [Role] the role being used.
270
+ def role
271
+ @role ||= @server.role(@role_id)
272
+ end
273
+ end
274
+
275
+ # @return [Entry] the latest entry in the audit logs.
276
+ def latest
277
+ @entries.first
278
+ end
279
+ alias_method :first, :latest
280
+
281
+ # Gets a user in the audit logs data based on user ID
282
+ # @note This only uses data given by the audit logs request
283
+ # @param id [String, Integer] The user ID to look for
284
+ def user(id)
285
+ @users[id.resolve_id]
286
+ end
287
+
288
+ # Gets a webhook in the audit logs data based on webhook ID
289
+ # @note This only uses data given by the audit logs request
290
+ # @param id [String, Integer] The webhook ID to look for
291
+ def webhook(id)
292
+ @webhooks[id.resolve_id]
293
+ end
294
+
295
+ # Process user objects given by the request
296
+ # @note For internal use only
297
+ # @!visibility private
298
+ def process_users(users)
299
+ users.each do |element|
300
+ user = User.new(element, @bot)
301
+ @users[user.id] = user
302
+ end
303
+ end
304
+
305
+ # Process webhook objects given by the request
306
+ # @note For internal use only
307
+ # @!visibility private
308
+ def process_webhooks(webhooks)
309
+ webhooks.each do |element|
310
+ webhook = Webhook.new(element, @bot)
311
+ @webhooks[webhook.id] = webhook
312
+ end
313
+ end
314
+
315
+ # Find the type of target by it's action number
316
+ # @note For internal use only
317
+ # @!visibility private
318
+ def self.target_type_for(action)
319
+ case action
320
+ when 1..9 then :server
321
+ when 10..19 then :channel
322
+ when 20..29 then :user
323
+ when 30..39 then :role
324
+ when 40..49 then :invite
325
+ when 50..59 then :webhook
326
+ when 60..69 then :emoji
327
+ when 70..79 then :message
328
+ when 80..89 then :integration
329
+ else :unknown
330
+ end
331
+ end
332
+
333
+ # Find the type of action by its action number
334
+ # @note For internal use only
335
+ # @!visibility private
336
+ def self.action_type_for(action)
337
+ action = ACTIONS[action]
338
+ return :create if CREATE_ACTIONS.include?(action)
339
+ return :delete if DELETE_ACTIONS.include?(action)
340
+ return :update if UPDATE_ACTIONS.include?(action)
341
+
342
+ :unknown
343
+ end
344
+ end
345
+ end