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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +76 -0
- data/README.md +4 -2
- data/discordrb.gemspec +1 -1
- data/examples/commands.rb +2 -0
- data/examples/data/music.dca +0 -0
- data/examples/data/music.mp3 +0 -0
- data/examples/eval.rb +6 -3
- data/examples/ping.rb +14 -1
- data/examples/ping_with_respond_time.rb +6 -4
- data/examples/pm_send.rb +3 -0
- data/examples/shutdown.rb +7 -2
- data/examples/voice_send.rb +51 -0
- data/lib/discordrb/api.rb +66 -460
- data/lib/discordrb/api/channel.rb +306 -0
- data/lib/discordrb/api/invite.rb +41 -0
- data/lib/discordrb/api/server.rb +357 -0
- data/lib/discordrb/api/user.rb +134 -0
- data/lib/discordrb/bot.rb +266 -576
- data/lib/discordrb/cache.rb +27 -28
- data/lib/discordrb/commands/command_bot.rb +44 -15
- data/lib/discordrb/commands/container.rb +3 -2
- data/lib/discordrb/commands/parser.rb +14 -6
- data/lib/discordrb/container.rb +30 -3
- data/lib/discordrb/data.rb +823 -189
- data/lib/discordrb/errors.rb +145 -0
- data/lib/discordrb/events/channels.rb +63 -3
- data/lib/discordrb/events/members.rb +1 -2
- data/lib/discordrb/events/message.rb +96 -17
- data/lib/discordrb/events/presence.rb +15 -0
- data/lib/discordrb/events/typing.rb +7 -1
- data/lib/discordrb/gateway.rb +724 -0
- data/lib/discordrb/light/light_bot.rb +6 -4
- data/lib/discordrb/logger.rb +26 -9
- data/lib/discordrb/permissions.rb +6 -3
- data/lib/discordrb/version.rb +1 -1
- data/lib/discordrb/voice/voice_bot.rb +29 -6
- metadata +12 -5
- data/lib/discordrb/token_cache.rb +0 -181
data/lib/discordrb/errors.rb
CHANGED
@@ -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 [
|
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, :
|
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 [
|
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 [
|
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)
|
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
|
-
|
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
|