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
@@ -6,7 +6,12 @@ module Discorb
6
6
  # @private
7
7
  #
8
8
  class RatelimitHandler
9
+ #
10
+ # Initialize a rate limit handler.
9
11
  # @private
12
+ #
13
+ # @param [Discorb::Client] client The client.
14
+ #
10
15
  def initialize(client)
11
16
  @client = client
12
17
  @path_ratelimit_bucket = {}
@@ -27,7 +32,7 @@ module Discorb
27
32
  # return if path.url.start_with?("https://")
28
33
  if @global && @global > Time.now.to_f
29
34
  time = @global - Time.now.to_f
30
- @client.log.info("global rate limit reached, waiting #{time} seconds")
35
+ @client.logger.info("global rate limit reached, waiting #{time} seconds")
31
36
  sleep(time)
32
37
  @global = false
33
38
  end
@@ -43,7 +48,7 @@ module Discorb
43
48
  return if (bucket[:remaining]).positive?
44
49
 
45
50
  time = bucket[:reset_at] - Time.now.to_f
46
- @client.log.info("rate limit for #{path.identifier} with #{path.major_param} reached, waiting #{time.round(4)} seconds")
51
+ @client.logger.info("rate limit for #{path.identifier} with #{path.major_param} reached, waiting #{time.round(4)} seconds")
47
52
  sleep(time)
48
53
  end
49
54
 
@@ -16,7 +16,13 @@ module Discorb
16
16
  alias me? me
17
17
  alias reacted? me
18
18
 
19
+ #
20
+ # Initialize a new reaction.
19
21
  # @private
22
+ #
23
+ # @param [Discorb::Message] message The message that this reaction is on.
24
+ # @param [Hash] data The data of the reaction.
25
+ #
20
26
  def initialize(message, data)
21
27
  @message = message
22
28
  _set_data(data)
data/lib/discorb/role.rb CHANGED
@@ -42,7 +42,14 @@ module Discorb
42
42
 
43
43
  include Comparable
44
44
 
45
+ #
46
+ # Initializes a new role.
45
47
  # @private
48
+ #
49
+ # @param [Discorb::Client] client The client.
50
+ # @param [Discorb::Guild] guild The guild the role belongs to.
51
+ # @param [Hash] data The data of the role.
52
+ #
46
53
  def initialize(client, guild, data)
47
54
  @client = client
48
55
  @guild = guild
@@ -176,7 +183,12 @@ module Discorb
176
183
  # @!attribute [r] integration?
177
184
  # @return [Boolean] Whether the role is an integration role.
178
185
 
186
+ #
187
+ # Initializes a new tag.
179
188
  # @private
189
+ #
190
+ # @param [Hash] data The data of the tag.
191
+ #
180
192
  def initialize(data)
181
193
  @bot_id = Snowflake.new(data[:bot_id])
182
194
  @integration_id = Snowflake.new(data[:integration_id])
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discorb
4
+ #
5
+ # Represents a shard.
6
+ #
7
+ class Shard
8
+ # @return [Integer] The ID of the shard.
9
+ attr_reader :id
10
+ # @return [Thread] The thread of the shard.
11
+ attr_reader :thread
12
+ # @return [Logger] The logger of the shard.
13
+ attr_reader :logger
14
+ # @private
15
+ # @return [Integer] The internal index of the shard.
16
+ attr_reader :index
17
+ # @private
18
+ attr_accessor :status, :connection, :session_id, :next_shard, :main_task
19
+
20
+ #
21
+ # Initializes a new shard.
22
+ # @private
23
+ #
24
+ # @param [Discorb::Client] client The client.
25
+ # @param [Integer] id The ID of the shard.
26
+ # @param [Integer] count The number of shards.
27
+ # @param [Integer] index The index of the shard.
28
+ #
29
+ def initialize(client, id, count, index)
30
+ @client = client
31
+ @id = id
32
+ @shard_count = count
33
+ @status = :idle
34
+ @index = index
35
+ @session_id = nil
36
+ @next_shard = nil
37
+ @main_task = nil
38
+ @logger = client.logger.dup.tap { |l| l.progname = "discorb: shard #{id}" }
39
+ @thread = Thread.new do
40
+ Thread.current.thread_variable_set("shard_id", id)
41
+ Thread.current.thread_variable_set("shard", self)
42
+ if @index.positive?
43
+ Thread.stop
44
+ sleep 5 # Somehow discord disconnects the shard without a little sleep.
45
+ end
46
+ client.send(:main_loop, id)
47
+ end
48
+ end
49
+
50
+ #
51
+ # Starts the shard.
52
+ #
53
+ # @return [void]
54
+ #
55
+ def start
56
+ @thread.wakeup
57
+ end
58
+
59
+ #
60
+ # Stops the shard.
61
+ #
62
+ # @return [void]
63
+ #
64
+ def close!
65
+ @status = :closed
66
+ @main_task&.stop
67
+ @thread.kill
68
+ end
69
+
70
+ def inspect
71
+ "#<#{self.class} #{id}/#{@shard_count} #{@status}>"
72
+ end
73
+ end
74
+ end
@@ -29,16 +29,27 @@ module Discorb
29
29
  attr_reader :available
30
30
  alias available? available
31
31
 
32
- @sticker_type = {
32
+ # @private
33
+ # @return [{Integer => Symbol}] The mapping of sticker types.
34
+ STICKER_TYPE = {
33
35
  1 => :official,
34
36
  2 => :guild,
35
37
  }.freeze
36
- @sticker_format = {
38
+
39
+ # @private
40
+ # @return [{Integer => Symbol}] The mapping of sticker format.
41
+ STICKER_FORMAT = {
37
42
  1 => :png,
38
43
  2 => :apng,
39
44
  3 => :lottie,
40
- }
45
+ }.freeze
46
+ #
47
+ # Initialize a new sticker.
41
48
  # @private
49
+ #
50
+ # @param [Discorb::Client] client The client.
51
+ # @param [Hash] data The sticker data.
52
+ #
42
53
  def initialize(client, data)
43
54
  @client = client
44
55
  _set_data(data)
@@ -51,15 +62,6 @@ module Discorb
51
62
  # @!attribute [r] guild
52
63
  # @macro client_cache
53
64
  # @return [Discorb::Guild] The guild the sticker is in.
54
- @sticker_type = {
55
- 1 => :official,
56
- 2 => :guild,
57
- }.freeze
58
- @sticker_format = {
59
- 1 => :png,
60
- 2 => :apng,
61
- 3 => :lottie,
62
- }
63
65
 
64
66
  def guild
65
67
  @client.guilds[@guild_id]
@@ -121,7 +123,13 @@ module Discorb
121
123
  # @return [Discorb::Asset] The banner of the pack.
122
124
  attr_reader :banner
123
125
 
126
+ #
127
+ # Initialize a new sticker pack.
124
128
  # @private
129
+ #
130
+ # @param [Discorb::Client] client The client.
131
+ # @param [Hash] data The sticker pack data.
132
+ #
125
133
  def initialize(client, data)
126
134
  @client = client
127
135
  @id = Snowflake.new(data[:id])
@@ -141,8 +149,8 @@ module Discorb
141
149
  @id = Snowflake.new(data[:id])
142
150
  @name = data[:name]
143
151
  @tags = data[:tags].split(",")
144
- @type = self.class.sticker_type[data[:type]]
145
- @format = self.class.sticker_format[data[:format]]
152
+ @type = STICKER_TYPE[data[:type]]
153
+ @format = STICKER_FORMAT[data[:format]]
146
154
  @description = data[:description]
147
155
  @available = data[:available]
148
156
  if @type == :official
data/lib/discorb/user.rb CHANGED
@@ -29,7 +29,13 @@ module Discorb
29
29
  # @!attribute [r] mention
30
30
  # @return [String] The user's mention.
31
31
 
32
+ #
33
+ # Initializes a new user.
32
34
  # @private
35
+ #
36
+ # @param [Discorb::Client] client The client.
37
+ # @param [Hash] data The user data.
38
+ #
33
39
  def initialize(client, data)
34
40
  @client = client
35
41
  @data = {}
@@ -79,7 +85,12 @@ module Discorb
79
85
 
80
86
  alias app_owner? bot_owner?
81
87
 
88
+ #
89
+ # Returns the dm channel id of the user.
82
90
  # @private
91
+ #
92
+ # @return [Async::Task<Discorb::Snowflake>] A task that resolves to the channel id.
93
+ #
83
94
  def channel_id
84
95
  Async do
85
96
  next @dm_channel_id if @dm_channel_id
@@ -46,7 +46,13 @@ module Discorb
46
46
  # @macro client_cache
47
47
  # @return [Discorb::User] The user this voice state is for.
48
48
 
49
+ #
50
+ # Initialize a new voice state.
49
51
  # @private
52
+ #
53
+ # @param [Discorb::Client] client The client this voice state belongs to.
54
+ # @param [Hash] data The data of the voice state.
55
+ #
50
56
  def initialize(client, data)
51
57
  @client = client
52
58
  _set_data(data)
@@ -135,7 +141,14 @@ module Discorb
135
141
  2 => :guild_only,
136
142
  }
137
143
 
144
+ #
145
+ # Initialize a new instance of the StageInstance class.
138
146
  # @private
147
+ #
148
+ # @param [Discorb::Client] client The client.
149
+ # @param [Hash] data The data of the stage instance.
150
+ # @param [Boolean] no_cache Whether to disable caching.
151
+ #
139
152
  def initialize(client, data, no_cache: false)
140
153
  @client = client
141
154
  @data = data
@@ -182,7 +195,7 @@ module Discorb
182
195
  Async do
183
196
  payload = {}
184
197
  payload[:topic] = topic if topic != Discorb::Unset
185
- payload[:privacy_level] = self.class.privacy_level.key(privacy_level) if privacy_level != Discorb::Unset
198
+ payload[:privacy_level] = PRIVACY_LEVEL.key(privacy_level) if privacy_level != Discorb::Unset
186
199
  @client.http.request(
187
200
  Route.new("/stage-instances/#{@channel_id}", "//stage-instances/:channel_id", :patch), payload, audit_log_reason: reason,
188
201
  ).wait
@@ -216,7 +229,7 @@ module Discorb
216
229
  @guild_id = Snowflake.new(data[:guild_id])
217
230
  @channel_id = Snowflake.new(data[:channel_id])
218
231
  @topic = data[:topic]
219
- @privacy_level = self.class.privacy_level[data[:privacy_level]]
232
+ @privacy_level = PRIVACY_LEVEL[data[:privacy_level]]
220
233
  @discoverable_disabled = data[:discoverable_disabled]
221
234
  end
222
235
 
@@ -246,7 +259,12 @@ module Discorb
246
259
  attr_reader :custom
247
260
  alias custom? custom
248
261
 
262
+ #
263
+ # Initialize a new instance of the VoiceRegion class.
249
264
  # @private
265
+ #
266
+ # @param [Hash] data The data of the voice region.
267
+ #
250
268
  def initialize(data)
251
269
  @id = data[:id]
252
270
  @name = data[:name]
@@ -22,7 +22,13 @@ module Discorb
22
22
  # @return [String] The URL of the webhook.
23
23
  attr_reader :token
24
24
 
25
+ #
26
+ # Initializes a webhook.
25
27
  # @private
28
+ #
29
+ # @param [Discorb::Client] client The client.
30
+ # @param [Hash] data The data of the webhook.
31
+ #
26
32
  def initialize(client, data)
27
33
  @name = data[:name]
28
34
  @guild_id = data[:guild_id] && Snowflake.new(data[:guild_id])
@@ -200,7 +206,13 @@ module Discorb
200
206
  # @!attribute [r] url
201
207
  # @return [String] The URL of the webhook.
202
208
 
209
+ #
210
+ # Initializes the incoming webhook.
203
211
  # @private
212
+ #
213
+ # @param [Discorb::Client] client The client.
214
+ # @param [String] url The URL of the webhook.
215
+ #
204
216
  def initialize(client, data)
205
217
  super
206
218
  @token = data[:token]
@@ -222,7 +234,13 @@ module Discorb
222
234
  # Represents a source channel of follower webhook.
223
235
  # @return [Discorb::Channel, Discorb::Webhook::FollowerWebhook::Channel] The source channel of follower webhook.
224
236
 
237
+ #
238
+ # Initializes the follower webhook.
225
239
  # @private
240
+ #
241
+ # @param [Discorb::Client] client The client.
242
+ # @param [Hash] data The data of the follower webhook.
243
+ #
226
244
  def initialize(client, data)
227
245
  super
228
246
  @source_guild = FollowerWebhook::Guild.new(data[:source_guild])
@@ -248,12 +266,21 @@ module Discorb
248
266
  # @return [Discorb::Asset] The icon of the guild.
249
267
  attr_reader :icon
250
268
 
269
+ #
270
+ # Initialize a new guild.
251
271
  # @private
272
+ #
273
+ # @param [Hash] data The data of the guild.
274
+ #
252
275
  def initialize(data)
253
276
  @id = Snowflake.new(data[:id])
254
277
  @name = data[:name]
255
278
  @icon = Asset.new(self, data[:icon])
256
279
  end
280
+
281
+ def inspect
282
+ "#<#{self.class.name} #{@id}: #{@name}>"
283
+ end
257
284
  end
258
285
 
259
286
  #
@@ -265,11 +292,20 @@ module Discorb
265
292
  # @return [String] The name of the channel.
266
293
  attr_reader :name
267
294
 
295
+ #
296
+ # Initialize a new channel.
268
297
  # @private
298
+ #
299
+ # @param [Hash] data The data of the channel.
300
+ #
269
301
  def initialize(data)
270
302
  @id = Snowflake.new(data[:id])
271
303
  @name = data[:name]
272
304
  end
305
+
306
+ def inspect
307
+ "#<#{self.class.name} #{@id}: #{@name}>"
308
+ end
273
309
  end
274
310
  end
275
311
 
@@ -290,7 +326,13 @@ module Discorb
290
326
  # @return [Discorb::Snowflake] The ID of the guild.
291
327
  attr_reader :guild_id
292
328
 
329
+ #
330
+ # Initializes the message.
293
331
  # @private
332
+ #
333
+ # @param [Discorb::Webhook] webhook The webhook.
334
+ # @param [Hash] data The data of the message.
335
+ # @param [Discorb::Client] client The client. This will be nil if it's created from {URLWebhook}.
294
336
  def initialize(webhook, data, client = nil)
295
337
  @client = client
296
338
  @webhook = webhook
@@ -329,12 +371,12 @@ module Discorb
329
371
 
330
372
  def _set_data(data)
331
373
  @id = Snowflake.new(data[:id])
332
- @type = Discorb::Message.message_type[data[:type]]
374
+ @type = Discorb::Message::MESSAGE_TYPE[data[:type]]
333
375
  @content = data[:content]
334
376
  @channel_id = Snowflake.new(data[:channel_id])
335
377
  @author = Author.new(data[:author])
336
378
  @attachments = data[:attachments].map { |a| Attachment.new(a) }
337
- @embeds = data[:embeds] ? data[:embeds].map { |e| Embed.new(data: e) } : []
379
+ @embeds = data[:embeds] ? data[:embeds].map { |e| Embed.from_hash(e) } : []
338
380
  @mentions = data[:mentions].map { |m| Mention.new(m) }
339
381
  @mention_roles = data[:mention_roles].map { |m| Snowflake.new(m) }
340
382
  @mention_everyone = data[:mention_everyone]
@@ -364,7 +406,12 @@ module Discorb
364
406
  # @return [String] The discriminator of the author.
365
407
  attr_reader :discriminator
366
408
 
409
+ #
410
+ # Initializes the author.
367
411
  # @private
412
+ #
413
+ # @param [Hash] data The data of the author.
414
+ #
368
415
  def initialize(data)
369
416
  @data = data
370
417
  @bot = data[:bot]
@@ -384,6 +431,10 @@ module Discorb
384
431
  end
385
432
 
386
433
  alias to_s_user to_s
434
+
435
+ def inspect
436
+ "#<#{self.class.name} #{self}>"
437
+ end
387
438
  end
388
439
  end
389
440
 
data/lib/discorb.rb CHANGED
@@ -4,7 +4,10 @@
4
4
  #
5
5
  # @author sevenc-nanashi
6
6
  module Discorb
7
+ #
8
+ # Method to define a macro for YARD.
7
9
  # @private
10
+ #
8
11
  # @!macro [new] async
9
12
  # @note This is an asynchronous method, it will return a `Async::Task` object. Use `Async::Task#wait` to get the result.
10
13
  #
@@ -23,7 +26,6 @@ module Discorb
23
26
  # @raise [Discorb::HTTPError] HTTP request failed.
24
27
  #
25
28
  def macro
26
- # NOTE: this method is only for YARD.
27
29
  puts "Wow, You found the easter egg!\n"
28
30
  red = "\e[31m"
29
31
  reset = "\e[m"
@@ -43,10 +45,10 @@ require_order = %w[common flag dictionary error rate_limit http intents emoji_ta
43
45
  %w[message_meta allowed_mentions] +
44
46
  %w[user member guild emoji channel embed message] +
45
47
  %w[application audit_logs color components event event_handler] +
46
- %w[file guild_template image integration interaction invite log permission] +
48
+ %w[attachment guild_template image integration interaction invite permission] +
47
49
  %w[presence reaction role sticker utils voice_state webhook] +
48
50
  %w[gateway_requests gateway app_command] +
49
- %w[asset extension client extend]
51
+ %w[asset extension shard client extend]
50
52
  require_order.each do |name|
51
53
  require_relative "discorb/#{name}.rb"
52
54
  end