discorb 0.19.0 → 0.20.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/.github/workflows/build_version.yml +2 -2
- data/.rubocop.yml +12 -75
- data/Changelog.md +10 -0
- data/Rakefile +482 -454
- data/lib/discorb/allowed_mentions.rb +68 -72
- data/lib/discorb/app_command/command.rb +466 -398
- data/lib/discorb/app_command/common.rb +65 -25
- data/lib/discorb/app_command/handler.rb +304 -266
- data/lib/discorb/app_command.rb +5 -5
- data/lib/discorb/application.rb +198 -197
- data/lib/discorb/asset.rb +101 -101
- data/lib/discorb/attachment.rb +134 -119
- data/lib/discorb/audit_logs.rb +412 -385
- data/lib/discorb/automod.rb +279 -269
- data/lib/discorb/channel/base.rb +107 -108
- data/lib/discorb/channel/category.rb +32 -32
- data/lib/discorb/channel/container.rb +44 -44
- data/lib/discorb/channel/dm.rb +26 -28
- data/lib/discorb/channel/guild.rb +311 -246
- data/lib/discorb/channel/stage.rb +156 -140
- data/lib/discorb/channel/text.rb +430 -336
- data/lib/discorb/channel/thread.rb +374 -325
- data/lib/discorb/channel/voice.rb +85 -79
- data/lib/discorb/channel.rb +5 -5
- data/lib/discorb/client.rb +635 -621
- data/lib/discorb/color.rb +178 -182
- data/lib/discorb/common.rb +168 -164
- data/lib/discorb/components/button.rb +107 -106
- data/lib/discorb/components/select_menu.rb +157 -145
- data/lib/discorb/components/text_input.rb +103 -106
- data/lib/discorb/components.rb +68 -66
- data/lib/discorb/dictionary.rb +135 -135
- data/lib/discorb/embed.rb +404 -398
- data/lib/discorb/emoji.rb +309 -302
- data/lib/discorb/emoji_table.rb +16099 -8857
- data/lib/discorb/error.rb +131 -131
- data/lib/discorb/event.rb +360 -314
- data/lib/discorb/event_handler.rb +39 -39
- data/lib/discorb/exe/about.rb +17 -17
- data/lib/discorb/exe/irb.rb +72 -67
- data/lib/discorb/exe/new.rb +323 -315
- data/lib/discorb/exe/run.rb +69 -68
- data/lib/discorb/exe/setup.rb +57 -55
- data/lib/discorb/exe/show.rb +12 -12
- data/lib/discorb/extend.rb +25 -45
- data/lib/discorb/extension.rb +89 -83
- data/lib/discorb/flag.rb +126 -128
- data/lib/discorb/gateway.rb +984 -804
- data/lib/discorb/gateway_events.rb +670 -638
- data/lib/discorb/gateway_requests.rb +45 -48
- data/lib/discorb/guild.rb +2115 -1626
- data/lib/discorb/guild_template.rb +280 -241
- data/lib/discorb/http.rb +247 -232
- data/lib/discorb/image.rb +42 -42
- data/lib/discorb/integration.rb +169 -161
- data/lib/discorb/intents.rb +161 -163
- data/lib/discorb/interaction/autocomplete.rb +76 -62
- data/lib/discorb/interaction/command.rb +279 -224
- data/lib/discorb/interaction/components.rb +114 -104
- data/lib/discorb/interaction/modal.rb +36 -32
- data/lib/discorb/interaction/response.rb +379 -336
- data/lib/discorb/interaction/root.rb +271 -257
- data/lib/discorb/interaction.rb +5 -5
- data/lib/discorb/invite.rb +154 -153
- data/lib/discorb/member.rb +344 -311
- data/lib/discorb/message.rb +615 -544
- data/lib/discorb/message_meta.rb +197 -186
- data/lib/discorb/modules.rb +371 -290
- data/lib/discorb/permission.rb +305 -291
- data/lib/discorb/presence.rb +352 -346
- data/lib/discorb/rate_limit.rb +81 -76
- data/lib/discorb/reaction.rb +55 -54
- data/lib/discorb/role.rb +272 -240
- data/lib/discorb/shard.rb +76 -74
- data/lib/discorb/sticker.rb +193 -171
- data/lib/discorb/user.rb +205 -188
- data/lib/discorb/utils/colored_puts.rb +16 -16
- data/lib/discorb/utils.rb +12 -16
- data/lib/discorb/voice_state.rb +305 -281
- data/lib/discorb/webhook.rb +537 -507
- data/lib/discorb.rb +62 -56
- data/sig/discorb/application.rbs +2 -0
- data/sig/discorb/automod.rbs +10 -1
- data/sig/discorb/guild.rbs +2 -0
- data/sig/discorb/message.rbs +2 -0
- data/sig/discorb/user.rbs +22 -20
- metadata +2 -2
@@ -1,257 +1,271 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Discorb
|
4
|
-
#
|
5
|
-
# Represents a user interaction with the bot.
|
6
|
-
#
|
7
|
-
class Interaction < DiscordModel
|
8
|
-
# @return [Discorb::Snowflake] The ID of the interaction.
|
9
|
-
attr_reader :id
|
10
|
-
# @return [Discorb::Snowflake] The ID of the application that created the interaction.
|
11
|
-
attr_reader :application_id
|
12
|
-
# @return [Symbol] The type of interaction.
|
13
|
-
attr_reader :type
|
14
|
-
# @return [Discorb::User, Discorb::Member] The user or member that created the interaction.
|
15
|
-
attr_reader :user
|
16
|
-
alias member user
|
17
|
-
# @return [Integer] The type of interaction.
|
18
|
-
# @note This is always `1` for now.
|
19
|
-
attr_reader :version
|
20
|
-
# @return [String] The token for the interaction.
|
21
|
-
attr_reader :token
|
22
|
-
# @return [Symbol] The locale of the user that created the interaction.
|
23
|
-
# @note This modifies the language code, `-` will be replaced with `_`.
|
24
|
-
attr_reader :locale
|
25
|
-
# @return [Symbol] The locale of the guild that created the interaction.
|
26
|
-
# @note This modifies the language code, `-` will be replaced with `_`.
|
27
|
-
attr_reader :guild_locale
|
28
|
-
# @return [Discorb::Permission] The permissions of the bot.
|
29
|
-
attr_reader :app_permissions
|
30
|
-
|
31
|
-
# @!attribute [r] guild
|
32
|
-
# @macro client_cache
|
33
|
-
# @return [Discorb::Guild] The guild the interaction took place in.
|
34
|
-
# @!attribute [r] channel
|
35
|
-
# @macro client_cache
|
36
|
-
# @return [Discorb::Channel] The channel the interaction took place in.
|
37
|
-
# @!attribute [r] target
|
38
|
-
# @return [Discorb::User, Discorb::Member] The user or member the interaction took place with.
|
39
|
-
|
40
|
-
@interaction_type = nil
|
41
|
-
@interaction_name = nil
|
42
|
-
|
43
|
-
#
|
44
|
-
# Initialize a new interaction.
|
45
|
-
# @private
|
46
|
-
#
|
47
|
-
# @param [Discorb::Client] client The client this interaction belongs to.
|
48
|
-
# @param [Hash] data The data of the interaction.
|
49
|
-
#
|
50
|
-
def initialize(client, data)
|
51
|
-
@client = client
|
52
|
-
@id = Snowflake.new(data[:id])
|
53
|
-
@application_id = Snowflake.new(data[:application_id])
|
54
|
-
@type = self.class.interaction_name
|
55
|
-
@type_id = self.class.interaction_type
|
56
|
-
@guild_id = data[:guild_id] && Snowflake.new(data[:guild_id])
|
57
|
-
@channel_id = data[:channel_id] && Snowflake.new(data[:channel_id])
|
58
|
-
if data[:member]
|
59
|
-
@user =
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
@
|
67
|
-
@
|
68
|
-
@
|
69
|
-
@
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
# @
|
93
|
-
#
|
94
|
-
# @param [
|
95
|
-
# @param [
|
96
|
-
# @param [Discorb::
|
97
|
-
# @param [Array<Discorb::
|
98
|
-
# @param [
|
99
|
-
# @param [
|
100
|
-
#
|
101
|
-
# @
|
102
|
-
#
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
payload
|
119
|
-
payload[:
|
120
|
-
|
121
|
-
payload[:
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
#
|
156
|
-
#
|
157
|
-
#
|
158
|
-
#
|
159
|
-
# @
|
160
|
-
#
|
161
|
-
#
|
162
|
-
# @
|
163
|
-
#
|
164
|
-
# @
|
165
|
-
#
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
}
|
187
|
-
|
188
|
-
payload.
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Discorb
|
4
|
+
#
|
5
|
+
# Represents a user interaction with the bot.
|
6
|
+
#
|
7
|
+
class Interaction < DiscordModel
|
8
|
+
# @return [Discorb::Snowflake] The ID of the interaction.
|
9
|
+
attr_reader :id
|
10
|
+
# @return [Discorb::Snowflake] The ID of the application that created the interaction.
|
11
|
+
attr_reader :application_id
|
12
|
+
# @return [Symbol] The type of interaction.
|
13
|
+
attr_reader :type
|
14
|
+
# @return [Discorb::User, Discorb::Member] The user or member that created the interaction.
|
15
|
+
attr_reader :user
|
16
|
+
alias member user
|
17
|
+
# @return [Integer] The type of interaction.
|
18
|
+
# @note This is always `1` for now.
|
19
|
+
attr_reader :version
|
20
|
+
# @return [String] The token for the interaction.
|
21
|
+
attr_reader :token
|
22
|
+
# @return [Symbol] The locale of the user that created the interaction.
|
23
|
+
# @note This modifies the language code, `-` will be replaced with `_`.
|
24
|
+
attr_reader :locale
|
25
|
+
# @return [Symbol] The locale of the guild that created the interaction.
|
26
|
+
# @note This modifies the language code, `-` will be replaced with `_`.
|
27
|
+
attr_reader :guild_locale
|
28
|
+
# @return [Discorb::Permission] The permissions of the bot.
|
29
|
+
attr_reader :app_permissions
|
30
|
+
|
31
|
+
# @!attribute [r] guild
|
32
|
+
# @macro client_cache
|
33
|
+
# @return [Discorb::Guild] The guild the interaction took place in.
|
34
|
+
# @!attribute [r] channel
|
35
|
+
# @macro client_cache
|
36
|
+
# @return [Discorb::Channel] The channel the interaction took place in.
|
37
|
+
# @!attribute [r] target
|
38
|
+
# @return [Discorb::User, Discorb::Member] The user or member the interaction took place with.
|
39
|
+
|
40
|
+
@interaction_type = nil
|
41
|
+
@interaction_name = nil
|
42
|
+
|
43
|
+
#
|
44
|
+
# Initialize a new interaction.
|
45
|
+
# @private
|
46
|
+
#
|
47
|
+
# @param [Discorb::Client] client The client this interaction belongs to.
|
48
|
+
# @param [Hash] data The data of the interaction.
|
49
|
+
#
|
50
|
+
def initialize(client, data)
|
51
|
+
@client = client
|
52
|
+
@id = Snowflake.new(data[:id])
|
53
|
+
@application_id = Snowflake.new(data[:application_id])
|
54
|
+
@type = self.class.interaction_name
|
55
|
+
@type_id = self.class.interaction_type
|
56
|
+
@guild_id = data[:guild_id] && Snowflake.new(data[:guild_id])
|
57
|
+
@channel_id = data[:channel_id] && Snowflake.new(data[:channel_id])
|
58
|
+
if data[:member]
|
59
|
+
@user =
|
60
|
+
guild.members[data[:member][:id]] ||
|
61
|
+
Member.new(@client, @guild_id, data[:member][:user], data[:member])
|
62
|
+
elsif data[:user]
|
63
|
+
@user =
|
64
|
+
@client.users[data[:user][:id]] || User.new(@client, data[:user])
|
65
|
+
end
|
66
|
+
@token = data[:token]
|
67
|
+
@locale = data[:locale].to_s.gsub("-", "_").to_sym
|
68
|
+
@guild_locale = data[:guild_locale].to_s.gsub("-", "_").to_sym
|
69
|
+
@app_permissions =
|
70
|
+
data[:app_permissions] && Permission.new(data[:app_permissions].to_i)
|
71
|
+
@version = data[:version]
|
72
|
+
@defered = false
|
73
|
+
@responded = false
|
74
|
+
_set_data(data[:data])
|
75
|
+
end
|
76
|
+
|
77
|
+
def guild
|
78
|
+
@client.guilds[@guild_id]
|
79
|
+
end
|
80
|
+
|
81
|
+
def channel
|
82
|
+
@client.channels[@channel_id]
|
83
|
+
end
|
84
|
+
|
85
|
+
def inspect
|
86
|
+
"#<#{self.class} id=#{@id}>"
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
# Send followup message.
|
91
|
+
#
|
92
|
+
# @async
|
93
|
+
#
|
94
|
+
# @param [String] content The content of the response.
|
95
|
+
# @param [Boolean] tts Whether to send the message as text-to-speech.
|
96
|
+
# @param [Discorb::Embed] embed The embed to send.
|
97
|
+
# @param [Array<Discorb::Embed>] embeds The embeds to send. (max: 10)
|
98
|
+
# @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions to send.
|
99
|
+
# @param [Discorb::Attachment] attachment The attachment to send.
|
100
|
+
# @param [Array<Discorb::Attachment>] attachments The attachments to send. (max: 10)
|
101
|
+
# @param [Array<Discorb::Component>, Array<Array<Discorb::Component>>] components The components to send.
|
102
|
+
# @param [Boolean] ephemeral Whether to make the response ephemeral.
|
103
|
+
#
|
104
|
+
# @return [Discorb::Webhook::Message] The message.
|
105
|
+
#
|
106
|
+
def post(
|
107
|
+
content = nil,
|
108
|
+
tts: false,
|
109
|
+
embed: nil,
|
110
|
+
embeds: nil,
|
111
|
+
allowed_mentions: nil,
|
112
|
+
attachment: nil,
|
113
|
+
attachments: nil,
|
114
|
+
components: nil,
|
115
|
+
ephemeral: false
|
116
|
+
)
|
117
|
+
Async do
|
118
|
+
payload = {}
|
119
|
+
payload[:content] = content if content
|
120
|
+
payload[:tts] = tts
|
121
|
+
payload[:embeds] = (embeds || [embed])
|
122
|
+
.map { |e| e&.to_hash }
|
123
|
+
.filter { _1 }
|
124
|
+
payload[:allowed_mentions] = allowed_mentions&.to_hash(
|
125
|
+
@client.allowed_mentions
|
126
|
+
) || @client.allowed_mentions.to_hash
|
127
|
+
payload[:components] = Component.to_payload(components) if components
|
128
|
+
payload[:flags] = (ephemeral ? 1 << 6 : 0)
|
129
|
+
attachments ||= attachment ? [attachment] : []
|
130
|
+
|
131
|
+
payload[:attachments] = attachments.map.with_index do |a, i|
|
132
|
+
{ id: i, filename: a.filename, description: a.description }
|
133
|
+
end
|
134
|
+
|
135
|
+
_resp, data =
|
136
|
+
@client
|
137
|
+
.http
|
138
|
+
.multipart_request(
|
139
|
+
Route.new(
|
140
|
+
"/webhooks/#{@application_id}/#{@token}",
|
141
|
+
"//webhooks/:webhook_id/:token",
|
142
|
+
:post
|
143
|
+
),
|
144
|
+
payload,
|
145
|
+
attachments
|
146
|
+
)
|
147
|
+
.wait
|
148
|
+
webhook =
|
149
|
+
Webhook::URLWebhook.new("/webhooks/#{@application_id}/#{@token}")
|
150
|
+
Webhook::Message.new(webhook, data, @client)
|
151
|
+
ret
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
#
|
156
|
+
# Edit the original response message.
|
157
|
+
# This method is low-level.
|
158
|
+
#
|
159
|
+
# @async
|
160
|
+
#
|
161
|
+
# @param [String] content The content of the response.
|
162
|
+
# @param [Discorb::Embed] embed The embed to send.
|
163
|
+
# @param [Array<Discorb::Embed>] embeds The embeds to send. (max: 10)
|
164
|
+
# @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions to send.
|
165
|
+
# @param [Discorb::Attachment] attachment The attachment to send.
|
166
|
+
# @param [Array<Discorb::Attachment>] attachments The attachments to send. (max: 10)
|
167
|
+
# @param [Array<Discorb::Component>, Array<Array<Discorb::Component>>] components The components to send.
|
168
|
+
#
|
169
|
+
# @return [Async::Task<void>] The task.
|
170
|
+
#
|
171
|
+
# @see CallbackMessage#edit
|
172
|
+
#
|
173
|
+
def edit_original_message(
|
174
|
+
content = nil,
|
175
|
+
embed: nil,
|
176
|
+
embeds: nil,
|
177
|
+
attachment: nil,
|
178
|
+
attachments: nil,
|
179
|
+
components: nil
|
180
|
+
)
|
181
|
+
Async do
|
182
|
+
payload = {}
|
183
|
+
payload[:content] = content if content
|
184
|
+
payload[:embeds] = (embeds || [embed])
|
185
|
+
.map { |e| e&.to_hash }
|
186
|
+
.filter { _1 }
|
187
|
+
.then { _1.empty? ? nil : _1 }
|
188
|
+
payload[:components] = Component.to_payload(components) if components
|
189
|
+
attachments ||= attachment && [attachment]
|
190
|
+
|
191
|
+
payload[:attachments] = attachments&.map&.with_index do |a, i|
|
192
|
+
{ id: i, filename: a.filename, description: a.description }
|
193
|
+
end
|
194
|
+
payload.compact!
|
195
|
+
|
196
|
+
@client
|
197
|
+
.http
|
198
|
+
.multipart_request(
|
199
|
+
Route.new(
|
200
|
+
"/webhooks/#{@application_id}/#{@token}/messages/@original",
|
201
|
+
"//webhooks/:webhook_id/:token/messages/@original",
|
202
|
+
:patch
|
203
|
+
),
|
204
|
+
payload,
|
205
|
+
attachments
|
206
|
+
)
|
207
|
+
.wait
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
#
|
212
|
+
# Delete the original response message.
|
213
|
+
# This method is low-level.
|
214
|
+
#
|
215
|
+
# @async
|
216
|
+
#
|
217
|
+
# @return [Async::Task<void>] The task.
|
218
|
+
#
|
219
|
+
def delete_original_message
|
220
|
+
Async do
|
221
|
+
@client
|
222
|
+
.http
|
223
|
+
.request(
|
224
|
+
Route.new(
|
225
|
+
"/webhooks/#{@application_id}/#{@token}/messages/@original",
|
226
|
+
"//webhooks/:webhook_id/:token/messages/@original",
|
227
|
+
:delete
|
228
|
+
)
|
229
|
+
)
|
230
|
+
.wait
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
class << self
|
235
|
+
# @private
|
236
|
+
attr_reader :interaction_type, :interaction_name, :event_name
|
237
|
+
|
238
|
+
#
|
239
|
+
# Create a new Interaction instance from the data.
|
240
|
+
# @private
|
241
|
+
#
|
242
|
+
# @param [Discorb::Client] client The client this interaction belongs to.
|
243
|
+
# @param [Hash] data The data of the interaction.
|
244
|
+
#
|
245
|
+
def make_interaction(client, data)
|
246
|
+
interaction = nil
|
247
|
+
descendants.each do |klass|
|
248
|
+
if !klass.interaction_type.nil? &&
|
249
|
+
klass.interaction_type == data[:type]
|
250
|
+
interaction = klass.make_interaction(client, data)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
if interaction.nil?
|
254
|
+
client.logger.warn(
|
255
|
+
"Unknown interaction type #{data[:type]}, initialized Interaction"
|
256
|
+
)
|
257
|
+
interaction = Interaction.new(client, data)
|
258
|
+
end
|
259
|
+
interaction
|
260
|
+
end
|
261
|
+
|
262
|
+
#
|
263
|
+
# Returns the descendants of the class.
|
264
|
+
# @private
|
265
|
+
#
|
266
|
+
def descendants
|
267
|
+
ObjectSpace.each_object(Class).select { |klass| klass < self }
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
data/lib/discorb/interaction.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
%w[root response command components autocomplete modal].each do |file|
|
4
|
-
require_relative "interaction/#{file}.rb"
|
5
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
%w[root response command components autocomplete modal].each do |file|
|
4
|
+
require_relative "interaction/#{file}.rb"
|
5
|
+
end
|