discordrb 2.1.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of discordrb might be problematic. Click here for more details.

@@ -19,5 +19,150 @@ module Discordrb
19
19
 
20
20
  # Raised when the bot gets a HTTP 502 error, which is usually caused by Cloudflare.
21
21
  class CloudflareError < RuntimeError; end
22
+
23
+ # Generic class for errors denoted by API error codes
24
+ class CodeError < RuntimeError
25
+ class << self
26
+ # @return [Integer] The error code represented by this error class.
27
+ attr_reader :code
28
+ end
29
+
30
+ # Create a new error with a particular message (the code should be defined by the class instance variable)
31
+ # @param message [String] the message to use
32
+ def initialize(message)
33
+ @message = message
34
+ end
35
+
36
+ # @return [Integer] The error code represented by this error.
37
+ def code
38
+ self.class.code
39
+ end
40
+
41
+ # @return [String] This error's represented message
42
+ attr_reader :message
43
+ end
44
+
45
+ # Create a new code error class
46
+ # rubocop:disable Style/MethodName
47
+ def self.Code(code)
48
+ classy = Class.new(CodeError)
49
+ classy.instance_variable_set('@code', code)
50
+
51
+ @code_classes ||= {}
52
+ @code_classes[code] = classy
53
+
54
+ classy
55
+ end
56
+
57
+ # @param code [Integer] The code to check
58
+ # @return [Class] the error class for the given code
59
+ def self.error_class_for(code)
60
+ @code_classes[code]
61
+ end
62
+
63
+ # Used when Discord doesn't provide a more specific code
64
+ UnknownError = Code(0)
65
+
66
+ # Unknown Account
67
+ UnknownAccount = Code(10_001)
68
+
69
+ # Unknown Application
70
+ UnknownApplication = Code(10_002)
71
+
72
+ # Unknown Channel
73
+ UnknownChannel = Code(10_003)
74
+
75
+ # Unknown Server
76
+ UnknownServer = Code(10_004)
77
+
78
+ # Unknown Integration
79
+ UnknownIntegration = Code(10_005)
80
+
81
+ # Unknown Invite
82
+ UnknownInvite = Code(10_006)
83
+
84
+ # Unknown Member
85
+ UnknownMember = Code(10_007)
86
+
87
+ # Unknown Message
88
+ UnknownMessage = Code(10_008)
89
+
90
+ # Unknown Overwrite
91
+ UnknownOverwrite = Code(10_009)
92
+
93
+ # Unknown Provider
94
+ UnknownProvider = Code(10_010)
95
+
96
+ # Unknown Role
97
+ UnknownRole = Code(10_011)
98
+
99
+ # Unknown Token
100
+ UnknownToken = Code(10_012)
101
+
102
+ # Unknown User
103
+ UnknownUser = Code(10_013)
104
+
105
+ # Bots cannot use this endpoint
106
+ EndpointNotForBots = Code(20_001)
107
+
108
+ # Only bots can use this endpoint
109
+ EndpointOnlyForBots = Code(20_002)
110
+
111
+ # Maximum number of servers reached (100)
112
+ ServerLimitReached = Code(30_001)
113
+
114
+ # Maximum number of friends reached (1000)
115
+ FriendLimitReached = Code(30_002)
116
+
117
+ # Unauthorized
118
+ Unauthorized = Unauthorised = Code(40_001)
119
+
120
+ # Missing Access
121
+ MissingAccess = Code(50_001)
122
+
123
+ # Invalid Account Type
124
+ InvalidAccountType = Code(50_002)
125
+
126
+ # Cannot execute action on a DM channel
127
+ InvalidForDM = Code(50_003)
128
+
129
+ # Embed Disabled
130
+ EmbedDisabled = Code(50_004)
131
+
132
+ # Cannot edit a message authored by another user
133
+ MessageAuthoredByOtherUser = Code(50_005)
134
+
135
+ # Cannot send an empty message
136
+ MessageEmpty = Code(50_006)
137
+
138
+ # Cannot send messages to this user
139
+ NoMessagesToUser = Code(50_007)
140
+
141
+ # Cannot send messages in a voice channel
142
+ NoMessagesInVoiceChannel = Code(50_008)
143
+
144
+ # Channel verification level is too high
145
+ VerificationLevelTooHigh = Code(50_009)
146
+
147
+ # OAuth2 application does not have a bot
148
+ NoBotForApplication = Code(50_010)
149
+
150
+ # OAuth2 application limit reached
151
+ ApplicationLimitReached = Code(50_011)
152
+
153
+ # Invalid OAuth State
154
+ InvalidOAuthState = Code(50_012)
155
+
156
+ # Missing Permissions
157
+ MissingPermissions = Code(50_013)
158
+
159
+ # Invalid authentication token
160
+ InvalidAuthToken = Code(50_014)
161
+
162
+ # Note is too long
163
+ NoteTooLong = Code(50_015)
164
+
165
+ # Provided too few or too many messages to delete. Must provide at least 2 and fewer than 100 messages to delete.
166
+ InvalidBulkDeleteCount = Code(50_016)
22
167
  end
23
168
  end
@@ -10,7 +10,7 @@ module Discordrb::Events
10
10
  attr_reader :channel
11
11
 
12
12
  # @!attribute [r] type
13
- # @return [String] the channel's type.
13
+ # @return [Integer] the channel's type (0: text, 1: private, 2: voice, 3: group).
14
14
  # @see Channel#type
15
15
  # @!attribute [r] topic
16
16
  # @return [String] the channel's topic.
@@ -27,7 +27,7 @@ module Discordrb::Events
27
27
  # @!attribute [r] server
28
28
  # @return [Server] the server the channel belongs to.
29
29
  # @see Channel#server
30
- delegate :type, :topic, :position, :name, :id, :server, to: :channel
30
+ delegate :name, :server, :type, :owner_id, :recipients, :topic, :user_limit, :position, :permission_overwrites, to: :channel
31
31
 
32
32
  def initialize(data, bot)
33
33
  @bot = bot
@@ -62,7 +62,7 @@ module Discordrb::Events
62
62
 
63
63
  # Raised when a channel is deleted
64
64
  class ChannelDeleteEvent < Event
65
- # @return [String] the channel's type (text or voice)
65
+ # @return [Integer] the channel's type (0: text, 1: private, 2: voice, 3: group).
66
66
  attr_reader :type
67
67
 
68
68
  # @return [String] the channel's topic
@@ -80,6 +80,9 @@ module Discordrb::Events
80
80
  # @return [Server] the channel's server
81
81
  attr_reader :server
82
82
 
83
+ # @return [Integer, nil] the channel's owner ID if this is a group channel
84
+ attr_reader :owner_id
85
+
83
86
  def initialize(data, bot)
84
87
  @bot = bot
85
88
 
@@ -90,6 +93,7 @@ module Discordrb::Events
90
93
  @is_private = data['is_private']
91
94
  @id = data['id'].to_i
92
95
  @server = bot.server(data['guild_id'].to_i) if data['guild_id']
96
+ @owner_id = bot.user(data['owner_id']) if @type == 3
93
97
  end
94
98
  end
95
99
 
@@ -118,6 +122,62 @@ module Discordrb::Events
118
122
  end
119
123
  end
120
124
 
125
+ # Generic subclass for recipient events (add/remove)
126
+ class ChannelRecipientEvent < Event
127
+ # @return [Channel] the channel in question.
128
+ attr_reader :channel
129
+ delegate :name, :server, :type, :owner_id, :recipients, :topic, :user_limit, :position, :permission_overwrites, to: :channel
130
+
131
+ # @return [Recipient] the recipient that was added/removed from the group
132
+ attr_reader :recipient
133
+ delegate :id, to: :recipient
134
+
135
+ def initialize(data, bot)
136
+ @bot = bot
137
+
138
+ @channel = bot.channel(data['channel_id'].to_i)
139
+ recipient = data['user']
140
+ recipient_user = bot.ensure_user(recipient)
141
+ @recipient = Discordrb::Recipient.new(recipient_user, @channel, bot)
142
+ end
143
+ end
144
+
145
+ # Generic event handler for channel recipient events
146
+ class ChannelRecipientEventHandler < EventHandler
147
+ def matches?(event)
148
+ # Check for the proper event type
149
+ return false unless event.is_a? ChannelRecipientEvent
150
+
151
+ [
152
+ matches_all(@attributes[:owner_id], event.owner_id) do |a, e|
153
+ a.resolve_id == e.resolve_id
154
+ end,
155
+ matches_all(@attributes[:id], event.id) do |a, e|
156
+ a.resolve_id == e.resolve_id
157
+ end,
158
+ matches_all(@attributes[:name], event.name) do |a, e|
159
+ a == if a.is_a? String
160
+ e.to_s
161
+ else
162
+ e
163
+ end
164
+ end
165
+ ]
166
+ end
167
+ end
168
+
169
+ # Raised when a user is added to a private channel
170
+ class ChannelRecipientAddEvent < ChannelRecipientEvent; end
171
+
172
+ # Event handler for ChannelRecipientAddEvent
173
+ class ChannelRecipientAddEventHandler < ChannelRecipientEventHandler; end
174
+
175
+ # Raised when a recipient that isn't the bot leaves or is kicked from a group channel
176
+ class ChannelRecipientRemoveEvent < ChannelRecipientEvent; end
177
+
178
+ # Event handler for ChannelRecipientRemoveEvent
179
+ class ChannelRecipientRemoveEventHandler < ChannelRecipientEventHandler; end
180
+
121
181
  # Raised when a channel is updated (e.g. topic changes)
122
182
  class ChannelUpdateEvent < ChannelCreateEvent; end
123
183
 
@@ -8,6 +8,7 @@ module Discordrb::Events
8
8
  class ServerMemberEvent < Event
9
9
  # @return [Member] the member in question.
10
10
  attr_reader :user
11
+ alias_method :member, :user
11
12
 
12
13
  # @return [Array<Role>] the member's roles.
13
14
  attr_reader :roles
@@ -15,8 +16,6 @@ module Discordrb::Events
15
16
  # @return [Server] the server on which the event happened.
16
17
  attr_reader :server
17
18
 
18
- alias_method :member, :user
19
-
20
19
  def initialize(data, bot)
21
20
  @bot = bot
22
21
 
@@ -1,18 +1,78 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'discordrb/events/generic'
4
+ require 'discordrb/data'
4
5
 
5
6
  module Discordrb::Events
7
+ # Module to make sending messages easier with the presence of a text channel in an event
8
+ module Respondable
9
+ # @return [Channel] the channel in which this event occured
10
+ attr_reader :channel
11
+
12
+ # Sends a message to the channel this message was sent in, right now. It is usually preferable to use {#<<} instead
13
+ # because it avoids rate limiting problems
14
+ # @param content [String] The message to send to the channel
15
+ # @return [Discordrb::Message] the message that was sent
16
+ def send_message(content)
17
+ @channel.send_message(content)
18
+ end
19
+
20
+ # Sends a temporary message to the channel this message was sent in, right now.
21
+ # @param content [String] The content to send. Should not be longer than 2000 characters or it will result in an error.
22
+ # @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)
25
+ end
26
+
27
+ # Adds a string to be sent after the event has finished execution. Avoids problems with rate limiting because only
28
+ # one message is ever sent. If it is used multiple times, the strings will bunch up into one message (separated by
29
+ # newlines)
30
+ # @param message [String] The message to send to the channel
31
+ def <<(message)
32
+ addition = "#{message}\n"
33
+ @saved_message = @saved_message ? @saved_message + addition : addition
34
+ nil
35
+ end
36
+
37
+ # Drains the currently saved message, which clears it out, resulting in everything being saved before being
38
+ # thrown away and nothing being sent to the channel (unless there is something saved after this).
39
+ # @see #<<
40
+ def drain
41
+ @saved_message = ''
42
+ nil
43
+ end
44
+
45
+ # Drains the currently saved message into a result string. This prepends it before that string, clears the saved
46
+ # message and returns the concatenation.
47
+ # @param result [String] The result string to drain into.
48
+ # @return [String] a string formed by concatenating the saved message and the argument.
49
+ def drain_into(result)
50
+ return if result.is_a?(Discordrb::Message)
51
+
52
+ result = (@saved_message.nil? ? '' : @saved_message.to_s) + (result.nil? ? '' : result.to_s)
53
+ drain
54
+ result
55
+ end
56
+
57
+ alias_method :send, :send_message
58
+ alias_method :respond, :send_message
59
+ alias_method :send_temp, :send_temporary_message
60
+ end
61
+
6
62
  # Event raised when a text message is sent to a channel
7
63
  class MessageEvent < Event
64
+ include Respondable
8
65
  # @return [Message] the message which triggered this event.
9
66
  attr_reader :message
10
67
 
11
68
  # @return [String] the message that has been saved by calls to {#<<} and will be sent to Discord upon completion.
12
69
  attr_reader :saved_message
13
70
 
71
+ # @return [File] the file that have been saved by calls to {#attach_file} and will be sent to Discord upon completion.
72
+ attr_reader :file
73
+
14
74
  # @!attribute [r] author
15
- # @return [User] who sent this message.
75
+ # @return [Member] who sent this message.
16
76
  # @see Message#author
17
77
  # @!attribute [r] channel
18
78
  # @return [Channel] the channel in which this message was sent.
@@ -33,7 +93,9 @@ module Discordrb::Events
33
93
  def initialize(message, bot)
34
94
  @bot = bot
35
95
  @message = message
96
+ @channel = message.channel
36
97
  @saved_message = ''
98
+ @file = nil
37
99
  end
38
100
 
39
101
  # Sends a message to the channel this message was sent in, right now. It is usually preferable to use {#<<} instead
@@ -44,6 +106,31 @@ module Discordrb::Events
44
106
  @message.channel.send_message(content)
45
107
  end
46
108
 
109
+ # Sends file with a caption to the channel this message was sent in, right now.
110
+ # It is usually preferable to use {#<<} and {#attach_file} instead
111
+ # because it avoids rate limiting problems
112
+ # @param file [File] The file to send to the channel
113
+ # @param caption [String] The caption attached to the file
114
+ # @return [Discordrb::Message] the message that was sent
115
+ def send_file(file, caption: nil)
116
+ @message.channel.send_file(file, caption: caption)
117
+ end
118
+
119
+ # Attaches a file to the message event and converts the message into
120
+ # a caption.
121
+ # @param file [File] The file to be attached
122
+ def attach_file(file)
123
+ raise ArgumentError, 'Argument is not a file!' unless file.is_a?(File)
124
+ @file = file
125
+ nil
126
+ end
127
+
128
+ # Detaches a file from the message event.
129
+ def detach_file
130
+ @file = nil
131
+ nil
132
+ end
133
+
47
134
  # @return [true, false] whether or not this message was sent by the bot itself
48
135
  def from_bot?
49
136
  @message.user.id == @bot.profile.id
@@ -55,19 +142,8 @@ module Discordrb::Events
55
142
  @bot.voice(@message.channel.server.id)
56
143
  end
57
144
 
58
- # Adds a string to be sent after the event has finished execution. Avoids problems with rate limiting because only
59
- # one message is ever sent. If it is used multiple times, the strings will bunch up into one message (separated by
60
- # newlines)
61
- # @param message [String] The message to send to the channel
62
- def <<(message)
63
- @saved_message += "#{message}\n"
64
- nil
65
- end
66
-
67
145
  alias_method :user, :author
68
146
  alias_method :text, :content
69
- alias_method :send, :send_message
70
- alias_method :respond, :send_message
71
147
  end
72
148
 
73
149
  # Event handler for MessageEvent
@@ -81,7 +157,7 @@ module Discordrb::Events
81
157
  if a.is_a? String
82
158
  e.start_with? a
83
159
  elsif a.is_a? Regexp
84
- (e =~ a) == 0
160
+ (e =~ a) && (e =~ a).zero?
85
161
  end
86
162
  end,
87
163
  matches_all(@attributes[:ending_with] || @attributes[:end_with], event.content) do |a, e|
@@ -135,7 +211,11 @@ module Discordrb::Events
135
211
 
136
212
  # @see EventHandler#after_call
137
213
  def after_call(event)
138
- event.send_message(event.saved_message) unless event.saved_message.empty?
214
+ if event.file.nil?
215
+ event.send_message(event.saved_message) unless event.saved_message.empty?
216
+ else
217
+ event.send_file(event.file, caption: event.saved_message)
218
+ end
139
219
  end
140
220
  end
141
221
 
@@ -153,16 +233,15 @@ module Discordrb::Events
153
233
 
154
234
  # A subset of MessageEvent that only contains a message ID and a channel
155
235
  class MessageIDEvent < Event
236
+ include Respondable
156
237
  # @return [Integer] the ID associated with this event
157
238
  attr_reader :id
158
239
 
159
- # @return [Channel] the channel in which this event occurred
160
- attr_reader :channel
161
-
162
240
  # @!visibility private
163
241
  def initialize(data, bot)
164
242
  @id = data['id'].to_i
165
243
  @channel = bot.channel(data['channel_id'].to_i)
244
+ @saved_message = ''
166
245
  @bot = bot
167
246
  end
168
247
  end