discorb 0.9.4 → 0.10.1

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.
data/docs/extension.md CHANGED
@@ -2,16 +2,16 @@
2
2
 
3
3
  # Extension
4
4
 
5
- Extension allows you to split your code into multiple files.
5
+ Extension allows you to seperate your code from the main application.
6
+
7
+ # @since
6
8
 
7
9
  ## Make a new extension
8
10
 
9
- Make a new module, and extend {Discorb::Extension}.
11
+ Make a new class that extends Extension.
10
12
 
11
13
  ```ruby
12
- module MyExtension
13
- extend Discorb::Extension
14
-
14
+ class MyExtension < Discorb::Extension
15
15
  # ...
16
16
  end
17
17
  ```
@@ -21,27 +21,25 @@ end
21
21
  Use {Discorb::Extension.event} to register event, or {Discorb::Extension.once_event} to register event only once.
22
22
 
23
23
  ```ruby
24
- module MyExtension
25
- extend Discorb::Extension
26
-
24
+ class MyExtension < Discorb::Extension
27
25
  event :message do |message|
28
26
  # ...
29
27
  end
30
28
 
31
- once_event :ready do |message|
29
+ once_event :standby do |message|
32
30
  # ...
33
31
  end
34
32
  end
35
33
  ```
36
34
 
35
+ Note block will be binded to the extension instance.
36
+
37
37
  ## Register Command
38
38
 
39
- Since v0.5.2, {Discorb::Extension} includes {Discorb::ApplicationCommand::Handler} module, so you can register command with {Discorb::ApplicationCommand::Handler#slash} and {Discorb::ApplicationCommand::Handler#slash_group}.
39
+ Use `Discorb::Extension.command` to register command, see {Discorb::ApplicationCommand::Handler} for more information.
40
40
 
41
41
  ```ruby
42
- module MyExtension
43
- extend Discorb::Extension
44
-
42
+ class MyExtension < Discorb::Extension
45
43
  slash("command", "Command") do |interaction|
46
44
  # ...
47
45
  end
@@ -63,18 +61,16 @@ end
63
61
 
64
62
  ## Load extension
65
63
 
66
- Use {Discorb::Client#extend} to load extension.
64
+ Use {Discorb::Client#load_extension} to load extension.
67
65
 
68
66
  ```ruby
69
- module MyExtension
70
- extend Discorb::Extension
71
-
67
+ class MyExtension < Discorb::Extension
72
68
  event :message do |message|
73
69
  # ...
74
70
  end
75
71
  end
76
72
 
77
- client.extend MyExtension
73
+ client.load_extension(MyExtension)
78
74
  ```
79
75
 
80
76
  ## Access Client from extension
@@ -82,10 +78,8 @@ client.extend MyExtension
82
78
  You can access {Discorb::Client} from extension with `@client`.
83
79
 
84
80
  ```ruby
85
- module MyExtension
86
- extend Discorb::Extension
87
-
88
- event :ready do |message|
81
+ class MyExtension < Discorb::Extension
82
+ event :standby do |message|
89
83
  puts "Logged in as #{@client.user}"
90
84
  end
91
85
  end
data/docs/license.md CHANGED
@@ -4,4 +4,8 @@
4
4
 
5
5
  discorb is licensed under the [MIT license](https://opensource.org/licenses/MIT).
6
6
 
7
- {include:file:License.txt}
7
+ ----
8
+
9
+ {include:file:LICENSE.txt}
10
+
11
+ ----
@@ -7,6 +7,6 @@ client.once :standby do
7
7
  puts "Logged in as #{client.user}"
8
8
  end
9
9
 
10
- client.extend(MessageExpander)
10
+ client.load_extension(MessageExpander)
11
11
 
12
12
  client.run(ENV["DISCORD_BOT_TOKEN"])
@@ -1,9 +1,7 @@
1
1
  require "discorb"
2
2
 
3
- module MessageExpander
4
- extend Discorb::Extension
5
-
6
- @message_regex = Regexp.new(
3
+ class MessageExpander < Discorb::Extension
4
+ @@message_regex = Regexp.new(
7
5
  '(?!<)https://(?:ptb\.|canary\.)?discord(?:app)?\.com/channels/' \
8
6
  "(?<guild>[0-9]{18})/(?<channel>[0-9]{18})/(?<message>[0-9]{18})(?!>)"
9
7
  )
@@ -11,7 +9,7 @@ module MessageExpander
11
9
  event :message do |message|
12
10
  next if message.author.bot?
13
11
 
14
- message.content.to_enum(:scan, @message_regex).map { Regexp.last_match }.each do |match|
12
+ message.content.to_enum(:scan, @@message_regex).map { Regexp.last_match }.each do |match|
15
13
  ch = @client.channels[match[:channel]]
16
14
  next if ch.nil?
17
15
 
@@ -27,7 +25,7 @@ module MessageExpander
27
25
  author: Discorb::Embed::Author.new(
28
26
  url_message.author.name,
29
27
  url: url_message.jump_url,
30
- icon: url_message.author.display_avatar.url,
28
+ icon: url_message.author.avatar.url,
31
29
  ),
32
30
  footer: Discorb::Embed::Footer.new(
33
31
  "#{url_message.guild.name} / #{ch.name}",
@@ -20,9 +20,11 @@ module Discorb
20
20
  # | Key | Type | Description |
21
21
  # | --- | --- | --- |
22
22
  # | `:description` | `String` | Description of the option. |
23
- # | `:optional` | `Boolean` | Whether the option is optional or not. |
23
+ # | `:required` | Whether the argument is required. `optional` will be used if not specified. |
24
+ # | `:optional` | Whether the argument is optional. `required` will be used if not specified. |
24
25
  # | `:type` | `Object` | Type of the option. |
25
26
  # | `:choice` | `Hash{String => String, Integer, Float}` | Type of the option. |
27
+ # | `:default` | `Object` | Default value of the option. |
26
28
  #
27
29
  # @param [Array<#to_s>, false, nil] guild_ids Guild IDs to set the command to. `false` to global command, `nil` to use default.
28
30
  # @param [Proc] block Command block.
@@ -231,7 +233,7 @@ module Discorb
231
233
  end,
232
234
  name: name,
233
235
  description: value[:description],
234
- required: !value[:optional],
236
+ required: value[:required].nil? ? !value[:optional] : value[:required],
235
237
  }
236
238
  if value[:choices]
237
239
  ret[:choices] = value[:choices].map { |t| { name: t[0], value: t[1] } }
@@ -52,6 +52,8 @@ module Discorb
52
52
  attr_reader :status
53
53
  # @return [Integer] The session ID of connection.
54
54
  attr_reader :session_id
55
+ # @return [Hash{String => Discorb::Extension}] The loaded extensions.
56
+ attr_reader :extensions
55
57
  # @private
56
58
  attr_reader :bottom_commands
57
59
 
@@ -97,6 +99,7 @@ module Discorb
97
99
  @status = :initialized
98
100
  @fetch_member = fetch_member
99
101
  @title = title
102
+ @extensions = {}
100
103
  set_default_events
101
104
  end
102
105
 
@@ -369,31 +372,38 @@ module Discorb
369
372
  #
370
373
  # Load the extension.
371
374
  #
372
- # @param [Module] mod The extension to load.
375
+ # @param [Class, Discorb::Extension] ext The extension to load.
376
+ # @param [Object] ... The arguments to pass to the `ext#initialize`.
373
377
  #
374
- def extend(mod)
375
- if mod.respond_to?(:events)
376
- @events.each_value do |event|
377
- event.delete_if { |c| c.metadata[:extension] == mod.name }
378
- end
379
- mod.events.each do |name, events|
380
- @events[name] ||= []
381
- @events[name].delete_if { |c| c.metadata[:override] }
382
- events.each do |event|
383
- @events[name] << event
384
- end
385
- end
386
- @commands.delete_if do |cmd|
387
- cmd.respond_to? :extension and cmd.extension == mod.name
388
- end
389
- mod.commands.each do |cmd|
390
- cmd.define_singleton_method(:extension) { mod.name }
391
- @commands << cmd
378
+ def load_extension(ext, ...)
379
+ if ext.is_a?(Class)
380
+ raise ArgumentError, "#{ext} is not a extension" unless ext < Discorb::Extension
381
+ ins = ext.new(self, ...)
382
+ elsif ext.is_a?(Discorb::Extension)
383
+ ins = ext
384
+ else
385
+ raise ArgumentError, "#{ext} is not a extension"
386
+ end
387
+
388
+ @events.each_value do |event|
389
+ event.delete_if { |c| c.metadata[:extension] == ins.class.name }
390
+ end
391
+ ins.events.each do |name, events|
392
+ @events[name] ||= []
393
+ events.each do |event|
394
+ @events[name] << event
392
395
  end
393
- @bottom_commands += mod.bottom_commands
394
- mod.client = self
395
396
  end
396
- super(mod)
397
+ @commands.delete_if do |cmd|
398
+ cmd.respond_to? :extension and cmd.extension == ins.name
399
+ end
400
+ ins.class.commands.each do |cmd|
401
+ cmd.define_singleton_method(:extension) { ins.name }
402
+ @commands << cmd
403
+ end
404
+ @bottom_commands += ins.class.bottom_commands
405
+ @extensions[ins.class.name] = ins
406
+ ins
397
407
  end
398
408
 
399
409
  include Discorb::Gateway::Handler
@@ -4,9 +4,9 @@ module Discorb
4
4
  # @return [String] The API base URL.
5
5
  API_BASE_URL = "https://discord.com/api/v9"
6
6
  # @return [String] The version of discorb.
7
- VERSION = "0.9.4"
7
+ VERSION = "0.10.1"
8
8
  # @return [String] The user agent for the bot.
9
- USER_AGENT = "DiscordBot (https://github.com/discorb-lib/discorb #{VERSION}) Ruby/#{RUBY_VERSION}"
9
+ USER_AGENT = "DiscordBot (https://discorb-lib.github.io #{VERSION}) Ruby/#{RUBY_VERSION}"
10
10
 
11
11
  #
12
12
  # @abstract
@@ -39,10 +39,11 @@ module Discorb
39
39
  # Represents Snowflake of Discord.
40
40
  #
41
41
  # @see https://discord.com/developers/docs/reference#snowflakes Official Discord API docs
42
- class Snowflake < DiscordModel
42
+ class Snowflake < String
43
43
  # @private
44
44
  def initialize(value)
45
45
  @value = value.to_i
46
+ super(@value.to_s)
46
47
  end
47
48
 
48
49
  # @!attribute [r] timestamp
@@ -64,26 +65,6 @@ module Discorb
64
65
  #
65
66
  # @return [Integer] Increment of snowflake.
66
67
 
67
- #
68
- # Stringify snowflake.
69
- #
70
- # @return [String] Stringified snowflake.
71
- #
72
- def to_s
73
- @value.to_s
74
- end
75
-
76
- alias to_str to_s
77
-
78
- #
79
- # Integerize snowflake.
80
- #
81
- # @return [Integer] Integerized snowflake.
82
- #
83
- def to_i
84
- @value.to_i
85
- end
86
-
87
68
  #
88
69
  # Compares snowflake with other object.
89
70
  #
@@ -36,6 +36,34 @@ module Discorb
36
36
  )
37
37
  end
38
38
  end
39
+
40
+ #
41
+ # Convert components to a hash.
42
+ #
43
+ # @param [Array<Discorb::Component>, Array<Array<Discorb::Component>>] components Components.
44
+ #
45
+ # @return [Array<Hash>] Hash data.
46
+ #
47
+ def to_payload(components)
48
+ tmp_components = []
49
+ tmp_row = []
50
+ components.each do |c|
51
+ case c
52
+ when Array
53
+ tmp_components << tmp_row
54
+ tmp_row = []
55
+ tmp_components << c
56
+ when SelectMenu
57
+ tmp_components << tmp_row
58
+ tmp_row = []
59
+ tmp_components << [c]
60
+ else
61
+ tmp_row << c
62
+ end
63
+ end
64
+ tmp_components << tmp_row
65
+ return tmp_components.filter { |c| c.length.positive? }.map { |c| { type: 1, components: c.map(&:to_hash) } }
66
+ end
39
67
  end
40
68
  end
41
69
 
@@ -152,7 +180,7 @@ module Discorb
152
180
  # @return [Integer] The maximum number of values.
153
181
  attr_accessor :max_values
154
182
  # @return [Boolean] Whether the select menu is disabled.
155
- attr_reader :disabled
183
+ attr_accessor :disabled
156
184
  alias disabled? disabled
157
185
 
158
186
  #
@@ -22,6 +22,7 @@ options = {
22
22
  log_color: nil,
23
23
  setup: nil,
24
24
  token: false,
25
+ bundler: :default,
25
26
  }
26
27
  opt.on("-l", "--log-level LEVEL", "Log level.") do |v|
27
28
  unless LOG_LEVELS.include? v.downcase
@@ -36,6 +37,7 @@ opt.on("-c", "--[no-]log-color", "Whether to colorize log output.") { |v| option
36
37
  opt.on("-s", "--setup", "Whether to setup application commands.") { |v| options[:setup] = v }
37
38
  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 }
38
39
  opt.on("-t", "--title TITLE", "The title of process.") { |v| options[:title] = v }
40
+ opt.on("-b", "--[no-]bundler", "Whether to use bundler. Default to true if Gemfile exists, otherwise false.") { |v| options[:bundler] = v }
39
41
  opt.parse!(ARGV)
40
42
 
41
43
  script = ARGV[0]
@@ -54,10 +56,25 @@ elsif options[:token].nil? || options[:token] == "-"
54
56
  puts ""
55
57
  end
56
58
 
59
+ if options[:bundler] == :default
60
+ dir = Dir.pwd.split("/")
61
+ options[:bundler] = false
62
+ dir.length.times.reverse_each do |i|
63
+ if File.exist? "#{dir[0..i].join("/")}/Gemfile"
64
+ options[:bundler] = true
65
+ break
66
+ end
67
+ end
68
+ end
69
+
57
70
  ENV["DISCORB_CLI_TITLE"] = options[:title]
58
71
 
59
- begin
60
- load script
61
- rescue LoadError
72
+ if File.exist? script
73
+ if options[:bundler]
74
+ system "bundle exec ruby #{script}"
75
+ else
76
+ system "ruby #{script}"
77
+ end
78
+ else
62
79
  eputs "Could not load script: \e[31m#{script}\e[91m"
63
80
  end
@@ -16,3 +16,24 @@ class Time
16
16
  end
17
17
  end
18
18
  end
19
+
20
+ # @private
21
+ class Async::Node
22
+ def description
23
+ @object_name ||= "#{self.class}:0x#{object_id.to_s(16)}#{@transient ? " transient" : nil}"
24
+
25
+ if @annotation
26
+ "#{@object_name} #{@annotation}"
27
+ elsif line = self.backtrace(0, 1)&.first
28
+ "#{@object_name} #{line}"
29
+ else
30
+ @object_name
31
+ end
32
+ end
33
+
34
+ def to_s
35
+ "\#<#{self.description}>"
36
+ end
37
+
38
+ alias inspect to_s
39
+ end
@@ -2,65 +2,78 @@
2
2
 
3
3
  module Discorb
4
4
  #
5
- # Module to make extension.
6
- # extend this module to make your own extension.
5
+ # Abstract class to make extension.
6
+ # Inherit from this class to make your own extension.
7
7
  # @see file:docs/extension.md
8
8
  # @abstract
9
9
  #
10
- module Extension
11
- include Discorb::ApplicationCommand::Handler
12
- undef setup_commands
10
+ class Extension
11
+ extend Discorb::ApplicationCommand::Handler
13
12
 
14
13
  @events = {}
15
- @client = nil
16
14
 
17
- #
18
- # Define a new event.
19
- #
20
- # @param [Symbol] event_name The name of the event.
21
- # @param [Symbol] id The id of the event. Used to delete the event.
22
- # @param [Hash] metadata Other metadata.
23
- # @param [Proc] block The block to execute when the event is triggered.
24
- #
25
- # @return [Discorb::Event] The event.
26
- #
27
- def event(event_name, id: nil, **metadata, &block)
28
- raise ArgumentError, "Event name must be a symbol" unless event_name.is_a?(Symbol)
29
- raise ArgumentError, "block must be a Proc" unless block.is_a?(Proc)
30
-
31
- @events[event_name] ||= []
32
- metadata[:extension] = self.name
33
- @events[event_name] << Discorb::Event.new(block, id, metadata)
15
+ def initialize(client)
16
+ @client = client
34
17
  end
35
18
 
36
- #
37
- # Define a new once event.
38
- #
39
- # @param [Symbol] event_name The name of the event.
40
- # @param [Symbol] id The id of the event. Used to delete the event.
41
- # @param [Hash] metadata Other metadata.
42
- # @param [Proc] block The block to execute when the event is triggered.
43
- #
44
- # @return [Discorb::Event] The event.
45
- #
46
- def once_event(event_name, id: nil, **metadata, &block)
47
- event(event_name, id: id, once: true, **metadata, &block)
19
+ def events
20
+ return @events if @events
21
+ ret = {}
22
+ self.class.events.each do |event, handlers|
23
+ ret[event] = handlers.map do |handler|
24
+ Discorb::Event.new(Proc.new { |*args, **kwargs| instance_exec(*args, **kwargs, &handler[2]) }, handler[0], handler[1])
25
+ end
26
+ end
27
+ @events = ret
48
28
  end
49
29
 
50
- # @return [Hash{Symbol => Array<Discorb::Event>}] The events of the extension.
51
- attr_reader :events
52
- # @return [Array<Discorb::ApplicationCommand::Command>] The commands of the extension.
53
- attr_reader :commands
54
- # @private
55
- attr_reader :bottom_commands
30
+ class << self
31
+ undef setup_commands
32
+
33
+ #
34
+ # Define a new event.
35
+ #
36
+ # @param [Symbol] event_name The name of the event.
37
+ # @param [Symbol] id The id of the event. Used to delete the event.
38
+ # @param [Hash] metadata Other metadata.
39
+ #
40
+ # @return [Discorb::Event] The event.
41
+ #
42
+ def event(event_name, id: nil, **metadata, &block)
43
+ raise ArgumentError, "Event name must be a symbol" unless event_name.is_a?(Symbol)
44
+ raise ArgumentError, "block must be given" unless block_given?
45
+
46
+ @events[event_name] ||= []
47
+ metadata[:extension] = self.name
48
+ @events[event_name] << [id, metadata, block]
49
+ end
50
+
51
+ #
52
+ # Define a new once event.
53
+ #
54
+ # @param [Symbol] event_name The name of the event.
55
+ # @param [Symbol] id The id of the event. Used to delete the event.
56
+ # @param [Hash] metadata Other metadata.
57
+ # @param [Proc] block The block to execute when the event is triggered.
58
+ #
59
+ # @return [Discorb::Event] The event.
60
+ #
61
+ def once_event(event_name, id: nil, **metadata, &block)
62
+ event(event_name, id: id, once: true, **metadata, &block)
63
+ end
56
64
 
57
- # @private
58
- attr_accessor :client
65
+ # @return [Hash{Symbol => Array<Discorb::Event>}] The events of the extension.
66
+ attr_reader :events
67
+ # @return [Array<Discorb::ApplicationCommand::Command>] The commands of the extension.
68
+ attr_reader :commands
69
+ # @private
70
+ attr_reader :bottom_commands
59
71
 
60
- def self.extended(obj)
61
- obj.instance_variable_set(:@events, {})
62
- obj.instance_variable_set(:@commands, [])
63
- obj.instance_variable_set(:@bottom_commands, [])
72
+ def inherited(klass)
73
+ klass.instance_variable_set(:@commands, [])
74
+ klass.instance_variable_set(:@bottom_commands, [])
75
+ klass.instance_variable_set(:@events, {})
76
+ end
64
77
  end
65
78
  end
66
79
  end
data/lib/discorb/file.rb CHANGED
@@ -60,6 +60,14 @@ module Discorb
60
60
  # @return [String] The content type of the file. If not set, it is guessed from the filename.
61
61
  attr_accessor :content_type
62
62
 
63
+ #
64
+ # Creates a new file from IO.
65
+ #
66
+ # @param [#read] io The IO of the file.
67
+ # @param [String] filename The filename of the file. If not set, path or object_id of the IO is used.
68
+ # @param [String] content_type The content type of the file. If not set, it is guessed from the filename.
69
+ # If failed to guess, it is set to `application/octet-stream`.
70
+ #
63
71
  def initialize(io, filename = nil, content_type: nil)
64
72
  @io = io
65
73
  @filename = filename || (io.respond_to?(:path) ? io.path : io.object_id)
@@ -67,8 +75,18 @@ module Discorb
67
75
  @content_type = "application/octet-stream" if @content_type == ""
68
76
  end
69
77
 
78
+ #
79
+ # Creates a new file from a string.
80
+ #
81
+ # @param [String] string The string to create the file from.
82
+ # @param [String] filename The filename of the file. object_id of the string is used if not set.
83
+ # @param [String] content_type The content type of the file. If not set, it is guessed from the filename.
84
+ #
85
+ # @return [File] The new file.
86
+ #
70
87
  def self.from_string(string, filename: nil, content_type: nil)
71
88
  io = StringIO.new(string)
89
+ filename ||= string.object_id.to_s + ".txt"
72
90
  new(io, filename, content_type: content_type)
73
91
  end
74
92
  end
@@ -198,7 +198,6 @@ module Discorb
198
198
  # @macro http
199
199
  # @macro edit
200
200
  #
201
- # @param [Discorb::Webhook::Message] message The message to edit.
202
201
  # @param [String] content The new content of the message.
203
202
  # @param [Discorb::Embed] embed The new embed of the message.
204
203
  # @param [Array<Discorb::Embed>] embeds The new embeds of the message.
@@ -256,7 +255,7 @@ module Discorb
256
255
  def defer_update(ephemeral: false)
257
256
  Async do
258
257
  @client.http.post("/interactions/#{@id}/#{@token}/callback", {
259
- type: 7,
258
+ type: 6,
260
259
  data: {
261
260
  flags: (ephemeral ? 1 << 6 : 0),
262
261
  },
@@ -311,7 +310,7 @@ module Discorb
311
310
  payload[:components] = tmp_components.filter { |c| c.length.positive? }.map { |c| { type: 1, components: c.map(&:to_hash) } }
312
311
  end
313
312
  payload[:flags] = (ephemeral ? 1 << 6 : 0)
314
- @client.http.post("/interactions/#{@id}/#{@token}/callback", { type: 6, data: payload }).wait
313
+ @client.http.post("/interactions/#{@id}/#{@token}/callback", { type: 7, data: payload }).wait
315
314
  end
316
315
  end
317
316
  end
@@ -363,28 +362,31 @@ module Discorb
363
362
  options = data[:options]
364
363
  end
365
364
  end
366
- options ||= []
367
- options.map! do |option|
368
- case option[:type]
369
- when 3, 4, 5, 10
370
- option[:value]
371
- when 6
372
- guild.members[option[:value]] || guild.fetch_member(option[:value]).wait
373
- when 7
374
- guild.channels[option[:value]] || guild.fetch_channels.wait.find { |channel| channel.id == option[:value] }
375
- when 8
376
- guild.roles[option[:value]] || guild.fetch_roles.wait.find { |role| role.id == option[:value] }
377
- when 9
378
- guild.members[option[:value]] || guild.roles[option[:value]] || guild.fetch_member(option[:value]).wait || guild.fetch_roles.wait.find { |role| role.id == option[:value] }
379
- end
380
- end
381
365
 
382
366
  unless (command = @client.bottom_commands.find { |c| c.to_s == name && c.type_raw == 1 })
383
367
  @client.log.warn "Unknown command name #{name}, ignoreing"
384
368
  next
385
369
  end
386
370
 
387
- command.block.call(self, *options)
371
+ option_map = command.options.map { |k, v| [k.to_s, v[:default]] }.to_h
372
+ options ||= []
373
+ options.each do |option|
374
+ val = case option[:type]
375
+ when 3, 4, 5, 10
376
+ option[:value]
377
+ when 6
378
+ guild.members[option[:value]] || guild.fetch_member(option[:value]).wait
379
+ when 7
380
+ guild.channels[option[:value]] || guild.fetch_channels.wait.find { |channel| channel.id == option[:value] }
381
+ when 8
382
+ guild.roles[option[:value]] || guild.fetch_roles.wait.find { |role| role.id == option[:value] }
383
+ when 9
384
+ guild.members[option[:value]] || guild.roles[option[:value]] || guild.fetch_member(option[:value]).wait || guild.fetch_roles.wait.find { |role| role.id == option[:value] }
385
+ end
386
+ option_map[option[:name]] = val
387
+ end
388
+
389
+ command.block.call(self, *command.options.map { |k, v| option_map[k.to_s] })
388
390
  end
389
391
  end
390
392
  end
@@ -458,6 +460,8 @@ module Discorb
458
460
  include Interaction::UpdateResponse
459
461
  # @return [String] The content of the response.
460
462
  attr_reader :custom_id
463
+ # @return [Discorb::Message] The target message.
464
+ attr_reader :message
461
465
 
462
466
  @interaction_type = 3
463
467
  @interaction_name = :message_component
@@ -296,11 +296,11 @@ module Discorb
296
296
  # @param [Array<Discorb::Component>, Array<Array<Discorb::Component>>] components The components to send.
297
297
  # @param [Boolean] supress Whether to supress embeds.
298
298
  #
299
- def edit(message_id, content = nil, embed: nil, embeds: nil, allowed_mentions: nil,
300
- components: nil, supress: nil)
299
+ def edit(content = nil, embed: nil, embeds: nil, allowed_mentions: nil,
300
+ components: nil, supress: nil)
301
301
  Async do
302
- channel.edit_message(@id, message_id, content, embed: embed, embeds: embeds, allowed_mentions: allowed_mentions,
303
- components: components, supress: supress).wait
302
+ channel.edit_message(@id, content, embed: embed, embeds: embeds, allowed_mentions: allowed_mentions,
303
+ components: components, supress: supress).wait
304
304
  end
305
305
  end
306
306