discordrb 1.4.0 → 1.4.1
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/.yardopts +1 -0
- data/discordrb.gemspec +2 -0
- data/lib/discordrb/api.rb +1 -0
- data/lib/discordrb/await.rb +27 -2
- data/lib/discordrb/bot.rb +141 -2
- data/lib/discordrb/commands/command_bot.rb +3 -2
- data/lib/discordrb/events/await.rb +10 -3
- data/lib/discordrb/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad6998ddf964b9fbb9898312e7d41d503a207bff
|
4
|
+
data.tar.gz: c2bfb298aacd612fee0800f8f1ff434fc0cfe90c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cfcf66d6d21815e39b66b9dfdc1508abfd2f22e11e0d435073aa9d7de45dec0dcef62fb6a50f1921d28ddadd3e8e5c4972364e70a65813bb2284859f305b685d
|
7
|
+
data.tar.gz: f43645f7d126eda651ee82027eb829b7b66e6661b4fe81a6283d81b7935bcb7305e66a7d7614c03af4355a5b6e6b05f71396aae1c720f949a1c36fd20a2c4311
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown
|
data/discordrb.gemspec
CHANGED
@@ -23,6 +23,8 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_dependency 'rest-client'
|
24
24
|
spec.add_dependency 'activesupport'
|
25
25
|
|
26
|
+
spec.required_ruby_version = '>= 2.1.0'
|
27
|
+
|
26
28
|
spec.add_development_dependency 'bundler', '~> 1.10'
|
27
29
|
spec.add_development_dependency 'rake', '~> 10.0'
|
28
30
|
end
|
data/lib/discordrb/api.rb
CHANGED
data/lib/discordrb/await.rb
CHANGED
@@ -1,8 +1,29 @@
|
|
1
1
|
module Discordrb
|
2
|
-
#
|
2
|
+
# Awaits are a way to register new, temporary event handlers on the fly. Awaits can be
|
3
|
+
# registered using {Bot#add_await}, {User#await}, {Message#await} and {Channel#await}.
|
4
|
+
#
|
5
|
+
# Awaits contain a block that will be called before the await event will be triggered.
|
6
|
+
# If this block returns anything that is not `false` exactly, the await will be deleted.
|
7
|
+
# If no block is present, the await will also be deleted. This is an easy way to make
|
8
|
+
# temporary events that are only temporary under certain conditions.
|
9
|
+
#
|
10
|
+
# Besides the given block, an {AwaitEvent} will also be executed with the key and
|
11
|
+
# the type of the await that was triggered. It's possible to register multiple events
|
12
|
+
# that trigger on the same await.
|
3
13
|
class Await
|
4
|
-
|
14
|
+
# The key that uniquely identifies this await.
|
15
|
+
# @return [Symbol] The unique key.
|
16
|
+
attr_reader :key
|
5
17
|
|
18
|
+
# The class of the event that this await listens for.
|
19
|
+
# @return [Class] The event class.
|
20
|
+
attr_reader :type
|
21
|
+
|
22
|
+
# The attributes of the event that will be listened for.
|
23
|
+
# @return [Hash] A hash of attributes.
|
24
|
+
attr_reader :attributes
|
25
|
+
|
26
|
+
# Makes a new await. For internal use only.
|
6
27
|
def initialize(bot, key, type, attributes, block = nil)
|
7
28
|
@bot = bot
|
8
29
|
@key = key
|
@@ -11,6 +32,10 @@ module Discordrb
|
|
11
32
|
@block = block
|
12
33
|
end
|
13
34
|
|
35
|
+
# Checks whether the await can be triggered by the given event, and if it can, execute the block
|
36
|
+
# and return its result along with this await's key.
|
37
|
+
# @param event [Event] An event to check for.
|
38
|
+
# @return [Array] This await's key and whether or not it should be deleted. If there was no match, both are nil.
|
14
39
|
def match(event)
|
15
40
|
dummy_handler = @bot.handler_class(@type).new(@attributes, @bot)
|
16
41
|
return [nil, nil] unless dummy_handler.matches?(event)
|
data/lib/discordrb/bot.rb
CHANGED
@@ -28,9 +28,43 @@ module Discordrb
|
|
28
28
|
class Bot
|
29
29
|
include Discordrb::Events
|
30
30
|
|
31
|
-
|
31
|
+
# The user that represents the bot itself. This version will always be identical to
|
32
|
+
# the user determined by {#user} called with the bot's ID.
|
33
|
+
# @return [User] The bot user.
|
34
|
+
attr_reader :bot_user
|
35
|
+
|
36
|
+
# The Discord API token received when logging in. Useful to explicitly call
|
37
|
+
# {API} methods.
|
38
|
+
# @return [String] The API token.
|
39
|
+
attr_reader :token
|
40
|
+
|
41
|
+
# The list of users the bot shares a server with.
|
42
|
+
# @return [Array<User>] The users.
|
43
|
+
attr_reader :users
|
44
|
+
|
45
|
+
# The list of servers the bot is currently in.
|
46
|
+
# @return [Array<Server>] The servers.
|
47
|
+
attr_reader :servers
|
48
|
+
|
49
|
+
# The list of currently running threads used to parse and call events.
|
50
|
+
# The threads will have a local variable `:discordrb_name` in the format of `et-1234`, where
|
51
|
+
# "et" stands for "event thread" and the number is a continually incrementing number representing
|
52
|
+
# how many events were executed before.
|
53
|
+
# @return [Array<Thread>] The threads.
|
54
|
+
attr_reader :event_threads
|
55
|
+
|
56
|
+
# The bot's user profile. This special user object can be used
|
57
|
+
# to edit user data like the current username (see {Profile#username=}).
|
58
|
+
# @return [Profile] The bot's profile that can be used to edit data.
|
59
|
+
attr_reader :profile
|
60
|
+
|
61
|
+
# Whether or not the bot should parse its own messages. Off by default.
|
32
62
|
attr_accessor :should_parse_self
|
33
63
|
|
64
|
+
# Makes a new bot with the given email and password. It will be ready to be added event handlers to and can eventually be run with {#run}.
|
65
|
+
# @param email [String] The email for your (or the bot's) Discord account.
|
66
|
+
# @param password [String] The valid password that should be used to log in to the account.
|
67
|
+
# @param debug [Boolean] Whether or not the bug should run in debug mode, which gives increased console output.
|
34
68
|
def initialize(email, password, debug = false)
|
35
69
|
# Make sure people replace the login details in the example files...
|
36
70
|
if email.end_with? 'example.com'
|
@@ -57,6 +91,12 @@ module Discordrb
|
|
57
91
|
@current_thread = 0
|
58
92
|
end
|
59
93
|
|
94
|
+
# Runs the bot, which logs into Discord and connects the WebSocket. This prevents all further execution unless it is executed with `async` = `:async`.
|
95
|
+
# @param async [Symbol] If it is `:async`, then the bot will allow further execution.
|
96
|
+
# It doesn't necessarily have to be that, anything truthy will work,
|
97
|
+
# however it is recommended to use `:async` for code readability reasons.
|
98
|
+
# If the bot is run in async mode, make sure to eventually run {#sync} so
|
99
|
+
# the script doesn't stop prematurely.
|
60
100
|
def run(async = false)
|
61
101
|
run_async
|
62
102
|
return if async
|
@@ -93,14 +133,20 @@ module Discordrb
|
|
93
133
|
debug('Confirmation received! Exiting run.')
|
94
134
|
end
|
95
135
|
|
136
|
+
# Prevents all further execution until the websocket thread stops (e. g. through a closed connection).
|
96
137
|
def sync
|
97
138
|
@ws_thread.join
|
98
139
|
end
|
99
140
|
|
141
|
+
# Kills the websocket thread, stopping all connections to Discord.
|
100
142
|
def stop
|
101
143
|
@ws_thread.kill
|
102
144
|
end
|
103
145
|
|
146
|
+
# Gets a channel given its ID. This queries the internal channel cache, and if the channel doesn't
|
147
|
+
# exist in there, it will get the data from Discord.
|
148
|
+
# @param id [Integer] The channel ID for which to search for.
|
149
|
+
# @return [Channel] The channel identified by the ID.
|
104
150
|
def channel(id)
|
105
151
|
debug("Obtaining data for channel with id #{id}")
|
106
152
|
return @channels[id] if @channels[id]
|
@@ -110,6 +156,11 @@ module Discordrb
|
|
110
156
|
@channels[id] = channel
|
111
157
|
end
|
112
158
|
|
159
|
+
# Creates a private channel for the given user ID, or if one exists already, returns that one.
|
160
|
+
# It is recommended that you use {User#pm} instead, as this is mainly for internal use. However,
|
161
|
+
# usage of this method may be unavoidable if only the user ID is known.
|
162
|
+
# @param id [Integer] The user ID to generate a private channel for.
|
163
|
+
# @return [Channel] A private channel for that user.
|
113
164
|
def private_channel(id)
|
114
165
|
debug("Creating private channel with user id #{id}")
|
115
166
|
return @private_channels[id] if @private_channels[id]
|
@@ -119,31 +170,61 @@ module Discordrb
|
|
119
170
|
@private_channels[id] = channel
|
120
171
|
end
|
121
172
|
|
173
|
+
# Gets the code for an invite.
|
174
|
+
# @param invite [String, Invite] The invite to get the code for. Possible formats are:
|
175
|
+
#
|
176
|
+
# * An {Invite} object
|
177
|
+
# * The code for an invite
|
178
|
+
# * A fully qualified invite URL (e. g. `https://discordapp.com/invite/0A37aN7fasF7n83q`)
|
179
|
+
# * A short invite URL with protocol (e. g. `https://discord.gg/0A37aN7fasF7n83q`)
|
180
|
+
# * A short invite URL without protocol (e. g. `discord.gg/0A37aN7fasF7n83q`)
|
181
|
+
# @return [String] Only the code for the invite.
|
122
182
|
def resolve_invite_code(invite)
|
123
183
|
invite = invite.code if invite.is_a? Discordrb::Invite
|
124
184
|
invite = invite[invite.rindex('/') + 1..-1] if invite.start_with?('http') || invite.start_with?('discord.gg')
|
125
185
|
invite
|
126
186
|
end
|
127
187
|
|
188
|
+
# Makes the bot join an invite to a server.
|
189
|
+
# @param invite [String, Invite] The invite to join. For possible formats see {#resolve_invite_code}.
|
128
190
|
def join(invite)
|
129
191
|
invite = resolve_invite_code(invite)
|
130
192
|
resolved = JSON.parse(API.resolve_invite(@token, invite))['code']
|
131
193
|
API.join_server(@token, resolved)
|
132
194
|
end
|
133
195
|
|
196
|
+
# Revokes an invite to a server. Will fail unless you have the *Manage Server* permission.
|
197
|
+
# It is recommended that you use {Invite#delete} instead.
|
198
|
+
# @param code [String, Invite] The invite to revoke. For possible formats see {#resolve_invite_code}.
|
134
199
|
def delete_invite(code)
|
135
200
|
invite = resolve_invite_code(code)
|
136
201
|
API.delete_invite(@token, invite)
|
137
202
|
end
|
138
203
|
|
204
|
+
# Gets a user by its ID.
|
205
|
+
# @note This can only resolve users known by the bot (i.e. that share a server with the bot).
|
206
|
+
# @param id [Integer] The user ID that should be resolved.
|
207
|
+
# @return [User, nil] The user identified by the ID, or `nil` if it couldn't be found.
|
139
208
|
def user(id)
|
140
209
|
@users[id]
|
141
210
|
end
|
142
211
|
|
212
|
+
# Gets a server by its ID.
|
213
|
+
# @note This can only resolve servers the bot is currently in.
|
214
|
+
# @param id [Integer] The server ID that should be resolved.
|
215
|
+
# @return [Server, nil] The server identified by the ID, or `nil` if it couldn't be found.
|
143
216
|
def server(id)
|
144
217
|
@servers[id]
|
145
218
|
end
|
146
219
|
|
220
|
+
# Finds a channel given its name and optionally the name of the server it is in. If the threshold
|
221
|
+
# is not 0, it will use a Levenshtein distance function to find the channel in a fuzzy way, which
|
222
|
+
# allows slight misspellings.
|
223
|
+
# @param channel_name [String] The channel to search for.
|
224
|
+
# @param server_name [String] The server to search for, or `nil` if only the channel should be searched for.
|
225
|
+
# @param threshold [Integer] The threshold for the Levenshtein algorithm. The larger
|
226
|
+
# the threshold is, the more misspellings will be allowed.
|
227
|
+
# @return [Array<Channel>] The array of channels that were found. May be empty if none were found.
|
147
228
|
def find(channel_name, server_name = nil, threshold = 0)
|
148
229
|
require 'levenshtein'
|
149
230
|
|
@@ -165,23 +246,51 @@ module Discordrb
|
|
165
246
|
results
|
166
247
|
end
|
167
248
|
|
249
|
+
# Sends a text message to a channel given its ID and the message's content.
|
250
|
+
# @param channel_id [Integer] The ID that identifies the channel to send something to.
|
251
|
+
# @param content [String] The text that should be sent as a message. It is limited to 2000 characters (Discord imposed).
|
252
|
+
# @return [Message] The message that was sent.
|
168
253
|
def send_message(channel_id, content)
|
169
254
|
debug("Sending message to #{channel_id} with content '#{content}'")
|
170
255
|
response = API.send_message(@token, channel_id, content)
|
171
256
|
Message.new(JSON.parse(response), self)
|
172
257
|
end
|
173
258
|
|
259
|
+
# Sends a file to a channel. If it is an image, it will automatically be embedded.
|
260
|
+
# @note This executes in a blocking way, so if you're sending long files, be wary of delays.
|
261
|
+
# @param channel_id [Integer] The ID that identifies the channel to send something to.
|
262
|
+
# @param file [File] The file that should be sent.
|
174
263
|
def send_file(channel_id, file)
|
175
264
|
API.send_file(@token, channel_id, file)
|
176
265
|
end
|
177
266
|
|
267
|
+
# Add an await the bot should listen to. For information on awaits, see {Await}.
|
268
|
+
# @param key [Symbol] The key that uniquely identifies the await for {AwaitEvent}s to listen to (see {#await}).
|
269
|
+
# @param type [Class] The event class that should be listened for.
|
270
|
+
# @param attributes [Hash] The attributes the event should check for. The block will only be executed if all attributes match.
|
271
|
+
# @yield Is executed when the await is triggered.
|
272
|
+
# @yieldparam event [Event] The event object that was triggered.
|
273
|
+
# @return [Await] The await that was created.
|
178
274
|
def add_await(key, type, attributes = {}, &block)
|
179
275
|
fail "You can't await an AwaitEvent!" if type == Discordrb::Events::AwaitEvent
|
180
276
|
await = Await.new(self, key, type, attributes, block)
|
181
277
|
@awaits[key] = await
|
182
278
|
end
|
183
279
|
|
184
|
-
#
|
280
|
+
# Creates a server on Discord with a specified name and a region.
|
281
|
+
# @note Discord's API doesn't directly return the server when creating it, so this method
|
282
|
+
# waits until the data has been received via the websocket. This may make the execution take a while.
|
283
|
+
# @param name [String] The name the new server should have. Doesn't have to be alphanumeric.
|
284
|
+
# @param region [Symbol] The region where the server should be created. Possible regions are:
|
285
|
+
#
|
286
|
+
# * `:london`
|
287
|
+
# * `:amsterdam`
|
288
|
+
# * `:frankfurt`
|
289
|
+
# * `:us-east`
|
290
|
+
# * `:us-west`
|
291
|
+
# * `:singapore`
|
292
|
+
# * `:sydney`
|
293
|
+
# @return [Server] The server that was created.
|
185
294
|
def create_server(name, region = :london)
|
186
295
|
response = API.create_server(@token, name, region)
|
187
296
|
id = JSON.parse(response)['id'].to_i
|
@@ -191,12 +300,18 @@ module Discordrb
|
|
191
300
|
server
|
192
301
|
end
|
193
302
|
|
303
|
+
# Gets the user from a mention of the user.
|
304
|
+
# @param mention [String] The mention, which should look like <@12314873129>.
|
305
|
+
# @return [User] The user identified by the mention, or `nil` if none exists.
|
194
306
|
def parse_mention(mention)
|
195
307
|
# Mention format: <@id>
|
196
308
|
return nil unless /\<@(?<id>\d+)\>?/ =~ mention
|
197
309
|
user(id)
|
198
310
|
end
|
199
311
|
|
312
|
+
# Sets the currently playing game to the specified game.
|
313
|
+
# @param name_or_id [String, Fixnum] The name or the ID of the game to be played.
|
314
|
+
# @return [Game] The game object that is being played now.
|
200
315
|
def game=(name_or_id)
|
201
316
|
game = Discordrb::Games.find_game(name_or_id)
|
202
317
|
@game = game
|
@@ -213,6 +328,7 @@ module Discordrb
|
|
213
328
|
game
|
214
329
|
end
|
215
330
|
|
331
|
+
# Sets debug mode. If debug mode is on, many things will be outputted to STDOUT.
|
216
332
|
attr_writer :debug
|
217
333
|
|
218
334
|
## ## ### ## ## ######## ## ######## ######## ######
|
@@ -223,6 +339,21 @@ module Discordrb
|
|
223
339
|
## ## ## ## ## ### ## ## ## ## ## ## ## ##
|
224
340
|
## ## ## ## ## ## ######## ######## ######## ## ## ######
|
225
341
|
|
342
|
+
# This **event** is raised when a message is sent to a text channel the bot is currently in.
|
343
|
+
# @param attributes [Hash] The event's attributes.
|
344
|
+
# @option attributes [String, Regexp] :start_with Matches the string the message starts with.
|
345
|
+
# @option attributes [String, Regexp] :end_with Matches the string the message ends with.
|
346
|
+
# @option attributes [String, Regexp] :contains Matches a string the message contains.
|
347
|
+
# @option attributes [String, Integer, Channel] :in Matches the channel the message was sent in.
|
348
|
+
# @option attributes [String, Integer, User] :from Matches the user that sent the message.
|
349
|
+
# @option attributes [String] :content Exactly matches the entire content of the message.
|
350
|
+
# @option attributes [String] :content Exactly matches the entire content of the message.
|
351
|
+
# @option attributes [Time] :after Matches a time after the time the message was sent at.
|
352
|
+
# @option attributes [Time] :before Matches a time before the time the message was sent at.
|
353
|
+
# @option attributes [Boolean] :private Matches whether or not the channel is private.
|
354
|
+
# @yield The block is executed when the event is raised.
|
355
|
+
# @yieldparam event [MessageEvent] The event that was raised.
|
356
|
+
# @return [MessageEventHandler] The event handler that was registered.
|
226
357
|
def message(attributes = {}, &block)
|
227
358
|
register_event(MessageEvent, attributes, block)
|
228
359
|
end
|
@@ -308,6 +439,14 @@ module Discordrb
|
|
308
439
|
register_event(GuildDeleteEvent, attributes, block)
|
309
440
|
end
|
310
441
|
|
442
|
+
# This **event** is raised when an {Await} is triggered. It provides an easy way to execute code
|
443
|
+
# on an await without having to rely on the await's block.
|
444
|
+
# @param attributes [Hash] The event's attributes.
|
445
|
+
# @option attributes [Symbol] :key Exactly matches the await's key.
|
446
|
+
# @option attributes [Class] :type Exactly matches the event's type.
|
447
|
+
# @yield The block is executed when the event is raised.
|
448
|
+
# @yieldparam event [AwaitEvent] The event that was raised.
|
449
|
+
# @return [AwaitEventHandler] The event handler that was registered.
|
311
450
|
def await(attributes = {}, &block)
|
312
451
|
register_event(AwaitEvent, attributes, block)
|
313
452
|
end
|
@@ -22,7 +22,8 @@ module Discordrb::Commands
|
|
22
22
|
help_command: attributes[:help_command] || :help,
|
23
23
|
|
24
24
|
# The message to display for when a command doesn't exist, %command% to get the command name in question and nil for no message
|
25
|
-
|
25
|
+
# No default value here because it may not be desired behaviour
|
26
|
+
command_doesnt_exist_message: attributes[:command_doesnt_exist_message],
|
26
27
|
|
27
28
|
# All of the following need to be one character
|
28
29
|
# String to designate previous result in command chain
|
@@ -129,7 +130,7 @@ module Discordrb::Commands
|
|
129
130
|
debug("Parsing command chain #{chain}")
|
130
131
|
result = (@attributes[:advanced_functionality]) ? CommandChain.new(chain, self).execute(event) : simple_execute(chain, event)
|
131
132
|
result = event.saved_message + (result || '')
|
132
|
-
event.respond result
|
133
|
+
event.respond result unless result.nil? || result.empty?
|
133
134
|
rescue => e
|
134
135
|
log_exception(e)
|
135
136
|
ensure
|
@@ -2,11 +2,18 @@ require 'discordrb/events/generic'
|
|
2
2
|
require 'discordrb/await'
|
3
3
|
|
4
4
|
module Discordrb::Events
|
5
|
-
#
|
5
|
+
# @see Bot#await
|
6
6
|
class AwaitEvent
|
7
|
-
|
7
|
+
# The await that was triggered.
|
8
|
+
# @return [Await] The await
|
9
|
+
attr_reader :await
|
10
|
+
|
11
|
+
# The event that triggered the await.
|
12
|
+
# @return [Event] The event
|
13
|
+
attr_reader :event
|
8
14
|
delegate :key, :type, :attributes, to: :await
|
9
15
|
|
16
|
+
# For internal use only
|
10
17
|
def initialize(await, event, bot)
|
11
18
|
@await = await
|
12
19
|
@event = event
|
@@ -14,7 +21,7 @@ module Discordrb::Events
|
|
14
21
|
end
|
15
22
|
end
|
16
23
|
|
17
|
-
# Event handler for AwaitEvent
|
24
|
+
# Event handler for {AwaitEvent}
|
18
25
|
class AwaitEventHandler < EventHandler
|
19
26
|
def matches?(event)
|
20
27
|
# Check for the proper event type
|
data/lib/discordrb/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: discordrb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- meew0
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-12-
|
11
|
+
date: 2015-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faye-websocket
|
@@ -91,6 +91,7 @@ files:
|
|
91
91
|
- ".rspec"
|
92
92
|
- ".rubocop.yml"
|
93
93
|
- ".travis.yml"
|
94
|
+
- ".yardopts"
|
94
95
|
- Gemfile
|
95
96
|
- LICENSE.txt
|
96
97
|
- README.md
|
@@ -142,7 +143,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
142
143
|
requirements:
|
143
144
|
- - ">="
|
144
145
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
146
|
+
version: 2.1.0
|
146
147
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
148
|
requirements:
|
148
149
|
- - ">="
|