discorb 0.13.4 → 0.15.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.
- checksums.yaml +4 -4
- data/.gitattributes +2 -0
- data/.github/workflows/build_version.yml +1 -1
- data/.github/workflows/codeql-analysis.yml +70 -0
- data/.github/workflows/lint-push.yml +20 -0
- data/.github/workflows/lint.yml +16 -0
- data/.rubocop.yml +74 -0
- data/Changelog.md +30 -0
- data/Gemfile +7 -3
- data/Rakefile +28 -22
- data/discorb.gemspec +1 -0
- data/docs/events.md +50 -0
- data/docs/faq.md +8 -8
- 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 +71 -0
- data/lib/discorb/app_command/command.rb +336 -0
- data/lib/discorb/app_command/handler.rb +168 -0
- data/lib/discorb/app_command.rb +2 -426
- data/lib/discorb/application.rb +16 -7
- data/lib/discorb/asset.rb +11 -0
- data/lib/discorb/{file.rb → attachment.rb} +55 -33
- data/lib/discorb/audit_logs.rb +45 -7
- data/lib/discorb/channel.rb +65 -15
- data/lib/discorb/client.rb +34 -27
- data/lib/discorb/common.rb +19 -27
- data/lib/discorb/components/button.rb +105 -0
- data/lib/discorb/components/select_menu.rb +143 -0
- data/lib/discorb/components/text_input.rb +96 -0
- data/lib/discorb/components.rb +11 -276
- data/lib/discorb/dictionary.rb +5 -0
- data/lib/discorb/embed.rb +73 -40
- data/lib/discorb/emoji.rb +48 -5
- data/lib/discorb/error.rb +9 -5
- data/lib/discorb/event.rb +36 -24
- 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 +112 -51
- data/lib/discorb/gateway_requests.rb +4 -7
- data/lib/discorb/guild.rb +73 -41
- data/lib/discorb/guild_template.rb +26 -5
- data/lib/discorb/http.rb +38 -18
- data/lib/discorb/integration.rb +24 -9
- data/lib/discorb/intents.rb +16 -11
- data/lib/discorb/interaction/autocomplete.rb +6 -5
- data/lib/discorb/interaction/command.rb +66 -12
- data/lib/discorb/interaction/components.rb +19 -3
- data/lib/discorb/interaction/modal.rb +33 -0
- data/lib/discorb/interaction/response.rb +45 -4
- data/lib/discorb/interaction/root.rb +16 -0
- data/lib/discorb/interaction.rb +2 -1
- data/lib/discorb/invite.rb +11 -7
- data/lib/discorb/log.rb +5 -5
- data/lib/discorb/member.rb +22 -3
- data/lib/discorb/message.rb +39 -234
- data/lib/discorb/message_meta.rb +186 -0
- data/lib/discorb/modules.rb +39 -15
- data/lib/discorb/permission.rb +16 -7
- data/lib/discorb/presence.rb +45 -9
- data/lib/discorb/rate_limit.rb +7 -4
- data/lib/discorb/reaction.rb +6 -0
- data/lib/discorb/role.rb +12 -0
- data/lib/discorb/sticker.rb +22 -14
- data/lib/discorb/user.rb +12 -1
- data/lib/discorb/utils/colored_puts.rb +1 -0
- data/lib/discorb/voice_state.rb +23 -2
- data/lib/discorb/webhook.rb +54 -3
- data/lib/discorb.rb +5 -2
- data/sig/discorb.rbs +838 -702
- 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 +17 -3
@@ -33,7 +33,13 @@ module Discorb
|
|
33
33
|
# @return [Discorb::Guild] The guild this template is based on.
|
34
34
|
# @return [nil] Client wasn't able to find the guild this template is based on.
|
35
35
|
|
36
|
+
#
|
37
|
+
# Initialize a new template.
|
36
38
|
# @private
|
39
|
+
#
|
40
|
+
# @param [Discorb::Client] client The client.
|
41
|
+
# @param [Hash] data The data from Discord.
|
42
|
+
#
|
37
43
|
def initialize(client, data)
|
38
44
|
@client = client
|
39
45
|
_set_data(data)
|
@@ -120,14 +126,19 @@ module Discorb
|
|
120
126
|
attr_reader :widget_enabled
|
121
127
|
alias widget_enabled? widget_enabled
|
122
128
|
|
129
|
+
#
|
130
|
+
# Initialize a new guild in guild template.
|
123
131
|
# @private
|
132
|
+
#
|
133
|
+
# @param [Hash] data The data from Discord.
|
134
|
+
#
|
124
135
|
def initialize(data)
|
125
136
|
@name = data[:name]
|
126
137
|
@description = data[:description]
|
127
138
|
@region = data[:region]
|
128
|
-
@verification_level = Discorb::Guild
|
129
|
-
@default_message_notifications = Discorb::Guild
|
130
|
-
@explicit_content_filter = Discorb::Guild
|
139
|
+
@verification_level = Discorb::Guild::MFA_LEVELS[data[:verification_level]]
|
140
|
+
@default_message_notifications = Discorb::Guild::NOTIFICATION_LEVELS[data[:default_message_notifications]]
|
141
|
+
@explicit_content_filter = Discorb::Guild::EXPLICIT_CONTENT_FILTERS[data[:explicit_content_filter]]
|
131
142
|
@preferred_locale = data[:preferred_locale]
|
132
143
|
@afk_timeout = data[:afk_timeout]
|
133
144
|
@roles = data[:roles].map { |r| Role.new(r) }
|
@@ -146,7 +157,12 @@ module Discorb
|
|
146
157
|
# @return [Discorb::Color] The color of the role.
|
147
158
|
attr_reader :color
|
148
159
|
|
160
|
+
#
|
161
|
+
# Initialize a new role in guild template.
|
149
162
|
# @private
|
163
|
+
#
|
164
|
+
# @param [Hash] data The data from Discord.
|
165
|
+
#
|
150
166
|
def initialize(data)
|
151
167
|
@name = data[:name]
|
152
168
|
@permissions = Permission.new(data[:permissions])
|
@@ -177,7 +193,12 @@ module Discorb
|
|
177
193
|
# @return [Class] The class of the channel.
|
178
194
|
attr_reader :type
|
179
195
|
|
196
|
+
#
|
197
|
+
# Initialize a new channel in guild template.
|
180
198
|
# @private
|
199
|
+
#
|
200
|
+
# @param [Hash] data The data from Discord.
|
201
|
+
#
|
181
202
|
def initialize(data)
|
182
203
|
@name = data[:name]
|
183
204
|
@position = data[:position]
|
@@ -187,9 +208,9 @@ module Discorb
|
|
187
208
|
@nsfw = data[:nsfw]
|
188
209
|
@rate_limit_per_user = data[:rate_limit_per_user]
|
189
210
|
@parent_id = data[:parent_id]
|
190
|
-
@permission_overwrites = data[:permission_overwrites].
|
211
|
+
@permission_overwrites = data[:permission_overwrites].to_h do |ow|
|
191
212
|
[Snowflake.new(ow[:id]), PermissionOverwrite.new(ow[:allow], ow[:deny])]
|
192
|
-
end
|
213
|
+
end
|
193
214
|
@type = Discorb::Channel.descendants.find { |c| c.channel_type == data[:type] }
|
194
215
|
end
|
195
216
|
end
|
data/lib/discorb/http.rb
CHANGED
@@ -10,7 +10,12 @@ module Discorb
|
|
10
10
|
class HTTP
|
11
11
|
@nil_body = nil
|
12
12
|
|
13
|
+
#
|
14
|
+
# Initializes the http client.
|
13
15
|
# @private
|
16
|
+
#
|
17
|
+
# @param [Discorb::Client] client The client.
|
18
|
+
#
|
14
19
|
def initialize(client)
|
15
20
|
@client = client
|
16
21
|
@ratelimit_handler = RatelimitHandler.new(client)
|
@@ -32,13 +37,13 @@ module Discorb
|
|
32
37
|
# @raise [Discorb::HTTPError] The request was failed.
|
33
38
|
#
|
34
39
|
def request(path, body = "", headers: nil, audit_log_reason: nil, **kwargs)
|
35
|
-
Async do |
|
40
|
+
Async do |_task|
|
36
41
|
@ratelimit_handler.wait(path)
|
37
|
-
if %i[post patch put].include? path.method
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
+
resp = if %i[post patch put].include? path.method
|
43
|
+
http.send(path.method, get_path(path), get_body(body), get_headers(headers, body, audit_log_reason), **kwargs)
|
44
|
+
else
|
45
|
+
http.send(path.method, get_path(path), get_headers(headers, body, audit_log_reason), **kwargs)
|
46
|
+
end
|
42
47
|
data = get_response_data(resp)
|
43
48
|
@ratelimit_handler.save(path, resp)
|
44
49
|
handle_response(resp, data, path, body, headers, audit_log_reason, kwargs)
|
@@ -61,8 +66,8 @@ module Discorb
|
|
61
66
|
#
|
62
67
|
# @raise [Discorb::HTTPError] The request was failed.
|
63
68
|
#
|
64
|
-
def multipart_request(path, body
|
65
|
-
Async do |
|
69
|
+
def multipart_request(path, body, files, headers: nil, audit_log_reason: nil, **kwargs)
|
70
|
+
Async do |_task|
|
66
71
|
@ratelimit_handler.wait(path)
|
67
72
|
req = Net::HTTP.const_get(path.method.to_s.capitalize).new(get_path(path), get_headers(headers, body, audit_log_reason), **kwargs)
|
68
73
|
data = [
|
@@ -70,12 +75,23 @@ module Discorb
|
|
70
75
|
]
|
71
76
|
files&.each_with_index do |file, i|
|
72
77
|
next if file.nil?
|
73
|
-
|
78
|
+
if file.created_by == :discord
|
79
|
+
request_io = StringIO.new(
|
80
|
+
cdn_http.get(URI.parse(file.url).path, {
|
81
|
+
"Content-Type" => nil,
|
82
|
+
"User-Agent" => Discorb::USER_AGENT,
|
83
|
+
}).body
|
84
|
+
)
|
85
|
+
data << ["files[#{i}]", request_io, { filename: file.filename, content_type: file.content_type }]
|
86
|
+
else
|
87
|
+
data << ["files[#{i}]", file.io, { filename: file.filename, content_type: file.content_type }]
|
88
|
+
end
|
74
89
|
end
|
75
90
|
req.set_form(data, "multipart/form-data")
|
76
91
|
session = Net::HTTP.new("discord.com", 443)
|
77
92
|
session.use_ssl = true
|
78
93
|
resp = session.request(req)
|
94
|
+
files&.then { _1.filter(&:will_close).each { |f| f.io.close } }
|
79
95
|
data = get_response_data(resp)
|
80
96
|
@ratelimit_handler.save(path, resp)
|
81
97
|
handle_response(resp, data, path, body, headers, audit_log_reason, kwargs)
|
@@ -112,7 +128,7 @@ module Discorb
|
|
112
128
|
{ "User-Agent" => USER_AGENT, "authorization" => "Bot #{@client.token}" }
|
113
129
|
else
|
114
130
|
{ "User-Agent" => USER_AGENT, "authorization" => "Bot #{@client.token}",
|
115
|
-
"content-type" => "application/json" }
|
131
|
+
"content-type" => "application/json", }
|
116
132
|
end
|
117
133
|
ret.merge!(headers) if !headers.nil? && headers.length.positive?
|
118
134
|
ret["X-Audit-Log-Reason"] = audit_log_reason unless audit_log_reason.nil?
|
@@ -143,15 +159,13 @@ module Discorb
|
|
143
159
|
begin
|
144
160
|
data = JSON.parse(resp.body, symbolize_names: true)
|
145
161
|
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)
|
162
|
+
data = if resp.body.nil? || resp.body.empty?
|
163
|
+
nil
|
164
|
+
else
|
165
|
+
resp.body
|
166
|
+
end
|
154
167
|
end
|
168
|
+
raise CloudFlareBanError.new(resp, @client) if resp["Via"].nil? && resp.code == "429" && data.is_a?(String)
|
155
169
|
data
|
156
170
|
end
|
157
171
|
|
@@ -161,6 +175,12 @@ module Discorb
|
|
161
175
|
https
|
162
176
|
end
|
163
177
|
|
178
|
+
def cdn_http
|
179
|
+
https = Net::HTTP.new("cdn.discordapp.com", 443)
|
180
|
+
https.use_ssl = true
|
181
|
+
https
|
182
|
+
end
|
183
|
+
|
164
184
|
def recr_utf8(data)
|
165
185
|
case data
|
166
186
|
when Hash
|
data/lib/discorb/integration.rb
CHANGED
@@ -38,13 +38,22 @@ module Discorb
|
|
38
38
|
# @macro client_cache
|
39
39
|
# @return [Discorb::Guild] The guild this integration is in.
|
40
40
|
|
41
|
-
@
|
41
|
+
# @private
|
42
|
+
# @return [{Integer => String}] The map of the expire behavior.
|
43
|
+
EXPIRE_BEHAVIOR = {
|
42
44
|
0 => :remove_role,
|
43
45
|
1 => :kick,
|
44
|
-
}
|
46
|
+
}.freeze
|
45
47
|
|
48
|
+
#
|
49
|
+
# Initialize a new integration.
|
46
50
|
# @private
|
47
|
-
|
51
|
+
#
|
52
|
+
# @param [Discorb::Client] client The client.
|
53
|
+
# @param [Hash] data The data of the welcome screen.
|
54
|
+
# @param [Discorb::Guild] guild The guild this integration is in.
|
55
|
+
#
|
56
|
+
def initialize(client, data, guild_id)
|
48
57
|
@client = client
|
49
58
|
@data = data
|
50
59
|
@guild_id = guild_id
|
@@ -80,7 +89,7 @@ module Discorb
|
|
80
89
|
@syncing = data[:syncing]
|
81
90
|
@role_id = Snowflake.new(data[:role_id])
|
82
91
|
@enable_emoticons = data[:enable_emoticons]
|
83
|
-
@expire_behavior =
|
92
|
+
@expire_behavior = EXPIRE_BEHAVIOR[data[:expire_behavior]]
|
84
93
|
@expire_grace_period = data[:expire_grace_period]
|
85
94
|
@user = @client.users[data[:user][:id]] or Discorb::User.new(@client, data[:user])
|
86
95
|
@account = Account.new(data[:account])
|
@@ -89,11 +98,6 @@ module Discorb
|
|
89
98
|
@application = data[:application] and Application.new(@client, data[:application])
|
90
99
|
end
|
91
100
|
|
92
|
-
class << self
|
93
|
-
# @private
|
94
|
-
attr_reader :expire_behavior
|
95
|
-
end
|
96
|
-
|
97
101
|
#
|
98
102
|
# Represents an account for an integration.
|
99
103
|
#
|
@@ -103,7 +107,12 @@ module Discorb
|
|
103
107
|
# @return [String] The name of the account.
|
104
108
|
attr_reader :name
|
105
109
|
|
110
|
+
#
|
111
|
+
# Initialize a new account.
|
106
112
|
# @private
|
113
|
+
#
|
114
|
+
# @param [Hash] data The data from Discord.
|
115
|
+
#
|
107
116
|
def initialize(data)
|
108
117
|
@id = data[:id]
|
109
118
|
@name = data[:name]
|
@@ -129,7 +138,13 @@ module Discorb
|
|
129
138
|
# @return [nil] If the application has no bot user.
|
130
139
|
attr_reader :bot
|
131
140
|
|
141
|
+
#
|
142
|
+
# Initialize a new application.
|
132
143
|
# @private
|
144
|
+
#
|
145
|
+
# @param [Discorb::Client] client The client.
|
146
|
+
# @param [Hash] data The data from Discord.
|
147
|
+
#
|
133
148
|
def initialize(client, data)
|
134
149
|
@id = Snowflake.new(data[:id])
|
135
150
|
@name = data[:name]
|
data/lib/discorb/intents.rb
CHANGED
@@ -3,7 +3,9 @@
|
|
3
3
|
module Discorb
|
4
4
|
# Represents intents.
|
5
5
|
class Intents
|
6
|
-
@
|
6
|
+
# @private
|
7
|
+
# @return [{Symbol => Integer}] The mapping of intent names to bit values.
|
8
|
+
INTENT_BITS = {
|
7
9
|
guilds: 1 << 0,
|
8
10
|
members: 1 << 1,
|
9
11
|
bans: 1 << 2,
|
@@ -19,6 +21,7 @@ module Discorb
|
|
19
21
|
dm_messages: 1 << 12,
|
20
22
|
dm_reactions: 1 << 13,
|
21
23
|
dm_typing: 1 << 14,
|
24
|
+
message_content: 1 << 15,
|
22
25
|
scheduled_events: 1 << 16,
|
23
26
|
}.freeze
|
24
27
|
|
@@ -39,9 +42,13 @@ module Discorb
|
|
39
42
|
# @param dm_messages [Boolean] Whether dm messages related events are enabled.
|
40
43
|
# @param dm_reactions [Boolean] Whether dm reactions related events are enabled.
|
41
44
|
# @param dm_typing [Boolean] Whether dm typing related events are enabled.
|
45
|
+
# @param message_content [Boolean] Whether message content will be sent with events.
|
42
46
|
# @param scheduled_events [Boolean] Whether events related scheduled events are enabled.
|
43
47
|
#
|
44
48
|
# @note You must enable privileged intents to use `members` and/or `presences` intents.
|
49
|
+
# @note Message Content Intent is not required to use `message_content` intents for now,
|
50
|
+
# this will be required in April 30, 2022. [Learn More](https://support-dev.discord.com/hc/en-us/articles/4404772028055).
|
51
|
+
# You should specify `message_content` intent for preventing unexpected changes in the future.
|
45
52
|
#
|
46
53
|
def initialize(guilds: true,
|
47
54
|
members: false,
|
@@ -58,6 +65,7 @@ module Discorb
|
|
58
65
|
dm_messages: true,
|
59
66
|
dm_reactions: true,
|
60
67
|
dm_typing: true,
|
68
|
+
message_content: nil,
|
61
69
|
scheduled_events: true)
|
62
70
|
@raw_value = {
|
63
71
|
guilds: guilds,
|
@@ -75,6 +83,7 @@ module Discorb
|
|
75
83
|
dm_messages: dm_messages,
|
76
84
|
dm_reactions: dm_reactions,
|
77
85
|
dm_typing: dm_typing,
|
86
|
+
message_content: message_content,
|
78
87
|
scheduled_events: scheduled_events,
|
79
88
|
}
|
80
89
|
end
|
@@ -86,7 +95,7 @@ module Discorb
|
|
86
95
|
if @raw_value.key?(name)
|
87
96
|
@raw_value[name]
|
88
97
|
elsif name.end_with?("=") && @raw_value.key?(name[0..-2].to_sym)
|
89
|
-
raise ArgumentError, "true/false expected" unless args.is_a?
|
98
|
+
raise ArgumentError, "true/false expected" unless args.is_a?(TrueClass) || args.is_a?(FalseClass)
|
90
99
|
|
91
100
|
@raw_value[name[0..-2].to_sym] = args
|
92
101
|
else
|
@@ -94,7 +103,7 @@ module Discorb
|
|
94
103
|
end
|
95
104
|
end
|
96
105
|
|
97
|
-
def respond_to_missing?(
|
106
|
+
def respond_to_missing?(name, include_private)
|
98
107
|
@raw_value.key?(name) ? true : super
|
99
108
|
end
|
100
109
|
|
@@ -102,7 +111,7 @@ module Discorb
|
|
102
111
|
# @return [Integer] The value of the intent.
|
103
112
|
def value
|
104
113
|
res = 0
|
105
|
-
|
114
|
+
INTENT_BITS.each do |intent, bit|
|
106
115
|
res += bit if @raw_value[intent]
|
107
116
|
end
|
108
117
|
res
|
@@ -121,7 +130,7 @@ module Discorb
|
|
121
130
|
# @param value [Integer] The value of the intent.
|
122
131
|
def from_value(value)
|
123
132
|
raw_value = {}
|
124
|
-
|
133
|
+
INTENT_BITS.each do |intent, bit|
|
125
134
|
raw_value[intent] = value & bit != 0
|
126
135
|
end
|
127
136
|
new(**raw_value)
|
@@ -129,21 +138,17 @@ module Discorb
|
|
129
138
|
|
130
139
|
# Create new intent object with default values.
|
131
140
|
# This will return intents without members and presence.
|
132
|
-
|
133
|
-
from_value(@intent_bits.values.reduce(:+) - @intent_bits[:members] - @intent_bits[:presences])
|
134
|
-
end
|
141
|
+
alias default new
|
135
142
|
|
136
143
|
# Create new intent object with all intents.
|
137
144
|
def all
|
138
|
-
from_value(
|
145
|
+
from_value(INTENT_BITS.values.reduce(:+))
|
139
146
|
end
|
140
147
|
|
141
148
|
# Create new intent object with no intents.
|
142
149
|
def none
|
143
150
|
from_value(0)
|
144
151
|
end
|
145
|
-
|
146
|
-
attr_reader :intent_bits
|
147
152
|
end
|
148
153
|
end
|
149
154
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Discorb
|
2
3
|
#
|
3
4
|
# Represents auto complete interaction.
|
@@ -6,7 +7,8 @@ module Discorb
|
|
6
7
|
@interaction_type = 4
|
7
8
|
@interaction_name = :auto_complete
|
8
9
|
|
9
|
-
|
10
|
+
private
|
11
|
+
|
10
12
|
def _set_data(data)
|
11
13
|
super
|
12
14
|
Sync do
|
@@ -17,15 +19,14 @@ module Discorb
|
|
17
19
|
next
|
18
20
|
end
|
19
21
|
|
20
|
-
option_map = command.options.
|
21
|
-
Discorb::CommandInteraction::SlashCommand.modify_option_map(option_map, options, guild)
|
22
|
+
option_map = command.options.to_h { |k, v| [k.to_s, v[:default]] }
|
23
|
+
Discorb::CommandInteraction::SlashCommand.modify_option_map(option_map, options, guild, {}, {})
|
22
24
|
focused_index = options.find_index { |o| o[:focused] }
|
23
|
-
val = command.options.values[focused_index][:autocomplete]&.call(self, *command.options.map { |k,
|
25
|
+
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
26
|
send_complete_result(val)
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
28
|
-
# @private
|
29
30
|
def send_complete_result(val)
|
30
31
|
@client.http.request(Route.new("/interactions/#{@id}/#{@token}/callback", "//interactions/:interaction_id/:token/callback", :post), {
|
31
32
|
type: 8,
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Discorb
|
2
3
|
#
|
3
4
|
# Represents a command interaction.
|
@@ -5,13 +6,15 @@ 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.
|
12
14
|
#
|
13
15
|
class SlashCommand < CommandInteraction
|
14
16
|
@command_type = 1
|
17
|
+
@event_name = :slash_command
|
15
18
|
|
16
19
|
private
|
17
20
|
|
@@ -25,14 +28,19 @@ module Discorb
|
|
25
28
|
return
|
26
29
|
end
|
27
30
|
|
28
|
-
option_map = command.options.
|
29
|
-
SlashCommand.modify_option_map(option_map, options, guild)
|
31
|
+
option_map = command.options.to_h { |k, v| [k.to_s, v[:default]] }
|
32
|
+
SlashCommand.modify_option_map(option_map, options, guild, @members, @attachments)
|
30
33
|
|
31
|
-
command.block.call(self, *command.options.map { |k,
|
34
|
+
command.block.call(self, *command.options.map { |k, _v| option_map[k.to_s] })
|
32
35
|
end
|
33
36
|
|
34
37
|
class << self
|
38
|
+
#
|
39
|
+
# Get command data from the given data.
|
35
40
|
# @private
|
41
|
+
#
|
42
|
+
# @param [Hash] data The data of the command.
|
43
|
+
#
|
36
44
|
def get_command_data(data)
|
37
45
|
name = data[:name]
|
38
46
|
options = nil
|
@@ -55,24 +63,34 @@ module Discorb
|
|
55
63
|
options = data[:options]
|
56
64
|
end
|
57
65
|
|
58
|
-
|
66
|
+
[name, options]
|
59
67
|
end
|
60
68
|
|
69
|
+
#
|
70
|
+
# Modify the option map with the given options.
|
61
71
|
# @private
|
62
|
-
|
72
|
+
#
|
73
|
+
# @param [Hash] option_map The option map to modify.
|
74
|
+
# @param [Array<Hash>] options The options for modifying.
|
75
|
+
# @param [Discorb::Guild] guild The guild where the command is executed.
|
76
|
+
# @param [{Discorb::Snowflake => Discorb::Member}] members The cached members of the guild.
|
77
|
+
# @param [{Integer => Discorb::Attachment}] attachments The cached attachments of the message.
|
78
|
+
def modify_option_map(option_map, options, guild, members, attachments)
|
63
79
|
options ||= []
|
64
|
-
options.
|
80
|
+
options.each do |option|
|
65
81
|
val = case option[:type]
|
66
82
|
when 3, 4, 5, 10
|
67
83
|
option[:value]
|
68
84
|
when 6
|
69
|
-
guild.members[option[:value]] || guild.fetch_member(option[:value]).wait
|
85
|
+
members[option[:value]] || guild.members[option[:value]] || guild.fetch_member(option[:value]).wait
|
70
86
|
when 7
|
71
87
|
guild.channels[option[:value]] || guild.fetch_channels.wait.find { |channel| channel.id == option[:value] }
|
72
88
|
when 8
|
73
89
|
guild.roles[option[:value]] || guild.fetch_roles.wait.find { |role| role.id == option[:value] }
|
74
90
|
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] }
|
91
|
+
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] }
|
92
|
+
when 11
|
93
|
+
attachments[option[:value]]
|
76
94
|
end
|
77
95
|
option_map[option[:name]] = val
|
78
96
|
end
|
@@ -85,6 +103,7 @@ module Discorb
|
|
85
103
|
#
|
86
104
|
class UserMenuCommand < CommandInteraction
|
87
105
|
@command_type = 2
|
106
|
+
@event_name = :user_command
|
88
107
|
|
89
108
|
# @return [Discorb::Member, Discorb::User] The target user.
|
90
109
|
attr_reader :target
|
@@ -92,6 +111,7 @@ module Discorb
|
|
92
111
|
private
|
93
112
|
|
94
113
|
def _set_data(data)
|
114
|
+
super
|
95
115
|
@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
116
|
@client.commands.find { |c| c.name == data[:name] && c.type_raw == 2 }.block.call(self, @target)
|
97
117
|
end
|
@@ -102,6 +122,7 @@ module Discorb
|
|
102
122
|
#
|
103
123
|
class MessageMenuCommand < CommandInteraction
|
104
124
|
@command_type = 3
|
125
|
+
@event_name = :message_command
|
105
126
|
|
106
127
|
# @return [Discorb::Message] The target message.
|
107
128
|
attr_reader :target
|
@@ -109,7 +130,8 @@ module Discorb
|
|
109
130
|
private
|
110
131
|
|
111
132
|
def _set_data(data)
|
112
|
-
|
133
|
+
super
|
134
|
+
@target = @messages[data[:target_id]]
|
113
135
|
@client.commands.find { |c| c.name == data[:name] && c.type_raw == 3 }.block.call(self, @target)
|
114
136
|
end
|
115
137
|
end
|
@@ -117,23 +139,55 @@ module Discorb
|
|
117
139
|
private
|
118
140
|
|
119
141
|
def _set_data(data)
|
142
|
+
super
|
120
143
|
@name = data[:name]
|
144
|
+
@messages, @attachments, @members = {}, {}, {}
|
145
|
+
|
146
|
+
if data[:resolved]
|
147
|
+
data[:resolved][:users]&.each do |id, user|
|
148
|
+
@client.users[id] = Discorb::User.new(@client, user)
|
149
|
+
end
|
150
|
+
data[:resolved][:members]&.each do |id, member|
|
151
|
+
@members[id] = Discorb::Member.new(
|
152
|
+
@client, @guild_id, data[:resolved][:users][id], member
|
153
|
+
)
|
154
|
+
end
|
155
|
+
data[:resolved][:messages]&.to_h do |id, _message|
|
156
|
+
@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)
|
157
|
+
end
|
158
|
+
data[:resolved][:attachments]&.to_h do |id, attachment|
|
159
|
+
@attachments[id.to_s] = Attachment.new(attachment)
|
160
|
+
end
|
161
|
+
end
|
121
162
|
end
|
122
163
|
|
123
164
|
class << self
|
124
165
|
# @private
|
125
|
-
attr_reader :command_type
|
166
|
+
attr_reader :command_type, :event_name
|
126
167
|
|
168
|
+
#
|
169
|
+
# Creates a new CommandInteraction instance for the given data.
|
127
170
|
# @private
|
171
|
+
#
|
172
|
+
# @param [Discorb::Client] client The client.
|
173
|
+
# @param [Hash] data The data for the command.
|
174
|
+
#
|
128
175
|
def make_interaction(client, data)
|
129
176
|
nested_classes.each do |klass|
|
130
|
-
|
177
|
+
if !klass.command_type.nil? && klass.command_type == data[:data][:type]
|
178
|
+
interaction = klass.new(client, data)
|
179
|
+
client.dispatch(klass.event_name, interaction)
|
180
|
+
return interaction
|
181
|
+
end
|
131
182
|
end
|
132
183
|
client.log.warn("Unknown command type #{data[:type]}, initialized CommandInteraction")
|
133
184
|
CommandInteraction.new(client, data)
|
134
185
|
end
|
135
186
|
|
187
|
+
#
|
188
|
+
# Returns the classes under this class.
|
136
189
|
# @private
|
190
|
+
#
|
137
191
|
def nested_classes
|
138
192
|
constants.select { |c| const_get(c).is_a? Class }.map { |c| const_get(c) }
|
139
193
|
end
|
@@ -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.
|
@@ -15,17 +18,27 @@ module Discorb
|
|
15
18
|
@interaction_type = 3
|
16
19
|
@interaction_name = :message_component
|
17
20
|
|
21
|
+
#
|
22
|
+
# Initialize a new message component interaction.
|
18
23
|
# @private
|
24
|
+
#
|
25
|
+
# @param [Discorb::Client] client The client.
|
26
|
+
# @param [Hash] data The data.
|
27
|
+
#
|
19
28
|
def initialize(client, data)
|
20
29
|
super
|
21
|
-
@message = Message.new(@client, data[:message].merge({ member: data[:member] }))
|
30
|
+
@message = Message.new(@client, data[:message].merge({ member: data[:member], guild_id: data[:guild_id] }))
|
22
31
|
end
|
23
32
|
|
24
33
|
class << self
|
25
34
|
# @private
|
35
|
+
# @return [Integer] The component type.
|
26
36
|
attr_reader :component_type
|
27
37
|
|
38
|
+
#
|
39
|
+
# Create a MessageComponentInteraction instance for the given data.
|
28
40
|
# @private
|
41
|
+
#
|
29
42
|
def make_interaction(client, data)
|
30
43
|
nested_classes.each do |klass|
|
31
44
|
return klass.new(client, data) if !klass.component_type.nil? && klass.component_type == data[:data][:component_type]
|
@@ -34,7 +47,10 @@ module Discorb
|
|
34
47
|
MessageComponentInteraction.new(client, data)
|
35
48
|
end
|
36
49
|
|
50
|
+
#
|
51
|
+
# Returns the classes under this class.
|
37
52
|
# @private
|
53
|
+
#
|
38
54
|
def nested_classes
|
39
55
|
constants.select { |c| const_get(c).is_a? Class }.map { |c| const_get(c) }
|
40
56
|
end
|
@@ -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
|