discordrb 2.0.4 → 2.1.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/CHANGELOG.md +14 -0
- data/LICENSE.txt +1 -1
- data/lib/discordrb.rb +0 -7
- data/lib/discordrb/api.rb +60 -48
- data/lib/discordrb/bot.rb +23 -6
- data/lib/discordrb/commands/command_bot.rb +41 -7
- data/lib/discordrb/commands/container.rb +5 -0
- data/lib/discordrb/commands/parser.rb +3 -0
- data/lib/discordrb/container.rb +15 -0
- data/lib/discordrb/data.rb +60 -4
- data/lib/discordrb/events/lifetime.rb +6 -0
- data/lib/discordrb/permissions.rb +3 -1
- data/lib/discordrb/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e61613220092ee639a9cd4db8f5fad0d7485b5a8
|
4
|
+
data.tar.gz: 008902a804d2938eff3d369bb500d6a755ccb605
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fedc89d8c0ccb3229425382413e2ce4bb946e676924542092290985f4ba11b2d5e402ce210df590fbeb29393536593ef8e09d5189cd795f225b40156fa052e55
|
7
|
+
data.tar.gz: 9793bdc3c7ed44daa090145e0bf693c0ab12070ebe1e73f89204a0c8423c6d7e734461caef25b461fee1a0893a1c9717c7fda6dc2fbc7badbe458eeed44e2038
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 2.1.0
|
4
|
+
|
5
|
+
- API support for the April 29 Discord update, which was the first feature update in a while with more than a few additions to the API, was added. This includes: ([#111](https://github.com/meew0/discordrb/pull/111))
|
6
|
+
- Members' nicknames can now be set and read (`Member#nick`) and updates to them are being tracked.
|
7
|
+
- Roles now have a `mentionable?` property and a `mention` utility method.
|
8
|
+
- `Message` now tracks a message's role mentions.
|
9
|
+
- The internal REST rate limit handler was updated:
|
10
|
+
- It now tracks message rate limits server wide to properly handle new bot account rate limits. ([#100](https://github.com/meew0/discordrb/issues/100))
|
11
|
+
- It now keeps track of all requests, even those that are known not to be rate limited (it just won't do anything to them). This allows for more flexibility should future rate limits be added.
|
12
|
+
- Guild sharding is now supported using the optional `shard_id` and `num_shards` to bot initializers. Read about it here: https://github.com/hammerandchisel/discord-api-docs/issues/17 ([#98](https://github.com/meew0/discordrb/issues/98))
|
13
|
+
- Commands can now require users to have specific action permissions to be able to execute them using the `:required_permissions` attribute. ([#104](https://github.com/meew0/discordrb/issues/104) / [#112](https://github.com/meew0/discordrb/pull/112))
|
14
|
+
- A `heartbeat` event was added that gets triggered every now and then to allow for roughly periodic actions. ([#110](https://github.com/meew0/discordrb/pull/110))
|
15
|
+
- Prefixes are now more flexible in the format they can have - arrays and callables are now allowed as well. Read the documentation for more info.([#107](https://github.com/meew0/discordrb/issues/107) / [#109](https://github.com/meew0/discordrb/pull/109))
|
16
|
+
|
3
17
|
## 2.0.4
|
4
18
|
|
5
19
|
- Added a utility method `Invite#url` ([#86](https://github.com/meew0/discordrb/issues/86)/[#101](https://github.com/meew0/discordrb/pull/101), thanks @PoVa)
|
data/LICENSE.txt
CHANGED
data/lib/discordrb.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
unless ENV['DISCORDRB_V2_MESSAGE']
|
4
|
-
puts "You're using version 2 of discordrb which has some breaking changes!"
|
5
|
-
puts "Don't worry if your bot crashes, you can find a list and migration advice here:"
|
6
|
-
puts ' https://github.com/meew0/discordrb/blob/master/CHANGELOG.md#200'
|
7
|
-
puts 'This message will go away in version 2.1 or can be disabled by setting the DISCORDRB_V2_MESSAGE environment variable.'
|
8
|
-
end
|
9
|
-
|
10
3
|
require 'discordrb/version'
|
11
4
|
require 'discordrb/bot'
|
12
5
|
require 'discordrb/commands/command_bot'
|
data/lib/discordrb/api.rb
CHANGED
@@ -43,9 +43,7 @@ module Discordrb::API
|
|
43
43
|
|
44
44
|
# Resets all rate limit mutexes
|
45
45
|
def reset_mutexes
|
46
|
-
@mutexes = {
|
47
|
-
message: Mutex.new
|
48
|
-
}
|
46
|
+
@mutexes = {}
|
49
47
|
end
|
50
48
|
|
51
49
|
# Performs a RestClient request.
|
@@ -68,6 +66,8 @@ module Discordrb::API
|
|
68
66
|
|
69
67
|
begin
|
70
68
|
if key
|
69
|
+
@mutexes[key] = Mutex.new unless @mutexes[key]
|
70
|
+
|
71
71
|
# Lock and unlock, i. e. wait for the mutex to unlock and don't do anything with it afterwards
|
72
72
|
@mutexes[key].lock
|
73
73
|
@mutexes[key].unlock
|
@@ -106,7 +106,7 @@ module Discordrb::API
|
|
106
106
|
# Ban a user from a server and delete their messages from the last message_days days
|
107
107
|
def ban_user(token, server_id, user_id, message_days)
|
108
108
|
request(
|
109
|
-
|
109
|
+
__method__,
|
110
110
|
:put,
|
111
111
|
"#{api_base}/guilds/#{server_id}/bans/#{user_id}?delete-message-days=#{message_days}",
|
112
112
|
nil,
|
@@ -117,7 +117,7 @@ module Discordrb::API
|
|
117
117
|
# Unban a user from a server
|
118
118
|
def unban_user(token, server_id, user_id)
|
119
119
|
request(
|
120
|
-
|
120
|
+
__method__,
|
121
121
|
:delete,
|
122
122
|
"#{api_base}/guilds/#{server_id}/bans/#{user_id}",
|
123
123
|
Authorization: token
|
@@ -127,7 +127,7 @@ module Discordrb::API
|
|
127
127
|
# Kick a user from a server
|
128
128
|
def kick_user(token, server_id, user_id)
|
129
129
|
request(
|
130
|
-
|
130
|
+
__method__,
|
131
131
|
:delete,
|
132
132
|
"#{api_base}/guilds/#{server_id}/members/#{user_id}",
|
133
133
|
Authorization: token
|
@@ -137,7 +137,7 @@ module Discordrb::API
|
|
137
137
|
# Move a user to a different voice channel
|
138
138
|
def move_user(token, server_id, user_id, channel_id)
|
139
139
|
request(
|
140
|
-
|
140
|
+
__method__,
|
141
141
|
:patch,
|
142
142
|
"#{api_base}/guilds/#{server_id}/members/#{user_id}",
|
143
143
|
{ channel_id: channel_id }.to_json,
|
@@ -146,10 +146,22 @@ module Discordrb::API
|
|
146
146
|
)
|
147
147
|
end
|
148
148
|
|
149
|
+
# Change a user's nickname on a server
|
150
|
+
def change_nickname(token, server_id, user_id, nick)
|
151
|
+
request(
|
152
|
+
__method__,
|
153
|
+
:patch,
|
154
|
+
"#{api_base}/guilds/#{server_id}/members/#{user_id}",
|
155
|
+
{ nick: nick }.to_json,
|
156
|
+
Authorization: token,
|
157
|
+
content_type: :json
|
158
|
+
)
|
159
|
+
end
|
160
|
+
|
149
161
|
# Get a server's banned users
|
150
162
|
def bans(token, server_id)
|
151
163
|
request(
|
152
|
-
|
164
|
+
__method__,
|
153
165
|
:get,
|
154
166
|
"#{api_base}/guilds/#{server_id}/bans",
|
155
167
|
Authorization: token
|
@@ -159,7 +171,7 @@ module Discordrb::API
|
|
159
171
|
# Login to the server
|
160
172
|
def login(email, password)
|
161
173
|
request(
|
162
|
-
|
174
|
+
__method__,
|
163
175
|
:post,
|
164
176
|
"#{api_base}/auth/login",
|
165
177
|
email: email,
|
@@ -170,7 +182,7 @@ module Discordrb::API
|
|
170
182
|
# Logout from the server
|
171
183
|
def logout(token)
|
172
184
|
request(
|
173
|
-
|
185
|
+
__method__,
|
174
186
|
:post,
|
175
187
|
"#{api_base}/auth/logout",
|
176
188
|
nil,
|
@@ -181,7 +193,7 @@ module Discordrb::API
|
|
181
193
|
# Create an OAuth application
|
182
194
|
def create_oauth_application(token, name, redirect_uris)
|
183
195
|
request(
|
184
|
-
|
196
|
+
__method__,
|
185
197
|
:post,
|
186
198
|
"#{api_base}/oauth2/applications",
|
187
199
|
{ name: name, redirect_uris: redirect_uris }.to_json,
|
@@ -193,7 +205,7 @@ module Discordrb::API
|
|
193
205
|
# Change an OAuth application's properties
|
194
206
|
def update_oauth_application(token, name, redirect_uris, description = '', icon = nil)
|
195
207
|
request(
|
196
|
-
|
208
|
+
__method__,
|
197
209
|
:put,
|
198
210
|
"#{api_base}/oauth2/applications",
|
199
211
|
{ name: name, redirect_uris: redirect_uris, description: description, icon: icon }.to_json,
|
@@ -205,7 +217,7 @@ module Discordrb::API
|
|
205
217
|
# Create a server
|
206
218
|
def create_server(token, name, region = :london)
|
207
219
|
request(
|
208
|
-
|
220
|
+
__method__,
|
209
221
|
:post,
|
210
222
|
"#{api_base}/guilds",
|
211
223
|
{ name: name, region: region.to_s }.to_json,
|
@@ -217,7 +229,7 @@ module Discordrb::API
|
|
217
229
|
# Update a server
|
218
230
|
def update_server(token, server_id, name, region, icon, afk_channel_id, afk_timeout)
|
219
231
|
request(
|
220
|
-
|
232
|
+
__method__,
|
221
233
|
:patch,
|
222
234
|
"#{api_base}/guilds/#{server_id}",
|
223
235
|
{ name: name, region: region, icon: icon, afk_channel_id: afk_channel_id, afk_timeout: afk_timeout }.to_json,
|
@@ -229,7 +241,7 @@ module Discordrb::API
|
|
229
241
|
# Transfer server ownership
|
230
242
|
def transfer_ownership(token, server_id, user_id)
|
231
243
|
request(
|
232
|
-
|
244
|
+
__method__,
|
233
245
|
:patch,
|
234
246
|
"#{api_base}/guilds/#{server_id}",
|
235
247
|
{ owner_id: user_id }.to_json,
|
@@ -241,7 +253,7 @@ module Discordrb::API
|
|
241
253
|
# Delete a server
|
242
254
|
def delete_server(token, server_id)
|
243
255
|
request(
|
244
|
-
|
256
|
+
__method__,
|
245
257
|
:delete,
|
246
258
|
"#{api_base}/guilds/#{server_id}",
|
247
259
|
Authorization: token
|
@@ -251,7 +263,7 @@ module Discordrb::API
|
|
251
263
|
# Leave a server
|
252
264
|
def leave_server(token, server_id)
|
253
265
|
request(
|
254
|
-
|
266
|
+
__method__,
|
255
267
|
:delete,
|
256
268
|
"#{api_base}/users/@me/guilds/#{server_id}",
|
257
269
|
Authorization: token
|
@@ -261,7 +273,7 @@ module Discordrb::API
|
|
261
273
|
# Get a channel's data
|
262
274
|
def channel(token, channel_id)
|
263
275
|
request(
|
264
|
-
|
276
|
+
__method__,
|
265
277
|
:get,
|
266
278
|
"#{api_base}/channels/#{channel_id}",
|
267
279
|
Authorization: token
|
@@ -271,7 +283,7 @@ module Discordrb::API
|
|
271
283
|
# Get a server's data
|
272
284
|
def server(token, server_id)
|
273
285
|
request(
|
274
|
-
|
286
|
+
__method__,
|
275
287
|
:get,
|
276
288
|
"#{api_base}/guilds/#{server_id}",
|
277
289
|
Authorization: token
|
@@ -281,7 +293,7 @@ module Discordrb::API
|
|
281
293
|
# Get a member's data
|
282
294
|
def member(token, server_id, user_id)
|
283
295
|
request(
|
284
|
-
|
296
|
+
__method__,
|
285
297
|
:get,
|
286
298
|
"#{api_base}/guilds/#{server_id}/members/#{user_id}",
|
287
299
|
Authorization: token
|
@@ -291,7 +303,7 @@ module Discordrb::API
|
|
291
303
|
# Create a channel
|
292
304
|
def create_channel(token, server_id, name, type)
|
293
305
|
request(
|
294
|
-
|
306
|
+
__method__,
|
295
307
|
:post,
|
296
308
|
"#{api_base}/guilds/#{server_id}/channels",
|
297
309
|
{ name: name, type: type }.to_json,
|
@@ -303,7 +315,7 @@ module Discordrb::API
|
|
303
315
|
# Update a channel's data
|
304
316
|
def update_channel(token, channel_id, name, topic, position = 0)
|
305
317
|
request(
|
306
|
-
|
318
|
+
__method__,
|
307
319
|
:patch,
|
308
320
|
"#{api_base}/channels/#{channel_id}",
|
309
321
|
{ name: name, position: position, topic: topic }.to_json,
|
@@ -315,7 +327,7 @@ module Discordrb::API
|
|
315
327
|
# Delete a channel
|
316
328
|
def delete_channel(token, channel_id)
|
317
329
|
request(
|
318
|
-
|
330
|
+
__method__,
|
319
331
|
:delete,
|
320
332
|
"#{api_base}/channels/#{channel_id}",
|
321
333
|
Authorization: token
|
@@ -325,7 +337,7 @@ module Discordrb::API
|
|
325
337
|
# Join a server using an invite
|
326
338
|
def join_server(token, invite_code)
|
327
339
|
request(
|
328
|
-
|
340
|
+
__method__,
|
329
341
|
:post,
|
330
342
|
"#{api_base}/invite/#{invite_code}",
|
331
343
|
nil,
|
@@ -336,7 +348,7 @@ module Discordrb::API
|
|
336
348
|
# Resolve an invite
|
337
349
|
def resolve_invite(token, invite_code)
|
338
350
|
request(
|
339
|
-
|
351
|
+
__method__,
|
340
352
|
:get,
|
341
353
|
"#{api_base}/invite/#{invite_code}",
|
342
354
|
Authorization: token
|
@@ -346,7 +358,7 @@ module Discordrb::API
|
|
346
358
|
# Create a private channel
|
347
359
|
def create_private(token, bot_user_id, user_id)
|
348
360
|
request(
|
349
|
-
|
361
|
+
__method__,
|
350
362
|
:post,
|
351
363
|
"#{api_base}/users/#{bot_user_id}/channels",
|
352
364
|
{ recipient_id: user_id }.to_json,
|
@@ -360,7 +372,7 @@ module Discordrb::API
|
|
360
372
|
# Create an instant invite from a server or a channel id
|
361
373
|
def create_invite(token, channel_id, max_age = 0, max_uses = 0, temporary = false, xkcd = false)
|
362
374
|
request(
|
363
|
-
|
375
|
+
__method__,
|
364
376
|
:post,
|
365
377
|
"#{api_base}/channels/#{channel_id}/invites",
|
366
378
|
{ max_age: max_age, max_uses: max_uses, temporary: temporary, xkcdpass: xkcd }.to_json,
|
@@ -372,7 +384,7 @@ module Discordrb::API
|
|
372
384
|
# Delete an invite by code
|
373
385
|
def delete_invite(token, code)
|
374
386
|
request(
|
375
|
-
|
387
|
+
__method__,
|
376
388
|
:delete,
|
377
389
|
"#{api_base}/invites/#{code}",
|
378
390
|
Authorization: token
|
@@ -380,9 +392,9 @@ module Discordrb::API
|
|
380
392
|
end
|
381
393
|
|
382
394
|
# Send a message to a channel
|
383
|
-
def send_message(token, channel_id, message, mentions = [], tts = false)
|
395
|
+
def send_message(token, channel_id, message, mentions = [], tts = false, guild_id = nil)
|
384
396
|
request(
|
385
|
-
|
397
|
+
"message-#{guild_id}".to_sym,
|
386
398
|
:post,
|
387
399
|
"#{api_base}/channels/#{channel_id}/messages",
|
388
400
|
{ content: message, mentions: mentions, tts: tts }.to_json,
|
@@ -396,7 +408,7 @@ module Discordrb::API
|
|
396
408
|
# Delete a message
|
397
409
|
def delete_message(token, channel_id, message_id)
|
398
410
|
request(
|
399
|
-
|
411
|
+
__method__,
|
400
412
|
:delete,
|
401
413
|
"#{api_base}/channels/#{channel_id}/messages/#{message_id}",
|
402
414
|
Authorization: token
|
@@ -420,7 +432,7 @@ module Discordrb::API
|
|
420
432
|
# so this is an easy way to catch up on messages
|
421
433
|
def acknowledge_message(token, channel_id, message_id)
|
422
434
|
request(
|
423
|
-
|
435
|
+
__method__,
|
424
436
|
:post,
|
425
437
|
"#{api_base}/channels/#{channel_id}/messages/#{message_id}/ack",
|
426
438
|
nil,
|
@@ -431,7 +443,7 @@ module Discordrb::API
|
|
431
443
|
# Send a file as a message to a channel
|
432
444
|
def send_file(token, channel_id, file)
|
433
445
|
request(
|
434
|
-
|
446
|
+
__method__,
|
435
447
|
:post,
|
436
448
|
"#{api_base}/channels/#{channel_id}/messages",
|
437
449
|
{ file: file },
|
@@ -442,7 +454,7 @@ module Discordrb::API
|
|
442
454
|
# Create a role (parameters such as name and colour will have to be set by update_role afterwards)
|
443
455
|
def create_role(token, server_id)
|
444
456
|
request(
|
445
|
-
|
457
|
+
__method__,
|
446
458
|
:post,
|
447
459
|
"#{api_base}/guilds/#{server_id}/roles",
|
448
460
|
nil,
|
@@ -456,7 +468,7 @@ module Discordrb::API
|
|
456
468
|
# connecting to voice, speaking and voice activity (push-to-talk isn't mandatory)
|
457
469
|
def update_role(token, server_id, role_id, name, colour, hoist = false, packed_permissions = 36_953_089)
|
458
470
|
request(
|
459
|
-
|
471
|
+
__method__,
|
460
472
|
:patch,
|
461
473
|
"#{api_base}/guilds/#{server_id}/roles/#{role_id}",
|
462
474
|
{ color: colour, name: name, hoist: hoist, permissions: packed_permissions }.to_json,
|
@@ -468,7 +480,7 @@ module Discordrb::API
|
|
468
480
|
# Delete a role
|
469
481
|
def delete_role(token, server_id, role_id)
|
470
482
|
request(
|
471
|
-
|
483
|
+
__method__,
|
472
484
|
:delete,
|
473
485
|
"#{api_base}/guilds/#{server_id}/roles/#{role_id}",
|
474
486
|
Authorization: token
|
@@ -478,7 +490,7 @@ module Discordrb::API
|
|
478
490
|
# Update a user's roles
|
479
491
|
def update_user_roles(token, server_id, user_id, roles)
|
480
492
|
request(
|
481
|
-
|
493
|
+
__method__,
|
482
494
|
:patch,
|
483
495
|
"#{api_base}/guilds/#{server_id}/members/#{user_id}",
|
484
496
|
{ roles: roles }.to_json,
|
@@ -490,7 +502,7 @@ module Discordrb::API
|
|
490
502
|
# Update a user's permission overrides in a channel
|
491
503
|
def update_user_overrides(token, channel_id, user_id, allow, deny)
|
492
504
|
request(
|
493
|
-
|
505
|
+
__method__,
|
494
506
|
:put,
|
495
507
|
"#{api_base}/channels/#{channel_id}/permissions/#{user_id}",
|
496
508
|
{ type: 'member', id: user_id, allow: allow, deny: deny }.to_json,
|
@@ -502,7 +514,7 @@ module Discordrb::API
|
|
502
514
|
# Update a role's permission overrides in a channel
|
503
515
|
def update_role_overrides(token, channel_id, role_id, allow, deny)
|
504
516
|
request(
|
505
|
-
|
517
|
+
__method__,
|
506
518
|
:put,
|
507
519
|
"#{api_base}/channels/#{channel_id}/permissions/#{role_id}",
|
508
520
|
{ type: 'role', id: role_id, allow: allow, deny: deny }.to_json,
|
@@ -514,7 +526,7 @@ module Discordrb::API
|
|
514
526
|
# Get the gateway to be used
|
515
527
|
def gateway(token)
|
516
528
|
request(
|
517
|
-
|
529
|
+
__method__,
|
518
530
|
:get,
|
519
531
|
"#{api_base}/gateway",
|
520
532
|
Authorization: token
|
@@ -524,7 +536,7 @@ module Discordrb::API
|
|
524
536
|
# Validate a token (this request will fail if the token is invalid)
|
525
537
|
def validate_token(token)
|
526
538
|
request(
|
527
|
-
|
539
|
+
__method__,
|
528
540
|
:post,
|
529
541
|
"#{api_base}/auth/login",
|
530
542
|
{}.to_json,
|
@@ -536,7 +548,7 @@ module Discordrb::API
|
|
536
548
|
# Start typing (needs to be resent every 5 seconds to keep up the typing)
|
537
549
|
def start_typing(token, channel_id)
|
538
550
|
request(
|
539
|
-
|
551
|
+
__method__,
|
540
552
|
:post,
|
541
553
|
"#{api_base}/channels/#{channel_id}/typing",
|
542
554
|
nil,
|
@@ -547,7 +559,7 @@ module Discordrb::API
|
|
547
559
|
# Get user data
|
548
560
|
def user(token, user_id)
|
549
561
|
request(
|
550
|
-
|
562
|
+
__method__,
|
551
563
|
:get,
|
552
564
|
"#{api_base}/users/#{user_id}",
|
553
565
|
Authorization: token
|
@@ -557,7 +569,7 @@ module Discordrb::API
|
|
557
569
|
# Get profile data
|
558
570
|
def profile(token)
|
559
571
|
request(
|
560
|
-
|
572
|
+
__method__,
|
561
573
|
:get,
|
562
574
|
"#{api_base}/users/@me",
|
563
575
|
Authorization: token
|
@@ -567,7 +579,7 @@ module Discordrb::API
|
|
567
579
|
# Get information about a user's connections
|
568
580
|
def connections(token)
|
569
581
|
request(
|
570
|
-
|
582
|
+
__method__,
|
571
583
|
:get,
|
572
584
|
"#{api_base}/users/@me/connections",
|
573
585
|
Authorization: token
|
@@ -577,7 +589,7 @@ module Discordrb::API
|
|
577
589
|
# Update user data
|
578
590
|
def update_user(token, email, password, new_username, avatar, new_password = nil)
|
579
591
|
request(
|
580
|
-
|
592
|
+
__method__,
|
581
593
|
:patch,
|
582
594
|
"#{api_base}/users/@me",
|
583
595
|
{ avatar: avatar, email: email, new_password: new_password, password: password, username: new_username }.to_json,
|
@@ -589,7 +601,7 @@ module Discordrb::API
|
|
589
601
|
# Get the servers a user is connected to
|
590
602
|
def servers(token)
|
591
603
|
request(
|
592
|
-
|
604
|
+
__method__,
|
593
605
|
:get,
|
594
606
|
"#{api_base}/users/@me/guilds",
|
595
607
|
Authorization: token
|
@@ -599,7 +611,7 @@ module Discordrb::API
|
|
599
611
|
# Get a list of messages from a channel's history
|
600
612
|
def channel_log(token, channel_id, amount, before = nil, after = nil)
|
601
613
|
request(
|
602
|
-
|
614
|
+
__method__,
|
603
615
|
:get,
|
604
616
|
"#{api_base}/channels/#{channel_id}/messages?limit=#{amount}#{"&before=#{before}" if before}#{"&after=#{after}" if after}",
|
605
617
|
Authorization: token
|
data/lib/discordrb/bot.rb
CHANGED
@@ -109,6 +109,9 @@ module Discordrb
|
|
109
109
|
# same codebase. Not required but I recommend setting it anyway.
|
110
110
|
attr_accessor :name
|
111
111
|
|
112
|
+
# @return [Array(Integer, Integer)] the current shard key
|
113
|
+
attr_reader :shard_key
|
114
|
+
|
112
115
|
include EventContainer
|
113
116
|
include Cache
|
114
117
|
|
@@ -145,10 +148,15 @@ module Discordrb
|
|
145
148
|
# Useful for very large bots running in debug or verbose log_mode.
|
146
149
|
# @param parse_self [true, false] Whether the bot should react on its own messages. It's best to turn this off
|
147
150
|
# unless you really need this so you don't inadvertently create infinite loops.
|
151
|
+
# @param shard_id [Integer] The number of the shard this bot should handle. See
|
152
|
+
# https://github.com/hammerandchisel/discord-api-docs/issues/17 for how to do sharding.
|
153
|
+
# @param num_shards [Integer] The total number of shards that should be running. See
|
154
|
+
# https://github.com/hammerandchisel/discord-api-docs/issues/17 for how to do sharding.
|
148
155
|
def initialize(
|
149
156
|
email: nil, password: nil, log_mode: :normal,
|
150
157
|
token: nil, application_id: nil,
|
151
|
-
type: nil, name: '', fancy_log: false, suppress_ready: false, parse_self: false
|
158
|
+
type: nil, name: '', fancy_log: false, suppress_ready: false, parse_self: false,
|
159
|
+
shard_id: nil, num_shards: nil)
|
152
160
|
# Make sure people replace the login details in the example files...
|
153
161
|
if email.is_a?(String) && email.end_with?('example.com')
|
154
162
|
puts 'You have to replace the login details in the example files with your own!'
|
@@ -172,6 +180,8 @@ module Discordrb
|
|
172
180
|
|
173
181
|
@name = name
|
174
182
|
|
183
|
+
@shard_key = num_shards ? [shard_id, num_shards] : nil
|
184
|
+
|
175
185
|
LOGGER.fancy = fancy_log
|
176
186
|
@prevent_ready = suppress_ready
|
177
187
|
|
@@ -390,11 +400,11 @@ module Discordrb
|
|
390
400
|
# @param content [String] The text that should be sent as a message. It is limited to 2000 characters (Discord imposed).
|
391
401
|
# @param tts [true, false] Whether or not this message should be sent using Discord text-to-speech.
|
392
402
|
# @return [Message] The message that was sent.
|
393
|
-
def send_message(channel_id, content, tts = false)
|
403
|
+
def send_message(channel_id, content, tts = false, server_id = nil)
|
394
404
|
channel_id = channel_id.resolve_id
|
395
405
|
debug("Sending message to #{channel_id} with content '#{content}'")
|
396
406
|
|
397
|
-
response = API.send_message(token, channel_id, content, [], tts)
|
407
|
+
response = API.send_message(token, channel_id, content, [], tts, server_id)
|
398
408
|
Message.new(JSON.parse(response), self)
|
399
409
|
end
|
400
410
|
|
@@ -433,7 +443,7 @@ module Discordrb
|
|
433
443
|
end
|
434
444
|
|
435
445
|
# Creates a new application to do OAuth authorization with. This allows you to use OAuth to authorize users using
|
436
|
-
# Discord. For information how to use this, see
|
446
|
+
# Discord. For information how to use this, see the docs: https://discordapp.com/developers/docs/topics/oauth2
|
437
447
|
# @param name [String] What your application should be called.
|
438
448
|
# @param redirect_uris [Array<String>] URIs that Discord should redirect your users to after authorizing.
|
439
449
|
# @return [Array(String, String)] your applications' client ID and client secret to be used in OAuth authorization.
|
@@ -457,7 +467,7 @@ module Discordrb
|
|
457
467
|
# @return [User] The user identified by the mention, or `nil` if none exists.
|
458
468
|
def parse_mention(mention)
|
459
469
|
# Mention format: <@id>
|
460
|
-
return nil unless
|
470
|
+
return nil unless /<@!?(?<id>\d+)>?/ =~ mention
|
461
471
|
user(id.to_i)
|
462
472
|
end
|
463
473
|
|
@@ -724,6 +734,7 @@ module Discordrb
|
|
724
734
|
|
725
735
|
member = server.member(data['user']['id'].to_i)
|
726
736
|
member.update_roles(data['roles'])
|
737
|
+
member.update_nick(data['nick'])
|
727
738
|
end
|
728
739
|
|
729
740
|
# Internal handler for GUILD_MEMBER_DELETE
|
@@ -1095,7 +1106,7 @@ module Discordrb
|
|
1095
1106
|
return if message.from_bot? && !should_parse_self
|
1096
1107
|
|
1097
1108
|
unless message.author
|
1098
|
-
LOGGER.
|
1109
|
+
LOGGER.debug("Edited a message with nil author! Content: #{message.content.inspect}, channel: #{message.channel.inspect}")
|
1099
1110
|
return
|
1100
1111
|
end
|
1101
1112
|
|
@@ -1296,6 +1307,9 @@ module Discordrb
|
|
1296
1307
|
}
|
1297
1308
|
}
|
1298
1309
|
|
1310
|
+
# Discord is very strict about the existence of the shard parameter, so only add it if it actually exists
|
1311
|
+
packet[:d][:shard] = @shard_key if @shard_key
|
1312
|
+
|
1299
1313
|
@ws.send(packet.to_json)
|
1300
1314
|
end
|
1301
1315
|
|
@@ -1343,6 +1357,9 @@ module Discordrb
|
|
1343
1357
|
|
1344
1358
|
def send_heartbeat(sequence = nil)
|
1345
1359
|
sequence ||= @sequence
|
1360
|
+
|
1361
|
+
raise_event(HeartbeatEvent.new(self))
|
1362
|
+
|
1346
1363
|
LOGGER.out("Sending heartbeat with sequence #{sequence}")
|
1347
1364
|
data = {
|
1348
1365
|
op: Opcodes::HEARTBEAT,
|
@@ -23,9 +23,18 @@ module Discordrb::Commands
|
|
23
23
|
# Creates a new CommandBot and logs in to Discord.
|
24
24
|
# @param attributes [Hash] The attributes to initialize the CommandBot with.
|
25
25
|
# @see {Discordrb::Bot#initialize} for other attributes that should be used to create the underlying regular bot.
|
26
|
-
# @option attributes [String] :prefix The prefix that should trigger this bot's commands.
|
27
|
-
#
|
28
|
-
#
|
26
|
+
# @option attributes [String, Array<String>, #call] :prefix The prefix that should trigger this bot's commands. It
|
27
|
+
# can be:
|
28
|
+
#
|
29
|
+
# * Any string (including the empty string). This has the effect that if a message starts with the prefix, the
|
30
|
+
# prefix will be stripped and the rest of the chain will be parsed as a command chain. Note that it will be
|
31
|
+
# literal - if the prefix is "hi" then the corresponding trigger string for a command called "test" would be
|
32
|
+
# "hitest". Don't forget to put spaces in if you need them!
|
33
|
+
# * An array of prefixes. Those will behave similarly to setting one string as a prefix, but instead of only one
|
34
|
+
# string, any of the strings in the array can be used.
|
35
|
+
# * Something Proc-like (responds to :call) that takes a string as an argument (the message) and returns either
|
36
|
+
# the command chain in raw form or `nil` if the given string shouldn't be parsed. This can be used to make more
|
37
|
+
# complicated dynamic prefixes, or even something else entirely (suffixes, or most adventurous, infixes).
|
29
38
|
# @option attributes [true, false] :advanced_functionality Whether to enable advanced functionality (very powerful
|
30
39
|
# way to nest commands into chains, see https://github.com/meew0/discordrb/wiki/Commands#command-chain-syntax
|
31
40
|
# for info. Default is true.
|
@@ -62,7 +71,9 @@ module Discordrb::Commands
|
|
62
71
|
name: attributes[:name],
|
63
72
|
fancy_log: attributes[:fancy_log],
|
64
73
|
suppress_ready: attributes[:suppress_ready],
|
65
|
-
parse_self: attributes[:parse_self]
|
74
|
+
parse_self: attributes[:parse_self],
|
75
|
+
shard_id: attributes[:shard_id],
|
76
|
+
num_shards: attributes[:num_shards])
|
66
77
|
|
67
78
|
@prefix = attributes[:prefix]
|
68
79
|
@attributes = {
|
@@ -150,7 +161,8 @@ module Discordrb::Commands
|
|
150
161
|
event.respond @attributes[:command_doesnt_exist_message].gsub('%command%', name.to_s) if @attributes[:command_doesnt_exist_message]
|
151
162
|
return
|
152
163
|
end
|
153
|
-
if permission?(event.user, command.attributes[:permission_level], event.server)
|
164
|
+
if permission?(event.user, command.attributes[:permission_level], event.server) &&
|
165
|
+
required_permissions?(event.author, command.attributes[:required_permissions], event.channel)
|
154
166
|
event.command = command
|
155
167
|
result = command.call(event, arguments, chained)
|
156
168
|
stringify(result)
|
@@ -205,8 +217,8 @@ module Discordrb::Commands
|
|
205
217
|
|
206
218
|
event = CommandEvent.new(message, self)
|
207
219
|
|
208
|
-
|
209
|
-
|
220
|
+
chain = trigger?(message.content)
|
221
|
+
return unless chain
|
210
222
|
|
211
223
|
# Don't allow spaces between the prefix and the command
|
212
224
|
if chain.start_with?(' ') && !@attributes[:spaces_allowed]
|
@@ -222,6 +234,28 @@ module Discordrb::Commands
|
|
222
234
|
execute_chain(chain, event)
|
223
235
|
end
|
224
236
|
|
237
|
+
# Check whether a message should trigger command execution, and if it does, return the raw chain
|
238
|
+
def trigger?(message)
|
239
|
+
if @prefix.is_a? String
|
240
|
+
standard_prefix_trigger(message, @prefix)
|
241
|
+
elsif @prefix.is_a? Array
|
242
|
+
@prefix.map { |e| standard_prefix_trigger(message, e) }.reduce { |a, e| a || e }
|
243
|
+
elsif @prefix.respond_to? :call
|
244
|
+
@prefix.call(message)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def standard_prefix_trigger(message, prefix)
|
249
|
+
return nil unless message.start_with? prefix
|
250
|
+
message[prefix.length..-1]
|
251
|
+
end
|
252
|
+
|
253
|
+
def required_permissions?(member, required, channel = nil)
|
254
|
+
required.reduce(true) do |a, action|
|
255
|
+
a && member.permission?(action, channel)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
225
259
|
def execute_chain(chain, event)
|
226
260
|
t = Thread.new do
|
227
261
|
@event_threads << t
|
@@ -9,6 +9,9 @@ module Discordrb::Commands
|
|
9
9
|
module CommandContainer
|
10
10
|
include RateLimiter
|
11
11
|
|
12
|
+
# @return [Array<Command>] the list of commands this container has.
|
13
|
+
attr_reader :commands
|
14
|
+
|
12
15
|
# Adds a new command to the container.
|
13
16
|
# @param name [Symbol] The name of the command to add.
|
14
17
|
# @param attributes [Hash] The attributes to initialize the command with.
|
@@ -17,6 +20,8 @@ module Discordrb::Commands
|
|
17
20
|
# @option attributes [String, false] :permission_message Message to display when a user does not have sufficient
|
18
21
|
# permissions to execute a command. %name% in the message will be replaced with the name of the command. Disable
|
19
22
|
# the message by setting this option to false.
|
23
|
+
# @option attributes [Array<Symbol>] :required_permissions Discord action permissions (e.g. `:kick_members`) that
|
24
|
+
# should be required to use this command. See {Discordrb::Permissions::Flags} for a list.
|
20
25
|
# @option attributes [true, false] :chain_usable Whether this command is able to be used inside of a command chain
|
21
26
|
# or sub-chain. Typically used for administrative commands that shouldn't be done carelessly.
|
22
27
|
# @option attributes [true, false] :help_available Whether this command is visible in the help command. See the
|
@@ -19,6 +19,9 @@ module Discordrb::Commands
|
|
19
19
|
# Message to display when a user does not have sufficient permissions to execute a command
|
20
20
|
permission_message: (attributes[:permission_message].is_a? FalseClass) ? nil : (attributes[:permission_message] || "You don't have permission to execute command %name%!"),
|
21
21
|
|
22
|
+
# Discord action permissions required to use this command
|
23
|
+
required_permissions: attributes[:required_permissions] || [],
|
24
|
+
|
22
25
|
# Whether this command is usable in a command chain
|
23
26
|
chain_usable: attributes[:chain_usable].nil? ? true : attributes[:chain_usable],
|
24
27
|
|
data/lib/discordrb/container.rb
CHANGED
@@ -56,6 +56,21 @@ module Discordrb
|
|
56
56
|
register_event(DisconnectEvent, attributes, block)
|
57
57
|
end
|
58
58
|
|
59
|
+
# This **event** is raised every time the bot sends a heartbeat over the galaxy. This happens roughly every 40
|
60
|
+
# seconds, but may happen at a lower rate should Discord change their interval. It may also happen more quickly for
|
61
|
+
# periods of time, especially for unstable connections, since discordrb rather sends a heartbeat than not if there's
|
62
|
+
# a choice. (You shouldn't rely on all this to be accurately timed.)
|
63
|
+
#
|
64
|
+
# All this makes this event useful to periodically trigger something, like doing some API request every hour,
|
65
|
+
# setting some kind of uptime variable or whatever else. The only limit is yourself.
|
66
|
+
# @param attributes [Hash] Event attributes, none in this particular case
|
67
|
+
# @yield The block is executed when the event is raised.
|
68
|
+
# @yieldparam event [HeartbeatEvent] The event that was raised.
|
69
|
+
# @return [HeartbeatEventHandler] The event handler that was registered.
|
70
|
+
def heartbeat(attributes = {}, &block)
|
71
|
+
register_event(HeartbeatEvent, attributes, block)
|
72
|
+
end
|
73
|
+
|
59
74
|
# This **event** is raised when somebody starts typing in a channel the bot is also in. The official Discord
|
60
75
|
# client would display the typing indicator for five seconds after receiving this event. If the user continues
|
61
76
|
# typing after five seconds, the event will be re-raised.
|
data/lib/discordrb/data.rb
CHANGED
@@ -229,6 +229,10 @@ module Discordrb
|
|
229
229
|
# @return [Time] when this member joined the server.
|
230
230
|
attr_reader :joined_at
|
231
231
|
|
232
|
+
# @return [String, nil] the nickname this member has, or nil if it has none.
|
233
|
+
attr_reader :nick
|
234
|
+
alias_method :nickname, :nick
|
235
|
+
|
232
236
|
# @return [Array<Role>] the roles this member has.
|
233
237
|
attr_reader :roles
|
234
238
|
|
@@ -342,6 +346,8 @@ module Discordrb
|
|
342
346
|
# Initialize the roles by getting the roles from the server one-by-one
|
343
347
|
update_roles(data['roles'])
|
344
348
|
|
349
|
+
@nick = data['nick']
|
350
|
+
|
345
351
|
@deaf = data['deaf']
|
346
352
|
@mute = data['mute']
|
347
353
|
@joined_at = data['joined_at'] ? Time.parse(data['joined_at']) : nil
|
@@ -379,6 +385,23 @@ module Discordrb
|
|
379
385
|
API.update_user_roles(@bot.token, @server.id, @user.id, new_role_ids)
|
380
386
|
end
|
381
387
|
|
388
|
+
# Sets or resets this member's nickname. Requires the Change Nickname permission for the bot itself and Manage
|
389
|
+
# Nicknames for other users.
|
390
|
+
# @param nick [String, nil] The string to set the nickname to, or nil if it should be reset.
|
391
|
+
def nick=(nick)
|
392
|
+
# Discord uses the empty string to signify 'no nickname' so we convert nil into that
|
393
|
+
nick ||= ''
|
394
|
+
|
395
|
+
API.change_nickname(@bot.token, @server.id, @user.id, nick)
|
396
|
+
end
|
397
|
+
|
398
|
+
alias_method :nickname=, :nick=
|
399
|
+
|
400
|
+
# @return [String] the name the user displays as (nickname if they have one, username otherwise)
|
401
|
+
def display_name
|
402
|
+
nickname || username
|
403
|
+
end
|
404
|
+
|
382
405
|
# Update this member's roles
|
383
406
|
# @note For internal use only.
|
384
407
|
# @!visibility private
|
@@ -388,6 +411,13 @@ module Discordrb
|
|
388
411
|
end
|
389
412
|
end
|
390
413
|
|
414
|
+
# Update this member's nick
|
415
|
+
# @note For internal use only.
|
416
|
+
# @!visibility private
|
417
|
+
def update_nick(nick)
|
418
|
+
@nick = nick
|
419
|
+
end
|
420
|
+
|
391
421
|
# Update this member's voice state
|
392
422
|
# @note For internal use only.
|
393
423
|
# @!visibility private
|
@@ -540,6 +570,10 @@ module Discordrb
|
|
540
570
|
# @return [true, false] whether or not this role should be displayed separately from other users
|
541
571
|
attr_reader :hoist
|
542
572
|
|
573
|
+
# @return [true, false] whether this role can be mentioned using a role mention
|
574
|
+
attr_reader :mentionable
|
575
|
+
alias_method :mentionable?, :mentionable
|
576
|
+
|
543
577
|
# @return [ColourRGB] the role colour
|
544
578
|
attr_reader :colour
|
545
579
|
|
@@ -567,10 +601,18 @@ module Discordrb
|
|
567
601
|
@permissions = Permissions.new(data['permissions'], RoleWriter.new(self, @bot.token))
|
568
602
|
@name = data['name']
|
569
603
|
@id = data['id'].to_i
|
604
|
+
|
570
605
|
@hoist = data['hoist']
|
606
|
+
@mentionable = data['mentionable']
|
607
|
+
|
571
608
|
@colour = ColourRGB.new(data['color'])
|
572
609
|
end
|
573
610
|
|
611
|
+
# @return [String] a string that will mention this role, if it is mentionable.
|
612
|
+
def mention
|
613
|
+
"<@&#{@id}>"
|
614
|
+
end
|
615
|
+
|
574
616
|
# Updates the data cache from another Role object
|
575
617
|
# @note For internal use only
|
576
618
|
# @!visibility private
|
@@ -853,7 +895,7 @@ module Discordrb
|
|
853
895
|
# @param tts [true, false] Whether or not this message should be sent using Discord text-to-speech.
|
854
896
|
# @return [Message] the message that was sent.
|
855
897
|
def send_message(content, tts = false)
|
856
|
-
@bot.send_message(@id, content, tts)
|
898
|
+
@bot.send_message(@id, content, tts, @server && @server.id)
|
857
899
|
end
|
858
900
|
|
859
901
|
# Sends multiple messages to a channel
|
@@ -963,9 +1005,11 @@ module Discordrb
|
|
963
1005
|
JSON.parse(logs).map { |message| Message.new(message, @bot) }
|
964
1006
|
end
|
965
1007
|
|
966
|
-
# Deletes the last N messages on this channel.
|
967
|
-
#
|
968
|
-
#
|
1008
|
+
# Deletes the last N messages on this channel. Each delete request is performed in a separate thread for performance
|
1009
|
+
# reasons, so if a large number of messages are pruned, many threads will be created.
|
1010
|
+
# @note As of the April 29 update, the message delete request is rate limited, which means this method will take
|
1011
|
+
# a long time. It will eventually be updated to use batch deletes once those are released, but that will be in the
|
1012
|
+
# far future.
|
969
1013
|
# @param amount [Integer] How many messages to delete. Must be 100 or less (Discord limitation)
|
970
1014
|
# @raise [ArgumentError] if more than 100 messages are requested.
|
971
1015
|
def prune(amount)
|
@@ -1097,6 +1141,9 @@ module Discordrb
|
|
1097
1141
|
# @return [Array<User>] the users that were mentioned in this message.
|
1098
1142
|
attr_reader :mentions
|
1099
1143
|
|
1144
|
+
# @return [Array<Role>] the roles that were mentioned in this message.
|
1145
|
+
attr_reader :role_mentions
|
1146
|
+
|
1100
1147
|
# @return [Array<Attachment>] the files attached to this message.
|
1101
1148
|
attr_reader :attachments
|
1102
1149
|
|
@@ -1129,6 +1176,15 @@ module Discordrb
|
|
1129
1176
|
@mentions << bot.ensure_user(element)
|
1130
1177
|
end if data['mentions']
|
1131
1178
|
|
1179
|
+
@role_mentions = []
|
1180
|
+
|
1181
|
+
# Role mentions can only happen on public servers so make sure we only parse them there
|
1182
|
+
unless @channel.private?
|
1183
|
+
data['mention_roles'].each do |element|
|
1184
|
+
@role_mentions << @channel.server.role(element.to_i)
|
1185
|
+
end if data['mention_roles']
|
1186
|
+
end
|
1187
|
+
|
1132
1188
|
@attachments = []
|
1133
1189
|
@attachments = data['attachments'].map { |e| Attachment.new(e, self, @bot) } if data['attachments']
|
1134
1190
|
end
|
@@ -22,4 +22,10 @@ module Discordrb::Events
|
|
22
22
|
|
23
23
|
# Event handler for {DisconnectEvent}
|
24
24
|
class DisconnectEventHandler < TrueEventHandler; end
|
25
|
+
|
26
|
+
# @see Discordrb::EventContainer#heartbeat
|
27
|
+
class HeartbeatEvent < LifetimeEvent; end
|
28
|
+
|
29
|
+
# Event handler for {HeartbeatEvent}
|
30
|
+
class HeartbeatEventHandler < TrueEventHandler; end
|
25
31
|
end
|
@@ -32,7 +32,9 @@ module Discordrb
|
|
32
32
|
22 => :mute_members, # 4194304
|
33
33
|
23 => :deafen_members, # 8388608
|
34
34
|
24 => :move_members, # 16777216
|
35
|
-
25 => :use_voice_activity
|
35
|
+
25 => :use_voice_activity, # 33554432
|
36
|
+
26 => :change_nickname, # 67108864
|
37
|
+
27 => :manage_nicknames # 134217728
|
36
38
|
}.freeze
|
37
39
|
|
38
40
|
Flags.each do |position, flag|
|
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: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- meew0
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-04-
|
11
|
+
date: 2016-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|