discorb 0.9.4 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
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