discordrb 3.3.0 → 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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +126 -0
  3. data/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +0 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +25 -0
  6. data/.github/pull_request_template.md +37 -0
  7. data/.rubocop.yml +34 -37
  8. data/.travis.yml +5 -6
  9. data/CHANGELOG.md +472 -347
  10. data/Gemfile +2 -0
  11. data/LICENSE.txt +1 -1
  12. data/README.md +61 -79
  13. data/Rakefile +2 -0
  14. data/bin/console +1 -0
  15. data/discordrb-webhooks.gemspec +6 -6
  16. data/discordrb.gemspec +17 -17
  17. data/lib/discordrb.rb +73 -0
  18. data/lib/discordrb/allowed_mentions.rb +36 -0
  19. data/lib/discordrb/api.rb +40 -15
  20. data/lib/discordrb/api/channel.rb +57 -39
  21. data/lib/discordrb/api/invite.rb +3 -3
  22. data/lib/discordrb/api/server.rb +55 -50
  23. data/lib/discordrb/api/user.rb +8 -8
  24. data/lib/discordrb/api/webhook.rb +6 -6
  25. data/lib/discordrb/await.rb +0 -1
  26. data/lib/discordrb/bot.rb +164 -72
  27. data/lib/discordrb/cache.rb +4 -2
  28. data/lib/discordrb/colour_rgb.rb +43 -0
  29. data/lib/discordrb/commands/command_bot.rb +22 -6
  30. data/lib/discordrb/commands/container.rb +20 -23
  31. data/lib/discordrb/commands/parser.rb +18 -18
  32. data/lib/discordrb/commands/rate_limiter.rb +3 -2
  33. data/lib/discordrb/container.rb +77 -17
  34. data/lib/discordrb/data.rb +25 -4180
  35. data/lib/discordrb/data/activity.rb +264 -0
  36. data/lib/discordrb/data/application.rb +50 -0
  37. data/lib/discordrb/data/attachment.rb +56 -0
  38. data/lib/discordrb/data/audit_logs.rb +345 -0
  39. data/lib/discordrb/data/channel.rb +849 -0
  40. data/lib/discordrb/data/embed.rb +251 -0
  41. data/lib/discordrb/data/emoji.rb +82 -0
  42. data/lib/discordrb/data/integration.rb +83 -0
  43. data/lib/discordrb/data/invite.rb +137 -0
  44. data/lib/discordrb/data/member.rb +297 -0
  45. data/lib/discordrb/data/message.rb +334 -0
  46. data/lib/discordrb/data/overwrite.rb +102 -0
  47. data/lib/discordrb/data/profile.rb +91 -0
  48. data/lib/discordrb/data/reaction.rb +33 -0
  49. data/lib/discordrb/data/recipient.rb +34 -0
  50. data/lib/discordrb/data/role.rb +191 -0
  51. data/lib/discordrb/data/server.rb +1002 -0
  52. data/lib/discordrb/data/user.rb +204 -0
  53. data/lib/discordrb/data/voice_region.rb +45 -0
  54. data/lib/discordrb/data/voice_state.rb +41 -0
  55. data/lib/discordrb/data/webhook.rb +145 -0
  56. data/lib/discordrb/errors.rb +2 -1
  57. data/lib/discordrb/events/bans.rb +7 -5
  58. data/lib/discordrb/events/channels.rb +2 -0
  59. data/lib/discordrb/events/guilds.rb +16 -9
  60. data/lib/discordrb/events/invites.rb +125 -0
  61. data/lib/discordrb/events/members.rb +6 -2
  62. data/lib/discordrb/events/message.rb +69 -27
  63. data/lib/discordrb/events/presence.rb +14 -4
  64. data/lib/discordrb/events/raw.rb +1 -3
  65. data/lib/discordrb/events/reactions.rb +49 -3
  66. data/lib/discordrb/events/typing.rb +6 -4
  67. data/lib/discordrb/events/voice_server_update.rb +47 -0
  68. data/lib/discordrb/events/voice_state_update.rb +15 -10
  69. data/lib/discordrb/events/webhooks.rb +9 -6
  70. data/lib/discordrb/gateway.rb +72 -57
  71. data/lib/discordrb/id_object.rb +39 -0
  72. data/lib/discordrb/light/integrations.rb +1 -1
  73. data/lib/discordrb/light/light_bot.rb +1 -1
  74. data/lib/discordrb/logger.rb +4 -4
  75. data/lib/discordrb/paginator.rb +57 -0
  76. data/lib/discordrb/permissions.rb +103 -8
  77. data/lib/discordrb/version.rb +1 -1
  78. data/lib/discordrb/voice/encoder.rb +3 -3
  79. data/lib/discordrb/voice/network.rb +84 -43
  80. data/lib/discordrb/voice/sodium.rb +96 -0
  81. data/lib/discordrb/voice/voice_bot.rb +34 -26
  82. metadata +93 -55
@@ -27,20 +27,22 @@ module Discordrb::Events
27
27
 
28
28
  [
29
29
  matches_all(@attributes[:user], event.user) do |a, e|
30
- if a.is_a? String
30
+ case a
31
+ when String
31
32
  a == e.name
32
- elsif a.is_a? Integer
33
+ when Integer
33
34
  a == e.id
34
- elsif a == :bot
35
+ when :bot
35
36
  e.current_bot?
36
37
  else
37
38
  a == e
38
39
  end
39
40
  end,
40
41
  matches_all(@attributes[:server], event.server) do |a, e|
41
- a == if a.is_a? String
42
+ a == case a
43
+ when String
42
44
  e.name
43
- elsif a.is_a? Integer
45
+ when Integer
44
46
  e.id
45
47
  else
46
48
  e
@@ -126,10 +126,12 @@ module Discordrb::Events
126
126
  class ChannelRecipientEvent < Event
127
127
  # @return [Channel] the channel in question.
128
128
  attr_reader :channel
129
+
129
130
  delegate :name, :server, :type, :owner_id, :recipients, :topic, :user_limit, :position, :permission_overwrites, to: :channel
130
131
 
131
132
  # @return [Recipient] the recipient that was added/removed from the group
132
133
  attr_reader :recipient
134
+
133
135
  delegate :id, to: :recipient
134
136
 
135
137
  def initialize(data, bot)
@@ -30,9 +30,10 @@ module Discordrb::Events
30
30
 
31
31
  [
32
32
  matches_all(@attributes[:server], event.server) do |a, e|
33
- a == if a.is_a? String
33
+ a == case a
34
+ when String
34
35
  e.name
35
- elsif a.is_a? Integer
36
+ when Integer
36
37
  e.id
37
38
  else
38
39
  e
@@ -56,12 +57,16 @@ module Discordrb::Events
56
57
  # Event handler for {ServerUpdateEvent}
57
58
  class ServerUpdateEventHandler < ServerEventHandler; end
58
59
 
59
- # Server is deleted
60
+ # Server is deleted, the server was left because the bot was kicked, or the
61
+ # bot made itself leave the server.
60
62
  # @see Discordrb::EventContainer#server_delete
61
63
  class ServerDeleteEvent < ServerEvent
64
+ # @return [Integer] The ID of the server that was left.
65
+ attr_reader :server
66
+
62
67
  # Override init_server to account for the deleted server
63
- def init_server(data, bot)
64
- @server = Discordrb::Server.new(data, bot, false)
68
+ def init_server(data, _bot)
69
+ @server = data['id'].to_i
65
70
  end
66
71
  end
67
72
 
@@ -141,9 +146,10 @@ module Discordrb::Events
141
146
 
142
147
  [
143
148
  matches_all(@attributes[:server], event.server) do |a, e|
144
- a == if a.is_a? String
149
+ a == case a
150
+ when String
145
151
  e.name
146
- elsif a.is_a? Integer
152
+ when Integer
147
153
  e.id
148
154
  else
149
155
  e
@@ -169,9 +175,10 @@ module Discordrb::Events
169
175
 
170
176
  [
171
177
  matches_all(@attributes[:server], event.server) do |a, e|
172
- a == if a.is_a? String
178
+ a == case a
179
+ when String
173
180
  e.name
174
- elsif a.is_a? Integer
181
+ when Integer
175
182
  e.id
176
183
  else
177
184
  e
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discordrb::Events
4
+ # Raised when an invite is created.
5
+ class InviteCreateEvent < Event
6
+ # @return [Invite] The invite that was created.
7
+ attr_reader :invite
8
+
9
+ # @return [Server, nil] The server the invite was created for.
10
+ attr_reader :server
11
+
12
+ # @return [Channel] The channel the invite was created for.
13
+ attr_reader :channel
14
+
15
+ # @!attribute [r] code
16
+ # @return [String] The code for the created invite.
17
+ # @see Invite#code
18
+ # @!attribute [r] created_at
19
+ # @return [Time] The time the invite was created at.
20
+ # @see Invite#created_at
21
+ # @!attribute [r] max_age
22
+ # @return [Integer] The maximum age of the created invite.
23
+ # @see Invite#max_age
24
+ # @!attribute [r] max_uses
25
+ # @return [Integer] The maximum number of uses before the invite expires.
26
+ # @see Invite#max_uses
27
+ # @!attribute [r] temporary
28
+ # @return [true, false] Whether or not this invite grants temporary membership.
29
+ # @see Invite#temporary
30
+ # @!attribute [r] inviter
31
+ # @return [User] The user that created the invite.
32
+ # @see Invite#inviter
33
+ delegate :code, :created_at, :max_age, :max_uses, :temporary, :inviter, to: :invite
34
+
35
+ alias temporary? temporary
36
+
37
+ def initialize(data, invite, bot)
38
+ @bot = bot
39
+ @invite = invite
40
+ @channel = bot.channel(data['channel_id'])
41
+ @server = bot.server(data['guild_id']) if data['guild_id']
42
+ end
43
+ end
44
+
45
+ # Raised when an invite is deleted.
46
+ class InviteDeleteEvent < Event
47
+ # @return [Channel] The channel the deleted invite was for.
48
+ attr_reader :channel
49
+
50
+ # @return [Server, nil] The server the deleted invite was for.
51
+ attr_reader :server
52
+
53
+ # @return [String] The code of the deleted invite.
54
+ attr_reader :code
55
+
56
+ def initialize(data, bot)
57
+ @bot = bot
58
+ @channel = bot.channel(data['channel_id'])
59
+ @server = bot.server(data['guild_id']) if data['guild_id']
60
+ @code = data['code']
61
+ end
62
+ end
63
+
64
+ # Event handler for InviteCreateEvent.
65
+ class InviteCreateEventHandler < EventHandler
66
+ def matches?(event)
67
+ return false unless event.is_a? InviteCreateEvent
68
+
69
+ [
70
+ matches_all(@attributes[:server], event.server) do |a, e|
71
+ a == case a
72
+ when String
73
+ e.name
74
+ when Integer
75
+ e.id
76
+ else
77
+ e
78
+ end
79
+ end,
80
+ matches_all(@attributes[:channel], event.channel) do |a, e|
81
+ a == case a
82
+ when String
83
+ e.name
84
+ when Integer
85
+ e.id
86
+ else
87
+ e
88
+ end
89
+ end,
90
+ matches_all(@attributes[:temporary], event.temporary?, &:==),
91
+ matches_all(@attributes[:inviter], event.inviter, &:==)
92
+ ].reduce(true, &:&)
93
+ end
94
+ end
95
+
96
+ # Event handler for InviteDeleteEvent
97
+ class InviteDeleteEventHandler < EventHandler
98
+ def matches?(event)
99
+ return false unless event.is_a? InviteDeleteEvent
100
+
101
+ [
102
+ matches_all(@attributes[:server], event.server) do |a, e|
103
+ a == case a
104
+ when String
105
+ e.name
106
+ when Integer
107
+ e.id
108
+ else
109
+ e
110
+ end
111
+ end,
112
+ matches_all(@attributes[:channel], event.channel) do |a, e|
113
+ a == case a
114
+ when String
115
+ e.name
116
+ when Integer
117
+ e.id
118
+ else
119
+ e
120
+ end
121
+ end
122
+ ].reduce(true, &:&)
123
+ end
124
+ end
125
+ end
@@ -34,8 +34,9 @@ module Discordrb::Events
34
34
  end
35
35
 
36
36
  def init_roles(data, _)
37
- @roles = []
37
+ @roles = [@server.role(@server.id)]
38
38
  return unless data['roles']
39
+
39
40
  data['roles'].each do |element|
40
41
  role_id = element.to_i
41
42
  @roles << @server.roles.find { |r| r.id == role_id }
@@ -78,10 +79,13 @@ module Discordrb::Events
78
79
  # Member leaves
79
80
  # @see Discordrb::EventContainer#member_leave
80
81
  class ServerMemberDeleteEvent < ServerMemberEvent
81
- # Overide init_user to account for the deleted user on the server
82
+ # Override init_user to account for the deleted user on the server
82
83
  def init_user(data, bot)
83
84
  @user = Discordrb::User.new(data['user'], bot)
84
85
  end
86
+
87
+ # @return [User] the user in question.
88
+ attr_reader :user
85
89
  end
86
90
 
87
91
  # Event handler for {ServerMemberDeleteEvent}
@@ -14,27 +14,38 @@ module Discordrb::Events
14
14
  # @param content [String] The message to send to the channel
15
15
  # @param tts [true, false] Whether or not this message should be sent using Discord text-to-speech.
16
16
  # @param embed [Hash, Discordrb::Webhooks::Embed, nil] The rich embed to append to this message.
17
+ # @param attachments [Array<File>] Files that can be referenced in embeds via `attachment://file.png`
18
+ # @param allowed_mentions [Hash, Discordrb::AllowedMentions, false, nil] Mentions that are allowed to ping on this message. `false` disables all pings
19
+ # @param message_reference [Message, String, Integer, nil] The message, or message ID, to reply to if any.
17
20
  # @return [Discordrb::Message] the message that was sent
18
- def send_message(content, tts = false, embed = nil)
19
- channel.send_message(content, tts, embed)
21
+ def send_message(content, tts = false, embed = nil, attachments = nil, allowed_mentions = nil, message_reference = nil)
22
+ channel.send_message(content, tts, embed, attachments, allowed_mentions, message_reference)
20
23
  end
21
24
 
22
25
  # The same as {#send_message}, but yields a {Webhooks::Embed} for easy building of embedded content inside a block.
23
26
  # @see Channel#send_embed
24
27
  # @param message [String] The message that should be sent along with the embed. If this is the empty string, only the embed will be shown.
25
28
  # @param embed [Discordrb::Webhooks::Embed, nil] The embed to start the building process with, or nil if one should be created anew.
29
+ # @param attachments [Array<File>] Files that can be referenced in embeds via `attachment://file.png`
30
+ # @param tts [true, false] Whether or not this message should be sent using Discord text-to-speech.
31
+ # @param allowed_mentions [Hash, Discordrb::AllowedMentions, false, nil] Mentions that are allowed to ping on this message. `false` disables all pings
32
+ # @param message_reference [Message, String, Integer, nil] The message, or message ID, to reply to if any.
26
33
  # @yield [embed] Yields the embed to allow for easy building inside a block.
27
34
  # @yieldparam embed [Discordrb::Webhooks::Embed] The embed from the parameters, or a new one.
28
35
  # @return [Message] The resulting message.
29
- def send_embed(message = '', embed = nil, &block)
30
- channel.send_embed(message, embed, &block)
36
+ def send_embed(message = '', embed = nil, attachments = nil, tts = false, allowed_mentions = nil, message_reference = nil, &block)
37
+ channel.send_embed(message, embed, attachments, tts, allowed_mentions, message_reference, &block)
31
38
  end
32
39
 
33
40
  # Sends a temporary message to the channel this message was sent in, right now.
34
41
  # @param content [String] The content to send. Should not be longer than 2000 characters or it will result in an error.
35
42
  # @param timeout [Float] The amount of time in seconds after which the message sent will be deleted.
36
- def send_temporary_message(content, timeout)
37
- channel.send_temporary_message(content, timeout)
43
+ # @param tts [true, false] Whether or not this message should be sent using Discord text-to-speech.
44
+ # @param embed [Hash, Discordrb::Webhooks::Embed, nil] The rich embed to append to this message.
45
+ # @param attachments [Array<File>] Files that can be referenced in embeds via `attachment://file.png`
46
+ # @param allowed_mentions [Hash, Discordrb::AllowedMentions, false, nil] Mentions that are allowed to ping on this message. `false` disables all pings
47
+ def send_temporary_message(content, timeout, tts = false, embed = nil, attachments = nil, allowed_mentions = nil)
48
+ channel.send_temporary_message(content, timeout, tts, embed, attachments, allowed_mentions)
38
49
  end
39
50
 
40
51
  # Adds a string to be sent after the event has finished execution. Avoids problems with rate limiting because only
@@ -82,9 +93,15 @@ module Discordrb::Events
82
93
  # @return [String] the message that has been saved by calls to {#<<} and will be sent to Discord upon completion.
83
94
  attr_reader :saved_message
84
95
 
85
- # @return [File] the file that have been saved by calls to {#attach_file} and will be sent to Discord upon completion.
96
+ # @return [File] the file that has been saved by a call to {#attach_file} and will be sent to Discord upon completion.
86
97
  attr_reader :file
87
98
 
99
+ # @return [String] the filename set in {#attach_file} that will override the original filename when sent.
100
+ attr_reader :filename
101
+
102
+ # @return [true, false] Whether or not this file should appear as a spoiler. Set by {#attach_file}
103
+ attr_reader :file_spoiler
104
+
88
105
  # @!attribute [r] author
89
106
  # @return [Member, User] who sent this message.
90
107
  # @see Message#author
@@ -110,6 +127,8 @@ module Discordrb::Events
110
127
  @channel = message.channel
111
128
  @saved_message = ''
112
129
  @file = nil
130
+ @filename = nil
131
+ @file_spoiler = nil
113
132
  end
114
133
 
115
134
  # Sends file with a caption to the channel this message was sent in, right now.
@@ -117,25 +136,34 @@ module Discordrb::Events
117
136
  # because it avoids rate limiting problems
118
137
  # @param file [File] The file to send to the channel
119
138
  # @param caption [String] The caption attached to the file
139
+ # @param filename [String] Overrides the filename of the uploaded file
140
+ # @param spoiler [true, false] Whether or not this file should appear as a spoiler.
120
141
  # @return [Discordrb::Message] the message that was sent
121
142
  # @example Send a file from disk
122
143
  # event.send_file(File.open('rubytaco.png', 'r'))
123
- def send_file(file, caption: nil)
124
- @message.channel.send_file(file, caption: caption)
144
+ def send_file(file, caption: nil, filename: nil, spoiler: nil)
145
+ @message.channel.send_file(file, caption: caption, filename: filename, spoiler: spoiler)
125
146
  end
126
147
 
127
148
  # Attaches a file to the message event and converts the message into
128
149
  # a caption.
129
150
  # @param file [File] The file to be attached
130
- def attach_file(file)
151
+ # @param filename [String] Overrides the filename of the uploaded file
152
+ # @param spoiler [true, false] Whether or not this file should appear as a spoiler.
153
+ def attach_file(file, filename: nil, spoiler: nil)
131
154
  raise ArgumentError, 'Argument is not a file!' unless file.is_a?(File)
155
+
132
156
  @file = file
157
+ @filename = filename
158
+ @file_spoiler = spoiler
133
159
  nil
134
160
  end
135
161
 
136
162
  # Detaches a file from the message event.
137
163
  def detach_file
138
164
  @file = nil
165
+ @filename = nil
166
+ @file_spoiler = nil
139
167
  end
140
168
 
141
169
  # @return [true, false] whether or not this message was sent by the bot itself
@@ -161,51 +189,57 @@ module Discordrb::Events
161
189
 
162
190
  [
163
191
  matches_all(@attributes[:starting_with] || @attributes[:start_with], event.content) do |a, e|
164
- if a.is_a? String
192
+ case a
193
+ when String
165
194
  e.start_with? a
166
- elsif a.is_a? Regexp
167
- (e =~ a) && (e =~ a).zero?
195
+ when Regexp
196
+ (e =~ a)&.zero?
168
197
  end
169
198
  end,
170
199
  matches_all(@attributes[:ending_with] || @attributes[:end_with], event.content) do |a, e|
171
- if a.is_a? String
200
+ case a
201
+ when String
172
202
  e.end_with? a
173
- elsif a.is_a? Regexp
203
+ when Regexp
174
204
  !(e =~ Regexp.new("#{a}$")).nil?
175
205
  end
176
206
  end,
177
207
  matches_all(@attributes[:containing] || @attributes[:contains], event.content) do |a, e|
178
- if a.is_a? String
208
+ case a
209
+ when String
179
210
  e.include? a
180
- elsif a.is_a? Regexp
211
+ when Regexp
181
212
  (e =~ a)
182
213
  end
183
214
  end,
184
215
  matches_all(@attributes[:in], event.channel) do |a, e|
185
- if a.is_a? String
216
+ case a
217
+ when String
186
218
  # Make sure to remove the "#" from channel names in case it was specified
187
219
  a.delete('#') == e.name
188
- elsif a.is_a? Integer
220
+ when Integer
189
221
  a == e.id
190
222
  else
191
223
  a == e
192
224
  end
193
225
  end,
194
226
  matches_all(@attributes[:from], event.author) do |a, e|
195
- if a.is_a? String
227
+ case a
228
+ when String
196
229
  a == e.name
197
- elsif a.is_a? Integer
230
+ when Integer
198
231
  a == e.id
199
- elsif a == :bot
232
+ when :bot
200
233
  e.current_bot?
201
234
  else
202
235
  a == e
203
236
  end
204
237
  end,
205
238
  matches_all(@attributes[:with_text] || @attributes[:content] || @attributes[:exact_text], event.content) do |a, e|
206
- if a.is_a? String
239
+ case a
240
+ when String
207
241
  e == a
208
- elsif a.is_a? Regexp
242
+ when Regexp
209
243
  match = a.match(e)
210
244
  match ? (e == match[0]) : false
211
245
  end
@@ -221,7 +255,7 @@ module Discordrb::Events
221
255
  if event.file.nil?
222
256
  event.send_message(event.saved_message) unless event.saved_message.empty?
223
257
  else
224
- event.send_file(event.file, caption: event.saved_message)
258
+ event.send_file(event.file, caption: event.saved_message, filename: event.filename, spoiler: event.file_spoiler)
225
259
  end
226
260
  end
227
261
  end
@@ -265,10 +299,11 @@ module Discordrb::Events
265
299
  a.resolve_id == e.resolve_id
266
300
  end,
267
301
  matches_all(@attributes[:in], event.channel) do |a, e|
268
- if a.is_a? String
302
+ case a
303
+ when String
269
304
  # Make sure to remove the "#" from channel names in case it was specified
270
305
  a.delete('#') == e.name
271
- elsif a.is_a? Integer
306
+ when Integer
272
307
  a == e.id
273
308
  else
274
309
  a == e
@@ -291,4 +326,11 @@ module Discordrb::Events
291
326
 
292
327
  # Event handler for {MessageDeleteEvent}
293
328
  class MessageDeleteEventHandler < MessageIDEventHandler; end
329
+
330
+ # Raised whenever a MESSAGE_UPDATE is received
331
+ # @see Discordrb::EventContainer#message_update
332
+ class MessageUpdateEvent < MessageEvent; end
333
+
334
+ # Event handler for {MessageUpdateEvent}
335
+ class MessageUpdateEventHandler < MessageEventHandler; end
294
336
  end