discorb 0.16.0 → 0.18.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.
Files changed (199) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/build_main.yml +2 -2
  4. data/.github/workflows/build_version.yml +1 -1
  5. data/.github/workflows/codeql-analysis.yml +1 -1
  6. data/.github/workflows/lint-push.yml +3 -5
  7. data/.github/workflows/lint.yml +2 -4
  8. data/.github/workflows/spec.yml +33 -0
  9. data/.github/workflows/validate.yml +21 -0
  10. data/.gitignore +2 -0
  11. data/.lefthook/commit-msg/validator.rb +5 -0
  12. data/.rspec +2 -0
  13. data/.rspec_parallel +2 -0
  14. data/.rubocop.yml +43 -6
  15. data/Changelog.md +30 -1
  16. data/Gemfile +20 -8
  17. data/Rakefile +226 -98
  18. data/Steepfile +28 -0
  19. data/bin/console +3 -3
  20. data/docs/Examples.md +1 -1
  21. data/docs/application_command.md +156 -47
  22. data/docs/cli/irb.md +2 -2
  23. data/docs/cli/new.md +14 -9
  24. data/docs/cli/run.md +7 -11
  25. data/docs/cli.md +17 -10
  26. data/docs/events.md +247 -213
  27. data/docs/extension.md +1 -2
  28. data/docs/faq.md +0 -1
  29. data/docs/tutorial.md +18 -18
  30. data/docs/voice_events.md +106 -106
  31. data/examples/commands/message.rb +68 -0
  32. data/examples/commands/permission.rb +19 -0
  33. data/examples/commands/slash.rb +48 -0
  34. data/examples/commands/user.rb +54 -0
  35. data/examples/components/authorization_button.rb +4 -3
  36. data/examples/components/select_menu.rb +6 -3
  37. data/examples/extension/main.rb +2 -1
  38. data/examples/extension/message_expander.rb +6 -2
  39. data/examples/sig/commands/message.rbs +5 -0
  40. data/examples/simple/eval.rb +3 -2
  41. data/examples/simple/ping_pong.rb +2 -1
  42. data/examples/simple/rolepanel.rb +17 -6
  43. data/examples/simple/shard.rb +3 -2
  44. data/examples/simple/wait_for_message.rb +4 -1
  45. data/exe/discorb +33 -18
  46. data/lefthook.yml +45 -0
  47. data/lib/discorb/allowed_mentions.rb +2 -1
  48. data/lib/discorb/app_command/command.rb +130 -72
  49. data/lib/discorb/app_command/common.rb +25 -0
  50. data/lib/discorb/app_command/handler.rb +130 -33
  51. data/lib/discorb/app_command.rb +2 -1
  52. data/lib/discorb/application.rb +1 -0
  53. data/lib/discorb/asset.rb +1 -2
  54. data/lib/discorb/attachment.rb +1 -1
  55. data/lib/discorb/audit_logs.rb +19 -10
  56. data/lib/discorb/automod.rb +269 -0
  57. data/lib/discorb/channel/base.rb +108 -0
  58. data/lib/discorb/channel/category.rb +32 -0
  59. data/lib/discorb/channel/container.rb +44 -0
  60. data/lib/discorb/channel/dm.rb +28 -0
  61. data/lib/discorb/channel/guild.rb +246 -0
  62. data/lib/discorb/channel/stage.rb +140 -0
  63. data/lib/discorb/channel/text.rb +336 -0
  64. data/lib/discorb/channel/thread.rb +325 -0
  65. data/lib/discorb/channel/voice.rb +79 -0
  66. data/lib/discorb/channel.rb +2 -1165
  67. data/lib/discorb/client.rb +50 -36
  68. data/lib/discorb/color.rb +37 -60
  69. data/lib/discorb/common.rb +2 -1
  70. data/lib/discorb/components/button.rb +2 -1
  71. data/lib/discorb/components/select_menu.rb +4 -2
  72. data/lib/discorb/components/text_input.rb +12 -2
  73. data/lib/discorb/components.rb +1 -1
  74. data/lib/discorb/dictionary.rb +1 -1
  75. data/lib/discorb/embed.rb +26 -10
  76. data/lib/discorb/emoji.rb +31 -4
  77. data/lib/discorb/emoji_table.rb +4969 -3
  78. data/lib/discorb/event.rb +29 -4
  79. data/lib/discorb/exe/about.rb +2 -1
  80. data/lib/discorb/exe/irb.rb +2 -4
  81. data/lib/discorb/exe/new.rb +89 -26
  82. data/lib/discorb/exe/run.rb +8 -22
  83. data/lib/discorb/exe/setup.rb +25 -12
  84. data/lib/discorb/exe/show.rb +4 -3
  85. data/lib/discorb/extend.rb +1 -0
  86. data/lib/discorb/extension.rb +6 -7
  87. data/lib/discorb/flag.rb +13 -2
  88. data/lib/discorb/gateway.rb +79 -589
  89. data/lib/discorb/gateway_events.rb +638 -0
  90. data/lib/discorb/guild.rb +318 -67
  91. data/lib/discorb/guild_template.rb +11 -5
  92. data/lib/discorb/http.rb +53 -24
  93. data/lib/discorb/integration.rb +4 -1
  94. data/lib/discorb/intents.rb +28 -19
  95. data/lib/discorb/interaction/autocomplete.rb +28 -16
  96. data/lib/discorb/interaction/command.rb +42 -14
  97. data/lib/discorb/interaction/components.rb +5 -2
  98. data/lib/discorb/interaction/modal.rb +0 -1
  99. data/lib/discorb/interaction/response.rb +125 -26
  100. data/lib/discorb/interaction/root.rb +13 -13
  101. data/lib/discorb/interaction.rb +1 -0
  102. data/lib/discorb/invite.rb +5 -2
  103. data/lib/discorb/member.rb +28 -8
  104. data/lib/discorb/message.rb +60 -25
  105. data/lib/discorb/message_meta.rb +3 -3
  106. data/lib/discorb/modules.rb +59 -16
  107. data/lib/discorb/presence.rb +2 -0
  108. data/lib/discorb/rate_limit.rb +7 -2
  109. data/lib/discorb/reaction.rb +2 -2
  110. data/lib/discorb/role.rb +20 -5
  111. data/lib/discorb/shard.rb +1 -1
  112. data/lib/discorb/sticker.rb +9 -8
  113. data/lib/discorb/user.rb +4 -3
  114. data/lib/discorb/utils/colored_puts.rb +1 -0
  115. data/lib/discorb/voice_state.rb +6 -2
  116. data/lib/discorb/webhook.rb +64 -31
  117. data/lib/discorb.rb +7 -5
  118. data/po/yard.pot +20 -20
  119. data/rbs_collection.lock.yaml +88 -0
  120. data/rbs_collection.yaml +21 -0
  121. data/sig/async.rbs +11 -0
  122. data/sig/discorb/activity.rbs +23 -0
  123. data/sig/discorb/allowed_mentions.rbs +44 -0
  124. data/sig/discorb/app_command/base.rbs +282 -0
  125. data/sig/discorb/app_command/handler.rbs +171 -0
  126. data/sig/discorb/application.rbs +142 -0
  127. data/sig/discorb/asset.rbs +32 -0
  128. data/sig/discorb/attachment.rbs +91 -0
  129. data/sig/discorb/audit_log.rbs +231 -0
  130. data/sig/discorb/automod.rbs +128 -0
  131. data/sig/discorb/avatar.rbs +26 -0
  132. data/sig/discorb/channel/base.rbs +179 -0
  133. data/sig/discorb/channel/category.rbs +56 -0
  134. data/sig/discorb/channel/container.rbs +29 -0
  135. data/sig/discorb/channel/dm.rbs +14 -0
  136. data/sig/discorb/channel/news.rbs +20 -0
  137. data/sig/discorb/channel/stage.rbs +77 -0
  138. data/sig/discorb/channel/text.rbs +158 -0
  139. data/sig/discorb/channel/thread.rbs +185 -0
  140. data/sig/discorb/channel/voice.rbs +41 -0
  141. data/sig/discorb/client.rbs +2495 -0
  142. data/sig/discorb/color.rbs +142 -0
  143. data/sig/discorb/component/base.rbs +28 -0
  144. data/sig/discorb/component/button.rbs +65 -0
  145. data/sig/discorb/component/select_menu.rbs +107 -0
  146. data/sig/discorb/component/text_input.rbs +69 -0
  147. data/sig/discorb/connectable.rbs +8 -0
  148. data/sig/discorb/custom_emoji.rbs +90 -0
  149. data/sig/discorb/dictionary.rbs +85 -0
  150. data/sig/discorb/discord_model.rbs +15 -0
  151. data/sig/discorb/embed.rbs +279 -0
  152. data/sig/discorb/emoji.rbs +13 -0
  153. data/sig/discorb/error.rbs +73 -0
  154. data/sig/discorb/event_handler.rbs +27 -0
  155. data/sig/discorb/extension.rbs +1734 -0
  156. data/sig/discorb/flag.rbs +72 -0
  157. data/sig/discorb/gateway.rbs +481 -0
  158. data/sig/discorb/guild.rbs +870 -0
  159. data/sig/discorb/guild_template.rbs +174 -0
  160. data/sig/discorb/http.rbs +147 -0
  161. data/sig/discorb/image.rbs +20 -0
  162. data/sig/discorb/integration.rbs +118 -0
  163. data/sig/discorb/intents.rbs +97 -0
  164. data/sig/discorb/interaction/autocomplete.rbs +9 -0
  165. data/sig/discorb/interaction/base.rbs +66 -0
  166. data/sig/discorb/interaction/command.rbs +66 -0
  167. data/sig/discorb/interaction/message_component.rbs +140 -0
  168. data/sig/discorb/interaction/modal.rbs +50 -0
  169. data/sig/discorb/interaction/responder.rbs +157 -0
  170. data/sig/discorb/invite.rbs +86 -0
  171. data/sig/discorb/member.rbs +187 -0
  172. data/sig/discorb/message.rbs +469 -0
  173. data/sig/discorb/messageable.rbs +153 -0
  174. data/sig/discorb/partial_emoji.rbs +35 -0
  175. data/sig/discorb/permissions.rbs +149 -0
  176. data/sig/discorb/presence.rbs +237 -0
  177. data/sig/discorb/reaction.rbs +33 -0
  178. data/sig/discorb/role.rbs +145 -0
  179. data/sig/discorb/scheduled_event.rbs +148 -0
  180. data/sig/discorb/shard.rbs +62 -0
  181. data/sig/discorb/snowflake.rbs +56 -0
  182. data/sig/discorb/stage_instance.rbs +63 -0
  183. data/sig/discorb/sticker.rbs +116 -0
  184. data/sig/discorb/system_channel_flag.rbs +17 -0
  185. data/sig/discorb/unicode_emoji.rbs +49 -0
  186. data/sig/discorb/user.rbs +93 -0
  187. data/sig/discorb/utils.rbs +8 -0
  188. data/sig/discorb/voice_region.rbs +30 -0
  189. data/sig/discorb/voice_state.rbs +71 -0
  190. data/sig/discorb/webhook.rbs +327 -0
  191. data/sig/discorb/welcome_screen.rbs +78 -0
  192. data/sig/discorb.rbs +6 -7230
  193. data/sig/manifest.yaml +3 -0
  194. data/sig/override.rbs +19 -0
  195. data/template-replace/files/css/common.css +4 -0
  196. metadata +102 -6
  197. data/examples/commands/bookmarker.rb +0 -42
  198. data/examples/commands/hello.rb +0 -10
  199. data/examples/commands/inspect.rb +0 -25
@@ -1,16 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Discorb
4
- #
5
- # Handles application commands.
6
- #
7
4
  module ApplicationCommand
8
5
  #
9
6
  # Represents a application command.
10
7
  # @abstract
11
8
  #
12
9
  class Command < DiscordModel
13
- # @return [String] The name of the command.
10
+ # @return [Hash{String => String}] The name of the command.
14
11
  attr_reader :name
15
12
  # @return [Array<#to_s>] The guild ids that the command is enabled in.
16
13
  attr_reader :guild_ids
@@ -20,8 +17,10 @@ module Discorb
20
17
  attr_reader :type
21
18
  # @return [Integer] The raw type of the command.
22
19
  attr_reader :type_raw
23
- # @return [Discorb::Dictionary{Discorb::Snowflake, :global => Discorb::Snowflake}] The ID mapping.
24
- attr_reader :id_map
20
+ # @return [Discorb::Permission] The default permissions for this command.
21
+ attr_reader :default_permission
22
+ # @return [Boolean] Whether the command is enabled in DMs.
23
+ attr_reader :dm_permission
25
24
 
26
25
  # @private
27
26
  # @return [{Integer => Symbol}] The mapping of raw types to types.
@@ -35,23 +34,25 @@ module Discorb
35
34
  # Initialize a new command.
36
35
  # @private
37
36
  #
38
- # @param [String] name The name of the command.
39
- # @param [Array<#to_s>] guild_ids The guild ids that the command is enabled in.
37
+ # @param [String, Hash{Symbol => String}] name The name of the command.
38
+ # @param [Array<#to_s>, false, nil] guild_ids The guild ids that the command is enabled in.
40
39
  # @param [Proc] block The block of the command.
41
- # @param [:chat_input, :user, :message] type The type of the command.
40
+ # @param [Integer] type The type of the command.
41
+ # @param [Boolean] dm_permission Whether the command is enabled in DMs.
42
+ # @param [Discorb::Permission] default_permission The default permission of the command.
42
43
  #
43
- def initialize(name, guild_ids, block, type)
44
- @name = name
44
+ def initialize(name, guild_ids, block, type, dm_permission = true, default_permission = nil) # rubocop:disable Style/OptionalBooleanParameter
45
+ @name = name.is_a?(String) ? { "default" => name } : ApplicationCommand.modify_localization_hash(name)
45
46
  @guild_ids = guild_ids&.map(&:to_s)
46
47
  @block = block
47
- @raw_type = type
48
48
  @type = Discorb::ApplicationCommand::Command::TYPES[type]
49
49
  @type_raw = type
50
- @id_map = Discorb::Dictionary.new
50
+ @dm_permission = dm_permission
51
+ @default_permission = default_permission
51
52
  end
52
53
 
53
54
  #
54
- # Changes the self pointer to the given object.
55
+ # Changes the self pointer of block to the given object.
55
56
  # @private
56
57
  #
57
58
  # @param [Object] instance The object to change the self pointer to.
@@ -71,17 +72,19 @@ module Discorb
71
72
  #
72
73
  def to_hash
73
74
  {
74
- name: @name,
75
- default_permission: @default_permission,
75
+ name: @name["default"],
76
+ name_localizations: @name.except("default"),
76
77
  type: @type_raw,
78
+ dm_permission: @dm_permission,
79
+ default_member_permissions: @default_permission&.value&.to_s,
77
80
  }
78
81
  end
79
82
 
80
83
  #
81
84
  # Represents the slash command.
82
85
  #
83
- class SlashCommand < Command
84
- # @return [String] The description of the command.
86
+ class ChatInputCommand < Command
87
+ # @return [Hash{String => String}] The description of the command.
85
88
  attr_reader :description
86
89
  # @return [Hash{String => Hash}] The options of the command.
87
90
  attr_reader :options
@@ -90,21 +93,29 @@ module Discorb
90
93
  # Initialize a new slash command.
91
94
  # @private
92
95
  #
93
- # @param [String] name The name of the command.
94
- # @param [String] description The description of the command.
96
+ # @param [String, Hash{Symbol => String}] name The name of the command.
97
+ # The hash should have `default`, and language keys.
98
+ # @param [String, Hash{Symbol => String}] description The description of the command.
99
+ # The hash should have `default`, and language keys.
95
100
  # @param [Hash{String => Hash}] options The options of the command.
96
101
  # @param [Array<#to_s>] guild_ids The guild ids that the command is enabled in.
97
102
  # @param [Proc] block The block of the command.
98
- # @param [:chat_input, :user, :message] type The type of the command.
103
+ # @param [Integer] type The type of the command.
99
104
  # @param [Discorb::ApplicationCommand::Command, nil] parent The parent command.
105
+ # @param [Boolean] dm_permission Whether the command is enabled in DMs.
106
+ # @param [Discorb::Permission] default_permission The default permission of the command.
100
107
  #
101
- def initialize(name, description, options, guild_ids, block, type, parent)
102
- super(name, guild_ids, block, type)
103
- @description = description
108
+ def initialize(name, description, options, guild_ids, block, type, parent, dm_permission, default_permission)
109
+ super(name, guild_ids, block, type, dm_permission, default_permission)
110
+ @description = if description.is_a?(String)
111
+ {
112
+ "default" => description,
113
+ }
114
+ else
115
+ ApplicationCommand.modify_localization_hash(description)
116
+ end
104
117
  @options = options
105
- @id = nil
106
118
  @parent = parent
107
- @id_map = Discorb::Dictionary.new
108
119
  end
109
120
 
110
121
  #
@@ -113,7 +124,7 @@ module Discorb
113
124
  # @return [String] The name of the command.
114
125
  #
115
126
  def to_s
116
- (@parent + " " + @name).strip
127
+ "#{@parent} #{@name["default"]}".strip
117
128
  end
118
129
 
119
130
  #
@@ -148,11 +159,34 @@ module Discorb
148
159
  raise ArgumentError, "Invalid option type: #{value[:type]}"
149
160
  end,
150
161
  name: name,
151
- description: value[:description],
162
+ name_localizations: ApplicationCommand.modify_localization_hash(value[:name_localizations]),
152
163
  required: value[:required].nil? ? !value[:optional] : value[:required],
153
164
  }
154
165
 
155
- ret[:choices] = value[:choices].map { |t| { name: t[0], value: t[1] } } if value[:choices]
166
+ if value[:description].is_a?(String)
167
+ ret[:description] = value[:description]
168
+ else
169
+ description = ApplicationCommand.modify_localization_hash(value[:description])
170
+ ret[:description] = description["default"]
171
+ ret[:description_localizations] = description.except("default")
172
+ end
173
+ if value[:choices]
174
+ ret[:choices] = value[:choices].map do |k, v|
175
+ r = {
176
+ name: k, value: v,
177
+ }
178
+ if choices_localizations = value[:choices_localizations].clone
179
+ name_localizations = ApplicationCommand.modify_localization_hash(choices_localizations.delete(k) do
180
+ warn "Missing localization for #{k}"
181
+ {}
182
+ end)
183
+ r[:name_localizations] = name_localizations.except("default")
184
+ r[:name] = name_localizations["default"]
185
+ r.delete(:name_localizations) if r[:name_localizations].nil?
186
+ end
187
+ r
188
+ end
189
+ end
156
190
 
157
191
  ret[:channel_types] = value[:channel_types].map(&:channel_type) if value[:channel_types]
158
192
 
@@ -164,10 +198,13 @@ module Discorb
164
198
  ret
165
199
  end
166
200
  {
167
- name: @name,
168
- default_permission: true,
169
- description: @description,
201
+ name: @name["default"],
202
+ name_localizations: @name.except("default"),
203
+ description: @description["default"],
204
+ description_localizations: @description.except("default"),
170
205
  options: options_payload,
206
+ dm_permission: @dm_permission,
207
+ default_member_permissions: @default_permission&.value&.to_s,
171
208
  }
172
209
  end
173
210
  end
@@ -176,38 +213,54 @@ module Discorb
176
213
  # Represents the command with subcommands.
177
214
  #
178
215
  class GroupCommand < Command
179
- # @return [Array<Discorb::ApplicationCommand::Command::SlashCommand, Discorb::ApplicationCommand::Command::SubcommandGroup>] The subcommands of the command.
216
+ # @return [Array<Discorb::ApplicationCommand::Command>] The subcommands of the command.
180
217
  attr_reader :commands
181
- # @return [String] The description of the command.
218
+ # @return [Hash{String => String}] The description of the command.
182
219
  attr_reader :description
183
220
 
184
221
  #
185
222
  # Initialize a new group command.
186
223
  # @private
187
224
  #
188
- # @param [String] name The name of the command.
189
- # @param [String] description The description of the command.
225
+ # @param [String, Hash{Symbol => String}] name The name of the command.
226
+ # @param [String, Hash{Symbol => String}] description The description of the command.
190
227
  # @param [Array<#to_s>] guild_ids The guild ids that the command is enabled in.
191
- # @param [:chat_input, :user, :message] type The type of the command.
192
228
  # @param [Discorb::Client] client The client of the command.
229
+ # @param [Boolean] dm_permission Whether the command is enabled in DMs.
230
+ # @param [Discorb::Permission] default_permission The default permission of the command.
193
231
  #
194
- def initialize(name, description, guild_ids, type, client)
195
- super(name, guild_ids, block, type)
196
- @description = description
232
+ def initialize(name, description, guild_ids, client, dm_permission, default_permission)
233
+ super(name, guild_ids, block, 1, dm_permission, default_permission)
234
+ @description = if description.is_a?(String)
235
+ {
236
+ "default" => description,
237
+ }
238
+ else
239
+ ApplicationCommand.modify_localization_hash(description)
240
+ end
197
241
  @commands = []
198
242
  @client = client
199
- @id_map = Discorb::Dictionary.new
200
243
  end
201
244
 
202
245
  #
203
246
  # Add new subcommand.
204
247
  #
205
248
  # @param (see Discorb::ApplicationCommand::Handler#slash)
206
- # @return [Discorb::ApplicationCommand::Command::SlashCommand] The added subcommand.
207
- #
208
- def slash(command_name, description, options = {}, &block)
209
- command = Discorb::ApplicationCommand::Command::SlashCommand.new(command_name, description, options, [], block, 1, @name)
210
- @client.bottom_commands << command
249
+ # @return [Discorb::ApplicationCommand::Command::ChatInputCommand] The added subcommand.
250
+ #
251
+ def slash(command_name, description, options = {}, dm_permission: true, default_permission: nil, &block)
252
+ command = Discorb::ApplicationCommand::Command::ChatInputCommand.new(
253
+ command_name,
254
+ description,
255
+ options,
256
+ [],
257
+ block,
258
+ 1,
259
+ self,
260
+ dm_permission,
261
+ default_permission
262
+ )
263
+ @client.callable_commands << command
211
264
  @commands << command
212
265
  command
213
266
  end
@@ -225,9 +278,9 @@ module Discorb
225
278
  #
226
279
  # @see file:docs/application_command.md Application Commands
227
280
  #
228
- def group(command_name, description, &block)
229
- command = Discorb::ApplicationCommand::Command::SubcommandGroup.new(command_name, description, @name, @client)
230
- command.yield_self(&block) if block_given?
281
+ def group(command_name, description)
282
+ command = Discorb::ApplicationCommand::Command::SubcommandGroup.new(command_name, description, self, @client)
283
+ yield command if block_given?
231
284
  @commands << command
232
285
  command
233
286
  end
@@ -238,7 +291,7 @@ module Discorb
238
291
  # @return [String] The command name.
239
292
  #
240
293
  def to_s
241
- @name
294
+ @name["default"]
242
295
  end
243
296
 
244
297
  #
@@ -260,29 +313,36 @@ module Discorb
260
313
  #
261
314
  def to_hash
262
315
  options_payload = @commands.map do |command|
263
- if command.is_a?(SlashCommand)
316
+ if command.is_a?(ChatInputCommand)
264
317
  {
265
- name: command.name,
266
- description: command.description,
267
- default_permission: true,
318
+ name: command.name["default"],
319
+ name_localizations: command.name.except("default"),
320
+ description: command.description["default"],
321
+ description_localizations: command.description.except("default"),
268
322
  type: 1,
269
323
  options: command.to_hash[:options],
270
324
  }
271
325
  else
272
326
  {
273
- name: command.name,
274
- description: command.description,
275
- default_permission: true,
327
+ name: command.name["default"],
328
+ name_localizations: command.name.except("default"),
329
+ description: command.description["default"],
330
+ description_localizations: command.description.except("default"),
276
331
  type: 2,
277
- options: command.commands.map { |c| c.to_hash.merge(type: 1) },
332
+ options: command.commands.map do |c|
333
+ c.to_hash.merge(type: 1).except(:dm_permission, :default_member_permissions)
334
+ end,
278
335
  }
279
336
  end
280
337
  end
281
338
 
282
339
  {
283
- name: @name,
284
- default_permission: @enabled,
285
- description: @description,
340
+ name: @name["default"],
341
+ name_localizations: @name.except("default"),
342
+ description: @description["default"],
343
+ description_localizations: @description.except("default"),
344
+ dm_permission: @dm_permission,
345
+ default_member_permissions: @default_permission&.value&.to_s,
286
346
  options: options_payload,
287
347
  }
288
348
  end
@@ -292,7 +352,7 @@ module Discorb
292
352
  # Represents the subcommand group.
293
353
  #
294
354
  class SubcommandGroup < GroupCommand
295
- # @return [Array<Discorb::ApplicationCommand::Command::SlashCommand>] The subcommands of the command.
355
+ # @return [Array<Discorb::ApplicationCommand::Command::ChatInputCommand>] The subcommands of the command.
296
356
  attr_reader :commands
297
357
 
298
358
  #
@@ -304,33 +364,31 @@ module Discorb
304
364
  # @param [Discorb::ApplicationCommand::Command::GroupCommand] parent The parent command.
305
365
  # @param [Discorb::Client] client The client.
306
366
  def initialize(name, description, parent, client)
307
- super(name, description, [], 1, client)
367
+ super(name, description, [], client, nil, nil)
308
368
 
309
369
  @commands = []
310
370
  @parent = parent
311
371
  end
312
372
 
313
373
  def to_s
314
- @parent + " " + @name
374
+ "#{@parent} #{@name}"
315
375
  end
316
376
 
317
377
  #
318
378
  # Add new subcommand.
319
379
  # @param (see Discorb::ApplicationCommand::Handler#slash)
320
- # @return [Discorb::ApplicationCommand::Command::SlashCommand] The added subcommand.
380
+ # @return [Discorb::ApplicationCommand::Command::ChatInputCommand] The added subcommand.
321
381
  #
322
382
  def slash(command_name, description, options = {}, &block)
323
- command = Discorb::ApplicationCommand::Command::SlashCommand.new(command_name, description, options, [], block, 1, @parent + " " + @name)
383
+ command = Discorb::ApplicationCommand::Command::ChatInputCommand.new(
384
+ command_name, description, options, [],
385
+ block, 1, self, nil, nil
386
+ )
324
387
  @commands << command
325
- @client.bottom_commands << command
388
+ @client.callable_commands << command
326
389
  command
327
390
  end
328
391
  end
329
-
330
- class << self
331
- # @private
332
- attr_reader :types
333
- end
334
392
  end
335
393
  end
336
394
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discorb
4
+ #
5
+ # Handles application commands.
6
+ #
7
+ module ApplicationCommand
8
+ # @return [Array<String>] List of valid locales.
9
+ VALID_LOCALES = %w[da de en-GB en-US es-ES fr hr it lt hu nl no pl pt-BR ro fi sv-SE vi tr cs el bg ru uk hi th
10
+ zh-CN ja zh-TW ko].freeze
11
+
12
+ module_function
13
+
14
+ def modify_localization_hash(hash)
15
+ hash.to_h do |rkey, value|
16
+ key = rkey.to_s.gsub("_", "-")
17
+ raise ArgumentError, "Invalid locale: #{key}" if VALID_LOCALES.none? do |valid|
18
+ valid.downcase == key.downcase
19
+ end && key != "default"
20
+
21
+ [key == "default" ? "default" : VALID_LOCALES.find { |valid| valid.downcase == key.downcase }, value]
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,55 +1,94 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Discorb
4
- #
5
- # Handles application commands.
6
- #
7
4
  module ApplicationCommand
8
5
  #
9
6
  # Module to handle application commands.
10
7
  #
11
8
  module Handler
9
+ # @type instance: Discorb::Client
10
+
12
11
  #
13
12
  # Add new top-level command.
14
13
  #
15
- # @param [String] command_name Command name.
16
- # @param [String] description Command description.
17
- # @param [Hash{String => Hash{:description => String, :optional => Boolean, :type => Object}}] options Command options.
14
+ # @param [String, Hash{Symbol => String}] command_name Command name.
15
+ # If hash is passed, it must be a pair of Language code and Command name, and `:default` key is required.
16
+ # You can use `_` instead of `-` in language code.
17
+ # @param [String, Hash{Symbol => String}] description Command description.
18
+ # If hash is passed, it must be a pair of Language code and Command description, and `:default` key is required.
19
+ # You can use `_` instead of `-` in language code.
20
+ # @param [Hash{String => Hash{:description => String, :optional => Boolean, :type => Object}}] options
21
+ # Command options.
18
22
  # The key is the option name, the value is a hash with the following keys:
19
23
  #
20
24
  # | Key | Type | Description |
21
25
  # | --- | --- | --- |
22
- # | `:description` | `String` | Description of the option. |
23
- # | `:required` | Whether the argument is required. `optional` will be used if not specified. |
24
- # | `:optional` | Whether the argument is optional. `required` will be used if not specified. |
26
+ # | `:name_localizations` | Hash{Symbol => String} | Localizations of option name. |
27
+ # | `:description` | `String` \| `Hash{Symbol => String}` |
28
+ # Description of the option. If hash is passed, it must be a pair of Language code and description,
29
+ # and `:default` key is required. You can use `_` instead of `-` in language code. |
30
+ # | `:required` | Boolean(true | false) |
31
+ # Whether the argument is required. `optional` will be used if not specified. |
32
+ # | `:optional` | Boolean(true | false) |
33
+ # Whether the argument is optional. `required` will be used if not specified. |
25
34
  # | `:type` | `Object` | Type of the option. |
26
- # | `:choice` | `Hash{String => String, Integer, Float}` | Type of the option. |
35
+ # | `:choices` | `Hash{String => String, Integer, Float}` | Type of the option. |
36
+ # | `:choices_localizations` | `Hash{String => Hash{Symbol => String}}` |
37
+ # Localization of the choice. Key must be the name of a choice. |
27
38
  # | `:default` | `Object` | Default value of the option. |
28
39
  # | `:channel_types` | `Array<Class<Discorb::Channel>>` | Type of the channel option. |
29
40
  # | `:autocomplete` | `Proc` | Autocomplete function. |
30
41
  # | `:range` | `Range` | Range of the option. Only valid for numeric options. (`:int`, `:float`) |
31
42
  #
32
- # @param [Array<#to_s>, false, nil] guild_ids Guild IDs to set the command to. `false` to global command, `nil` to use default.
43
+ # @param [Array<#to_s>, false, nil] guild_ids
44
+ # Guild IDs to set the command to. `false` to global command, `nil` to use default.
45
+ # @param [Boolean] dm_permission Whether the command is available in DM.
46
+ # @param [Discorb::Permission] default_permission The default permission of the command.
33
47
  # @param [Proc] block Command block.
34
48
  #
35
- # @return [Discorb::ApplicationCommand::Command::SlashCommand] Command object.
49
+ # @return [Discorb::ApplicationCommand::Command::ChatInputCommand] Command object.
36
50
  #
37
51
  # @see file:docs/application_command.md#register-slash-command Application Comamnds: Register Slash Command
38
52
  # @see file:docs/cli/setup.md CLI: setup
39
53
  #
40
- def slash(command_name, description, options = {}, guild_ids: nil, &block)
41
- command = Discorb::ApplicationCommand::Command::SlashCommand.new(command_name, description, options, guild_ids, block, 1, "")
54
+ def slash(
55
+ command_name,
56
+ description,
57
+ options = {},
58
+ guild_ids: nil,
59
+ dm_permission: true,
60
+ default_permission: nil,
61
+ &block
62
+ )
63
+ command_name = { default: command_name } if command_name.is_a?(String)
64
+ description = { default: description } if description.is_a?(String)
65
+ command_name = ApplicationCommand.modify_localization_hash(command_name)
66
+ description = ApplicationCommand.modify_localization_hash(description)
67
+ command = Discorb::ApplicationCommand::Command::ChatInputCommand.new(
68
+ command_name,
69
+ description,
70
+ options,
71
+ guild_ids,
72
+ block,
73
+ 1,
74
+ nil,
75
+ dm_permission,
76
+ default_permission
77
+ )
42
78
  @commands << command
43
- @bottom_commands << command
79
+ @callable_commands << command
44
80
  command
45
81
  end
46
82
 
47
83
  #
48
84
  # Add new command with group.
49
85
  #
50
- # @param [String] command_name Command name.
51
- # @param [String] description Command description.
52
- # @param [Array<#to_s>, false, nil] guild_ids Guild IDs to set the command to. `false` to global command, `nil` to use default.
86
+ # @param [String, Hash{Symbol => String}] command_name Command name.
87
+ # @param [String, Hash{Symbol => String}] description Command description.
88
+ # @param [Array<#to_s>, false, nil] guild_ids
89
+ # Guild IDs to set the command to. `false` to global command, `nil` to use default.
90
+ # @param [Boolean] dm_permission Whether the command is available in DM.
91
+ # @param [Discorb::Permission] default_permission The default permission of the command.
53
92
  #
54
93
  # @yield Block to yield with the command.
55
94
  # @yieldparam [Discorb::ApplicationCommand::Command::GroupCommand] group Group command.
@@ -59,9 +98,20 @@ module Discorb
59
98
  # @see file:docs/application_command.md Application Commands
60
99
  # @see file:docs/cli/setup.md CLI: setup
61
100
  #
62
- def slash_group(command_name, description, guild_ids: nil, &block)
63
- command = Discorb::ApplicationCommand::Command::GroupCommand.new(command_name, description, guild_ids, nil, self)
64
- command.yield_self(&block) if block_given?
101
+ def slash_group(command_name, description, guild_ids: nil, dm_permission: true, default_permission: nil)
102
+ command_name = { default: command_name } if command_name.is_a?(String)
103
+ description = { default: description } if description.is_a?(String)
104
+ command_name = ApplicationCommand.modify_localization_hash(command_name)
105
+ description = ApplicationCommand.modify_localization_hash(description)
106
+ command = Discorb::ApplicationCommand::Command::GroupCommand.new(
107
+ command_name,
108
+ description,
109
+ guild_ids,
110
+ self,
111
+ dm_permission,
112
+ default_permission
113
+ )
114
+ yield command if block_given?
65
115
  @commands << command
66
116
  command
67
117
  end
@@ -69,8 +119,11 @@ module Discorb
69
119
  #
70
120
  # Add message context menu command.
71
121
  #
72
- # @param [String] command_name Command name.
73
- # @param [Array<#to_s>, false, nil] guild_ids Guild IDs to set the command to. `false` to global command, `nil` to use default.
122
+ # @param [String, Hash{Symbol => String}] command_name Command name.
123
+ # @param [Array<#to_s>, false, nil] guild_ids
124
+ # Guild IDs to set the command to. `false` to global command, `nil` to use default.
125
+ # @param [Boolean] dm_permission Whether the command is available in DM.
126
+ # @param [Discorb::Permission] default_permission The default permission of the command.
74
127
  # @param [Proc] block Command block.
75
128
  # @yield [interaction, message] Block to execute.
76
129
  # @yieldparam [Discorb::CommandInteraction::UserMenuCommand] interaction Interaction object.
@@ -78,8 +131,17 @@ module Discorb
78
131
  #
79
132
  # @return [Discorb::ApplicationCommand::Command] Command object.
80
133
  #
81
- def message_command(command_name, guild_ids: nil, &block)
82
- command = Discorb::ApplicationCommand::Command.new(command_name, guild_ids, block, 3)
134
+ def message_command(command_name, guild_ids: nil, dm_permission: true, default_permission: nil, &block)
135
+ command_name = { default: command_name } if command_name.is_a?(String)
136
+ command_name = ApplicationCommand.modify_localization_hash(command_name)
137
+ command = Discorb::ApplicationCommand::Command.new(
138
+ command_name,
139
+ guild_ids,
140
+ block,
141
+ 3,
142
+ dm_permission,
143
+ default_permission
144
+ )
83
145
  @commands << command
84
146
  command
85
147
  end
@@ -87,8 +149,11 @@ module Discorb
87
149
  #
88
150
  # Add user context menu command.
89
151
  #
90
- # @param [String] command_name Command name.
91
- # @param [Array<#to_s>, false, nil] guild_ids Guild IDs to set the command to. `false` to global command, `nil` to use default.
152
+ # @param [String, Hash{Symbol => String}] command_name Command name.
153
+ # @param [Array<#to_s>, false, nil] guild_ids
154
+ # Guild IDs to set the command to. `false` to global command, `nil` to use default.
155
+ # @param [Boolean] dm_permission Whether the command is available in DM.
156
+ # @param [Discorb::Permission] default_permission The default permission of the command.
92
157
  # @param [Proc] block Command block.
93
158
  # @yield [interaction, user] Block to execute.
94
159
  # @yieldparam [Discorb::CommandInteraction::UserMenuCommand] interaction Interaction object.
@@ -96,8 +161,11 @@ module Discorb
96
161
  #
97
162
  # @return [Discorb::ApplicationCommand::Command] Command object.
98
163
  #
99
- def user_command(command_name, guild_ids: nil, &block)
100
- command = Discorb::ApplicationCommand::Command.new(command_name, guild_ids, block, 2)
164
+ def user_command(command_name, guild_ids: nil, dm_permission: true, default_permission: nil, &block)
165
+ command_name = { default: command_name } if command_name.is_a?(String)
166
+ command_name = ApplicationCommand.modify_localization_hash(command_name)
167
+ command = Discorb::ApplicationCommand::Command.new(command_name, guild_ids, block, 2, dm_permission,
168
+ default_permission)
101
169
  @commands << command
102
170
  command
103
171
  end
@@ -108,7 +176,8 @@ module Discorb
108
176
  # @see Client#initialize
109
177
  #
110
178
  # @param [String] token Bot token.
111
- # @param [Array<#to_s>, false, nil] guild_ids Guild IDs to use as default. If `false` is given, it will be global command.
179
+ # @param [Array<#to_s>, false, nil] guild_ids
180
+ # Guild IDs to use as default. If `false` is given, it will be global command.
112
181
  #
113
182
  # @note `token` parameter only required if you don't run client.
114
183
  #
@@ -139,10 +208,10 @@ module Discorb
139
208
  global_commands.map(&:to_hash)
140
209
  ).wait
141
210
  end
142
- if ENV["DISCORB_CLI_FLAG"] == "setup"
211
+ if ENV.fetch("DISCORB_CLI_FLAG", nil) == "setup"
143
212
  sputs "Registered commands for global:"
144
213
  global_commands.each do |command|
145
- iputs "- #{command.name}"
214
+ iputs "- #{command.name["default"]}"
146
215
  end
147
216
  end
148
217
  unless final_guild_ids.empty?
@@ -156,13 +225,41 @@ module Discorb
156
225
  ).wait
157
226
  sputs "Registered commands for #{guild_id}:"
158
227
  commands.each do |command|
159
- iputs "- #{command.name}"
228
+ iputs "- #{command.name["default"]}"
160
229
  end
161
230
  end
162
231
  end
163
232
  @logger.info "Successfully setup commands"
164
233
  end
165
234
  end
235
+
236
+ #
237
+ # Claer commands in specified guilds.
238
+ # @async
239
+ # @see Client#initialize
240
+ #
241
+ # @param [String] token Bot token.
242
+ # @param [Array<#to_s>, false, nil] guild_ids Guild IDs to clear.
243
+ #
244
+ # @note `token` parameter only required if you don't run client.
245
+ #
246
+ def clear_commands(token, guild_ids)
247
+ Async do
248
+ @token ||= token
249
+ @http = HTTP.new(self)
250
+ app_info = fetch_application.wait
251
+
252
+ guild_ids.each do |guild_id|
253
+ @http.request(
254
+ Route.new("/applications/#{app_info.id}/guilds/#{guild_id}/commands",
255
+ "//applications/:application_id/guilds/:guild_id/commands",
256
+ :put),
257
+ []
258
+ ).wait
259
+ end
260
+ sputs "Cleared commands for #{guild_ids.length} guilds." if ENV.fetch("DISCORB_CLI_FLAG", nil) == "setup"
261
+ end
262
+ end
166
263
  end
167
264
  end
168
265
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
- %w[command handler].each do |file|
2
+
3
+ %w[common command handler].each do |file|
3
4
  require_relative "app_command/#{file}.rb"
4
5
  end