discorb 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6b979da1f1325d5d9cae229e0262cce1d6cf16b6aca91feba731ec6a0146fe42
4
- data.tar.gz: e6e1fcbe4265cfb54828fef5c7e2d6304dd306544e941cb787233ad563d9abaf
3
+ metadata.gz: d57f5fd6920be7c5549687ec85d3012dede743981482fc806099789d3d9f4048
4
+ data.tar.gz: 513c3e45c0da27f8e509c4ed7238c5f6da3cd39b61a0681874a97d507068ffc6
5
5
  SHA512:
6
- metadata.gz: bb35c0736b2e549964030103dfb1202ef7711fd3c36323710d3f94631b958a9976f7c111f340d03cf2ed67032a8f74f5165f66b5ff92c59d0628af25b4a95e79
7
- data.tar.gz: 01d59859fb5e84beaafdc48e333ba841398a8fe5867c52bb9621b2d676493dbc776297c94e303297ffeef591c7f2e527ea30aaae381323e4ed8e8b1ce632b1ef
6
+ metadata.gz: 7603b6c7017898fbd705ffaa602f370111c6d122a2e68a7b6c017c6fa622d9b6990e684bf574104844e8dc6601176a47894815cfb3756ae16305fe74709da118
7
+ data.tar.gz: 0fa148e0c26c45a8aa0c3a9e2dbdfb4995bc9e939c9588d93b575b711baccc906b20ba3f8edfe4906ae5838565bd0be6befc5cf7e6b2ca25f1f465e21fa6622a
@@ -0,0 +1,34 @@
1
+ name: Publish Gem
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@master
15
+
16
+ - name: Set up Ruby
17
+ uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: "3.0"
20
+
21
+ - name: Setup Release Credentials
22
+ env:
23
+ GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
24
+ run: |
25
+ mkdir -p $HOME/.gem
26
+ touch $HOME/.gem/credentials
27
+ chmod 600 $HOME/.gem/credentials
28
+ echo "---" >$HOME/.gem/credentials
29
+ echo ":github: Bearer ${GITHUB_TOKEN}" >> $HOME/.gem/credentials
30
+ - name: Publish Gem to GitHub Packages
31
+ run: |
32
+ export OWNER=$( echo ${{ github.repository }} | cut -d "/" -f 1 )
33
+ gem build *.gemspec
34
+ gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
data/Changelog.md CHANGED
@@ -2,8 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## v0.12
6
+
7
+ ### v0.12.0
8
+
9
+ - Refactor: Refactor the code
10
+ - Fix: Fix resuming gateway, finally
11
+ - Fix: Fix `@client` in slash command handler in extension
12
+
5
13
  ## v0.11
6
14
 
15
+ ### v0.11.4
16
+
17
+ - Fix: Fix unpinning messages
18
+
19
+ ### v0.11.3
20
+
21
+ - Add: Add `Snowflake#id` as alias for `Snowflake#to_s`
22
+ - Fix: Fix `Message#unpin`
23
+
24
+ ### v0.11.2
25
+
26
+ - Add: Add `setup` event
27
+ - Fix: Fix gateway resuming
28
+ - Add: Add GitHub Packages
29
+
7
30
  ### v0.11.1
8
31
 
9
32
  - Improve: Improve rate limit handling
data/README.md CHANGED
@@ -4,11 +4,12 @@
4
4
  <a href="https://rubygems.org/gems/discorb"><img src="https://img.shields.io/gem/dt/discorb?logo=rubygems&logoColor=fff&label=Downloads&style=flat-square&labelColor=2f3136" alt="Gem"></a>
5
5
  <a href="https://rubygems.org/gems/discorb"><img src="https://img.shields.io/gem/v/discorb?logo=rubygems&logoColor=fff&label=Version&style=flat-square&labelColor=2f3136" alt="Gem"></a>
6
6
  <a href="https://discord.gg/hCP6zq8Vpj"><img src="https://img.shields.io/discord/863581274916913193?logo=discord&logoColor=fff&color=5865f2&label=Discord&style=flat-square&labelColor=2f3136" alt="Discord"></a>
7
- <a href="https://github.com/discorb-lib/discorb"><img src="https://img.shields.io/github/stars/discorb-lib/discorb?color=24292e&label=Stars&logo=GitHub&logoColor=fff&style=flat-square&labelColor=2f3136" alt="GitHub"></a></div>
7
+ <a href="https://github.com/discorb-lib/discorb"><img src="https://img.shields.io/github/stars/discorb-lib/discorb?color=24292e&label=Stars&logo=GitHub&logoColor=fff&style=flat-square&labelColor=2f3136" alt="GitHub"></a>
8
+ <a href="https://codeclimate.com/github/discorb-lib/discorb"><img alt="Code Climate maintainability" src="https://img.shields.io/codeclimate/maintainability/discorb-lib/discorb?logo=Code%20Climate&logoColor=ffffff&style=flat-square&labelColor=2f3136&label=Maintainability"></a></div>
8
9
 
9
10
  ----
10
11
 
11
- discorb is a Discord API wrapper for Ruby.
12
+ discorb is a Discord API wrapper written in Ruby.
12
13
 
13
14
  ## Installation
14
15
 
@@ -98,7 +99,7 @@ end
98
99
  client.run(ENV["DISCORD_BOT_TOKEN"])
99
100
  ```
100
101
 
101
- Note: You must run `discorb setup` before using slash commands.
102
+ Note you must run `discorb setup` before using slash commands.
102
103
 
103
104
  ## Contributing
104
105
 
data/discorb.gemspec CHANGED
@@ -13,8 +13,6 @@ Gem::Specification.new do |spec|
13
13
  spec.license = "MIT"
14
14
  spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
15
15
 
16
- spec.metadata["allowed_push_host"] = "https://rubygems.org"
17
-
18
16
  spec.metadata["homepage_uri"] = spec.homepage
19
17
  spec.metadata["source_code_uri"] = "https://github.com/discorb-lib/discorb"
20
18
  spec.metadata["changelog_uri"] = "https://discorb-lib.github.io/file.Changelog.html"
File without changes
data/docs/cli/setup.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # discorb setup
4
4
 
5
- This command will setup application commands.
5
+ This command will setup application commands, and call `setup` event.
6
6
 
7
7
  ## Usage
8
8
 
data/docs/cli.md CHANGED
@@ -16,7 +16,7 @@ Currently, discorb has the following commands:
16
16
 
17
17
  | Command | Description |
18
18
  |---------|-------------|
19
- | {file:docs/cli/init.md `init`} | Create a new project. |
19
+ | {file:docs/cli/new.md `new`} | Create a new project. |
20
20
  | {file:docs/cli/irb.md `irb`} | Start an interactive Ruby shell with connected client. |
21
21
  | {file:docs/cli/run.md `run`} | Run a client. |
22
22
  | {file:docs/cli/setup.md `setup`} | Setup application commands. |
data/docs/events.md CHANGED
@@ -88,6 +88,11 @@ Fires when the client is resumed connection.
88
88
  Fires when an error occurs during an event.
89
89
  Defaults to printing the error to stderr, override to handle it yourself.
90
90
 
91
+ #### `setup()`
92
+
93
+ Fires when `discorb setup` is run.
94
+ This is useful for setting up some dependencies, such as the database.
95
+
91
96
  ### Guild events
92
97
 
93
98
  #### `guild_join(guild)`
@@ -172,6 +172,14 @@ module Discorb
172
172
  @id_map = Discorb::Dictionary.new
173
173
  end
174
174
 
175
+ # @private
176
+ def replace_block(instance)
177
+ current_block = @block.dup
178
+ @block = Proc.new do |*args|
179
+ instance.instance_exec(*args, &current_block)
180
+ end
181
+ end
182
+
175
183
  # @private
176
184
  def to_hash
177
185
  {
@@ -314,6 +322,12 @@ module Discorb
314
322
  @name
315
323
  end
316
324
 
325
+ # @private
326
+ def block_replace(instance)
327
+ super
328
+ @commands.each { |c| c.replace_block(instance) }
329
+ end
330
+
317
331
  # @private
318
332
  def to_hash
319
333
  options_payload = @commands.map do |command|
@@ -482,48 +482,6 @@ module Discorb
482
482
  end
483
483
  end
484
484
 
485
- #
486
- # Fetch the pinned messages in the channel.
487
- # @macro async
488
- # @macro http
489
- #
490
- # @return [Async::Task<Array<Discorb::Message>>] The pinned messages in the channel.
491
- #
492
- def fetch_pins
493
- Async do
494
- _resp, data = @client.http.get("/channels/#{@id}/pins").wait
495
- data.map { |pin| Message.new(@client, pin) }
496
- end
497
- end
498
-
499
- #
500
- # Pin a message in the channel.
501
- # @macro async
502
- # @macro http
503
- #
504
- # @param [Discorb::Message] message The message to pin.
505
- # @param [String] reason The reason of pinning the message.
506
- #
507
- def pin_message(message, reason: nil)
508
- Async do
509
- @client.http.put("/channels/#{@id}/pins/#{message.id}", {}, audit_log_reason: reason).wait
510
- end
511
- end
512
-
513
- #
514
- # Unpin a message in the channel.
515
- # @macro async
516
- # @macro http
517
- #
518
- # @param [Discorb::Message] message The message to unpin.
519
- # @param [String] reason The reason of unpinning the message.
520
- #
521
- def unpin_message(message, reason: nil)
522
- Async do
523
- @client.http.delete("/channels/#{@id}/pins/#{message.id}", {}, audit_log_reason: reason).wait
524
- end
525
- end
526
-
527
485
  #
528
486
  # Start thread in the channel.
529
487
  # @macro async
@@ -395,10 +395,11 @@ module Discorb
395
395
  end
396
396
  end
397
397
  @commands.delete_if do |cmd|
398
- cmd.respond_to? :extension and cmd.extension == ins.name
398
+ cmd.respond_to? :extension and cmd.extension == ins.class.name
399
399
  end
400
400
  ins.class.commands.each do |cmd|
401
- cmd.define_singleton_method(:extension) { ins.name }
401
+ cmd.define_singleton_method(:extension) { ins.class.name }
402
+ cmd.replace_block(ins)
402
403
  @commands << cmd
403
404
  end
404
405
 
@@ -428,46 +429,10 @@ module Discorb
428
429
  when nil
429
430
  start_client(token)
430
431
  when "run"
431
- require "json"
432
- options = JSON.parse(ENV["DISCORB_CLI_OPTIONS"], symbolize_names: true)
433
- @daemon = options[:daemon]
434
-
435
- setup_commands(token) if options[:setup]
436
- if options[:log_level]
437
- if options[:log_level] == "none"
438
- @log.out = nil
439
- else
440
- @log.out = case options[:log_file]
441
- when nil, "stderr"
442
- $stderr
443
- when "stdout"
444
- $stdout
445
- else
446
- ::File.open(options[:log_file], "a")
447
- end
448
- @log.level = options[:log_level].to_sym
449
- @log.colorize_log = case options[:log_color]
450
- when nil
451
- if @log.out == $stdout || @log.out == $stderr
452
- true
453
- else
454
- false
455
- end
456
- when true, false
457
- options[:log_color]
458
- end
459
- end
460
- end
432
+ before_run(token)
461
433
  start_client(token)
462
434
  when "setup"
463
- guild_ids = "global"
464
- if guilds = ENV["DISCORB_SETUP_GUILDS"]
465
- guild_ids = guilds.split(",")
466
- end
467
- if guild_ids == ["global"]
468
- guild_ids = false
469
- end
470
- setup_commands(token, guild_ids: guild_ids).wait
435
+ run_setup(token)
471
436
  end
472
437
  end
473
438
 
@@ -483,17 +448,55 @@ module Discorb
483
448
 
484
449
  private
485
450
 
451
+ def before_run(token)
452
+ require "json"
453
+ options = JSON.parse(ENV["DISCORB_CLI_OPTIONS"], symbolize_names: true)
454
+ setup_commands(token) if options[:setup]
455
+ if options[:log_level]
456
+ if options[:log_level] == "none"
457
+ @log.out = nil
458
+ else
459
+ @log.out = case options[:log_file]
460
+ when nil, "stderr"
461
+ $stderr
462
+ when "stdout"
463
+ $stdout
464
+ else
465
+ ::File.open(options[:log_file], "a")
466
+ end
467
+ @log.level = options[:log_level].to_sym
468
+ @log.colorize_log = options[:log_color] == nil ? @log.out.isatty : options[:log_color]
469
+ end
470
+ end
471
+ end
472
+
473
+ def run_setup(token)
474
+ guild_ids = "global"
475
+ if guilds = ENV["DISCORB_SETUP_GUILDS"]
476
+ guild_ids = guilds.split(",")
477
+ end
478
+ if guild_ids == ["global"]
479
+ guild_ids = false
480
+ end
481
+ setup_commands(token, guild_ids: guild_ids).wait
482
+ @events[:setup]&.each do |event|
483
+ event.call
484
+ end
485
+ self.on_setup if respond_to? :on_setup
486
+ end
487
+
486
488
  def start_client(token)
487
489
  Async do |task|
488
- trap(:SIGINT) {
490
+ Signal.trap(:SIGINT) {
489
491
  @log.info "SIGINT received, closing..."
492
+ Signal.trap(:SIGINT, "DEFAULT")
490
493
  close!
491
494
  }
492
495
  @token = token.to_s
493
496
  @close_condition = Async::Condition.new
494
497
  @main_task = Async do
495
498
  @status = :running
496
- connect_gateway(true).wait
499
+ connect_gateway(false).wait
497
500
  rescue
498
501
  @status = :stopped
499
502
  @close_condition.signal
data/lib/discorb/color.rb CHANGED
@@ -130,6 +130,7 @@ module Discorb
130
130
  #
131
131
  # Create a color from a Discord's color.
132
132
  # Currently these colors are supported:
133
+ #
133
134
  # | Color Name | Hexadecimal |
134
135
  # |------------|------------|
135
136
  # | `:teal` | `#1abc9c` |
@@ -4,7 +4,7 @@ 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.11.1"
7
+ VERSION = "0.12.0"
8
8
  # @return [String] The user agent for the bot.
9
9
  USER_AGENT = "DiscordBot (https://discorb-lib.github.io #{VERSION}) Ruby/#{RUBY_VERSION}"
10
10
 
@@ -64,6 +64,10 @@ module Discorb
64
64
  # Increment of snowflake.
65
65
  #
66
66
  # @return [Integer] Increment of snowflake.
67
+ # @!attribute [r] id
68
+ # Alias of to_s.
69
+ #
70
+ # @return [String] The snowflake.
67
71
 
68
72
  #
69
73
  # Compares snowflake with other object.
@@ -105,5 +109,7 @@ module Discorb
105
109
  def increment
106
110
  @value & 0xFFF
107
111
  end
112
+
113
+ alias id to_s
108
114
  end
109
115
  end
data/lib/discorb/error.rb CHANGED
@@ -38,7 +38,8 @@ module Discorb
38
38
  # @abstract
39
39
  #
40
40
  class HTTPError < DiscorbError
41
- # @return [String] the HTTP response code.
41
+ # @return [String] the JSON response code.
42
+ # @see https://discord.com/developers/docs/topics/opcodes-and-status-codes#json-json-error-codes
42
43
  attr_reader :code
43
44
  # @return [Net::HTTPResponse] the HTTP response.
44
45
  attr_reader :response
@@ -47,7 +48,7 @@ module Discorb
47
48
  def initialize(resp, data)
48
49
  @code = data[:code]
49
50
  @response = resp
50
- super(data[:message])
51
+ super(data[:message] + " (#{@code})")
51
52
  end
52
53
  end
53
54
 
@@ -60,9 +61,11 @@ module Discorb
60
61
  @code = data[:code]
61
62
  @response = resp
62
63
  DiscorbError.instance_method(:initialize).bind(self).call(
63
- [data[:message], enumerate_errors(data[:errors]).map do |ek, ev|
64
- "#{ek}=>#{ev}"
65
- end.join("\n")].join("\n")
64
+ [
65
+ data[:message] + " (#{@code})", enumerate_errors(data[:errors])
66
+ .map { |ek, ev| "#{ek}=>#{ev}" }
67
+ .join("\n"),
68
+ ].join("\n")
66
69
  )
67
70
  end
68
71
  end
@@ -481,54 +481,74 @@ module Discorb
481
481
  module Handler
482
482
  private
483
483
 
484
- def connect_gateway(first)
485
- @log.info "Connecting to gateway."
484
+ def connect_gateway(reconnect)
485
+ if reconnect
486
+ @log.info "Reconnecting to gateway..."
487
+ else
488
+ @log.info "Connecting to gateway..."
489
+ end
486
490
  Async do
487
- @http = HTTP.new(self) if first
488
- @first = first
491
+ @connection&.close
492
+ @http = HTTP.new(self)
489
493
  _, gateway_response = @http.get("/gateway").wait
490
494
  gateway_url = gateway_response[:url]
491
495
  endpoint = Async::HTTP::Endpoint.parse("#{gateway_url}?v=9&encoding=json&compress=zlib-stream",
492
496
  alpn_protocols: Async::HTTP::Protocol::HTTP11.names)
493
497
  begin
494
- Async::WebSocket::Client.connect(endpoint, headers: [["User-Agent", Discorb::USER_AGENT]], handler: RawConnection) do |connection|
495
- @connection = connection
496
- @zlib_stream = Zlib::Inflate.new(Zlib::MAX_WBITS)
497
- @buffer = +""
498
-
498
+ @connection = Async::WebSocket::Client.connect(endpoint, headers: [["User-Agent", Discorb::USER_AGENT]], handler: RawConnection)
499
+ @zlib_stream = Zlib::Inflate.new(Zlib::MAX_WBITS)
500
+ buffer = +""
501
+ begin
499
502
  while (message = @connection.read)
500
- @buffer << message
503
+ buffer << message
501
504
  if message.end_with?((+"\x00\x00\xff\xff").force_encoding("ASCII-8BIT"))
502
505
  begin
503
- data = @zlib_stream.inflate(@buffer)
504
- @buffer = +""
506
+ data = @zlib_stream.inflate(buffer)
507
+ buffer = +""
505
508
  message = JSON.parse(data, symbolize_names: true)
506
509
  rescue JSON::ParserError
507
- @buffer = +""
510
+ buffer = +""
508
511
  @log.error "Received invalid JSON from gateway."
509
512
  @log.debug "#{data}"
510
513
  else
511
- handle_gateway(message)
514
+ handle_gateway(message, reconnect)
512
515
  end
513
516
  end
514
517
  end
518
+ rescue Async::Wrapper::Cancelled, OpenSSL::SSL::SSLError, Async::Wrapper::WaitError, EOFError => e
519
+ @log.error "Gateway connection closed: #{e.class}: #{e.message}"
520
+ connect_gateway(true)
521
+ else # should never happen
522
+ connect_gateway(true)
515
523
  end
516
524
  rescue Protocol::WebSocket::ClosedError => e
517
- case e.message
518
- when "Authentication failed."
519
- @tasks.map(&:stop)
520
- raise ClientError.new("Authentication failed."), cause: nil
521
- when "Discord WebSocket requesting client reconnect."
522
- @log.info "Discord WebSocket requesting client reconnect"
523
- connect_gateway(false)
525
+ @tasks.map(&:stop)
526
+ case e.code
527
+ when 4004
528
+ raise ClientError.new("Authentication failed"), cause: nil
529
+ when 4009
530
+ @log.info "Session timed out, reconnecting."
531
+ connect_gateway(true)
532
+ when 4014
533
+ raise ClientError.new("Disallowed intents were specified"), cause: nil
534
+ when 4002, 4003, 4005, 4007
535
+ raise ClientError.new(<<~EOS), cause: e
536
+ Disconnected from gateway, probably due to library issues.
537
+ #{e.message}
538
+
539
+ Please report this to the library issue tracker.
540
+ https://github.com/discorb-lib/discorb/issues
541
+ EOS
542
+ when 1001
543
+ @log.info "Gateway closed with code 1001, reconnecting."
544
+ connect_gateway(true)
524
545
  else
525
- @log.error "Discord WebSocket closed: #{e.message}"
546
+ @log.error "Discord WebSocket closed with code #{e.code}."
547
+ @log.debug "#{e.message}"
526
548
  connect_gateway(false)
527
549
  end
528
- rescue EOFError, Async::Wrapper::Cancelled, Async::Wrapper::WaitError
529
- connect_gateway(false)
530
550
  rescue => e
531
- @log.error "Discord WebSocket error: #{e.message}"
551
+ @log.error "Discord WebSocket error: #{e.full_message}"
532
552
  connect_gateway(false)
533
553
  end
534
554
  end
@@ -540,15 +560,23 @@ module Discorb
540
560
  @log.debug "Sent message #{{ op: opcode, d: value }.to_json.gsub(@token, "[Token]")}"
541
561
  end
542
562
 
543
- def handle_gateway(payload)
563
+ def handle_gateway(payload, reconnect)
544
564
  Async do |task|
545
565
  data = payload[:d]
546
566
  @last_s = payload[:s] if payload[:s]
547
- @log.debug "Received message with opcode #{payload[:op]} from gateway: #{data}"
567
+ @log.debug "Received message with opcode #{payload[:op]} from gateway:"
568
+ @log.debug "#{payload.to_json.gsub(@token, "[Token]")}"
548
569
  case payload[:op]
549
570
  when 10
550
571
  @heartbeat_interval = data[:heartbeat_interval]
551
- if @first
572
+ if reconnect
573
+ payload = {
574
+ token: @token,
575
+ session_id: @session_id,
576
+ seq: @last_s,
577
+ }
578
+ send_gateway(6, **payload)
579
+ else
552
580
  payload = {
553
581
  token: @token,
554
582
  intents: @intents.value,
@@ -557,38 +585,22 @@ module Discorb
557
585
  }
558
586
  payload[:presence] = @identify_presence if @identify_presence
559
587
  send_gateway(2, **payload)
560
- Async do
561
- sleep 2
562
- next unless @uncached_guilds.nil?
563
-
564
- raise ClientError, "Failed to connect to gateway.\nHint: This usually means that your intents are invalid."
565
- exit 1
566
- end
567
- else
568
- payload = {
569
- token: @token,
570
- session_id: @session_id,
571
- seq: @last_s,
572
- }
573
- send_gateway(6, **payload)
574
588
  end
575
589
  when 7
576
590
  @log.info "Received opcode 7, reconnecting"
577
591
  @tasks.map(&:stop)
578
- @connection.close
579
- connect_gateway(false)
580
592
  when 9
581
593
  @log.warn "Received opcode 9, closed connection"
582
594
  @tasks.map(&:stop)
583
595
  if data
584
596
  @log.info "Connection is resumable, reconnecting"
585
597
  @connection.close
586
- connect_gateway(false)
598
+ connect_gateway(true)
587
599
  else
588
600
  @log.info "Connection is not resumable, reconnecting with opcode 2"
589
- sleep(2)
590
601
  @connection.close
591
- connect_gateway(true)
602
+ sleep(2)
603
+ connect_gateway(false)
592
604
  end
593
605
  when 11
594
606
  @log.debug "Received opcode 11"
@@ -1028,6 +1040,7 @@ module Discorb
1028
1040
  dispatch(interaction.class.event_name, interaction)
1029
1041
  when "RESUMED"
1030
1042
  @log.info("Successfully resumed connection")
1043
+ @tasks << handle_heartbeat
1031
1044
  dispatch(:resumed)
1032
1045
  else
1033
1046
  if respond_to?("event_" + event_name.downcase)
@@ -0,0 +1,49 @@
1
+ module Discorb
2
+ #
3
+ # Represents auto complete interaction.
4
+ #
5
+ class AutoComplete < Interaction
6
+ @interaction_type = 4
7
+ @interaction_name = :auto_complete
8
+
9
+ # @private
10
+ def _set_data(data)
11
+ super
12
+ Sync do
13
+ name, options = Discorb::CommandInteraction::SlashCommand.get_command_data(data)
14
+
15
+ unless (command = @client.bottom_commands.find { |c| c.to_s == name && c.type_raw == 1 })
16
+ @client.log.warn "Unknown command name #{name}, ignoring"
17
+ next
18
+ end
19
+
20
+ option_map = command.options.map { |k, v| [k.to_s, v[:default]] }.to_h
21
+ Discorb::CommandInteraction::SlashCommand.modify_option_map(option_map, options)
22
+ focused_index = options.find_index { |o| o[:focused] }
23
+ val = command.options.values[focused_index][:autocomplete]&.call(self, *command.options.map { |k, v| option_map[k.to_s] })
24
+ send_complete_result(val)
25
+ end
26
+ end
27
+
28
+ # @private
29
+ def send_complete_result(val)
30
+ @client.http.post("/interactions/#{@id}/#{@token}/callback", {
31
+ type: 8,
32
+ data: {
33
+ choices: val.map do |vk, vv|
34
+ {
35
+ name: vk,
36
+ value: vv,
37
+ }
38
+ end,
39
+ },
40
+ }).wait
41
+ rescue Discorb::NotFoundError
42
+ @client.log.warn "Failed to send auto complete result, This may be caused by the suggestion is taking too long (over 3 seconds) to respond", fallback: $stderr
43
+ end
44
+
45
+ class << self
46
+ alias make_interaction new
47
+ end
48
+ end
49
+ end