discorb 0.15.0 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) 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 +1 -1
  8. data/.github/workflows/spec.yml +30 -0
  9. data/.lefthook/commit-msg/validator.rb +5 -0
  10. data/.rspec +2 -0
  11. data/.rspec_parallel +2 -0
  12. data/.rubocop.yml +49 -8
  13. data/Changelog.md +32 -1
  14. data/Gemfile +14 -8
  15. data/Rakefile +46 -25
  16. data/bin/console +3 -3
  17. data/docs/Examples.md +1 -1
  18. data/docs/application_command.md +138 -46
  19. data/docs/cli/irb.md +2 -2
  20. data/docs/cli/new.md +14 -9
  21. data/docs/cli/run.md +7 -11
  22. data/docs/cli.md +17 -10
  23. data/docs/events.md +257 -193
  24. data/docs/extension.md +1 -2
  25. data/docs/faq.md +0 -1
  26. data/docs/tutorial.md +12 -12
  27. data/docs/voice_events.md +106 -106
  28. data/examples/commands/message.rb +63 -0
  29. data/examples/commands/permission.rb +18 -0
  30. data/examples/commands/slash.rb +44 -0
  31. data/examples/commands/user.rb +51 -0
  32. data/examples/components/authorization_button.rb +2 -2
  33. data/examples/components/select_menu.rb +2 -2
  34. data/examples/extension/main.rb +1 -1
  35. data/examples/extension/message_expander.rb +5 -2
  36. data/examples/simple/eval.rb +2 -2
  37. data/examples/simple/ping_pong.rb +1 -1
  38. data/examples/simple/rolepanel.rb +2 -2
  39. data/examples/simple/shard.rb +17 -0
  40. data/examples/simple/wait_for_message.rb +1 -1
  41. data/exe/discorb +31 -16
  42. data/lefthook.yml +45 -0
  43. data/lib/discorb/allowed_mentions.rb +8 -0
  44. data/lib/discorb/app_command/command.rb +184 -60
  45. data/lib/discorb/app_command/common.rb +25 -0
  46. data/lib/discorb/app_command/handler.rb +116 -34
  47. data/lib/discorb/app_command.rb +2 -1
  48. data/lib/discorb/application.rb +17 -7
  49. data/lib/discorb/asset.rb +10 -2
  50. data/lib/discorb/attachment.rb +17 -2
  51. data/lib/discorb/audit_logs.rb +53 -12
  52. data/lib/discorb/channel/base.rb +108 -0
  53. data/lib/discorb/channel/category.rb +32 -0
  54. data/lib/discorb/channel/container.rb +44 -0
  55. data/lib/discorb/channel/dm.rb +28 -0
  56. data/lib/discorb/channel/guild.rb +245 -0
  57. data/lib/discorb/channel/stage.rb +140 -0
  58. data/lib/discorb/channel/text.rb +345 -0
  59. data/lib/discorb/channel/thread.rb +321 -0
  60. data/lib/discorb/channel/voice.rb +79 -0
  61. data/lib/discorb/channel.rb +2 -1126
  62. data/lib/discorb/client.rb +160 -64
  63. data/lib/discorb/common.rb +18 -3
  64. data/lib/discorb/components/button.rb +7 -7
  65. data/lib/discorb/components/select_menu.rb +6 -18
  66. data/lib/discorb/components/text_input.rb +12 -2
  67. data/lib/discorb/components.rb +1 -1
  68. data/lib/discorb/dictionary.rb +2 -0
  69. data/lib/discorb/embed.rb +55 -14
  70. data/lib/discorb/emoji.rb +59 -5
  71. data/lib/discorb/emoji_table.rb +4970 -4
  72. data/lib/discorb/error.rb +7 -1
  73. data/lib/discorb/event.rb +56 -21
  74. data/lib/discorb/exe/about.rb +1 -0
  75. data/lib/discorb/exe/irb.rb +2 -4
  76. data/lib/discorb/exe/new.rb +95 -28
  77. data/lib/discorb/exe/run.rb +9 -37
  78. data/lib/discorb/exe/setup.rb +25 -12
  79. data/lib/discorb/exe/show.rb +4 -3
  80. data/lib/discorb/extend.rb +1 -0
  81. data/lib/discorb/extension.rb +6 -3
  82. data/lib/discorb/flag.rb +11 -0
  83. data/lib/discorb/gateway.rb +312 -169
  84. data/lib/discorb/gateway_requests.rb +4 -7
  85. data/lib/discorb/guild.rb +255 -89
  86. data/lib/discorb/guild_template.rb +34 -7
  87. data/lib/discorb/http.rb +23 -11
  88. data/lib/discorb/integration.rb +27 -9
  89. data/lib/discorb/intents.rb +8 -8
  90. data/lib/discorb/interaction/autocomplete.rb +31 -19
  91. data/lib/discorb/interaction/command.rb +70 -17
  92. data/lib/discorb/interaction/components.rb +20 -4
  93. data/lib/discorb/interaction/modal.rb +0 -1
  94. data/lib/discorb/interaction/response.rb +73 -22
  95. data/lib/discorb/interaction/root.rb +29 -14
  96. data/lib/discorb/interaction.rb +1 -0
  97. data/lib/discorb/invite.rb +16 -9
  98. data/lib/discorb/member.rb +46 -5
  99. data/lib/discorb/message.rb +56 -15
  100. data/lib/discorb/message_meta.rb +39 -9
  101. data/lib/discorb/modules.rb +56 -14
  102. data/lib/discorb/permission.rb +14 -5
  103. data/lib/discorb/presence.rb +43 -10
  104. data/lib/discorb/rate_limit.rb +13 -3
  105. data/lib/discorb/reaction.rb +10 -4
  106. data/lib/discorb/role.rb +31 -4
  107. data/lib/discorb/shard.rb +74 -0
  108. data/lib/discorb/sticker.rb +30 -21
  109. data/lib/discorb/user.rb +13 -1
  110. data/lib/discorb/utils/colored_puts.rb +1 -0
  111. data/lib/discorb/voice_state.rb +30 -8
  112. data/lib/discorb/webhook.rb +88 -25
  113. data/lib/discorb.rb +10 -6
  114. data/po/yard.pot +9 -9
  115. data/sig/discorb.rbs +7232 -5837
  116. metadata +23 -6
  117. data/examples/commands/bookmarker.rb +0 -42
  118. data/examples/commands/hello.rb +0 -10
  119. data/examples/commands/inspect.rb +0 -25
  120. data/lib/discorb/log.rb +0 -81
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
  require "discorb"
3
3
 
4
+ #
5
+ # Class for expanding message URL.
6
+ #
4
7
  class MessageExpander
5
8
  include Discorb::Extension
6
9
 
7
- @@message_regex = Regexp.new(
10
+ MESSAGE_PATTERN = Regexp.new(
8
11
  '(?!<)https://(?:ptb\.|canary\.)?discord(?:app)?\.com/channels/' \
9
12
  "(?<guild>[0-9]{18})/(?<channel>[0-9]{18})/(?<message>[0-9]{18})(?!>)"
10
13
  )
@@ -12,7 +15,7 @@ class MessageExpander
12
15
  event :message do |message|
13
16
  next if message.author.bot?
14
17
 
15
- message.content.to_enum(:scan, @@message_regex).map { Regexp.last_match }.each do |match|
18
+ message.content.to_enum(:scan, MESSAGE_PATTERN).map { Regexp.last_match }.each do |match|
16
19
  ch = @client.channels[match[:channel]]
17
20
  next if ch.nil?
18
21
 
@@ -25,9 +25,9 @@ client.on :message do |message|
25
25
  res = res.wait if res.is_a? Async::Task
26
26
  message.channel.post("```rb\n#{res.inspect[...1990]}\n```")
27
27
  end
28
- rescue Exception => e
28
+ rescue Exception => e # rubocop:disable Lint/RescueException
29
29
  message.reply embed: Discorb::Embed.new("Error!", "```rb\n#{e.full_message(highlight: false)[...1990]}\n```",
30
30
  color: Discorb::Color[:red])
31
31
  end
32
32
 
33
- client.run(ENV["discord_bot_token"])
33
+ client.run(ENV.fetch("discord_bot_token", nil))
@@ -14,4 +14,4 @@ client.on :message do |message|
14
14
  message.channel.post("Pong!")
15
15
  end
16
16
 
17
- client.run(ENV["DISCORD_BOT_TOKEN"])
17
+ client.run(ENV.fetch("DISCORD_BOT_TOKEN", nil))
@@ -2,7 +2,7 @@
2
2
  require "discorb"
3
3
  intents = Discorb::Intents.new
4
4
  intents.members = true
5
- client = Discorb::Client.new(intents: intents, log: $stdout, colorize_log: true)
5
+ client = Discorb::Client.new(intents: intents)
6
6
 
7
7
  def convert_role(guild, string)
8
8
  guild.roles.find do |role|
@@ -63,4 +63,4 @@ client.on :message do |message|
63
63
  end
64
64
  end
65
65
 
66
- client.run(ENV["DISCORD_BOT_TOKEN"])
66
+ client.run(ENV.fetch("DISCORD_BOT_TOKEN", nil))
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ require "discorb"
3
+
4
+ client = Discorb::Client.new(log: Logger.new($stdout))
5
+
6
+ client.once :standby do
7
+ puts "Logged in as #{client.user}"
8
+ end
9
+
10
+ client.on :message do |message|
11
+ next if message.author.bot?
12
+ next unless message.content == "!inspect"
13
+
14
+ message.channel.post("I'm #{client.user}, running on shard #{client.shard_id}!")
15
+ end
16
+
17
+ client.run(ENV.fetch("DISCORD_BOT_TOKEN", nil), shards: [0, 1], shard_count: 2)
@@ -28,4 +28,4 @@ client.on :message do |message|
28
28
  end
29
29
  end
30
30
 
31
- client.run(ENV["DISCORD_BOT_TOKEN"])
31
+ client.run(ENV.fetch("DISCORD_BOT_TOKEN", nil))
data/exe/discorb CHANGED
@@ -1,32 +1,47 @@
1
1
  #! /usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- script = ARGV[0]
4
+ require "optparse"
5
5
 
6
- if script.nil?
7
- puts "\e[94mThis is a tool for discorb. Currently these tools are available:\e[m"
8
-
9
- discorb_path = $LOAD_PATH.find { |path| File.directory?(path + "/discorb") }
10
- scripts = {}
6
+ options = {
7
+ bundler: true,
8
+ }
9
+ discorb_paths = $LOAD_PATH.filter { |path| File.directory?(path + "/discorb") }
10
+ scripts = {}
11
+ discorb_paths.each do |discorb_path|
11
12
  Dir.glob(discorb_path + "/discorb/exe/*.rb") do |exe_script|
12
13
  name = File.basename(exe_script, ".rb")
13
14
  description = File.read(exe_script).match(/# description: (.+)/)&.[](1) || "No description"
14
15
  scripts[name] = description
15
16
  end
16
- max_length = scripts.keys.map(&:length).max
17
- scripts.sort.each do |name, description|
18
- puts "\e[90m#{name.rjust(max_length)}\e[m - #{description}"
17
+ end
18
+ max_length = scripts.keys.map(&:length).max
19
+ global = OptionParser.new do |opts|
20
+ opts.banner = "Usage: discorb [options] [subcommand [options]]"
21
+ opts.on("-b", "--[no-]bundler", "Whether to use bundler.") do |v|
22
+ options[:bundler] = v
19
23
  end
24
+ opts.separator ""
25
+ commands = +"Subcommands:\n"
26
+ commands << scripts.sort.map do |name, description|
27
+ " #{name.rjust(max_length)} - #{description}"
28
+ end.join("\n")
29
+ commands << "\n\nYou can run `discorb [subcommand] --help` for more information."
30
+ opts.separator commands
31
+ end
32
+ global.order!(ARGV)
20
33
 
21
- puts "\e[94m\nTo run a tool, type:\e[m\n" \
22
- "\e[34m discorb [script]\e[m"
23
-
24
- exit 1
34
+ if ARGV.empty?
35
+ puts global
36
+ abort
25
37
  end
26
38
 
39
+ require "bundler/setup" if options[:bundler]
40
+
41
+ command = ARGV.shift
42
+
27
43
  begin
28
- require "discorb/exe/#{script}"
44
+ require "discorb/exe/#{command}"
29
45
  rescue LoadError
30
- puts "\e[91mThis tool is not available: \e[90m#{script}\e[m"
31
- exit 1
46
+ warn "Unknown subcommand: #{command}"
32
47
  end
data/lefthook.yml ADDED
@@ -0,0 +1,45 @@
1
+ # EXAMPLE USAGE
2
+ # Refer for explanation to following link:
3
+ # https://github.com/evilmartians/lefthook/blob/master/docs/full_guide.md
4
+ #
5
+ # pre-push:
6
+ # commands:
7
+ # packages-audit:
8
+ # tags: frontend security
9
+ # run: yarn audit
10
+ # gems-audit:
11
+ # tags: backend security
12
+ # run: bundle audit
13
+ #
14
+ # pre-commit:
15
+ # parallel: true
16
+ # commands:
17
+ # eslint:
18
+ # glob: "*.{js,ts}"
19
+ # run: yarn eslint {staged_files}
20
+ # rubocop:
21
+ # tags: backend style
22
+ # glob: "*.rb"
23
+ # exclude: "application.rb|routes.rb"
24
+ # run: bundle exec rubocop --force-exclusion {all_files}
25
+ # govet:
26
+ # tags: backend style
27
+ # files: git ls-files -m
28
+ # glob: "*.go"
29
+ # run: go vet {files}
30
+ # scripts:
31
+ # "hello.js":
32
+ # runner: node
33
+ # "any.go":
34
+ # runner: go run
35
+ pre-commit:
36
+ parallel: true
37
+ commands:
38
+ linting:
39
+ glob: "*.rb"
40
+ run: rubocop {staged_files}
41
+
42
+ commit-msg:
43
+ scripts:
44
+ "validator.rb":
45
+ runner: ruby
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Discorb
3
4
  #
4
5
  # Represents a allowed mentions in a message.
@@ -32,7 +33,14 @@ module Discorb
32
33
  "#<#{self.class} @everyone=#{@everyone} @roles=#{@roles} @users=#{@users} @replied_user=#{@replied_user}>"
33
34
  end
34
35
 
36
+ #
37
+ # Converts the object to a hash.
35
38
  # @private
39
+ #
40
+ # @param [Discorb::AllowedMentions, nil] other The object to merge.
41
+ #
42
+ # @return [Hash] The hash.
43
+ #
36
44
  def to_hash(other = nil)
37
45
  payload = {
38
46
  parse: %w[everyone roles users],
@@ -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{Symbol => 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,27 +17,46 @@ 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
- @types = {
25
+ # @private
26
+ # @return [{Integer => Symbol}] The mapping of raw types to types.
27
+ TYPES = {
27
28
  1 => :chat_input,
28
29
  2 => :user,
29
30
  3 => :message,
30
31
  }.freeze
31
32
 
33
+ #
34
+ # Initialize a new command.
32
35
  # @private
33
- def initialize(name, guild_ids, block, type)
34
- @name = name
36
+ #
37
+ # @param [String, Hash{Symbol => String}] name The name of the command.
38
+ # @param [Array<#to_s>] guild_ids The guild ids that the command is enabled in.
39
+ # @param [Proc] block The block of the command.
40
+ # @param [:chat_input, :user, :message] 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.
43
+ #
44
+ def initialize(name, guild_ids, block, type, dm_permission = nil, default_permission = nil)
45
+ @name = name.is_a?(String) ? { "default" => name } : ApplicationCommand.modify_localization_hash(name)
35
46
  @guild_ids = guild_ids&.map(&:to_s)
36
47
  @block = block
37
- @raw_type = type
38
- @type = Discorb::ApplicationCommand::Command.types[type]
48
+ @type = Discorb::ApplicationCommand::Command::TYPES[type]
39
49
  @type_raw = type
40
- @id_map = Discorb::Dictionary.new
50
+ @dm_permission = dm_permission
51
+ @default_permission = default_permission
41
52
  end
42
53
 
54
+ #
55
+ # Changes the self pointer of block to the given object.
43
56
  # @private
57
+ #
58
+ # @param [Object] instance The object to change the self pointer to.
59
+ #
44
60
  def replace_block(instance)
45
61
  current_block = @block.dup
46
62
  @block = proc do |*args|
@@ -48,32 +64,58 @@ module Discorb
48
64
  end
49
65
  end
50
66
 
67
+ #
68
+ # Converts the object to a hash.
51
69
  # @private
70
+ #
71
+ # @return [Hash] The hash represents the object.
72
+ #
52
73
  def to_hash
53
74
  {
54
- name: @name,
55
- default_permission: @default_permission,
75
+ name: @name["default"],
76
+ name_localizations: @name.except("default"),
56
77
  type: @type_raw,
78
+ dm_permission: @dm_permission,
79
+ default_member_permissions: @default_permission&.value&.to_s,
57
80
  }
58
81
  end
59
82
 
60
83
  #
61
84
  # Represents the slash command.
62
85
  #
63
- class SlashCommand < Command
64
- # @return [String] The description of the command.
86
+ class ChatInputCommand < Command
87
+ # @return [Hash{String => String}] The description of the command.
65
88
  attr_reader :description
66
89
  # @return [Hash{String => Hash}] The options of the command.
67
90
  attr_reader :options
68
91
 
92
+ #
93
+ # Initialize a new slash command.
69
94
  # @private
70
- def initialize(name, description, options, guild_ids, block, type, parent)
71
- super(name, guild_ids, block, type)
72
- @description = description
95
+ #
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.
100
+ # @param [Hash{String => Hash}] options The options of the command.
101
+ # @param [Array<#to_s>] guild_ids The guild ids that the command is enabled in.
102
+ # @param [Proc] block The block of the command.
103
+ # @param [:chat_input, :user, :message] type The type of the command.
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.
107
+ #
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
73
117
  @options = options
74
- @id = nil
75
118
  @parent = parent
76
- @id_map = Discorb::Dictionary.new
77
119
  end
78
120
 
79
121
  #
@@ -82,10 +124,15 @@ module Discorb
82
124
  # @return [String] The name of the command.
83
125
  #
84
126
  def to_s
85
- (@parent + " " + @name).strip
127
+ "#{@parent} #{@name["default"]}".strip
86
128
  end
87
129
 
130
+ #
131
+ # Converts the object to a hash.
88
132
  # @private
133
+ #
134
+ # @return [Hash] The hash represents the object.
135
+ #
89
136
  def to_hash
90
137
  options_payload = options.map do |name, value|
91
138
  ret = {
@@ -112,11 +159,34 @@ module Discorb
112
159
  raise ArgumentError, "Invalid option type: #{value[:type]}"
113
160
  end,
114
161
  name: name,
115
- description: value[:description],
162
+ name_localizations: ApplicationCommand.modify_localization_hash(value[:name_localizations]),
116
163
  required: value[:required].nil? ? !value[:optional] : value[:required],
117
164
  }
118
165
 
119
- 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
120
190
 
121
191
  ret[:channel_types] = value[:channel_types].map(&:channel_type) if value[:channel_types]
122
192
 
@@ -128,10 +198,13 @@ module Discorb
128
198
  ret
129
199
  end
130
200
  {
131
- name: @name,
132
- default_permission: true,
133
- description: @description,
201
+ name: @name["default"],
202
+ name_localizations: @name.except("default"),
203
+ description: @description["default"],
204
+ description_localizations: @description.except("default"),
134
205
  options: options_payload,
206
+ dm_permission: @dm_permission,
207
+ default_member_permissions: @default_permission&.value&.to_s,
135
208
  }
136
209
  end
137
210
  end
@@ -140,29 +213,58 @@ module Discorb
140
213
  # Represents the command with subcommands.
141
214
  #
142
215
  class GroupCommand < Command
143
- # @return [Array<Discorb::ApplicationCommand::Command::SlashCommand, Discorb::ApplicationCommand::Command::SubcommandGroup>] The subcommands of the command.
216
+ # @return [Array<
217
+ # Discorb::ApplicationCommand::Command::ChatInputCommand,
218
+ # Discorb::ApplicationCommand::Command::SubcommandGroup
219
+ # >] The subcommands of the command.
144
220
  attr_reader :commands
145
221
  # @return [String] The description of the command.
146
222
  attr_reader :description
147
223
 
224
+ #
225
+ # Initialize a new group command.
148
226
  # @private
149
- def initialize(name, description, guild_ids, type, client)
150
- super(name, guild_ids, block, type)
151
- @description = description
227
+ #
228
+ # @param [String, Hash{Symbol => String}] name The name of the command.
229
+ # @param [String, Hash{Symbol => String}] description The description of the command.
230
+ # @param [Array<#to_s>] guild_ids The guild ids that the command is enabled in.
231
+ # @param [:chat_input, :user, :message] type The type of the command.
232
+ # @param [Discorb::Client] client The client of the command.
233
+ # @param [Boolean] dm_permission Whether the command is enabled in DMs.
234
+ # @param [Discorb::Permission] default_permission The default permission of the command.
235
+ #
236
+ def initialize(name, description, guild_ids, type, client, dm_permission, default_permission)
237
+ super(name, guild_ids, block, type, dm_permission, default_permission)
238
+ @description = if description.is_a?(String)
239
+ {
240
+ "default" => description,
241
+ }
242
+ else
243
+ ApplicationCommand.modify_localization_hash(description)
244
+ end
152
245
  @commands = []
153
246
  @client = client
154
- @id_map = Discorb::Dictionary.new
155
247
  end
156
248
 
157
249
  #
158
250
  # Add new subcommand.
159
251
  #
160
252
  # @param (see Discorb::ApplicationCommand::Handler#slash)
161
- # @return [Discorb::ApplicationCommand::Command::SlashCommand] The added subcommand.
253
+ # @return [Discorb::ApplicationCommand::Command::ChatInputCommand] The added subcommand.
162
254
  #
163
- def slash(command_name, description, options = {}, &block)
164
- command = Discorb::ApplicationCommand::Command::SlashCommand.new(command_name, description, options, [], block, 1, @name)
165
- @client.bottom_commands << command
255
+ def slash(command_name, description, options = {}, dm_permission: true, default_permission: nil, &block)
256
+ command = Discorb::ApplicationCommand::Command::ChatInputCommand.new(
257
+ command_name,
258
+ description,
259
+ options,
260
+ [],
261
+ block,
262
+ 1,
263
+ self,
264
+ dm_permission,
265
+ default_permission
266
+ )
267
+ @client.callable_commands << command
166
268
  @commands << command
167
269
  command
168
270
  end
@@ -182,7 +284,7 @@ module Discorb
182
284
  #
183
285
  def group(command_name, description, &block)
184
286
  command = Discorb::ApplicationCommand::Command::SubcommandGroup.new(command_name, description, @name, @client)
185
- command.yield_self(&block) if block_given?
287
+ command.then(&block) if block_given?
186
288
  @commands << command
187
289
  command
188
290
  end
@@ -193,41 +295,58 @@ module Discorb
193
295
  # @return [String] The command name.
194
296
  #
195
297
  def to_s
196
- @name
298
+ @name["default"]
197
299
  end
198
300
 
301
+ #
302
+ # Changes the self pointer to the given object.
199
303
  # @private
304
+ #
305
+ # @param [Object] instance The object to change to.
306
+ #
200
307
  def block_replace(instance)
201
308
  super
202
309
  @commands.each { |c| c.replace_block(instance) }
203
310
  end
204
311
 
312
+ #
313
+ # Converts the object to a hash.
205
314
  # @private
315
+ #
316
+ # @return [Hash] The hash represents the object.
317
+ #
206
318
  def to_hash
207
319
  options_payload = @commands.map do |command|
208
- if command.is_a?(SlashCommand)
320
+ if command.is_a?(ChatInputCommand)
209
321
  {
210
- name: command.name,
211
- description: command.description,
212
- default_permission: true,
322
+ name: command.name["default"],
323
+ name_localizations: command.name.except("default"),
324
+ description: command.description["default"],
325
+ description_localizations: command.description.except("default"),
213
326
  type: 1,
214
327
  options: command.to_hash[:options],
215
328
  }
216
329
  else
217
330
  {
218
- name: command.name,
219
- description: command.description,
220
- default_permission: true,
331
+ name: command.name["default"],
332
+ name_localizations: command.name.except("default"),
333
+ description: command.description["default"],
334
+ description_localizations: command.description.except("default"),
221
335
  type: 2,
222
- options: command.commands.map { |c| c.to_hash.merge(type: 1) },
336
+ options: command.commands.map do |c|
337
+ c.to_hash.merge(type: 1).except(:dm_permission, :default_member_permissions)
338
+ end,
223
339
  }
224
340
  end
225
341
  end
226
342
 
227
343
  {
228
- name: @name,
229
- default_permission: @enabled,
230
- description: @description,
344
+ name: @name["default"],
345
+ name_localizations: @name.except("default"),
346
+ description: @description["default"],
347
+ description_localizations: @description.except("default"),
348
+ dm_permission: @dm_permission,
349
+ default_member_permissions: @default_permission&.value&.to_s,
231
350
  options: options_payload,
232
351
  }
233
352
  end
@@ -237,38 +356,43 @@ module Discorb
237
356
  # Represents the subcommand group.
238
357
  #
239
358
  class SubcommandGroup < GroupCommand
240
- # @return [Array<Discorb::ApplicationCommand::Command::SlashCommand>] The subcommands of the command.
359
+ # @return [Array<Discorb::ApplicationCommand::Command::ChatInputCommand>] The subcommands of the command.
241
360
  attr_reader :commands
242
361
 
362
+ #
363
+ # Initialize a new subcommand group.
243
364
  # @private
365
+ #
366
+ # @param [String] name The name of the command.
367
+ # @param [String] description The description of the command.
368
+ # @param [Discorb::ApplicationCommand::Command::GroupCommand] parent The parent command.
369
+ # @param [Discorb::Client] client The client.
244
370
  def initialize(name, description, parent, client)
245
- super(name, description, [], 1, client)
371
+ super(name, description, [], 1, client, nil, nil)
246
372
 
247
373
  @commands = []
248
374
  @parent = parent
249
375
  end
250
376
 
251
377
  def to_s
252
- @parent + " " + @name
378
+ "#{@parent} #{@name}"
253
379
  end
254
380
 
255
381
  #
256
382
  # Add new subcommand.
257
383
  # @param (see Discorb::ApplicationCommand::Handler#slash)
258
- # @return [Discorb::ApplicationCommand::Command::SlashCommand] The added subcommand.
384
+ # @return [Discorb::ApplicationCommand::Command::ChatInputCommand] The added subcommand.
259
385
  #
260
386
  def slash(command_name, description, options = {}, &block)
261
- command = Discorb::ApplicationCommand::Command::SlashCommand.new(command_name, description, options, [], block, 1, @parent + " " + @name)
387
+ command = Discorb::ApplicationCommand::Command::ChatInputCommand.new(
388
+ command_name, description, options, [],
389
+ block, 1, self, nil, nil
390
+ )
262
391
  @commands << command
263
- @client.bottom_commands << command
392
+ @client.callable_commands << command
264
393
  command
265
394
  end
266
395
  end
267
-
268
- class << self
269
- # @private
270
- attr_reader :types
271
- end
272
396
  end
273
397
  end
274
398
  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