discorb 0.14.0 → 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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build_version.yml +1 -1
  3. data/.github/workflows/lint-push.yml +4 -2
  4. data/.rubocop.yml +6 -2
  5. data/Changelog.md +27 -0
  6. data/Rakefile +6 -0
  7. data/docs/events.md +71 -5
  8. data/docs/faq.md +8 -8
  9. data/examples/simple/rolepanel.rb +1 -1
  10. data/examples/simple/shard.rb +17 -0
  11. data/lib/discorb/allowed_mentions.rb +7 -0
  12. data/lib/discorb/app_command/command.rb +64 -2
  13. data/lib/discorb/app_command/handler.rb +1 -1
  14. data/lib/discorb/application.rb +16 -7
  15. data/lib/discorb/asset.rb +9 -0
  16. data/lib/discorb/{file.rb → attachment.rb} +55 -33
  17. data/lib/discorb/audit_logs.rb +42 -4
  18. data/lib/discorb/channel.rb +47 -12
  19. data/lib/discorb/client.rb +135 -51
  20. data/lib/discorb/common.rb +18 -4
  21. data/lib/discorb/components/button.rb +5 -6
  22. data/lib/discorb/components/select_menu.rb +2 -16
  23. data/lib/discorb/dictionary.rb +2 -0
  24. data/lib/discorb/embed.rb +71 -38
  25. data/lib/discorb/emoji.rb +29 -2
  26. data/lib/discorb/emoji_table.rb +1 -1
  27. data/lib/discorb/error.rb +7 -1
  28. data/lib/discorb/event.rb +27 -17
  29. data/lib/discorb/exe/new.rb +5 -5
  30. data/lib/discorb/exe/run.rb +1 -15
  31. data/lib/discorb/gateway.rb +262 -161
  32. data/lib/discorb/gateway_requests.rb +4 -7
  33. data/lib/discorb/guild.rb +67 -33
  34. data/lib/discorb/guild_template.rb +24 -3
  35. data/lib/discorb/http.rb +25 -3
  36. data/lib/discorb/integration.rb +23 -8
  37. data/lib/discorb/intents.rb +15 -10
  38. data/lib/discorb/interaction/autocomplete.rb +4 -4
  39. data/lib/discorb/interaction/command.rb +34 -5
  40. data/lib/discorb/interaction/components.rb +15 -2
  41. data/lib/discorb/interaction/response.rb +12 -0
  42. data/lib/discorb/interaction/root.rb +16 -1
  43. data/lib/discorb/invite.rb +11 -7
  44. data/lib/discorb/member.rb +21 -0
  45. data/lib/discorb/message.rb +59 -3
  46. data/lib/discorb/message_meta.rb +36 -55
  47. data/lib/discorb/modules.rb +38 -14
  48. data/lib/discorb/permission.rb +14 -5
  49. data/lib/discorb/presence.rb +41 -8
  50. data/lib/discorb/rate_limit.rb +7 -2
  51. data/lib/discorb/reaction.rb +6 -0
  52. data/lib/discorb/role.rb +12 -0
  53. data/lib/discorb/shard.rb +74 -0
  54. data/lib/discorb/sticker.rb +22 -14
  55. data/lib/discorb/user.rb +11 -0
  56. data/lib/discorb/voice_state.rb +20 -2
  57. data/lib/discorb/webhook.rb +53 -2
  58. data/lib/discorb.rb +5 -3
  59. data/sig/discorb.rbs +7234 -6714
  60. metadata +5 -4
  61. data/lib/discorb/log.rb +0 -81
@@ -14,7 +14,10 @@ module Discorb
14
14
  # @return [Array<Discorb::AuditLog::Entry>] The entries in this audit log.
15
15
  attr_reader :entries
16
16
 
17
+ #
18
+ # Initializes a new instance of the AuditLog class.
17
19
  # @private
20
+ #
18
21
  def initialize(client, data, guild)
19
22
  @client = client
20
23
  @guild = guild
@@ -24,6 +27,10 @@ module Discorb
24
27
  @entries = data[:audit_log_entries].map { |entry| AuditLog::Entry.new(@client, entry, guild.id) }
25
28
  end
26
29
 
30
+ def inspect
31
+ "<#{self.class} #{@entries.length} entries>"
32
+ end
33
+
27
34
  #
28
35
  # Gets an entry from entries.
29
36
  #
@@ -108,8 +115,11 @@ module Discorb
108
115
  # @!attribute [r] user
109
116
  # @return [Discorb::User] The user who performed the action.
110
117
 
118
+ #
119
+ # @return [{Integer => Symbol}] The map of events to their respective changes.
111
120
  # @private
112
- @events = {
121
+ #
122
+ EVENTS = {
113
123
  1 => :guild_update,
114
124
  10 => :channel_create,
115
125
  11 => :channel_update,
@@ -159,24 +169,30 @@ module Discorb
159
169
  112 => :thread_delete,
160
170
  }.freeze
161
171
 
172
+ #
173
+ # The converter for the change.
162
174
  # @private
163
- @converts = {
175
+ #
176
+ CONVERTERS = {
164
177
  channel: ->(client, id, _guild_id) { client.channels[id] },
165
178
  thread: ->(client, id, _guild_id) { client.channels[id] },
166
179
  role: ->(client, id, guild_id) { client.guilds[guild_id]&.roles&.[](id) },
167
180
  member: ->(client, id, guild_id) { client.guilds[guild_id]&.members&.[](id) },
168
181
  guild: ->(client, id, _guild_id) { client.guilds[id] },
169
182
  message: ->(client, id, _guild_id) { client.messages[id] },
170
- }
183
+ }.freeze
171
184
 
185
+ #
186
+ # Initializes a new AuditLog entry.
172
187
  # @private
188
+ #
173
189
  def initialize(client, data, guild_id)
174
190
  @client = client
175
191
  @guild_id = Snowflake.new(guild_id)
176
192
  @id = Snowflake.new(data[:id])
177
193
  @user_id = Snowflake.new(data[:user_id])
178
194
  @target_id = Snowflake.new(data[:target_id])
179
- @type = self.class.events[data[:action_type]]
195
+ @type = EVENTS[data[:action_type]]
180
196
  @target = self.class.converts[@type.to_s.split("_")[0].to_sym]&.call(client, @target_id, @gui)
181
197
  @target ||= Snowflake.new(data[:target_id])
182
198
  @changes = data[:changes] && Changes.new(data[:changes])
@@ -223,8 +239,11 @@ module Discorb
223
239
  attr_reader :data
224
240
 
225
241
  #
242
+ # Initializes a new changes object.
226
243
  # @private
227
244
  #
245
+ # @param [Hash] data The data to initialize with.
246
+ #
228
247
  def initialize(data)
229
248
  @data = data.to_h { |d| [d[:key].to_sym, d] }
230
249
  @data.each do |k, v|
@@ -232,6 +251,9 @@ module Discorb
232
251
  end
233
252
  end
234
253
 
254
+ #
255
+ # Formats the changes into a string.
256
+ #
235
257
  def inspect
236
258
  "#<#{self.class} #{@data.length} changes>"
237
259
  end
@@ -270,7 +292,10 @@ module Discorb
270
292
  # @return [Object] The new value of the change.
271
293
  attr_reader :new_value
272
294
 
295
+ #
296
+ # Initializes a new change object.
273
297
  # @private
298
+ #
274
299
  def initialize(data)
275
300
  @key = data[:key].to_sym
276
301
  method = case @key.to_s
@@ -298,10 +323,20 @@ module Discorb
298
323
  @new_value.__send__(method, ...)
299
324
  end
300
325
 
326
+ #
327
+ # Format the change into a string.
328
+ #
329
+ # @return [String] The string representation of the change.
330
+ #
301
331
  def inspect
302
332
  "#<#{self.class} #{@key.inspect} #{@old_value.inspect} -> #{@new_value.inspect}>"
303
333
  end
304
334
 
335
+ #
336
+ # Whether the change responds to the given method.
337
+ #
338
+ # @return [Boolean] Whether the change responds to the given method.
339
+ #
305
340
  def respond_to_missing?(method, include_private = false)
306
341
  @new_value.respond_to?(method, include_private)
307
342
  end
@@ -321,7 +356,10 @@ module Discorb
321
356
  # @return [Discorb::Integration::Account] The account of the integration.
322
357
  attr_reader :account
323
358
 
359
+ #
360
+ # Initializes a new integration object.
324
361
  # @private
362
+ #
325
363
  def initialize(data)
326
364
  @id = Snowflake.new(data[:id])
327
365
  @type = data[:type].to_sym
@@ -19,7 +19,10 @@ module Discorb
19
19
  @channel_type = nil
20
20
  @subclasses = []
21
21
 
22
+ #
23
+ # Initializes a new instance of the Channel class.
22
24
  # @private
25
+ #
23
26
  def initialize(client, data, no_cache: false)
24
27
  @client = client
25
28
  @data = {}
@@ -44,22 +47,35 @@ module Discorb
44
47
  "#<#{self.class} \"##{@name}\" id=#{@id}>"
45
48
  end
46
49
 
50
+ #
51
+ # Returns the descendants of the Channel class.
47
52
  # @private
53
+ #
48
54
  def self.descendants
49
55
  ObjectSpace.each_object(Class).select { |klass| klass < self }
50
56
  end
51
57
 
58
+ #
59
+ # Creates a new instance of the Channel class or instance of its descendants.
52
60
  # @private
61
+ #
62
+ # @param [Discorb::Client] client The client that instantiated the object.
63
+ # @param [Hash] data The data of the object.
64
+ # @param [Boolean] no_cache Whether to disable cache the object.
65
+ #
53
66
  def self.make_channel(client, data, no_cache: false)
54
67
  descendants.each do |klass|
55
68
  return klass.new(client, data, no_cache: no_cache) if !klass.channel_type.nil? && klass.channel_type == data[:type]
56
69
  end
57
- client.log.warn("Unknown channel type #{data[:type]}, initialized GuildChannel")
70
+ client.logger.warn("Unknown channel type #{data[:type]}, initialized GuildChannel")
58
71
  GuildChannel.new(client, data)
59
72
  end
60
73
 
61
74
  class << self
75
+ #
62
76
  # @private
77
+ # @return [Integer] The type of the channel.
78
+ #
63
79
  attr_reader :channel_type
64
80
  end
65
81
 
@@ -67,7 +83,12 @@ module Discorb
67
83
  self.class.channel_type
68
84
  end
69
85
 
86
+ #
87
+ # Returns the channel id to request.
70
88
  # @private
89
+ #
90
+ # @return [Async::Task<Discorb::Snowflake>] A task that resolves to the channel id.
91
+ #
71
92
  def channel_id
72
93
  Async do
73
94
  @id
@@ -114,7 +135,7 @@ module Discorb
114
135
  #
115
136
  # @param [Discorb::GuildChannel] other The channel to compare.
116
137
  #
117
- # @return [-1, 1] -1 if the channel is at lower than the other, 1 if the channel is at highter than the other.
138
+ # @return [-1, 0, 1] -1 if the channel is at lower than the other, 1 if the channel is at highter than the other.
118
139
  #
119
140
  def <=>(other)
120
141
  return 0 unless other.respond_to?(:position)
@@ -239,17 +260,15 @@ module Discorb
239
260
  # @return [Time] The time when the last pinned message was pinned.
240
261
  attr_reader :last_pin_timestamp
241
262
  alias last_pinned_at last_pin_timestamp
242
- # @return [Array<Discorb::ThreadChannel>] The threads in the channel.
243
- attr_reader :threads
244
263
 
245
264
  include Messageable
246
265
 
247
266
  @channel_type = 0
248
267
 
249
- # @private
250
- def initialize(client, data, no_cache: false)
251
- super
252
- @threads = Dictionary.new
268
+ # @!attribute [r] threads
269
+ # @return [Array<Discorb::ThreadChannel>] The threads in the channel.
270
+ def threads
271
+ guild.threads.select { |thread| thread.parent == self }
253
272
  end
254
273
 
255
274
  #
@@ -421,7 +440,7 @@ module Discorb
421
440
  def fetch_invites
422
441
  Async do
423
442
  _resp, data = @client.http.request(Route.new("/channels/#{@id}/invites", "//channels/:channel_id/invites", :get)).wait
424
- data.map { |invite| Invite.new(@client, invite) }
443
+ data.map { |invite| Invite.new(@client, invite, false) }
425
444
  end
426
445
  end
427
446
 
@@ -446,7 +465,7 @@ module Discorb
446
465
  temporary: temporary,
447
466
  unique: unique,
448
467
  }, audit_log_reason: reason).wait
449
- Invite.new(@client, data)
468
+ Invite.new(@client, data, false)
450
469
  end
451
470
  end
452
471
 
@@ -666,7 +685,10 @@ module Discorb
666
685
  attr_reader :bitrate
667
686
  # @return [Integer] The user limit of the voice channel.
668
687
  attr_reader :user_limit
688
+ #
669
689
  # @private
690
+ # @return [Discorb::Dictionary{Discorb::Snowflake => StageInstance}] The stage instances associated with the stage channel.
691
+ #
670
692
  attr_reader :stage_instances
671
693
 
672
694
  include Connectable
@@ -675,7 +697,10 @@ module Discorb
675
697
  # @return [Discorb::StageInstance] The stage instance of the channel.
676
698
 
677
699
  @channel_type = 13
700
+ #
701
+ # Initialize a new stage channel.
678
702
  # @private
703
+ #
679
704
  def initialize(...)
680
705
  @stage_instances = Dictionary.new
681
706
  super(...)
@@ -825,12 +850,17 @@ module Discorb
825
850
  include Messageable
826
851
  @channel_type = nil
827
852
 
853
+ #
854
+ # Initialize a new thread channel.
828
855
  # @private
856
+ #
857
+ # @param [Discorb::Client] client The client.
858
+ # @param [Hash] data The data of the thread channel.
859
+ # @param [Boolean] no_cache Whether to disable the cache.
860
+ #
829
861
  def initialize(client, data, no_cache: false)
830
862
  @members = Dictionary.new
831
863
  super
832
- @client.channels[@parent_id].threads[@id] = self
833
-
834
864
  @client.channels[@id] = self unless no_cache
835
865
  end
836
866
 
@@ -1117,7 +1147,12 @@ module Discorb
1117
1147
  class DMChannel < Channel
1118
1148
  include Messageable
1119
1149
 
1150
+ #
1151
+ # Returns the channel id to request.
1120
1152
  # @private
1153
+ #
1154
+ # @return [Async::Task<Discorb::Snowflake>] A task that resolves to the channel id.
1155
+ #
1121
1156
  def channel_id
1122
1157
  Async do
1123
1158
  @id
@@ -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,12 +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
53
+ # @return [Hash{Integer => Discorb::Shard}] The shards of the client.
54
+ attr_reader :shards
57
55
  # @private
56
+ # @return [Hash{Discorb::Snowflake => Discorb::ApplicationCommand::Command}] The commands on the top level.
58
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.
59
73
 
60
74
  #
61
75
  # Initializes a new client.
@@ -63,8 +77,7 @@ module Discorb
63
77
  # @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions that the client is using.
64
78
  # @param [Discorb::Intents] intents The intents that the client is currently using.
65
79
  # @param [Integer] message_caches The number of messages to cache.
66
- # @param [#write] log The IO object to use for logging.
67
- # @param [Boolean] colorize_log Whether to colorize the log.
80
+ # @param [Logger] logger The IO object to use for logging.
68
81
  # @param [:debug, :info, :warn, :error, :critical] log_level The log level.
69
82
  # @param [Boolean] wait_until_ready Whether to delay event dispatch until ready.
70
83
  # @param [Boolean] fetch_member Whether to fetch member on ready. This may slow down the client. Default to `false`.
@@ -72,7 +85,7 @@ module Discorb
72
85
  #
73
86
  def initialize(
74
87
  allowed_mentions: nil, intents: nil, message_caches: 1000,
75
- log: nil, colorize_log: false, log_level: :info,
88
+ logger: nil,
76
89
  wait_until_ready: true, fetch_member: false,
77
90
  title: nil
78
91
  )
@@ -80,7 +93,7 @@ module Discorb
80
93
  @intents = (intents or Intents.default)
81
94
  @events = {}
82
95
  @api_version = nil
83
- @log = Logger.new(log, colorize_log, log_level)
96
+ @logger = logger || Logger.new($stdout, progname: "discorb")
84
97
  @user = nil
85
98
  @users = Discorb::Dictionary.new
86
99
  @channels = Discorb::Dictionary.new
@@ -100,6 +113,8 @@ module Discorb
100
113
  @fetch_member = fetch_member
101
114
  @title = title
102
115
  @extensions = {}
116
+ @mutex = {}
117
+ @shards = {}
103
118
  set_default_events
104
119
  end
105
120
 
@@ -180,16 +195,16 @@ module Discorb
180
195
  events << event_method
181
196
  end
182
197
  if events.nil?
183
- @log.debug "Event #{event_name} doesn't have any proc, skipping"
198
+ logger.debug "Event #{event_name} doesn't have any proc, skipping"
184
199
  next
185
200
  end
186
- @log.debug "Dispatching event #{event_name}"
201
+ logger.debug "Dispatching event #{event_name}"
187
202
  events.each do |block|
188
203
  Async do
189
204
  Async(annotation: "Discorb event: #{event_name}") do |_task|
190
205
  @events[event_name].delete(block) if block.is_a?(Discorb::EventHandler) && block.metadata[:once]
191
206
  block.call(*args)
192
- @log.debug "Dispatched proc with ID #{block.id.inspect}"
207
+ logger.debug "Dispatched proc with ID #{block.id.inspect}"
193
208
  rescue StandardError, ScriptError => e
194
209
  dispatch(:error, event_name, args, e)
195
210
  end
@@ -309,10 +324,11 @@ module Discorb
309
324
  activities: [],
310
325
  status: status,
311
326
  since: nil,
327
+ afk: nil,
312
328
  }
313
329
  payload[:activities] = [activity.to_hash] unless activity.nil?
314
330
  payload[:status] = status unless status.nil?
315
- if @connection
331
+ if connection
316
332
  Async do
317
333
  send_gateway(3, **payload)
318
334
  end
@@ -423,15 +439,15 @@ module Discorb
423
439
  #
424
440
  # @note If the token is nil, you should use `discorb run` with the `-e` or `--env` option.
425
441
  #
426
- def run(token = nil)
442
+ def run(token = nil, shards: nil, shard_count: nil)
427
443
  token ||= ENV["DISCORB_CLI_TOKEN"]
428
444
  raise ArgumentError, "Token is not specified, and -e/--env is not specified" if token.nil?
429
445
  case ENV["DISCORB_CLI_FLAG"]
430
446
  when nil
431
- start_client(token)
447
+ start_client(token, shards: shards, shard_count: shard_count)
432
448
  when "run"
433
449
  before_run(token)
434
- start_client(token)
450
+ start_client(token, shards: shards, shard_count: shard_count)
435
451
  when "setup"
436
452
  run_setup(token)
437
453
  end
@@ -441,10 +457,33 @@ module Discorb
441
457
  # Stops the client.
442
458
  #
443
459
  def close!
444
- @connection.send_close
460
+ if @shards.any?
461
+ @shards.each(&:close!)
462
+ else
463
+ @connection.send_close
464
+ end
445
465
  @tasks.each(&:stop)
446
466
  @status = :closed
447
- @close_condition.signal
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")
448
487
  end
449
488
 
450
489
  private
@@ -453,22 +492,6 @@ module Discorb
453
492
  require "json"
454
493
  options = JSON.parse(ENV["DISCORB_CLI_OPTIONS"], symbolize_names: true)
455
494
  setup_commands(token) if options[:setup]
456
- if options[:log_level]
457
- if options[:log_level] == "none"
458
- @log.out = nil
459
- else
460
- @log.out = case options[:log_file]
461
- when nil, "stderr"
462
- $stderr
463
- when "stdout"
464
- $stdout
465
- else
466
- ::File.open(options[:log_file], "a")
467
- end
468
- @log.level = options[:log_level].to_sym
469
- @log.colorize_log = options[:log_color].nil? ? @log.out.isatty : options[:log_color]
470
- end
471
- end
472
495
  end
473
496
 
474
497
  def run_setup(token)
@@ -486,32 +509,93 @@ module Discorb
486
509
  end
487
510
  end
488
511
 
489
- def start_client(token)
490
- Async do |_task|
491
- Signal.trap(:SIGINT) do
492
- @log.info "SIGINT received, closing..."
493
- Signal.trap(:SIGINT, "DEFAULT")
494
- close!
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)
495
557
  end
496
- @token = token.to_s
497
- @close_condition = Async::Condition.new
498
- @main_task = Async do
499
- @status = :running
500
- connect_gateway(false).wait
501
- rescue StandardError
502
- @status = :stopped
503
- @close_condition.signal
504
- raise
558
+ @shards[..-1].each_with_index do |shard, i|
559
+ shard.next_shard = @shards[i + 1]
505
560
  end
506
- @close_condition.wait
507
- @main_task.stop
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
508
592
  end
509
593
  end
510
594
 
511
595
  def set_default_events
512
596
  on :error, override: true do |event_name, _args, e|
513
597
  message = "An error occurred while dispatching #{event_name}:\n#{e.full_message}"
514
- @log.error message, fallback: $stderr
598
+ logger.error message, fallback: $stderr
515
599
  end
516
600
 
517
601
  once :standby do
@@ -2,9 +2,11 @@
2
2
 
3
3
  module Discorb
4
4
  # @return [String] The API base URL.
5
- API_BASE_URL = "https://discord.com/api/v9"
5
+ API_BASE_URL = "https://discord.com/api/v10"
6
6
  # @return [String] The version of discorb.
7
- VERSION = "0.14.0"
7
+ VERSION = "0.16.0"
8
+ # @return [Array<Integer>] The version array of discorb.
9
+ VERSION_ARRAY = VERSION.split(".").map(&:to_i).freeze
8
10
  # @return [String] The user agent for the bot.
9
11
  USER_AGENT = "DiscordBot (https://discorb-lib.github.io #{VERSION}) Ruby/#{RUBY_VERSION}".freeze
10
12
 
@@ -25,8 +27,11 @@ module Discorb
25
27
  end
26
28
  end
27
29
 
28
- # @private
30
+ def inspect
31
+ "#<#{self.class}: #{@id}>"
32
+ end
29
33
 
34
+ # @private
30
35
  def hash
31
36
  @id.hash
32
37
  end
@@ -37,7 +42,12 @@ module Discorb
37
42
  #
38
43
  # @see https://discord.com/developers/docs/reference#snowflakes Official Discord API docs
39
44
  class Snowflake < String
45
+ #
46
+ # Initialize new snowflake.
40
47
  # @private
48
+ #
49
+ # @param [#to_s] value The value of the snowflake.
50
+ #
41
51
  def initialize(value)
42
52
  @value = value.to_i
43
53
  super(@value.to_s)
@@ -92,7 +102,7 @@ module Discorb
92
102
  end
93
103
 
94
104
  def timestamp
95
- Time.at(((@value >> 22) + 1_420_070_400_000) / 1000)
105
+ Time.at(((@value >> 22) + 1_420_070_400_000) / 1000.0)
96
106
  end
97
107
 
98
108
  def worker_id
@@ -127,6 +137,10 @@ module Discorb
127
137
  @method = method
128
138
  end
129
139
 
140
+ def inspect
141
+ "#<#{self.class} #{self.identifier}>"
142
+ end
143
+
130
144
  def hash
131
145
  @url.hash
132
146
  end
@@ -21,7 +21,9 @@ module Discorb
21
21
  attr_accessor :disabled
22
22
  alias disabled? disabled
23
23
 
24
- @styles = {
24
+ # @private
25
+ # @return [{Symbol => Integer}] The mapping of button styles.
26
+ STYLES = {
25
27
  primary: 1,
26
28
  secondary: 2,
27
29
  success: 3,
@@ -59,7 +61,7 @@ module Discorb
59
61
  {
60
62
  type: 2,
61
63
  label: @label,
62
- style: self.class.styles[@style],
64
+ style: STYLES[@style],
63
65
  url: @url,
64
66
  emoji: @emoji&.to_hash,
65
67
  disabled: @disabled,
@@ -68,7 +70,7 @@ module Discorb
68
70
  {
69
71
  type: 2,
70
72
  label: @label,
71
- style: self.class.styles[@style],
73
+ style: STYLES[@style],
72
74
  custom_id: @custom_id,
73
75
  emoji: @emoji&.to_hash,
74
76
  disabled: @disabled,
@@ -81,9 +83,6 @@ module Discorb
81
83
  end
82
84
 
83
85
  class << self
84
- # @private
85
- attr_reader :styles
86
-
87
86
  #
88
87
  # Creates a new button from a hash.
89
88
  #