discorb 0.13.4 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitattributes +2 -0
- data/.github/workflows/codeql-analysis.yml +70 -0
- data/.github/workflows/lint-push.yml +18 -0
- data/.github/workflows/lint.yml +16 -0
- data/.rubocop.yml +70 -0
- data/Changelog.md +12 -0
- data/Gemfile +7 -3
- data/Rakefile +22 -22
- data/discorb.gemspec +1 -0
- data/examples/commands/bookmarker.rb +2 -1
- data/examples/commands/hello.rb +1 -0
- data/examples/commands/inspect.rb +3 -2
- data/examples/components/authorization_button.rb +2 -1
- data/examples/components/select_menu.rb +2 -1
- data/examples/extension/main.rb +1 -0
- data/examples/extension/message_expander.rb +1 -0
- data/examples/simple/eval.rb +3 -2
- data/examples/simple/ping_pong.rb +1 -0
- data/examples/simple/rolepanel.rb +1 -0
- data/examples/simple/wait_for_message.rb +4 -3
- data/exe/discorb +8 -7
- data/lib/discorb/allowed_mentions.rb +64 -0
- data/lib/discorb/app_command/command.rb +274 -0
- data/lib/discorb/app_command/handler.rb +168 -0
- data/lib/discorb/app_command.rb +2 -426
- data/lib/discorb/asset.rb +2 -0
- data/lib/discorb/audit_logs.rb +3 -3
- data/lib/discorb/channel.rb +19 -4
- data/lib/discorb/client.rb +30 -27
- data/lib/discorb/common.rb +4 -26
- data/lib/discorb/components/button.rb +106 -0
- data/lib/discorb/components/select_menu.rb +157 -0
- data/lib/discorb/components/text_input.rb +96 -0
- data/lib/discorb/components.rb +11 -276
- data/lib/discorb/dictionary.rb +3 -0
- data/lib/discorb/embed.rb +2 -2
- data/lib/discorb/emoji.rb +19 -3
- data/lib/discorb/emoji_table.rb +1 -1
- data/lib/discorb/error.rb +4 -6
- data/lib/discorb/event.rb +9 -7
- data/lib/discorb/exe/about.rb +1 -0
- data/lib/discorb/exe/irb.rb +4 -3
- data/lib/discorb/exe/new.rb +6 -7
- data/lib/discorb/exe/run.rb +2 -1
- data/lib/discorb/exe/setup.rb +8 -5
- data/lib/discorb/exe/show.rb +1 -0
- data/lib/discorb/extend.rb +19 -14
- data/lib/discorb/extension.rb +5 -1
- data/lib/discorb/gateway.rb +28 -30
- data/lib/discorb/guild.rb +11 -13
- data/lib/discorb/guild_template.rb +2 -2
- data/lib/discorb/http.rb +15 -17
- data/lib/discorb/integration.rb +1 -1
- data/lib/discorb/intents.rb +1 -1
- data/lib/discorb/interaction/autocomplete.rb +4 -3
- data/lib/discorb/interaction/command.rb +34 -9
- data/lib/discorb/interaction/components.rb +5 -2
- data/lib/discorb/interaction/modal.rb +33 -0
- data/lib/discorb/interaction/response.rb +33 -4
- data/lib/discorb/interaction/root.rb +1 -0
- data/lib/discorb/interaction.rb +2 -1
- data/lib/discorb/log.rb +1 -1
- data/lib/discorb/member.rb +1 -3
- data/lib/discorb/message.rb +26 -277
- data/lib/discorb/message_meta.rb +205 -0
- data/lib/discorb/modules.rb +1 -1
- data/lib/discorb/permission.rb +2 -2
- data/lib/discorb/presence.rb +4 -1
- data/lib/discorb/rate_limit.rb +2 -4
- data/lib/discorb/user.rb +1 -1
- data/lib/discorb/utils/colored_puts.rb +1 -0
- data/lib/discorb/voice_state.rb +3 -0
- data/lib/discorb/webhook.rb +1 -1
- data/lib/discorb.rb +1 -0
- data/template-replace/scripts/arrow.rb +1 -0
- data/template-replace/scripts/favicon.rb +1 -0
- data/template-replace/scripts/index.rb +2 -1
- data/template-replace/scripts/locale_ja.rb +5 -4
- data/template-replace/scripts/sidebar.rb +1 -0
- data/template-replace/scripts/version.rb +7 -10
- data/template-replace/scripts/yard_replace.rb +5 -4
- metadata +16 -2
data/lib/discorb/gateway.rb
CHANGED
@@ -122,7 +122,7 @@ module Discorb
|
|
122
122
|
# @return [Discorb::User] The user associated with the integration.
|
123
123
|
|
124
124
|
# @private
|
125
|
-
def initialize(
|
125
|
+
def initialize(_client, data)
|
126
126
|
@id = Snowflake.new(data[:id])
|
127
127
|
@guild_id = data[:guild_id]
|
128
128
|
@user_id = data[:application_id]
|
@@ -261,7 +261,6 @@ module Discorb
|
|
261
261
|
#
|
262
262
|
# Represents a `MESSAGE_UPDATE` event.
|
263
263
|
#
|
264
|
-
|
265
264
|
class MessageUpdateEvent < GatewayEvent
|
266
265
|
# @return [Discorb::Message] The message before update.
|
267
266
|
attr_reader :before
|
@@ -393,6 +392,9 @@ module Discorb
|
|
393
392
|
end
|
394
393
|
end
|
395
394
|
|
395
|
+
#
|
396
|
+
# Represents a `GUILD_INTEGRATIONS_UPDATE` event.
|
397
|
+
#
|
396
398
|
class GuildIntegrationsUpdateEvent < GatewayEvent
|
397
399
|
def initialize(client, data)
|
398
400
|
@client = client
|
@@ -528,20 +530,16 @@ module Discorb
|
|
528
530
|
module Handler
|
529
531
|
private
|
530
532
|
|
531
|
-
def connect_gateway(reconnect
|
533
|
+
def connect_gateway(reconnect)
|
532
534
|
if reconnect
|
533
535
|
@log.info "Reconnecting to gateway..."
|
534
536
|
else
|
535
537
|
@log.info "Connecting to gateway..."
|
536
538
|
end
|
537
539
|
Async do
|
538
|
-
if @connection
|
540
|
+
if @connection && !@connection.closed?
|
539
541
|
Async do
|
540
|
-
|
541
|
-
@connection.force_close
|
542
|
-
else
|
543
|
-
@connection.close
|
544
|
-
end
|
542
|
+
@connection.close
|
545
543
|
end
|
546
544
|
end
|
547
545
|
@http = HTTP.new(self)
|
@@ -578,7 +576,8 @@ module Discorb
|
|
578
576
|
Errno::ECONNRESET,
|
579
577
|
IOError => e
|
580
578
|
@log.error "Gateway connection closed accidentally: #{e.class}: #{e.message}"
|
581
|
-
|
579
|
+
@connection.force_close
|
580
|
+
connect_gateway(true)
|
582
581
|
else # should never happen
|
583
582
|
connect_gateway(true)
|
584
583
|
end
|
@@ -593,13 +592,13 @@ module Discorb
|
|
593
592
|
when 4014
|
594
593
|
raise ClientError.new("Disallowed intents were specified"), cause: nil
|
595
594
|
when 4002, 4003, 4005, 4007
|
596
|
-
raise ClientError.new(<<~
|
597
|
-
|
598
|
-
|
595
|
+
raise ClientError.new(<<~ERROR), cause: e
|
596
|
+
Disconnected from gateway, probably due to library issues.
|
597
|
+
#{e.message}
|
599
598
|
|
600
|
-
|
601
|
-
|
602
|
-
|
599
|
+
Please report this to the library issue tracker.
|
600
|
+
https://github.com/discorb-lib/discorb/issues
|
601
|
+
ERROR
|
603
602
|
when 1001
|
604
603
|
@log.info "Gateway closed with code 1001, reconnecting."
|
605
604
|
connect_gateway(true)
|
@@ -608,8 +607,9 @@ module Discorb
|
|
608
607
|
@log.debug "#{e.message}"
|
609
608
|
connect_gateway(false)
|
610
609
|
end
|
611
|
-
rescue => e
|
610
|
+
rescue StandardError => e
|
612
611
|
@log.error "Discord WebSocket error: #{e.full_message}"
|
612
|
+
@connection.force_close
|
613
613
|
connect_gateway(false)
|
614
614
|
end
|
615
615
|
end
|
@@ -622,7 +622,7 @@ module Discorb
|
|
622
622
|
end
|
623
623
|
|
624
624
|
def handle_gateway(payload, reconnect)
|
625
|
-
Async do |
|
625
|
+
Async do |_task|
|
626
626
|
data = payload[:d]
|
627
627
|
@last_s = payload[:s] if payload[:s]
|
628
628
|
@log.debug "Received message with opcode #{payload[:op]} from gateway:"
|
@@ -648,7 +648,7 @@ module Discorb
|
|
648
648
|
send_gateway(2, **payload)
|
649
649
|
end
|
650
650
|
when 7
|
651
|
-
@log.info "Received opcode 7,
|
651
|
+
@log.info "Received opcode 7, stopping tasks"
|
652
652
|
@tasks.map(&:stop)
|
653
653
|
when 9
|
654
654
|
@log.warn "Received opcode 9, closed connection"
|
@@ -673,7 +673,7 @@ module Discorb
|
|
673
673
|
end
|
674
674
|
|
675
675
|
def handle_heartbeat
|
676
|
-
Async do |
|
676
|
+
Async do |_task|
|
677
677
|
interval = @heartbeat_interval
|
678
678
|
sleep((interval / 1000.0 - 1) * rand)
|
679
679
|
loop do
|
@@ -700,9 +700,7 @@ module Discorb
|
|
700
700
|
@session_id = data[:session_id]
|
701
701
|
@user = ClientUser.new(self, data[:user])
|
702
702
|
@uncached_guilds = data[:guilds].map { |g| g[:id] }
|
703
|
-
if @uncached_guilds == []
|
704
|
-
ready
|
705
|
-
end
|
703
|
+
ready if (@uncached_guilds == []) || !@intents.guilds
|
706
704
|
dispatch(:ready)
|
707
705
|
@tasks << handle_heartbeat
|
708
706
|
when "GUILD_CREATE"
|
@@ -905,7 +903,7 @@ module Discorb
|
|
905
903
|
when "INTEGRATION_UPDATE"
|
906
904
|
return @log.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
907
905
|
|
908
|
-
|
906
|
+
integration = Integration.new(self, data, data[:guild_id])
|
909
907
|
dispatch(:integration_update, integration)
|
910
908
|
when "INTEGRATION_DELETE"
|
911
909
|
return @log.warn "Unknown guild id #{data[:guild_id]}, ignoring" unless (guild = @guilds[data[:guild_id]])
|
@@ -1096,7 +1094,7 @@ module Discorb
|
|
1096
1094
|
dispatch(:typing_start, TypingStartEvent.new(self, data))
|
1097
1095
|
when "INTERACTION_CREATE"
|
1098
1096
|
interaction = Interaction.make_interaction(self, data)
|
1099
|
-
dispatch(:
|
1097
|
+
dispatch(:interaction_create, interaction)
|
1100
1098
|
|
1101
1099
|
dispatch(interaction.class.event_name, interaction)
|
1102
1100
|
when "RESUMED"
|
@@ -1114,15 +1112,15 @@ module Discorb
|
|
1114
1112
|
old = event.dup
|
1115
1113
|
event.send(:_set_data, data)
|
1116
1114
|
dispatch(:scheduled_event_update, old, event)
|
1117
|
-
if old.status
|
1115
|
+
if old.status == event.status
|
1116
|
+
dispatch(:scheduled_event_edit, old, event)
|
1117
|
+
else
|
1118
1118
|
case event.status
|
1119
1119
|
when :active
|
1120
1120
|
dispatch(:scheduled_event_start, event)
|
1121
1121
|
when :completed
|
1122
1122
|
dispatch(:scheduled_event_end, event)
|
1123
1123
|
end
|
1124
|
-
else
|
1125
|
-
dispatch(:scheduled_event_edit, old, event)
|
1126
1124
|
end
|
1127
1125
|
when "GUILD_SCHEDULED_EVENT_DELETE"
|
1128
1126
|
@log.warn("Unknown guild id #{data[:guild_id]}, ignoring") unless (guild = @guilds[data[:guild_id]])
|
@@ -1182,12 +1180,12 @@ module Discorb
|
|
1182
1180
|
def close
|
1183
1181
|
super
|
1184
1182
|
@closed = true
|
1185
|
-
rescue
|
1183
|
+
rescue StandardError
|
1186
1184
|
force_close
|
1187
1185
|
end
|
1188
1186
|
|
1189
1187
|
def force_close
|
1190
|
-
@framer.instance_variable_get(:@stream).close
|
1188
|
+
@framer.instance_variable_get(:@stream).instance_variable_get(:@io).instance_variable_get(:@io).instance_variable_get(:@io).close
|
1191
1189
|
@closed = true
|
1192
1190
|
end
|
1193
1191
|
|
data/lib/discorb/guild.rb
CHANGED
@@ -614,7 +614,7 @@ module Discorb
|
|
614
614
|
#
|
615
615
|
def fetch_members(limit: 0, after: nil)
|
616
616
|
Async do
|
617
|
-
unless limit
|
617
|
+
unless limit.zero?
|
618
618
|
_resp, data = @client.http.request(Route.new("/guilds/#{@id}/members?#{URI.encode_www_form({ after: after, limit: limit })}", "//guilds/:guild_id/members", :get)).wait
|
619
619
|
next data[:members].map { |m| Member.new(@client, @id, m[:user], m) }
|
620
620
|
end
|
@@ -625,9 +625,7 @@ module Discorb
|
|
625
625
|
_resp, data = @client.http.request(Route.new("/guilds/#{@id}/members?#{URI.encode_www_form(params)}", "//guilds/:guild_id/members", :get)).wait
|
626
626
|
ret += data.map { |m| Member.new(@client, @id, m[:user], m) }
|
627
627
|
after = data.last[:user][:id]
|
628
|
-
if data.length != 1000
|
629
|
-
break
|
630
|
-
end
|
628
|
+
break if data.length != 1000
|
631
629
|
end
|
632
630
|
ret
|
633
631
|
end
|
@@ -1099,7 +1097,7 @@ module Discorb
|
|
1099
1097
|
def iframe(theme: "dark", width: 350, height: 500)
|
1100
1098
|
[
|
1101
1099
|
%(<iframe src="https://canary.discord.com/widget?id=#{@guild_id}&theme=#{theme}" width="#{width}" height="#{height}"),
|
1102
|
-
%(allowtransparency="true" frameborder="0" sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts"></iframe>)
|
1100
|
+
%(allowtransparency="true" frameborder="0" sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts"></iframe>)
|
1103
1101
|
].join
|
1104
1102
|
end
|
1105
1103
|
end
|
@@ -1152,9 +1150,9 @@ module Discorb
|
|
1152
1150
|
@unavailable = false
|
1153
1151
|
@name = data[:name]
|
1154
1152
|
@members = Discorb::Dictionary.new
|
1155
|
-
data[:members]
|
1156
|
-
|
1157
|
-
|
1153
|
+
data[:members]&.each do |m|
|
1154
|
+
Member.new(@client, @id, m[:user], m)
|
1155
|
+
end
|
1158
1156
|
@splash = data[:splash] && Asset.new(self, data[:splash], path: "splashes/#{@id}")
|
1159
1157
|
@discovery_splash = data[:discovery_splash] && Asset.new(self, data[:discovery_splash], path: "discovery-splashes/#{@id}")
|
1160
1158
|
@owner_id = data[:owner_id]
|
@@ -1200,13 +1198,13 @@ module Discorb
|
|
1200
1198
|
tmp_channels = data[:channels].filter { |c| !c.key?(:thread_metadata) }.map do |c|
|
1201
1199
|
Channel.make_channel(@client, c.merge({ guild_id: @id }))
|
1202
1200
|
end
|
1203
|
-
@channels = Dictionary.new(tmp_channels.
|
1204
|
-
@voice_states = Dictionary.new(data[:voice_states].
|
1201
|
+
@channels = Dictionary.new(tmp_channels.to_h { |c| [c.id, c] }, sort: ->(c) { c[1].position })
|
1202
|
+
@voice_states = Dictionary.new(data[:voice_states].to_h { |v| [Snowflake.new(v[:user_id]), VoiceState.new(@client, v.merge({ guild_id: @id }))] })
|
1205
1203
|
@threads = data[:threads] ? data[:threads].map { |t| Channel.make_channel(@client, t) } : []
|
1206
|
-
@presences = Dictionary.new(data[:presences].
|
1204
|
+
@presences = Dictionary.new(data[:presences].to_h { |pr| [Snowflake.new(pr[:user][:id]), Presence.new(@client, pr)] })
|
1207
1205
|
@max_presences = data[:max_presences]
|
1208
|
-
@stage_instances = Dictionary.new(data[:stage_instances].
|
1209
|
-
@scheduled_events = Dictionary.new(data[:guild_scheduled_events].
|
1206
|
+
@stage_instances = Dictionary.new(data[:stage_instances].to_h { |s| [Snowflake.new(s[:id]), StageInstance.new(@client, s)] })
|
1207
|
+
@scheduled_events = Dictionary.new(data[:guild_scheduled_events].to_h { |s| [Snowflake.new(s[:id]), ScheduledEvent.new(@client, s)] })
|
1210
1208
|
@data.update(data)
|
1211
1209
|
end
|
1212
1210
|
end
|
@@ -187,9 +187,9 @@ module Discorb
|
|
187
187
|
@nsfw = data[:nsfw]
|
188
188
|
@rate_limit_per_user = data[:rate_limit_per_user]
|
189
189
|
@parent_id = data[:parent_id]
|
190
|
-
@permission_overwrites = data[:permission_overwrites].
|
190
|
+
@permission_overwrites = data[:permission_overwrites].to_h do |ow|
|
191
191
|
[Snowflake.new(ow[:id]), PermissionOverwrite.new(ow[:allow], ow[:deny])]
|
192
|
-
end
|
192
|
+
end
|
193
193
|
@type = Discorb::Channel.descendants.find { |c| c.channel_type == data[:type] }
|
194
194
|
end
|
195
195
|
end
|
data/lib/discorb/http.rb
CHANGED
@@ -32,13 +32,13 @@ module Discorb
|
|
32
32
|
# @raise [Discorb::HTTPError] The request was failed.
|
33
33
|
#
|
34
34
|
def request(path, body = "", headers: nil, audit_log_reason: nil, **kwargs)
|
35
|
-
Async do |
|
35
|
+
Async do |_task|
|
36
36
|
@ratelimit_handler.wait(path)
|
37
|
-
if %i[post patch put].include? path.method
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
resp = if %i[post patch put].include? path.method
|
38
|
+
http.send(path.method, get_path(path), get_body(body), get_headers(headers, body, audit_log_reason), **kwargs)
|
39
|
+
else
|
40
|
+
http.send(path.method, get_path(path), get_headers(headers, body, audit_log_reason), **kwargs)
|
41
|
+
end
|
42
42
|
data = get_response_data(resp)
|
43
43
|
@ratelimit_handler.save(path, resp)
|
44
44
|
handle_response(resp, data, path, body, headers, audit_log_reason, kwargs)
|
@@ -61,12 +61,12 @@ module Discorb
|
|
61
61
|
#
|
62
62
|
# @raise [Discorb::HTTPError] The request was failed.
|
63
63
|
#
|
64
|
-
def multipart_request(path, body
|
65
|
-
Async do |
|
64
|
+
def multipart_request(path, body, files, headers: nil, audit_log_reason: nil, **kwargs)
|
65
|
+
Async do |_task|
|
66
66
|
@ratelimit_handler.wait(path)
|
67
67
|
req = Net::HTTP.const_get(path.method.to_s.capitalize).new(get_path(path), get_headers(headers, body, audit_log_reason), **kwargs)
|
68
68
|
data = [
|
69
|
-
["payload_json", get_body(body)]
|
69
|
+
["payload_json", get_body(body)]
|
70
70
|
]
|
71
71
|
files&.each_with_index do |file, i|
|
72
72
|
next if file.nil?
|
@@ -143,15 +143,13 @@ module Discorb
|
|
143
143
|
begin
|
144
144
|
data = JSON.parse(resp.body, symbolize_names: true)
|
145
145
|
rescue JSON::ParserError, TypeError
|
146
|
-
if resp.body.nil? || resp.body.empty?
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
end
|
152
|
-
if resp["Via"].nil? && resp.code == "429" && data.is_a?(String)
|
153
|
-
raise CloudFlareBanError.new(resp, @client)
|
146
|
+
data = if resp.body.nil? || resp.body.empty?
|
147
|
+
nil
|
148
|
+
else
|
149
|
+
resp.body
|
150
|
+
end
|
154
151
|
end
|
152
|
+
raise CloudFlareBanError.new(resp, @client) if resp["Via"].nil? && resp.code == "429" && data.is_a?(String)
|
155
153
|
data
|
156
154
|
end
|
157
155
|
|
data/lib/discorb/integration.rb
CHANGED
data/lib/discorb/intents.rb
CHANGED
@@ -86,7 +86,7 @@ module Discorb
|
|
86
86
|
if @raw_value.key?(name)
|
87
87
|
@raw_value[name]
|
88
88
|
elsif name.end_with?("=") && @raw_value.key?(name[0..-2].to_sym)
|
89
|
-
raise ArgumentError, "true/false expected" unless args.is_a?
|
89
|
+
raise ArgumentError, "true/false expected" unless args.is_a?(TrueClass) || args.is_a?(FalseClass)
|
90
90
|
|
91
91
|
@raw_value[name[0..-2].to_sym] = args
|
92
92
|
else
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Discorb
|
2
3
|
#
|
3
4
|
# Represents auto complete interaction.
|
@@ -17,10 +18,10 @@ module Discorb
|
|
17
18
|
next
|
18
19
|
end
|
19
20
|
|
20
|
-
option_map = command.options.
|
21
|
-
Discorb::CommandInteraction::SlashCommand.modify_option_map(option_map, options, guild)
|
21
|
+
option_map = command.options.to_h { |k, v| [k.to_s, v[:default]] }
|
22
|
+
Discorb::CommandInteraction::SlashCommand.modify_option_map(option_map, options, guild, {}, {})
|
22
23
|
focused_index = options.find_index { |o| o[:focused] }
|
23
|
-
val = command.options.values[focused_index][:autocomplete]&.call(self, *command.options.map { |k,
|
24
|
+
val = command.options.values.filter { |option| option[:type] != :attachment }[focused_index][:autocomplete]&.call(self, *command.options.map { |k, _v| option_map[k.to_s] })
|
24
25
|
send_complete_result(val)
|
25
26
|
end
|
26
27
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Discorb
|
2
3
|
#
|
3
4
|
# Represents a command interaction.
|
@@ -5,7 +6,8 @@ module Discorb
|
|
5
6
|
class CommandInteraction < Interaction
|
6
7
|
@interaction_type = 2
|
7
8
|
@interaction_name = :application_command
|
8
|
-
include Interaction::
|
9
|
+
include Interaction::SourceResponder
|
10
|
+
include Interaction::ModalResponder
|
9
11
|
|
10
12
|
#
|
11
13
|
# Represents a slash command interaction.
|
@@ -25,10 +27,10 @@ module Discorb
|
|
25
27
|
return
|
26
28
|
end
|
27
29
|
|
28
|
-
option_map = command.options.
|
29
|
-
SlashCommand.modify_option_map(option_map, options, guild)
|
30
|
+
option_map = command.options.to_h { |k, v| [k.to_s, v[:default]] }
|
31
|
+
SlashCommand.modify_option_map(option_map, options, guild, @members, @attachments)
|
30
32
|
|
31
|
-
command.block.call(self, *command.options.map { |k,
|
33
|
+
command.block.call(self, *command.options.map { |k, _v| option_map[k.to_s] })
|
32
34
|
end
|
33
35
|
|
34
36
|
class << self
|
@@ -55,13 +57,13 @@ module Discorb
|
|
55
57
|
options = data[:options]
|
56
58
|
end
|
57
59
|
|
58
|
-
|
60
|
+
[name, options]
|
59
61
|
end
|
60
62
|
|
61
63
|
# @private
|
62
|
-
def modify_option_map(option_map, options, guild)
|
64
|
+
def modify_option_map(option_map, options, guild, members, attachments)
|
63
65
|
options ||= []
|
64
|
-
options.
|
66
|
+
options.each do |option|
|
65
67
|
val = case option[:type]
|
66
68
|
when 3, 4, 5, 10
|
67
69
|
option[:value]
|
@@ -72,7 +74,9 @@ module Discorb
|
|
72
74
|
when 8
|
73
75
|
guild.roles[option[:value]] || guild.fetch_roles.wait.find { |role| role.id == option[:value] }
|
74
76
|
when 9
|
75
|
-
guild.members[option[:value]] || guild.roles[option[:value]] || guild.fetch_member(option[:value]).wait || guild.fetch_roles.wait.find { |role| role.id == option[:value] }
|
77
|
+
members[option[:value]] || guild.members[option[:value]] || guild.roles[option[:value]] || guild.fetch_member(option[:value]).wait || guild.fetch_roles.wait.find { |role| role.id == option[:value] }
|
78
|
+
when 11
|
79
|
+
attachments[option[:value]]
|
76
80
|
end
|
77
81
|
option_map[option[:name]] = val
|
78
82
|
end
|
@@ -92,6 +96,7 @@ module Discorb
|
|
92
96
|
private
|
93
97
|
|
94
98
|
def _set_data(data)
|
99
|
+
super
|
95
100
|
@target = guild.members[data[:target_id]] || Discorb::Member.new(@client, @guild_id, data[:resolved][:users][data[:target_id].to_sym], data[:resolved][:members][data[:target_id].to_sym])
|
96
101
|
@client.commands.find { |c| c.name == data[:name] && c.type_raw == 2 }.block.call(self, @target)
|
97
102
|
end
|
@@ -109,7 +114,8 @@ module Discorb
|
|
109
114
|
private
|
110
115
|
|
111
116
|
def _set_data(data)
|
112
|
-
|
117
|
+
super
|
118
|
+
@target = @messages[data[:target_id]]
|
113
119
|
@client.commands.find { |c| c.name == data[:name] && c.type_raw == 3 }.block.call(self, @target)
|
114
120
|
end
|
115
121
|
end
|
@@ -117,7 +123,26 @@ module Discorb
|
|
117
123
|
private
|
118
124
|
|
119
125
|
def _set_data(data)
|
126
|
+
super
|
120
127
|
@name = data[:name]
|
128
|
+
@messages, @attachments, @members = {}, {}, {}
|
129
|
+
|
130
|
+
if data[:resolved]
|
131
|
+
data[:resolved][:users]&.each do |id, user|
|
132
|
+
@client.users[id] = Discorb::User.new(@client, user)
|
133
|
+
end
|
134
|
+
data[:resolved][:members]&.each do |id, member|
|
135
|
+
@members[id] = Discorb::Member.new(
|
136
|
+
@client, @guild_id, data[:resolved][:users][id], member
|
137
|
+
)
|
138
|
+
end
|
139
|
+
data[:resolved][:messages]&.to_h do |id, _message|
|
140
|
+
@messages[id.to_i] = Message.new(@client, data[:resolved][:messages][data[:target_id].to_sym].merge(guild_id: @guild_id.to_s)).merge(guild_id: @guild_id.to_s)
|
141
|
+
end
|
142
|
+
data[:resolved][:attachments]&.to_h do |id, attachment|
|
143
|
+
@attachments[id.to_s] = Attachment.new(attachment)
|
144
|
+
end
|
145
|
+
end
|
121
146
|
end
|
122
147
|
|
123
148
|
class << self
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Discorb
|
2
3
|
|
3
4
|
#
|
@@ -5,8 +6,10 @@ module Discorb
|
|
5
6
|
# @abstract
|
6
7
|
#
|
7
8
|
class MessageComponentInteraction < Interaction
|
8
|
-
include Interaction::
|
9
|
-
include Interaction::
|
9
|
+
include Interaction::SourceResponder
|
10
|
+
include Interaction::UpdateResponder
|
11
|
+
include Interaction::ModalResponder
|
12
|
+
|
10
13
|
# @return [String] The content of the response.
|
11
14
|
attr_reader :custom_id
|
12
15
|
# @return [Discorb::Message] The target message.
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Discorb
|
4
|
+
|
5
|
+
#
|
6
|
+
# Represents a modal interaction.
|
7
|
+
#
|
8
|
+
class ModalInteraction < Interaction
|
9
|
+
include Interaction::SourceResponder
|
10
|
+
|
11
|
+
@interaction_type = 5
|
12
|
+
@interaction_name = :modal_submit
|
13
|
+
@event_name = :modal_submit
|
14
|
+
|
15
|
+
# @return [String] The custom id of the modal.
|
16
|
+
attr_reader :custom_id
|
17
|
+
# @return [{String => String}] The contents of the modal.
|
18
|
+
attr_reader :contents
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def _set_data(data)
|
23
|
+
@custom_id = data[:custom_id]
|
24
|
+
@contents = data[:components].to_h do |component|
|
25
|
+
[component[:components][0][:custom_id], component[:components][0][:value]]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class << self
|
30
|
+
alias make_interaction new
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,9 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Discorb
|
3
|
+
#
|
4
|
+
# Represents an interaction of Discord.
|
5
|
+
#
|
2
6
|
class Interaction
|
3
7
|
#
|
4
8
|
# A module for response with source.
|
5
9
|
#
|
6
|
-
module
|
10
|
+
module SourceResponder
|
7
11
|
#
|
8
12
|
# Response with `DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE`(`5`).
|
9
13
|
#
|
@@ -38,14 +42,14 @@ module Discorb
|
|
38
42
|
# @param [Array<Discorb::Component>, Array<Array<Discorb::Component>>] components The components to send.
|
39
43
|
# @param [Boolean] ephemeral Whether to make the response ephemeral.
|
40
44
|
#
|
41
|
-
# @return [Discorb::Interaction::
|
45
|
+
# @return [Discorb::Interaction::SourceResponder::CallbackMessage, Discorb::Webhook::Message] The callback message.
|
42
46
|
#
|
43
47
|
def post(content = nil, tts: false, embed: nil, embeds: nil, allowed_mentions: nil, components: nil, ephemeral: false)
|
44
48
|
Async do
|
45
49
|
payload = {}
|
46
50
|
payload[:content] = content if content
|
47
51
|
payload[:tts] = tts
|
48
|
-
payload[:embeds] = (embeds || [embed])
|
52
|
+
payload[:embeds] = (embeds || [embed]).map { |e| e&.to_hash }.filter { _1 }
|
49
53
|
payload[:allowed_mentions] = allowed_mentions&.to_hash(@client.allowed_mentions) || @client.allowed_mentions.to_hash
|
50
54
|
payload[:components] = Component.to_payload(components) if components
|
51
55
|
payload[:flags] = (ephemeral ? 1 << 6 : 0)
|
@@ -66,6 +70,9 @@ module Discorb
|
|
66
70
|
end
|
67
71
|
end
|
68
72
|
|
73
|
+
#
|
74
|
+
# Represents of a callback message of interaction.
|
75
|
+
#
|
69
76
|
class CallbackMessage
|
70
77
|
# @private
|
71
78
|
def initialize(client, data, application_id, token)
|
@@ -127,7 +134,7 @@ module Discorb
|
|
127
134
|
#
|
128
135
|
# A module for response with update.
|
129
136
|
#
|
130
|
-
module
|
137
|
+
module UpdateResponder
|
131
138
|
#
|
132
139
|
# Response with `DEFERRED_UPDATE_MESSAGE`(`6`).
|
133
140
|
# @async
|
@@ -181,6 +188,28 @@ module Discorb
|
|
181
188
|
end
|
182
189
|
end
|
183
190
|
|
191
|
+
#
|
192
|
+
# A module for response with modal.
|
193
|
+
#
|
194
|
+
module ModalResponder
|
195
|
+
#
|
196
|
+
# Response with `MODAL`(`9`).
|
197
|
+
#
|
198
|
+
# @param [String] title The title of the modal.
|
199
|
+
# @param [String] custom_id The custom id of the modal.
|
200
|
+
# @param [Array<Discorb::TextInput>] components The text inputs to send.
|
201
|
+
#
|
202
|
+
# @return [Async::Task<void>] The task.
|
203
|
+
#
|
204
|
+
def show_modal(title, custom_id, components)
|
205
|
+
payload = { title: title, custom_id: custom_id, components: Component.to_payload(components) }
|
206
|
+
@client.http.request(
|
207
|
+
Route.new("/interactions/#{@id}/#{@token}/callback", "//interactions/:interaction_id/:token/callback", :post),
|
208
|
+
{ type: 9, data: payload }
|
209
|
+
).wait
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
184
213
|
private
|
185
214
|
|
186
215
|
def _set_data(*)
|
data/lib/discorb/interaction.rb
CHANGED
data/lib/discorb/log.rb
CHANGED
data/lib/discorb/member.rb
CHANGED