discorb 0.15.1 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Changelog.md +9 -0
- data/docs/events.md +21 -5
- data/examples/simple/rolepanel.rb +1 -1
- data/examples/simple/shard.rb +17 -0
- data/lib/discorb/app_command/handler.rb +1 -1
- data/lib/discorb/channel.rb +1 -1
- data/lib/discorb/client.rb +133 -53
- data/lib/discorb/common.rb +1 -1
- data/lib/discorb/exe/new.rb +5 -5
- data/lib/discorb/exe/run.rb +1 -15
- data/lib/discorb/gateway.rb +180 -142
- data/lib/discorb/http.rb +2 -2
- data/lib/discorb/interaction/autocomplete.rb +2 -2
- data/lib/discorb/interaction/command.rb +2 -2
- data/lib/discorb/interaction/components.rb +1 -1
- data/lib/discorb/interaction/root.rb +1 -1
- data/lib/discorb/rate_limit.rb +2 -2
- data/lib/discorb/shard.rb +74 -0
- data/lib/discorb.rb +2 -2
- data/sig/discorb.rbs +7234 -6850
- metadata +4 -3
- data/lib/discorb/log.rb +0 -81
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6537aa3c45f64e6b0e8040a5a0d989934fb58d766ee6de305bf04132630a7b94
|
4
|
+
data.tar.gz: 68512bc0d2abd0738cc6e81ba2b794feb87480d6d84197a51a6deba739d31d5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 239e4658a2ade0ea8382655970a1eecbb3c62c7c3619e3de8fdf932c1c0a4053e35b722bef5dcdbd67477754388cc3c157c9be6360ef7625fe9f84504b5ecf90
|
7
|
+
data.tar.gz: d830a06c7a505ee31aeb3242e7aa59dadf6abab24a26c357b9e29e5f94d5fef7a889b114d4b7793ffda3f50b19a6be0c3f87921934393b03e71c5f50bfa96de4
|
data/Changelog.md
CHANGED
@@ -4,6 +4,15 @@
|
|
4
4
|
|
5
5
|
# Changelog
|
6
6
|
|
7
|
+
## v0.16
|
8
|
+
|
9
|
+
### v0.16.0
|
10
|
+
|
11
|
+
- Change!: Use built-in Logger instead of custom Logger.
|
12
|
+
- Delete!: `--log-level`, `--[no-]log-color` is deleted.
|
13
|
+
- Add: Support sharding
|
14
|
+
- Add: Use Mutex for preventing connection duplications.
|
15
|
+
|
7
16
|
## v0.15
|
8
17
|
|
9
18
|
### v0.15.1
|
data/docs/events.md
CHANGED
@@ -30,13 +30,13 @@ class << client
|
|
30
30
|
end
|
31
31
|
```
|
32
32
|
|
33
|
-
If you want to
|
33
|
+
If you want to separate event handlers from the client, consider using {Discorb::Extension}. {file:docs/extension.md Learn more about extensions}.
|
34
34
|
|
35
|
-
Since v0.6.1, you can set `:override` to `true` to register
|
35
|
+
Since v0.6.1, you can set `:override` to `true` to register event handlers that can be overridden.
|
36
36
|
|
37
37
|
```ruby
|
38
38
|
client.on :message, override: true do |event|
|
39
|
-
puts "This event handler
|
39
|
+
puts "This event handler can be overridden."
|
40
40
|
end
|
41
41
|
|
42
42
|
client.on :message do |event|
|
@@ -44,8 +44,8 @@ client.on :message do |event|
|
|
44
44
|
end
|
45
45
|
```
|
46
46
|
|
47
|
-
This example will print `Override!`, but not `This event handler
|
48
|
-
This is useful for registering event handlers as default
|
47
|
+
This example will print `Override!`, but not `This event handler can be overridden.`.
|
48
|
+
This is useful for registering event handlers as default behavior, such as error handlers.
|
49
49
|
|
50
50
|
```ruby
|
51
51
|
# In the library...
|
@@ -95,6 +95,22 @@ Defaults to printing the error to stderr, override to handle it yourself.
|
|
95
95
|
Fires when `discorb setup` is run.
|
96
96
|
This is useful for setting up some dependencies, such as the database.
|
97
97
|
|
98
|
+
#### `shard_standby(shard)`
|
99
|
+
|
100
|
+
Fires when a shard is standby.
|
101
|
+
|
102
|
+
| Parameter | Type | Description |
|
103
|
+
| ---------- | ----- | ----------- |
|
104
|
+
|`shard` | {Discorb::Shard} | The shard that is standby. |
|
105
|
+
|
106
|
+
#### `shard_resumed(shard)`
|
107
|
+
|
108
|
+
Fires when a shard is resumed connection.
|
109
|
+
|
110
|
+
| Parameter | Type | Description |
|
111
|
+
| ---------- | ----- | ----------- |
|
112
|
+
|`shard` | {Discorb::Shard} | The shard that is standby. |
|
113
|
+
|
98
114
|
### Guild events
|
99
115
|
|
100
116
|
#### `guild_join(guild)`
|
@@ -2,7 +2,7 @@
|
|
2
2
|
require "discorb"
|
3
3
|
intents = Discorb::Intents.new
|
4
4
|
intents.members = true
|
5
|
-
client = Discorb::Client.new(intents: intents
|
5
|
+
client = Discorb::Client.new(intents: intents)
|
6
6
|
|
7
7
|
def convert_role(guild, string)
|
8
8
|
guild.roles.find do |role|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "discorb"
|
3
|
+
|
4
|
+
client = Discorb::Client.new(log: Logger.new($stdout))
|
5
|
+
|
6
|
+
client.once :standby do
|
7
|
+
puts "Logged in as #{client.user}"
|
8
|
+
end
|
9
|
+
|
10
|
+
client.on :message do |message|
|
11
|
+
next if message.author.bot?
|
12
|
+
next unless message.content == "!inspect"
|
13
|
+
|
14
|
+
message.channel.post("I'm #{client.user}, running on shard #{client.shard_id}!")
|
15
|
+
end
|
16
|
+
|
17
|
+
client.run(ENV["DISCORD_BOT_TOKEN"], shards: [0, 1], shard_count: 2)
|
data/lib/discorb/channel.rb
CHANGED
@@ -67,7 +67,7 @@ module Discorb
|
|
67
67
|
descendants.each do |klass|
|
68
68
|
return klass.new(client, data, no_cache: no_cache) if !klass.channel_type.nil? && klass.channel_type == data[:type]
|
69
69
|
end
|
70
|
-
client.
|
70
|
+
client.logger.warn("Unknown channel type #{data[:type]}, initialized GuildChannel")
|
71
71
|
GuildChannel.new(client, data)
|
72
72
|
end
|
73
73
|
|
data/lib/discorb/client.rb
CHANGED
@@ -40,8 +40,6 @@ module Discorb
|
|
40
40
|
attr_reader :emojis
|
41
41
|
# @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::Message}] A dictionary of messages.
|
42
42
|
attr_reader :messages
|
43
|
-
# @return [Discorb::Logger] The logger.
|
44
|
-
attr_reader :log
|
45
43
|
# @return [Array<Discorb::ApplicationCommand::Command>] The commands that the client is using.
|
46
44
|
attr_reader :commands
|
47
45
|
# @return [Float] The ping of the client.
|
@@ -50,15 +48,28 @@ module Discorb
|
|
50
48
|
attr_reader :ping
|
51
49
|
# @return [:initialized, :running, :closed] The status of the client.
|
52
50
|
attr_reader :status
|
53
|
-
# @return [Integer] The session ID of connection.
|
54
|
-
attr_reader :session_id
|
55
51
|
# @return [Hash{String => Discorb::Extension}] The loaded extensions.
|
56
52
|
attr_reader :extensions
|
57
|
-
#
|
53
|
+
# @return [Hash{Integer => Discorb::Shard}] The shards of the client.
|
54
|
+
attr_reader :shards
|
58
55
|
# @private
|
59
56
|
# @return [Hash{Discorb::Snowflake => Discorb::ApplicationCommand::Command}] The commands on the top level.
|
60
|
-
#
|
61
57
|
attr_reader :bottom_commands
|
58
|
+
# @private
|
59
|
+
# @return [{String => Thread::Mutex}] A hash of mutexes.
|
60
|
+
attr_reader :mutex
|
61
|
+
|
62
|
+
# @!attribute [r] session_id
|
63
|
+
# @return [String] The session ID of the client or current shard.
|
64
|
+
# @return [nil] If not connected to the gateway.
|
65
|
+
# @!attribute [r] shard
|
66
|
+
# @return [Discorb::Shard] The current shard. This is implemented with Thread variables.
|
67
|
+
# @return [nil] If client has no shard.
|
68
|
+
# @!attribute [r] shard_id
|
69
|
+
# @return [Discorb::Shard] The current shard ID. This is implemented with Thread variables.
|
70
|
+
# @return [nil] If client has no shard.
|
71
|
+
# @!attribute [r] logger
|
72
|
+
# @return [Logger] The logger.
|
62
73
|
|
63
74
|
#
|
64
75
|
# Initializes a new client.
|
@@ -66,8 +77,7 @@ module Discorb
|
|
66
77
|
# @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions that the client is using.
|
67
78
|
# @param [Discorb::Intents] intents The intents that the client is currently using.
|
68
79
|
# @param [Integer] message_caches The number of messages to cache.
|
69
|
-
# @param [
|
70
|
-
# @param [Boolean] colorize_log Whether to colorize the log.
|
80
|
+
# @param [Logger] logger The IO object to use for logging.
|
71
81
|
# @param [:debug, :info, :warn, :error, :critical] log_level The log level.
|
72
82
|
# @param [Boolean] wait_until_ready Whether to delay event dispatch until ready.
|
73
83
|
# @param [Boolean] fetch_member Whether to fetch member on ready. This may slow down the client. Default to `false`.
|
@@ -75,7 +85,7 @@ module Discorb
|
|
75
85
|
#
|
76
86
|
def initialize(
|
77
87
|
allowed_mentions: nil, intents: nil, message_caches: 1000,
|
78
|
-
|
88
|
+
logger: nil,
|
79
89
|
wait_until_ready: true, fetch_member: false,
|
80
90
|
title: nil
|
81
91
|
)
|
@@ -83,7 +93,7 @@ module Discorb
|
|
83
93
|
@intents = (intents or Intents.default)
|
84
94
|
@events = {}
|
85
95
|
@api_version = nil
|
86
|
-
@
|
96
|
+
@logger = logger || Logger.new($stdout, progname: "discorb")
|
87
97
|
@user = nil
|
88
98
|
@users = Discorb::Dictionary.new
|
89
99
|
@channels = Discorb::Dictionary.new
|
@@ -103,6 +113,8 @@ module Discorb
|
|
103
113
|
@fetch_member = fetch_member
|
104
114
|
@title = title
|
105
115
|
@extensions = {}
|
116
|
+
@mutex = {}
|
117
|
+
@shards = {}
|
106
118
|
set_default_events
|
107
119
|
end
|
108
120
|
|
@@ -183,16 +195,16 @@ module Discorb
|
|
183
195
|
events << event_method
|
184
196
|
end
|
185
197
|
if events.nil?
|
186
|
-
|
198
|
+
logger.debug "Event #{event_name} doesn't have any proc, skipping"
|
187
199
|
next
|
188
200
|
end
|
189
|
-
|
201
|
+
logger.debug "Dispatching event #{event_name}"
|
190
202
|
events.each do |block|
|
191
203
|
Async do
|
192
204
|
Async(annotation: "Discorb event: #{event_name}") do |_task|
|
193
205
|
@events[event_name].delete(block) if block.is_a?(Discorb::EventHandler) && block.metadata[:once]
|
194
206
|
block.call(*args)
|
195
|
-
|
207
|
+
logger.debug "Dispatched proc with ID #{block.id.inspect}"
|
196
208
|
rescue StandardError, ScriptError => e
|
197
209
|
dispatch(:error, event_name, args, e)
|
198
210
|
end
|
@@ -316,7 +328,7 @@ module Discorb
|
|
316
328
|
}
|
317
329
|
payload[:activities] = [activity.to_hash] unless activity.nil?
|
318
330
|
payload[:status] = status unless status.nil?
|
319
|
-
if
|
331
|
+
if connection
|
320
332
|
Async do
|
321
333
|
send_gateway(3, **payload)
|
322
334
|
end
|
@@ -427,15 +439,15 @@ module Discorb
|
|
427
439
|
#
|
428
440
|
# @note If the token is nil, you should use `discorb run` with the `-e` or `--env` option.
|
429
441
|
#
|
430
|
-
def run(token = nil)
|
442
|
+
def run(token = nil, shards: nil, shard_count: nil)
|
431
443
|
token ||= ENV["DISCORB_CLI_TOKEN"]
|
432
444
|
raise ArgumentError, "Token is not specified, and -e/--env is not specified" if token.nil?
|
433
445
|
case ENV["DISCORB_CLI_FLAG"]
|
434
446
|
when nil
|
435
|
-
start_client(token)
|
447
|
+
start_client(token, shards: shards, shard_count: shard_count)
|
436
448
|
when "run"
|
437
449
|
before_run(token)
|
438
|
-
start_client(token)
|
450
|
+
start_client(token, shards: shards, shard_count: shard_count)
|
439
451
|
when "setup"
|
440
452
|
run_setup(token)
|
441
453
|
end
|
@@ -445,10 +457,33 @@ module Discorb
|
|
445
457
|
# Stops the client.
|
446
458
|
#
|
447
459
|
def close!
|
448
|
-
@
|
460
|
+
if @shards.any?
|
461
|
+
@shards.each(&:close!)
|
462
|
+
else
|
463
|
+
@connection.send_close
|
464
|
+
end
|
449
465
|
@tasks.each(&:stop)
|
450
466
|
@status = :closed
|
451
|
-
|
467
|
+
end
|
468
|
+
|
469
|
+
def session_id
|
470
|
+
if shard
|
471
|
+
shard.session_id
|
472
|
+
else
|
473
|
+
@session_id
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
def logger
|
478
|
+
shard&.logger || @logger
|
479
|
+
end
|
480
|
+
|
481
|
+
def shard
|
482
|
+
Thread.current.thread_variable_get("shard")
|
483
|
+
end
|
484
|
+
|
485
|
+
def shard_id
|
486
|
+
Thread.current.thread_variable_get("shard_id")
|
452
487
|
end
|
453
488
|
|
454
489
|
private
|
@@ -457,22 +492,6 @@ module Discorb
|
|
457
492
|
require "json"
|
458
493
|
options = JSON.parse(ENV["DISCORB_CLI_OPTIONS"], symbolize_names: true)
|
459
494
|
setup_commands(token) if options[:setup]
|
460
|
-
if options[:log_level]
|
461
|
-
if options[:log_level] == "none"
|
462
|
-
@log.out = nil
|
463
|
-
else
|
464
|
-
@log.out = case options[:log_file]
|
465
|
-
when nil, "stderr"
|
466
|
-
$stderr
|
467
|
-
when "stdout"
|
468
|
-
$stdout
|
469
|
-
else
|
470
|
-
::File.open(options[:log_file], "a")
|
471
|
-
end
|
472
|
-
@log.level = options[:log_level].to_sym
|
473
|
-
@log.colorize_log = options[:log_color].nil? ? @log.out.isatty : options[:log_color]
|
474
|
-
end
|
475
|
-
end
|
476
495
|
end
|
477
496
|
|
478
497
|
def run_setup(token)
|
@@ -490,32 +509,93 @@ module Discorb
|
|
490
509
|
end
|
491
510
|
end
|
492
511
|
|
493
|
-
def
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
512
|
+
def set_status(status, shard)
|
513
|
+
if shard.nil?
|
514
|
+
@status = status
|
515
|
+
else
|
516
|
+
@shards[shard].status = status
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
def connection
|
521
|
+
if shard_id
|
522
|
+
@shards[shard_id].connection
|
523
|
+
else
|
524
|
+
@connection
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
def connection=(value)
|
529
|
+
if shard_id
|
530
|
+
@shards[shard_id].connection = value
|
531
|
+
else
|
532
|
+
@connection = value
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
def session_id=(value)
|
537
|
+
if shard_id
|
538
|
+
@shards[shard_id].session_id = value
|
539
|
+
else
|
540
|
+
@session_id = value
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
def start_client(token, shards: nil, shard_count: nil)
|
545
|
+
@token = token.to_s
|
546
|
+
@shard_count = shard_count
|
547
|
+
Signal.trap(:SIGINT) do
|
548
|
+
logger.info "SIGINT received, closing..."
|
549
|
+
Signal.trap(:SIGINT, "DEFAULT")
|
550
|
+
close!
|
551
|
+
end
|
552
|
+
if shards.nil?
|
553
|
+
main_loop(nil)
|
554
|
+
else
|
555
|
+
@shards = shards.map.with_index do |shard, i|
|
556
|
+
Shard.new(self, shard, shard_count, i)
|
499
557
|
end
|
500
|
-
@
|
501
|
-
|
502
|
-
@main_task = Async do
|
503
|
-
@status = :running
|
504
|
-
connect_gateway(false).wait
|
505
|
-
rescue StandardError
|
506
|
-
@status = :stopped
|
507
|
-
@close_condition.signal
|
508
|
-
raise
|
558
|
+
@shards[..-1].each_with_index do |shard, i|
|
559
|
+
shard.next_shard = @shards[i + 1]
|
509
560
|
end
|
510
|
-
@
|
511
|
-
|
561
|
+
@shards.each { |s| s.thread.join }
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
565
|
+
def main_loop(shard)
|
566
|
+
close_condition = Async::Condition.new
|
567
|
+
self.main_task = Async do
|
568
|
+
set_status(:running, shard)
|
569
|
+
connect_gateway(false).wait
|
570
|
+
rescue StandardError
|
571
|
+
set_status(:running, shard)
|
572
|
+
close_condition.signal
|
573
|
+
raise
|
574
|
+
end
|
575
|
+
close_condition.wait
|
576
|
+
main_task.stop
|
577
|
+
end
|
578
|
+
|
579
|
+
def main_task
|
580
|
+
if shard_id
|
581
|
+
shard.main_task
|
582
|
+
else
|
583
|
+
@main_task
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
587
|
+
def main_task=(value)
|
588
|
+
if shard_id
|
589
|
+
shard.main_task = value
|
590
|
+
else
|
591
|
+
@main_task = value
|
512
592
|
end
|
513
593
|
end
|
514
594
|
|
515
595
|
def set_default_events
|
516
596
|
on :error, override: true do |event_name, _args, e|
|
517
597
|
message = "An error occurred while dispatching #{event_name}:\n#{e.full_message}"
|
518
|
-
|
598
|
+
logger.error message, fallback: $stderr
|
519
599
|
end
|
520
600
|
|
521
601
|
once :standby do
|
data/lib/discorb/common.rb
CHANGED
@@ -4,7 +4,7 @@ module Discorb
|
|
4
4
|
# @return [String] The API base URL.
|
5
5
|
API_BASE_URL = "https://discord.com/api/v10"
|
6
6
|
# @return [String] The version of discorb.
|
7
|
-
VERSION = "0.
|
7
|
+
VERSION = "0.16.0"
|
8
8
|
# @return [Array<Integer>] The version array of discorb.
|
9
9
|
VERSION_ARRAY = VERSION.split(".").map(&:to_i).freeze
|
10
10
|
# @return [String] The user agent for the bot.
|
data/lib/discorb/exe/new.rb
CHANGED
@@ -164,8 +164,8 @@ def git_init
|
|
164
164
|
system "git add ."
|
165
165
|
system "git commit -m \"Initial commit\""
|
166
166
|
sputs "Initialized repository, use " \
|
167
|
-
|
168
|
-
|
167
|
+
"\e[32mgit commit --amend -m '...'\e[92m" \
|
168
|
+
" to change commit message of initial commit.\n"
|
169
169
|
end
|
170
170
|
|
171
171
|
# @private
|
@@ -228,9 +228,9 @@ if (dir = ARGV[0])
|
|
228
228
|
iputs "Found \e[30m#{dir}\e[90m and empty, using this directory."
|
229
229
|
elsif $values[:force]
|
230
230
|
iputs "Found \e[30m#{dir}\e[90m and not empty, but force is on, using this directory."
|
231
|
-
|
232
|
-
|
233
|
-
|
231
|
+
else
|
232
|
+
eputs "Directory \e[31m#{dir}\e[91m already exists and not empty. Use \e[31m-f\e[91m to force."
|
233
|
+
exit
|
234
234
|
end
|
235
235
|
else
|
236
236
|
Dir.mkdir($path)
|
data/lib/discorb/exe/run.rb
CHANGED
@@ -4,10 +4,9 @@ require "optparse"
|
|
4
4
|
require "json"
|
5
5
|
require "discorb/utils/colored_puts"
|
6
6
|
require "io/console"
|
7
|
+
require "discorb"
|
7
8
|
|
8
9
|
ARGV.delete_at 0
|
9
|
-
# @private
|
10
|
-
LOG_LEVELS = %w[none debug info warn error fatal].freeze
|
11
10
|
|
12
11
|
opt = OptionParser.new <<~BANNER
|
13
12
|
This command will run a client.
|
@@ -18,23 +17,10 @@ opt = OptionParser.new <<~BANNER
|
|
18
17
|
BANNER
|
19
18
|
options = {
|
20
19
|
title: nil,
|
21
|
-
log_level: nil,
|
22
|
-
log_file: nil,
|
23
|
-
log_color: nil,
|
24
20
|
setup: nil,
|
25
21
|
token: false,
|
26
22
|
bundler: :default,
|
27
23
|
}
|
28
|
-
opt.on("-l", "--log-level LEVEL", "Log level.") do |v|
|
29
|
-
unless LOG_LEVELS.include? v.downcase
|
30
|
-
eputs "Invalid log level: \e[31m#{v}\e[91m"
|
31
|
-
eputs "Valid log levels: \e[31m#{LOG_LEVELS.join("\e[91m, \e[31m")}\e[91m"
|
32
|
-
exit 1
|
33
|
-
end
|
34
|
-
options[:log_level] = v.downcase
|
35
|
-
end
|
36
|
-
opt.on("-f", "--log-file FILE", "File to write log to.") { |v| options[:log_file] = v }
|
37
|
-
opt.on("-c", "--[no-]log-color", "Whether to colorize log output.") { |v| options[:log_color] = v }
|
38
24
|
opt.on("-s", "--setup", "Whether to setup application commands.") { |v| options[:setup] = v }
|
39
25
|
opt.on("-e", "--env [ENV]", "The name of the environment variable to use for token, or just `-e` or `--env` for intractive prompt.") { |v| options[:token] = v }
|
40
26
|
opt.on("-t", "--title TITLE", "The title of process.") { |v| options[:title] = v }
|