discorb 0.11.4 → 0.12.0
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/Changelog.md +8 -0
- data/README.md +2 -1
- data/lib/discorb/app_command.rb +14 -0
- data/lib/discorb/client.rb +44 -36
- data/lib/discorb/common.rb +1 -1
- data/lib/discorb/error.rb +8 -5
- data/lib/discorb/gateway.rb +30 -23
- data/lib/discorb/interaction/autocomplete.rb +49 -0
- data/lib/discorb/interaction/command.rb +142 -0
- data/lib/discorb/interaction/components.rb +85 -0
- data/lib/discorb/interaction/response.rb +188 -0
- data/lib/discorb/interaction/root.rb +94 -0
- data/lib/discorb/interaction.rb +2 -618
- metadata +7 -2
@@ -0,0 +1,188 @@
|
|
1
|
+
module Discorb
|
2
|
+
class Interaction
|
3
|
+
#
|
4
|
+
# A module for response with source.
|
5
|
+
#
|
6
|
+
module SourceResponse
|
7
|
+
#
|
8
|
+
# Response with `DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE`(`5`).
|
9
|
+
#
|
10
|
+
# @macro async
|
11
|
+
# @macro http
|
12
|
+
#
|
13
|
+
# @param [Boolean] ephemeral Whether to make the response ephemeral.
|
14
|
+
#
|
15
|
+
def defer_source(ephemeral: false)
|
16
|
+
Async do
|
17
|
+
@client.http.post("/interactions/#{@id}/#{@token}/callback", {
|
18
|
+
type: 5,
|
19
|
+
data: {
|
20
|
+
flags: (ephemeral ? 1 << 6 : 0),
|
21
|
+
},
|
22
|
+
}).wait
|
23
|
+
@defered = true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Response with `CHANNEL_MESSAGE_WITH_SOURCE`(`4`).
|
29
|
+
#
|
30
|
+
# @macro async
|
31
|
+
# @macro http
|
32
|
+
#
|
33
|
+
# @param [String] content The content of the response.
|
34
|
+
# @param [Boolean] tts Whether to send the message as text-to-speech.
|
35
|
+
# @param [Discorb::Embed] embed The embed to send.
|
36
|
+
# @param [Array<Discorb::Embed>] embeds The embeds to send. (max: 10)
|
37
|
+
# @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions to send.
|
38
|
+
# @param [Array<Discorb::Component>, Array<Array<Discorb::Component>>] components The components to send.
|
39
|
+
# @param [Boolean] ephemeral Whether to make the response ephemeral.
|
40
|
+
#
|
41
|
+
# @return [Discorb::Interaction::SourceResponse::CallbackMessage, Discorb::Webhook::Message] The callback message.
|
42
|
+
#
|
43
|
+
def post(content = nil, tts: false, embed: nil, embeds: nil, allowed_mentions: nil, components: nil, ephemeral: false)
|
44
|
+
Async do
|
45
|
+
payload = {}
|
46
|
+
payload[:content] = content if content
|
47
|
+
payload[:tts] = tts
|
48
|
+
payload[:embeds] = (embeds || [embed])&.map { |e| e&.to_hash }.filter { _1 }
|
49
|
+
payload[:allowed_mentions] = allowed_mentions&.to_hash(@client.allowed_mentions) || @client.allowed_mentions.to_hash
|
50
|
+
payload[:components] = Component.to_payload(components) if components
|
51
|
+
payload[:flags] = (ephemeral ? 1 << 6 : 0)
|
52
|
+
|
53
|
+
ret = if @responded
|
54
|
+
_resp, data = @client.http.post("/webhooks/#{@application_id}/#{@token}", payload).wait
|
55
|
+
webhook = Webhook::URLWebhook.new("/webhooks/#{@application_id}/#{@token}")
|
56
|
+
Webhook::Message.new(webhook, data, @client)
|
57
|
+
elsif @defered
|
58
|
+
@client.http.patch("/webhooks/#{@application_id}/#{@token}/messages/@original", payload).wait
|
59
|
+
CallbackMessage.new(@client, payload, @application_id, @token)
|
60
|
+
else
|
61
|
+
@client.http.post("/interactions/#{@id}/#{@token}/callback", { type: 4, data: payload }).wait
|
62
|
+
CallbackMessage.new(@client, payload, @application_id, @token)
|
63
|
+
end
|
64
|
+
@responded = true
|
65
|
+
ret
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class CallbackMessage
|
70
|
+
# @private
|
71
|
+
def initialize(client, data, application_id, token)
|
72
|
+
@client = client
|
73
|
+
@data = data
|
74
|
+
@application_id = application_id
|
75
|
+
@token = token
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# Edits the callback message.
|
80
|
+
# @macro async
|
81
|
+
# @macro http
|
82
|
+
# @macro edit
|
83
|
+
#
|
84
|
+
# @param [String] content The new content of the message.
|
85
|
+
# @param [Discorb::Embed] embed The new embed of the message.
|
86
|
+
# @param [Array<Discorb::Embed>] embeds The new embeds of the message.
|
87
|
+
# @param [Array<Discorb::Attachment>] attachments The attachments to remain.
|
88
|
+
# @param [Discorb::File] file The file to send.
|
89
|
+
# @param [Array<Discorb::File>] files The files to send.
|
90
|
+
#
|
91
|
+
def edit(
|
92
|
+
content = :unset,
|
93
|
+
embed: :unset, embeds: :unset,
|
94
|
+
file: :unset, files: :unset,
|
95
|
+
attachments: :unset
|
96
|
+
)
|
97
|
+
Async do
|
98
|
+
payload = {}
|
99
|
+
payload[:content] = content if content != :unset
|
100
|
+
payload[:embeds] = embed ? [embed.to_hash] : [] if embed != :unset
|
101
|
+
payload[:embeds] = embeds.map(&:to_hash) if embeds != :unset
|
102
|
+
payload[:attachments] = attachments.map(&:to_hash) if attachments != :unset
|
103
|
+
files = [file] if file != :unset
|
104
|
+
if files == :unset
|
105
|
+
headers = {
|
106
|
+
"Content-Type" => "application/json",
|
107
|
+
}
|
108
|
+
else
|
109
|
+
headers, payload = HTTP.multipart(payload, files)
|
110
|
+
end
|
111
|
+
@client.http.patch("/webhooks/#{@application_id}/#{@token}/messages/@original", payload, headers: headers).wait
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
alias modify edit
|
116
|
+
|
117
|
+
#
|
118
|
+
# Deletes the callback message.
|
119
|
+
# @note This will fail if the message is ephemeral.
|
120
|
+
#
|
121
|
+
def delete!
|
122
|
+
Async do
|
123
|
+
@client.http.delete("/webhooks/#{@application_id}/#{@token}/messages/@original").wait
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
#
|
130
|
+
# A module for response with update.
|
131
|
+
#
|
132
|
+
module UpdateResponse
|
133
|
+
#
|
134
|
+
# Response with `DEFERRED_UPDATE_MESSAGE`(`6`).
|
135
|
+
#
|
136
|
+
# @param [Boolean] ephemeral Whether to make the response ephemeral.
|
137
|
+
#
|
138
|
+
def defer_update(ephemeral: false)
|
139
|
+
Async do
|
140
|
+
@client.http.post("/interactions/#{@id}/#{@token}/callback", {
|
141
|
+
type: 6,
|
142
|
+
data: {
|
143
|
+
flags: (ephemeral ? 1 << 6 : 0),
|
144
|
+
},
|
145
|
+
}).wait
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
#
|
150
|
+
# Response with `UPDATE_MESSAGE`(`7`).
|
151
|
+
#
|
152
|
+
# @macro async
|
153
|
+
# @macro http
|
154
|
+
#
|
155
|
+
# @param [String] content The content of the response.
|
156
|
+
# @param [Boolean] tts Whether to send the message as text-to-speech.
|
157
|
+
# @param [Discorb::Embed] embed The embed to send.
|
158
|
+
# @param [Array<Discorb::Embed>] embeds The embeds to send. (max: 10)
|
159
|
+
# @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions to send.
|
160
|
+
# @param [Array<Discorb::Component>, Array<Array<Discorb::Component>>] components The components to send.
|
161
|
+
# @param [Boolean] ephemeral Whether to make the response ephemeral.
|
162
|
+
#
|
163
|
+
def edit(content, tts: false, embed: nil, embeds: nil, allowed_mentions: nil, components: nil, ephemeral: false)
|
164
|
+
Async do
|
165
|
+
payload = {}
|
166
|
+
payload[:content] = content if content
|
167
|
+
payload[:tts] = tts
|
168
|
+
tmp_embed = if embed
|
169
|
+
[embed]
|
170
|
+
elsif embeds
|
171
|
+
embeds
|
172
|
+
end
|
173
|
+
payload[:embeds] = tmp_embed.map(&:to_hash) if tmp_embed
|
174
|
+
payload[:allowed_mentions] = allowed_mentions ? allowed_mentions.to_hash(@client.allowed_mentions) : @client.allowed_mentions.to_hash
|
175
|
+
payload[:components] = Component.to_payload(components) if components
|
176
|
+
payload[:flags] = (ephemeral ? 1 << 6 : 0)
|
177
|
+
@client.http.post("/interactions/#{@id}/#{@token}/callback", { type: 7, data: payload }).wait
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
def _set_data(*)
|
185
|
+
nil
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Discorb
|
2
|
+
#
|
3
|
+
# Represents a user interaction with the bot.
|
4
|
+
#
|
5
|
+
class Interaction < DiscordModel
|
6
|
+
# @return [Discorb::Snowflake] The ID of the interaction.
|
7
|
+
attr_reader :id
|
8
|
+
# @return [Discorb::Snowflake] The ID of the application that created the interaction.
|
9
|
+
attr_reader :application_id
|
10
|
+
# @return [Symbol] The type of interaction.
|
11
|
+
attr_reader :type
|
12
|
+
# @return [Discorb::Member] The member that created the interaction.
|
13
|
+
attr_reader :member
|
14
|
+
# @return [Discorb::User] The user that created the interaction.
|
15
|
+
attr_reader :user
|
16
|
+
# @return [Integer] The type of interaction.
|
17
|
+
# @note This is always `1` for now.
|
18
|
+
attr_reader :version
|
19
|
+
# @return [String] The token for the interaction.
|
20
|
+
attr_reader :token
|
21
|
+
|
22
|
+
# @!attribute [r] guild
|
23
|
+
# @macro client_cache
|
24
|
+
# @return [Discorb::Guild] The guild the interaction took place in.
|
25
|
+
# @!attribute [r] channel
|
26
|
+
# @macro client_cache
|
27
|
+
# @return [Discorb::Channel] The channel the interaction took place in.
|
28
|
+
# @!attribute [r] target
|
29
|
+
# @return [Discorb::User, Discorb::Member] The user or member the interaction took place with.
|
30
|
+
|
31
|
+
@interaction_type = nil
|
32
|
+
@interaction_name = nil
|
33
|
+
|
34
|
+
# @private
|
35
|
+
def initialize(client, data)
|
36
|
+
@client = client
|
37
|
+
@id = Snowflake.new(data[:id])
|
38
|
+
@application_id = Snowflake.new(data[:application_id])
|
39
|
+
@type = self.class.interaction_name
|
40
|
+
@type_id = self.class.interaction_type
|
41
|
+
@guild_id = data[:guild_id] && Snowflake.new(data[:guild_id])
|
42
|
+
@channel_id = data[:channel_id] && Snowflake.new(data[:channel_id])
|
43
|
+
@member = guild.members[data[:member][:id]] || Member.new(@client, @guild_id, data[:member][:user], data[:member]) if data[:member]
|
44
|
+
@user = @client.users[data[:user][:id]] || User.new(@client, data[:user]) if data[:user]
|
45
|
+
@token = data[:token]
|
46
|
+
@version = data[:version]
|
47
|
+
@defered = false
|
48
|
+
@responded = false
|
49
|
+
_set_data(data[:data])
|
50
|
+
end
|
51
|
+
|
52
|
+
def guild
|
53
|
+
@client.guilds[@guild_id]
|
54
|
+
end
|
55
|
+
|
56
|
+
def channel
|
57
|
+
@client.channels[@channel_id]
|
58
|
+
end
|
59
|
+
|
60
|
+
def target
|
61
|
+
@member || @user
|
62
|
+
end
|
63
|
+
|
64
|
+
alias fired_by target
|
65
|
+
alias from target
|
66
|
+
|
67
|
+
def inspect
|
68
|
+
"#<#{self.class} id=#{@id}>"
|
69
|
+
end
|
70
|
+
|
71
|
+
class << self
|
72
|
+
# @private
|
73
|
+
attr_reader :interaction_type, :interaction_name, :event_name
|
74
|
+
|
75
|
+
# @private
|
76
|
+
def make_interaction(client, data)
|
77
|
+
interaction = nil
|
78
|
+
descendants.each do |klass|
|
79
|
+
interaction = klass.make_interaction(client, data) if !klass.interaction_type.nil? && klass.interaction_type == data[:type]
|
80
|
+
end
|
81
|
+
if interaction.nil?
|
82
|
+
client.log.warn("Unknown interaction type #{data[:type]}, initialized Interaction")
|
83
|
+
interaction = Interaction.new(client, data)
|
84
|
+
end
|
85
|
+
interaction
|
86
|
+
end
|
87
|
+
|
88
|
+
# @private
|
89
|
+
def descendants
|
90
|
+
ObjectSpace.each_object(Class).select { |klass| klass < self }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|