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
@@ -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)
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/core_ext/module'
4
-
5
3
  # Events used by discordrb
6
4
  module Discordrb::Events
7
5
  # A negated object, used to not match something in event parameters.
@@ -21,7 +19,7 @@ module Discordrb::Events
21
19
  # 2. A single attribute, negated
22
20
  # 3. An array of attributes, not negated
23
21
  # 4. An array of attributes, not negated
24
- # Note that it doesn't allow an array of negated attributes. For info on negation stuff, see {not!}
22
+ # Note that it doesn't allow an array of negated attributes. For info on negation stuff, see {::#not!}
25
23
  # @param attributes [Object, Array<Object>, Negated<Object>, Negated<Array<Object>>, nil] One or more attributes to
26
24
  # compare to the to_check value.
27
25
  # @param to_check [Object] What to compare the attributes to.
@@ -55,6 +53,24 @@ module Discordrb::Events
55
53
  class Event
56
54
  # @return [Bot] the bot used to initialize this event.
57
55
  attr_reader :bot
56
+
57
+ class << self
58
+ protected
59
+
60
+ # Delegates a list of methods to a particular object. This is essentially a reimplementation of ActiveSupport's
61
+ # `#delegate`, but without the overhead provided by the rest. Used in subclasses of `Event` to delegate properties
62
+ # on events to properties on data objects.
63
+ # @param methods [Array<Symbol>] The methods to delegate.
64
+ # @param hash [Hash<Symbol => Symbol>] A hash with one `:to` key and the value the method to be delegated to.
65
+ def delegate(*methods, hash)
66
+ methods.each do |e|
67
+ define_method(e) do
68
+ object = __send__(hash[:to])
69
+ object.__send__(e)
70
+ end
71
+ end
72
+ end
73
+ end
58
74
  end
59
75
 
60
76
  # Generic event handler that can be extended
@@ -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? Fixnum
36
+ when Integer
36
37
  e.id
37
38
  else
38
39
  e
@@ -56,15 +57,137 @@ 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
62
- # Overide init_server to account for the deleted server
63
- def init_server(data, bot)
64
- @server = Discordrb::Server.new(data, bot, false)
64
+ # @return [Integer] The ID of the server that was left.
65
+ attr_reader :server
66
+
67
+ # Override init_server to account for the deleted server
68
+ def init_server(data, _bot)
69
+ @server = data['id'].to_i
65
70
  end
66
71
  end
67
72
 
68
73
  # Event handler for {ServerDeleteEvent}
69
74
  class ServerDeleteEventHandler < ServerEventHandler; end
75
+
76
+ # Emoji is created/deleted/updated
77
+ class ServerEmojiChangeEvent < ServerEvent
78
+ # @return [Server] the server in question.
79
+ attr_reader :server
80
+
81
+ # @return [Array<Emoji>] array of emojis.
82
+ attr_reader :emoji
83
+
84
+ def initialize(server, data, bot)
85
+ @bot = bot
86
+ @server = server
87
+ process_emoji(data)
88
+ end
89
+
90
+ # @!visibility private
91
+ def process_emoji(data)
92
+ @emoji = data['emojis'].map do |e|
93
+ @server.emoji[e['id']]
94
+ end
95
+ end
96
+ end
97
+
98
+ # Generic event helper for when an emoji is either created or deleted
99
+ class ServerEmojiCDEvent < ServerEvent
100
+ # @return [Server] the server in question.
101
+ attr_reader :server
102
+
103
+ # @return [Emoji] the emoji data.
104
+ attr_reader :emoji
105
+
106
+ def initialize(server, emoji, bot)
107
+ @bot = bot
108
+ @emoji = emoji
109
+ @server = server
110
+ end
111
+ end
112
+
113
+ # Emoji is created
114
+ class ServerEmojiCreateEvent < ServerEmojiCDEvent; end
115
+
116
+ # Emoji is deleted
117
+ class ServerEmojiDeleteEvent < ServerEmojiCDEvent; end
118
+
119
+ # Emoji is updated
120
+ class ServerEmojiUpdateEvent < ServerEvent
121
+ # @return [Server] the server in question.
122
+ attr_reader :server
123
+
124
+ # @return [Emoji, nil] the emoji data before the event.
125
+ attr_reader :old_emoji
126
+
127
+ # @return [Emoji, nil] the updated emoji data.
128
+ attr_reader :emoji
129
+
130
+ def initialize(server, old_emoji, emoji, bot)
131
+ @bot = bot
132
+ @old_emoji = old_emoji
133
+ @emoji = emoji
134
+ @server = server
135
+ end
136
+ end
137
+
138
+ # Event handler for {ServerEmojiChangeEvent}
139
+ class ServerEmojiChangeEventHandler < ServerEventHandler; end
140
+
141
+ # Generic handler for emoji create and delete
142
+ class ServerEmojiCDEventHandler < ServerEventHandler
143
+ def matches?(event)
144
+ # Check for the proper event type
145
+ return false unless event.is_a? ServerEmojiCDEvent
146
+
147
+ [
148
+ matches_all(@attributes[:server], event.server) do |a, e|
149
+ a == case a
150
+ when String
151
+ e.name
152
+ when Integer
153
+ e.id
154
+ else
155
+ e
156
+ end
157
+ end,
158
+ matches_all(@attributes[:id], event.emoji.id) { |a, e| a.resolve_id == e.resolve_id },
159
+ matches_all(@attributes[:name], event.emoji.name) { |a, e| a == e }
160
+ ].reduce(true, &:&)
161
+ end
162
+ end
163
+
164
+ # Event handler for {ServerEmojiCreateEvent}
165
+ class ServerEmojiCreateEventHandler < ServerEmojiCDEventHandler; end
166
+
167
+ # Event handler for {ServerEmojiDeleteEvent}
168
+ class ServerEmojiDeleteEventHandler < ServerEmojiCDEventHandler; end
169
+
170
+ # Event handler for {ServerEmojiUpdateEvent}
171
+ class ServerEmojiUpdateEventHandler < EventHandler
172
+ def matches?(event)
173
+ # Check for the proper event type
174
+ return false unless event.is_a? ServerEmojiUpdateEvent
175
+
176
+ [
177
+ matches_all(@attributes[:server], event.server) do |a, e|
178
+ a == case a
179
+ when String
180
+ e.name
181
+ when Integer
182
+ e.id
183
+ else
184
+ e
185
+ end
186
+ end,
187
+ matches_all(@attributes[:id], event.old_emoji.id) { |a, e| a.resolve_id == e.resolve_id },
188
+ matches_all(@attributes[:old_name], event.old_emoji.name) { |a, e| a == e },
189
+ matches_all(@attributes[:name], event.emoji.name) { |a, e| a == e }
190
+ ].reduce(true, &:&)
191
+ end
192
+ end
70
193
  end
@@ -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}
@@ -12,16 +12,40 @@ module Discordrb::Events
12
12
  # Sends a message to the channel this message was sent in, right now. It is usually preferable to use {#<<} instead
13
13
  # because it avoids rate limiting problems
14
14
  # @param content [String] The message to send to the channel
15
+ # @param tts [true, false] Whether or not this message should be sent using Discord text-to-speech.
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.
15
20
  # @return [Discordrb::Message] the message that was sent
16
- def send_message(content)
17
- @channel.send_message(content)
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)
23
+ end
24
+
25
+ # The same as {#send_message}, but yields a {Webhooks::Embed} for easy building of embedded content inside a block.
26
+ # @see Channel#send_embed
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.
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.
33
+ # @yield [embed] Yields the embed to allow for easy building inside a block.
34
+ # @yieldparam embed [Discordrb::Webhooks::Embed] The embed from the parameters, or a new one.
35
+ # @return [Message] The resulting message.
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)
18
38
  end
19
39
 
20
40
  # Sends a temporary message to the channel this message was sent in, right now.
21
41
  # @param content [String] The content to send. Should not be longer than 2000 characters or it will result in an error.
22
42
  # @param timeout [Float] The amount of time in seconds after which the message sent will be deleted.
23
- def send_temporary_message(content, timeout)
24
- @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)
25
49
  end
26
50
 
27
51
  # Adds a string to be sent after the event has finished execution. Avoids problems with rate limiting because only
@@ -62,17 +86,24 @@ module Discordrb::Events
62
86
  # Event raised when a text message is sent to a channel
63
87
  class MessageEvent < Event
64
88
  include Respondable
89
+
65
90
  # @return [Message] the message which triggered this event.
66
91
  attr_reader :message
67
92
 
68
93
  # @return [String] the message that has been saved by calls to {#<<} and will be sent to Discord upon completion.
69
94
  attr_reader :saved_message
70
95
 
71
- # @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.
72
97
  attr_reader :file
73
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
+
74
105
  # @!attribute [r] author
75
- # @return [Member] who sent this message.
106
+ # @return [Member, User] who sent this message.
76
107
  # @see Message#author
77
108
  # @!attribute [r] channel
78
109
  # @return [Channel] the channel in which this message was sent.
@@ -96,14 +127,8 @@ module Discordrb::Events
96
127
  @channel = message.channel
97
128
  @saved_message = ''
98
129
  @file = nil
99
- end
100
-
101
- # Sends a message to the channel this message was sent in, right now. It is usually preferable to use {#<<} instead
102
- # because it avoids rate limiting problems
103
- # @param content [String] The message to send to the channel
104
- # @return [Discordrb::Message] the message that was sent
105
- def send_message(content)
106
- @message.channel.send_message(content)
130
+ @filename = nil
131
+ @file_spoiler = nil
107
132
  end
108
133
 
109
134
  # Sends file with a caption to the channel this message was sent in, right now.
@@ -111,24 +136,34 @@ module Discordrb::Events
111
136
  # because it avoids rate limiting problems
112
137
  # @param file [File] The file to send to the channel
113
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.
114
141
  # @return [Discordrb::Message] the message that was sent
115
- def send_file(file, caption: nil)
116
- @message.channel.send_file(file, caption: caption)
142
+ # @example Send a file from disk
143
+ # event.send_file(File.open('rubytaco.png', 'r'))
144
+ def send_file(file, caption: nil, filename: nil, spoiler: nil)
145
+ @message.channel.send_file(file, caption: caption, filename: filename, spoiler: spoiler)
117
146
  end
118
147
 
119
148
  # Attaches a file to the message event and converts the message into
120
149
  # a caption.
121
150
  # @param file [File] The file to be attached
122
- 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)
123
154
  raise ArgumentError, 'Argument is not a file!' unless file.is_a?(File)
155
+
124
156
  @file = file
157
+ @filename = filename
158
+ @file_spoiler = spoiler
125
159
  nil
126
160
  end
127
161
 
128
162
  # Detaches a file from the message event.
129
163
  def detach_file
130
164
  @file = nil
131
- nil
165
+ @filename = nil
166
+ @file_spoiler = nil
132
167
  end
133
168
 
134
169
  # @return [true, false] whether or not this message was sent by the bot itself
@@ -154,51 +189,57 @@ module Discordrb::Events
154
189
 
155
190
  [
156
191
  matches_all(@attributes[:starting_with] || @attributes[:start_with], event.content) do |a, e|
157
- if a.is_a? String
192
+ case a
193
+ when String
158
194
  e.start_with? a
159
- elsif a.is_a? Regexp
160
- (e =~ a) && (e =~ a).zero?
195
+ when Regexp
196
+ (e =~ a)&.zero?
161
197
  end
162
198
  end,
163
199
  matches_all(@attributes[:ending_with] || @attributes[:end_with], event.content) do |a, e|
164
- if a.is_a? String
200
+ case a
201
+ when String
165
202
  e.end_with? a
166
- elsif a.is_a? Regexp
167
- a.match(e) ? e.end_with?(a.match(e)[-1]) : false
203
+ when Regexp
204
+ !(e =~ Regexp.new("#{a}$")).nil?
168
205
  end
169
206
  end,
170
207
  matches_all(@attributes[:containing] || @attributes[:contains], event.content) do |a, e|
171
- if a.is_a? String
208
+ case a
209
+ when String
172
210
  e.include? a
173
- elsif a.is_a? Regexp
211
+ when Regexp
174
212
  (e =~ a)
175
213
  end
176
214
  end,
177
215
  matches_all(@attributes[:in], event.channel) do |a, e|
178
- if a.is_a? String
216
+ case a
217
+ when String
179
218
  # Make sure to remove the "#" from channel names in case it was specified
180
219
  a.delete('#') == e.name
181
- elsif a.is_a? Fixnum
220
+ when Integer
182
221
  a == e.id
183
222
  else
184
223
  a == e
185
224
  end
186
225
  end,
187
226
  matches_all(@attributes[:from], event.author) do |a, e|
188
- if a.is_a? String
227
+ case a
228
+ when String
189
229
  a == e.name
190
- elsif a.is_a? Fixnum
230
+ when Integer
191
231
  a == e.id
192
- elsif a == :bot
232
+ when :bot
193
233
  e.current_bot?
194
234
  else
195
235
  a == e
196
236
  end
197
237
  end,
198
238
  matches_all(@attributes[:with_text] || @attributes[:content] || @attributes[:exact_text], event.content) do |a, e|
199
- if a.is_a? String
239
+ case a
240
+ when String
200
241
  e == a
201
- elsif a.is_a? Regexp
242
+ when Regexp
202
243
  match = a.match(e)
203
244
  match ? (e == match[0]) : false
204
245
  end
@@ -214,7 +255,7 @@ module Discordrb::Events
214
255
  if event.file.nil?
215
256
  event.send_message(event.saved_message) unless event.saved_message.empty?
216
257
  else
217
- 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)
218
259
  end
219
260
  end
220
261
  end
@@ -234,6 +275,7 @@ module Discordrb::Events
234
275
  # A subset of MessageEvent that only contains a message ID and a channel
235
276
  class MessageIDEvent < Event
236
277
  include Respondable
278
+
237
279
  # @return [Integer] the ID associated with this event
238
280
  attr_reader :id
239
281
 
@@ -257,10 +299,11 @@ module Discordrb::Events
257
299
  a.resolve_id == e.resolve_id
258
300
  end,
259
301
  matches_all(@attributes[:in], event.channel) do |a, e|
260
- if a.is_a? String
302
+ case a
303
+ when String
261
304
  # Make sure to remove the "#" from channel names in case it was specified
262
305
  a.delete('#') == e.name
263
- elsif a.is_a? Integer
306
+ when Integer
264
307
  a == e.id
265
308
  else
266
309
  a == e
@@ -283,4 +326,11 @@ module Discordrb::Events
283
326
 
284
327
  # Event handler for {MessageDeleteEvent}
285
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
286
336
  end