discorb 0.18.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.
Files changed (149) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build_version.yml +2 -2
  3. data/.rubocop.yml +12 -75
  4. data/Changelog.md +25 -0
  5. data/Gemfile +4 -4
  6. data/README.md +2 -1
  7. data/Rakefile +482 -459
  8. data/Steepfile +8 -6
  9. data/docs/application_command.md +1 -0
  10. data/docs/events.md +2 -2
  11. data/docs/voice_events.md +6 -6
  12. data/lib/discorb/allowed_mentions.rb +68 -72
  13. data/lib/discorb/app_command/command.rb +466 -394
  14. data/lib/discorb/app_command/common.rb +65 -25
  15. data/lib/discorb/app_command/handler.rb +304 -265
  16. data/lib/discorb/app_command.rb +5 -5
  17. data/lib/discorb/application.rb +198 -197
  18. data/lib/discorb/asset.rb +101 -101
  19. data/lib/discorb/attachment.rb +134 -119
  20. data/lib/discorb/audit_logs.rb +412 -385
  21. data/lib/discorb/automod.rb +279 -269
  22. data/lib/discorb/channel/base.rb +107 -108
  23. data/lib/discorb/channel/category.rb +32 -32
  24. data/lib/discorb/channel/container.rb +44 -44
  25. data/lib/discorb/channel/dm.rb +26 -28
  26. data/lib/discorb/channel/guild.rb +311 -246
  27. data/lib/discorb/channel/stage.rb +156 -140
  28. data/lib/discorb/channel/text.rb +430 -336
  29. data/lib/discorb/channel/thread.rb +374 -325
  30. data/lib/discorb/channel/voice.rb +85 -79
  31. data/lib/discorb/channel.rb +5 -5
  32. data/lib/discorb/client.rb +635 -623
  33. data/lib/discorb/color.rb +178 -182
  34. data/lib/discorb/common.rb +168 -164
  35. data/lib/discorb/components/button.rb +107 -106
  36. data/lib/discorb/components/select_menu.rb +157 -145
  37. data/lib/discorb/components/text_input.rb +103 -106
  38. data/lib/discorb/components.rb +68 -66
  39. data/lib/discorb/dictionary.rb +135 -135
  40. data/lib/discorb/embed.rb +404 -398
  41. data/lib/discorb/emoji.rb +309 -302
  42. data/lib/discorb/emoji_table.rb +16099 -8857
  43. data/lib/discorb/error.rb +131 -131
  44. data/lib/discorb/event.rb +360 -314
  45. data/lib/discorb/event_handler.rb +39 -39
  46. data/lib/discorb/exe/about.rb +17 -17
  47. data/lib/discorb/exe/irb.rb +72 -67
  48. data/lib/discorb/exe/new.rb +323 -315
  49. data/lib/discorb/exe/run.rb +69 -68
  50. data/lib/discorb/exe/setup.rb +57 -55
  51. data/lib/discorb/exe/show.rb +12 -12
  52. data/lib/discorb/extend.rb +25 -45
  53. data/lib/discorb/extension.rb +89 -83
  54. data/lib/discorb/flag.rb +126 -128
  55. data/lib/discorb/gateway.rb +984 -794
  56. data/lib/discorb/gateway_events.rb +670 -638
  57. data/lib/discorb/gateway_requests.rb +45 -48
  58. data/lib/discorb/guild.rb +2115 -1626
  59. data/lib/discorb/guild_template.rb +280 -241
  60. data/lib/discorb/http.rb +247 -232
  61. data/lib/discorb/image.rb +42 -42
  62. data/lib/discorb/integration.rb +169 -161
  63. data/lib/discorb/intents.rb +161 -163
  64. data/lib/discorb/interaction/autocomplete.rb +76 -62
  65. data/lib/discorb/interaction/command.rb +279 -224
  66. data/lib/discorb/interaction/components.rb +114 -104
  67. data/lib/discorb/interaction/modal.rb +36 -32
  68. data/lib/discorb/interaction/response.rb +379 -330
  69. data/lib/discorb/interaction/root.rb +271 -118
  70. data/lib/discorb/interaction.rb +5 -5
  71. data/lib/discorb/invite.rb +154 -153
  72. data/lib/discorb/member.rb +344 -311
  73. data/lib/discorb/message.rb +615 -544
  74. data/lib/discorb/message_meta.rb +197 -186
  75. data/lib/discorb/modules.rb +371 -290
  76. data/lib/discorb/permission.rb +305 -289
  77. data/lib/discorb/presence.rb +352 -346
  78. data/lib/discorb/rate_limit.rb +81 -76
  79. data/lib/discorb/reaction.rb +55 -54
  80. data/lib/discorb/role.rb +272 -240
  81. data/lib/discorb/shard.rb +76 -74
  82. data/lib/discorb/sticker.rb +193 -171
  83. data/lib/discorb/user.rb +205 -188
  84. data/lib/discorb/utils/colored_puts.rb +16 -16
  85. data/lib/discorb/utils.rb +12 -16
  86. data/lib/discorb/voice_state.rb +305 -281
  87. data/lib/discorb/webhook.rb +537 -507
  88. data/lib/discorb.rb +62 -56
  89. data/sig/discorb/activity.rbs +1 -0
  90. data/sig/discorb/allowed_mentions.rbs +1 -0
  91. data/sig/discorb/app_command/base.rbs +7 -1
  92. data/sig/discorb/application.rbs +6 -0
  93. data/sig/discorb/asset.rbs +2 -0
  94. data/sig/discorb/attachment.rbs +8 -0
  95. data/sig/discorb/audit_log.rbs +7 -0
  96. data/sig/discorb/automod.rbs +32 -6
  97. data/sig/discorb/avatar.rbs +1 -0
  98. data/sig/discorb/channel/base.rbs +8 -1
  99. data/sig/discorb/channel/category.rbs +1 -0
  100. data/sig/discorb/channel/container.rbs +4 -0
  101. data/sig/discorb/channel/stage.rbs +4 -0
  102. data/sig/discorb/channel/text.rbs +2 -2
  103. data/sig/discorb/channel/thread.rbs +11 -0
  104. data/sig/discorb/channel/voice.rbs +2 -0
  105. data/sig/discorb/client.rbs +21 -20
  106. data/sig/discorb/color.rbs +6 -0
  107. data/sig/discorb/component/base.rbs +1 -0
  108. data/sig/discorb/component/button.rbs +2 -0
  109. data/sig/discorb/component/select_menu.rbs +4 -0
  110. data/sig/discorb/component/text_input.rbs +1 -0
  111. data/sig/discorb/custom_emoji.rbs +5 -1
  112. data/sig/discorb/dictionary.rbs +2 -0
  113. data/sig/discorb/discord_model.rbs +2 -0
  114. data/sig/discorb/embed.rbs +7 -0
  115. data/sig/discorb/emoji.rbs +1 -0
  116. data/sig/discorb/event_handler.rbs +2 -1
  117. data/sig/discorb/extension.rbs +13 -12
  118. data/sig/discorb/flag.rbs +2 -0
  119. data/sig/discorb/gateway.rbs +5 -0
  120. data/sig/discorb/guild.rbs +8 -4
  121. data/sig/discorb/guild_template.rbs +1 -1
  122. data/sig/discorb/http.rbs +4 -1
  123. data/sig/discorb/image.rbs +2 -0
  124. data/sig/discorb/integration.rbs +1 -1
  125. data/sig/discorb/intents.rbs +4 -3
  126. data/sig/discorb/interaction/base.rbs +36 -0
  127. data/sig/discorb/interaction/message_component.rbs +1 -2
  128. data/sig/discorb/interaction/modal.rbs +1 -2
  129. data/sig/discorb/interaction/responder.rbs +49 -49
  130. data/sig/discorb/invite.rbs +1 -1
  131. data/sig/discorb/member.rbs +2 -0
  132. data/sig/discorb/message.rbs +8 -1
  133. data/sig/discorb/messageable.rbs +1 -4
  134. data/sig/discorb/partial_emoji.rbs +3 -0
  135. data/sig/discorb/permissions.rbs +7 -0
  136. data/sig/discorb/presence.rbs +2 -0
  137. data/sig/discorb/reaction.rbs +5 -1
  138. data/sig/discorb/role.rbs +7 -1
  139. data/sig/discorb/scheduled_event.rbs +2 -1
  140. data/sig/discorb/shard.rbs +2 -1
  141. data/sig/discorb/snowflake.rbs +2 -0
  142. data/sig/discorb/stage_instance.rbs +9 -3
  143. data/sig/discorb/sticker.rbs +1 -1
  144. data/sig/discorb/unicode_emoji.rbs +4 -0
  145. data/sig/discorb/user.rbs +24 -20
  146. data/sig/discorb/webhook.rbs +17 -6
  147. data/sig/discorb/welcome_screen.rbs +1 -0
  148. data/sig/override.rbs +2 -0
  149. metadata +3 -3
data/Rakefile CHANGED
@@ -1,459 +1,482 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/gem_tasks"
4
- require_relative "lib/discorb/utils/colored_puts"
5
- require "parallel_tests"
6
- task default: %i[]
7
-
8
- # @private
9
- def current_version
10
- require_relative "lib/discorb/common"
11
- tag = `git tag --points-at HEAD`.force_encoding("utf-8").strip
12
- if tag.empty?
13
- "main"
14
- else
15
- Discorb::VERSION
16
- end
17
- end
18
-
19
- desc "Run spec with parallel_rspec"
20
- task :spec do
21
- sh "parallel_rspec spec/*.spec.rb spec/**/*.spec.rb"
22
- end
23
-
24
- desc "Build emoji_table.rb"
25
- task :emoji_table do
26
- require_relative "lib/discorb"
27
-
28
- iputs "Building emoji_table.rb"
29
- res = {}
30
- Discorb::EmojiTable::DISCORD_TO_UNICODE.each do |discord, unicode|
31
- res[unicode] ||= []
32
- res[unicode] << discord
33
- end
34
-
35
- res_text = +""
36
- res.each do |unicode, discord|
37
- res_text << %(#{unicode.unpack("C*").pack("C*").inspect} => %w[#{discord.join(" ")}],\n)
38
- end
39
-
40
- table_script = File.read("lib/discorb/emoji_table.rb")
41
-
42
- table_script.gsub!(/(?<=UNICODE_TO_DISCORD = {\n)[\s\S]+(?=}\.freeze)/, res_text)
43
-
44
- File.open("lib/discorb/emoji_table.rb", "w") do |f|
45
- f.print(table_script)
46
- end
47
- `rufo lib/discorb/emoji_table.rb`
48
- sputs "Successfully made emoji_table.rb"
49
- end
50
-
51
- desc "Format files"
52
- task :format do
53
- Dir.glob("**/*.rb").each do |file|
54
- next if file.start_with?("vendor")
55
-
56
- iputs "Formatting #{file}"
57
- `rufo ./#{file}`
58
- content = ""
59
- File.open(file, "rb") do |f|
60
- content = f.read
61
- end
62
- content.gsub!("\r\n", "\n")
63
- File.open(file, "wb") do |f|
64
- f.print(content)
65
- end
66
- end
67
- end
68
-
69
- desc "Generate document and replace"
70
- namespace :document do
71
- version = current_version
72
- desc "Just generate document"
73
- task :yard do
74
- sh "bundle exec yardoc -o doc/#{version} --locale #{ENV.fetch("rake_locale", nil) or "en"}"
75
- end
76
-
77
- desc "Replace files"
78
- namespace :replace do
79
- require "fileutils"
80
-
81
- desc "Replace CSS"
82
- task :css do
83
- iputs "Replacing css"
84
- Dir.glob("template-replace/files/**/*.*")
85
- .map { |f| f.delete_prefix("template-replace/files") }.each do |file|
86
- FileUtils.cp("template-replace/files" + file, "doc/#{version}/#{file}")
87
- end
88
- sputs "Successfully replaced css"
89
- end
90
-
91
- desc "Replace HTML"
92
- task :html do
93
- require_relative "template-replace/scripts/sidebar"
94
- require_relative "template-replace/scripts/version"
95
- require_relative "template-replace/scripts/index"
96
- require_relative "template-replace/scripts/yard_replace"
97
- require_relative "template-replace/scripts/favicon"
98
- require_relative "template-replace/scripts/arrow"
99
- iputs "Resetting changes"
100
- Dir.glob("doc/#{version}/**/*.html") do |f|
101
- next if (m = f.match(/[0-9]+\.[0-9]+\.[0-9]+(-[a-z]+)?/)) && m[0] != version
102
-
103
- content = File.read(f)
104
- content.gsub!(/<!--od-->[\s\S]*<!--eod-->/, "")
105
- File.write(f, content)
106
- end
107
- iputs "Adding version tab"
108
- %w[file_list class_list method_list].each do |f|
109
- replace_sidebar("doc/#{version}/#{f}.html")
110
- end
111
-
112
- iputs "Building version tab"
113
- build_version_sidebar("doc/#{version}", version)
114
- iputs "Replacing _index.html"
115
- replace_index("doc/#{version}", version)
116
- iputs "Replacing YARD credits"
117
- yard_replace("doc/#{version}", version)
118
- iputs "Adding favicon"
119
- add_favicon("doc/#{version}")
120
- iputs "Replacing arrow"
121
- replace_arrow("doc/#{version}")
122
- iputs "Successfully replaced htmls"
123
- end
124
-
125
- desc "Replace EOL"
126
- task :eol do
127
- iputs "Replacing CRLF with LF"
128
- Dir.glob("doc/**/*.*") do |file|
129
- next unless File.file?(file)
130
- next unless %w[html css js].include? file.split(".").last
131
-
132
- content = ""
133
- File.open(file, "rb") do |f|
134
- content = f.read
135
- end
136
- content.gsub!("\r\n", "\n")
137
- File.open(file, "wb") do |f|
138
- f.print(content)
139
- end
140
- end
141
- sputs "Successfully replaced CRLF with LF"
142
- end
143
-
144
- desc "change locale of current document"
145
- task :locale do
146
- next if ENV["rake_locale"].nil?
147
-
148
- require_relative "template-replace/scripts/locale_#{ENV.fetch("rake_locale", nil)}.rb"
149
- replace_locale("doc/main")
150
- end
151
- end
152
- task replace: %i[replace:css replace:html replace:eol]
153
-
154
- desc "Build all versions"
155
- task :build_all do
156
- require "fileutils"
157
-
158
- iputs "Building all versions"
159
- begin
160
- FileUtils.rm_rf("doc")
161
- rescue StandardError
162
- nil
163
- end
164
- FileUtils.cp_r("./template-replace/.", "./tmp-template-replace")
165
- Rake::Task["document:yard"].execute
166
- Rake::Task["document:replace:html"].execute
167
- Rake::Task["document:replace:css"].execute
168
- Rake::Task["document:replace:eol"].execute
169
- Rake::Task["document:replace:locale"].execute
170
- tags = `git tag`.force_encoding("utf-8").split("\n").sort_by { |t| t[1..].split(".").map(&:to_i) }
171
- tags.each do |tag|
172
- sh "git checkout #{tag} -f"
173
- iputs "Building #{tag}"
174
- FileUtils.cp_r("./tmp-template-replace/.", "./template-replace")
175
- version = tag.delete_prefix("v")
176
- Rake::Task["document:yard"].execute
177
- Rake::Task["document:replace:html"].execute
178
- Rake::Task["document:replace:css"].execute
179
- Rake::Task["document:replace:eol"].execute
180
- Rake::Task["document:replace:locale"].execute
181
- FileUtils.cp_r("./doc/.", "./tmp-doc")
182
- FileUtils.rm_rf("doc")
183
- end
184
- sh "git switch main -f"
185
- FileUtils.cp_r("./tmp-doc/.", "./doc")
186
- FileUtils.cp_r("./doc/#{tags.last.delete_prefix("v")}/.", "./doc")
187
- sputs "Successfully built all versions"
188
- rescue StandardError => e
189
- sh "git switch main -f"
190
- raise e
191
- end
192
-
193
- desc "Push to discorb-lib/discorb-lib.github.io"
194
- task :push do
195
- iputs "Pushing documents"
196
- Dir.chdir("doc") do
197
- sh "git init"
198
- sh "git remote add origin git@github.com:discorb-lib/discorb-lib.github.io"
199
- sh "git add ."
200
- sh "git commit -m \"Update: Update document\""
201
- sh "git push -f"
202
- end
203
- sputs "Successfully pushed documents"
204
- end
205
-
206
- namespace :locale do
207
- desc "Generate Japanese document"
208
- task :ja do
209
- require "crowdin-api"
210
- require "zip"
211
- crowdin = Crowdin::Client.new do |config|
212
- config.api_token = ENV.fetch("CROWDIN_PERSONAL_TOKEN", nil)
213
- config.project_id = ENV["CROWDIN_PROJECT_ID"].to_i
214
- end
215
- build = crowdin.build_project_translation["data"]["id"]
216
- crowdin.download_project_translations("./tmp.zip", build)
217
-
218
- Zip::File.open("tmp.zip") do |zip|
219
- zip.each do |entry|
220
- zip.extract(entry, entry.name) { true }
221
- end
222
- end
223
- ENV["rake_locale"] = "ja"
224
- Rake::Task["document:yard"].execute
225
- Rake::Task["document:replace"].execute
226
- end
227
-
228
- desc "Generate English document"
229
- task :en do
230
- Rake::Task["document"].execute("locale:en")
231
- end
232
- end
233
- end
234
-
235
- desc "Generate rbs file"
236
- namespace :rbs do
237
- desc "Generate event signature"
238
- task :event do
239
- client_rbs = File.read("sig/discorb/client.rbs")
240
- extension_rbs = File.read("sig/discorb/extension.rbs")
241
- event_document = File.read("./docs/events.md")
242
- voice_event_document = File.read("./docs/voice_events.md")
243
- event_reference = event_document.split("## Event reference")[1]
244
- event_reference += voice_event_document.split("# Voice Events")[1]
245
- event_reference.gsub!(/^### (.*)$/, "")
246
- events = []
247
- event_reference.split("#### `")[1..].each do |event|
248
- header, content = event.split("`\n", 2)
249
- name = header.split("(")[0]
250
- description = content.split("| Parameter", 2)[0].strip
251
- parameters = if content.include?("| Parameter")
252
- content.scan(/\| `(.*?)` +\| (.*?) +\| (.*?) +\|/)
253
- else
254
- []
255
- end
256
- events << {
257
- name: name,
258
- description: description,
259
- parameters: parameters.map { |p| { name: p[0], type: p[1], description: p[2] } },
260
- }
261
- end
262
- event_sig = +""
263
- event_lock_sig = +""
264
- extension_sig = +""
265
- events.each do |event|
266
- args = []
267
- event[:parameters].each do |parameter|
268
- args << {
269
- name: parameter[:name],
270
- type: if parameter[:type].start_with?("?")
271
- parameter[:type][1..]
272
- else
273
- parameter[:type]
274
- end.tr("{}`", "").tr("<>", "[]").gsub(", ", " | ").then do |t|
275
- if event[:name] == "event_receive"
276
- case t
277
- when "Hash"
278
- next "Discorb::json"
279
- end
280
- end
281
- t
282
- end,
283
- }
284
- end
285
- sig = args.map { |a| "#{a[:type]} #{a[:name]}" }.join(", ")
286
- tuple_sig = args.map { |a| a[:type] }.join(", ")
287
- tuple_sig = "[" + tuple_sig + "]" if args.length > 1
288
- tuple_sig = "void" if args.length.zero?
289
- event_sig << <<~RBS
290
- | (:#{event[:name]} event_name, ?id: Symbol?, **untyped metadata) { (#{sig}) -> void } -> Discorb::EventHandler
291
- RBS
292
- event_lock_sig << <<~RBS
293
- | (:#{event[:name]} event, ?Integer? timeout) { (#{sig}) -> boolish } -> Async::Task[#{tuple_sig}]
294
- RBS
295
- extension_sig << <<~RBS
296
- | (:#{event[:name]} event_name, ?id: Symbol?, **untyped metadata) { (#{sig}) -> void } -> void
297
- RBS
298
- end
299
- event_sig.sub!("| ", " ").rstrip!
300
- event_lock_sig.sub!("| ", " ").rstrip!
301
- extension_sig.sub!("| ", " ").rstrip!
302
- res = client_rbs.gsub!(/\# marker: on\n(?:[\s\S]*?\n)?( +)\# endmarker: on\n/) do
303
- indent = Regexp.last_match(1)
304
- "# marker: on\n#{event_sig.gsub(/^/, "#{indent} ")}\n#{indent}# endmarker: on\n"
305
- end
306
- raise "Failed to generate Client#on" unless res
307
-
308
- res = client_rbs.gsub!(/\# marker: once\n(?:[\s\S]*?\n)?( +)\# endmarker: once\n/) do
309
- indent = Regexp.last_match(1)
310
- "# marker: once\n#{event_sig.gsub(/^/, "#{indent} ")}\n#{indent}# endmarker: once\n"
311
- end
312
- raise "Failed to generate Client#once" unless res
313
-
314
- res = client_rbs.gsub!(/\# marker: event_lock\n(?:[\s\S]*?\n)?( +)\# endmarker: event_lock\n/) do
315
- indent = Regexp.last_match(1)
316
- "# marker: event_lock\n#{event_lock_sig.gsub(/^/, "#{indent} ")}\n#{indent}# endmarker: event_lock\n"
317
- end
318
- raise "Failed to generate Client#event_lock" unless res
319
-
320
- res = extension_rbs.gsub!(/\# marker: event\n(?:[\s\S]*?\n)?( +)\# endmarker: event\n/) do
321
- indent = Regexp.last_match(1)
322
- "# marker: event\n#{extension_sig.gsub(/^/, "#{indent} ")}\n#{indent}# endmarker: event\n"
323
- end
324
- raise "Failed to generate Extension.event" unless res
325
-
326
- res = extension_rbs.gsub!(/\# marker: once_event\n(?:[\s\S]*?\n)?( +)\# endmarker: once_event\n/) do
327
- indent = Regexp.last_match(1)
328
- "# marker: once_event\n#{extension_sig.gsub(/^/, "#{indent} ")}\n#{indent}# endmarker: once_event\n"
329
- end
330
- raise "Failed to generate Extension.once_event" unless res
331
-
332
- File.write("sig/discorb/client.rbs", client_rbs, mode: "wb")
333
- File.write("sig/discorb/extension.rbs", extension_rbs, mode: "wb")
334
- end
335
-
336
- desc "Generate rbs file using sord"
337
- task :sord do
338
- require "open3"
339
- # rubocop: disable Layout/LineLength
340
- type_errors = {
341
- "SORD_ERROR_SymbolSymbolSymbolInteger" => "{ r: Integer, g: Integer, b: Integer}",
342
- "SORD_ERROR_DiscorbRoleDiscorbMemberDiscorbPermissionOverwrite" => "Hash[Discorb::Role | Discorb::Member, Discorb::PermissionOverwrite]",
343
- "SORD_ERROR_DiscorbRoleDiscorbMemberPermissionOverwrite" => "Hash[Discorb::Role | Discorb::Member, Discorb::PermissionOverwrite]",
344
- "SORD_ERROR_f | SORD_ERROR_F | SORD_ERROR_d | SORD_ERROR_D | SORD_ERROR_t | SORD_ERROR_T | SORD_ERROR_R" => '"f" | "F" | "d" | "D" | "t" | "T" | "R"',
345
- "SORD_ERROR_dark | SORD_ERROR_light" => '"dark" | "light"',
346
- "SORD_ERROR_SymbolStringSymbolboolSymbolObject" => "String | Integer | Float",
347
- }
348
- # rubocop: enable Layout/LineLength
349
- regenerate = ARGV.include?("--regenerate") || ARGV.include?("-r")
350
-
351
- sh "sord gen sig/discorb.rbs --keep-original-comments --no-sord-comments" +
352
- (regenerate ? " --regenerate" : " --no-regenerate")
353
- base = File.read("sig/discorb.rbs")
354
- base.gsub!(/\n +def _set_data: \(.+\) -> untyped\n\n/, "\n")
355
- # base.gsub!(/( )?( *)# @private.+?(?:\n\n(?=\1\2#)|(?=\n\2end))/sm, "")
356
- base.gsub!(/untyped ([a-z_]*id)/, "_ToS \\1")
357
- # #region rbs dictionary
358
- base.gsub!(/ class Dictionary.+?end\n/ms, <<-RBS)
359
- class Dictionary[K, V]
360
- #
361
- # Initialize a new Dictionary.
362
- #
363
- # @param [Hash] hash A hash of items to add to the dictionary.
364
- # @param [Integer] limit The maximum number of items in the dictionary.
365
- # @param [false, Proc] sort Whether to sort the items in the dictionary.
366
- def initialize: (?::Hash[untyped, untyped] hash, ?limit: Integer?, ?sort: (bool | Proc)) -> void
367
-
368
- #
369
- # Registers a new item in the dictionary.
370
- #
371
- # @param [#to_s] id The ID of the item.
372
- # @param [Object] body The item to register.
373
- #
374
- # @return [self] The dictionary.
375
- def register: (_ToS id, Object body) -> self
376
-
377
- #
378
- # Merges another dictionary into this one.
379
- #
380
- # @param [Discorb::Dictionary] other The dictionary to merge.
381
- def merge: (Discorb::Dictionary other) -> untyped
382
-
383
- #
384
- # Removes an item from the dictionary.
385
- #
386
- # @param [#to_s] id The ID of the item to remove.
387
- def remove: (_ToS id) -> untyped
388
-
389
- #
390
- # Get an item from the dictionary.
391
- #
392
- # @param [#to_s] id The ID of the item.
393
- # @return [Object] The item.
394
- # @return [nil] if the item was not found.
395
- #
396
- # @overload get(index)
397
- # @param [Integer] index The index of the item.
398
- #
399
- # @return [Object] The item.
400
- # @return [nil] if the item is not found.
401
- def get: (K id) -> V?
402
-
403
- #
404
- # Returns the values of the dictionary.
405
- #
406
- # @return [Array] The values of the dictionary.
407
- def values: () -> ::Array[V]
408
-
409
- #
410
- # Checks if the dictionary has an ID.
411
- #
412
- # @param [#to_s] id The ID to check.
413
- #
414
- # @return [Boolean] `true` if the dictionary has the ID, `false` otherwise.
415
- def has?: (_ToS id) -> bool
416
-
417
- #
418
- # Send a message to the array of values.
419
- def method_missing: (untyped name) -> untyped
420
-
421
- def respond_to_missing?: (untyped name, untyped args, untyped kwargs) -> bool
422
-
423
- def inspect: () -> String
424
-
425
- # @return [Integer] The maximum number of items in the dictionary.
426
- attr_accessor limit: Integer
427
- end
428
- RBS
429
- # #endregion
430
- type_errors.each do |error, type|
431
- base.gsub!(error, type)
432
- end
433
- base.gsub!("end\n\n\nend", "end\n")
434
- base.gsub!(/ +$/m, "")
435
- File.write("sig/discorb.rbs", base)
436
- end
437
-
438
- desc "Lint rbs with stree"
439
- task :lint do
440
- sh "stree check --plugins=rbs sig/**/*.rbs"
441
- end
442
-
443
- desc "Autofix rbs with stree"
444
- task "lint:fix" do
445
- sh "stree write --plugins=rbs sig/**/*.rbs"
446
- end
447
- end
448
-
449
- task document: %i[document:yard document:replace]
450
-
451
- desc "Lint code with rubocop"
452
- task :lint do
453
- sh "rubocop lib spec Rakefile"
454
- end
455
-
456
- desc "Autofix code with rubocop"
457
- task "lint:fix" do
458
- sh "rubocop lib spec Rakefile -A"
459
- end
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require_relative "lib/discorb/utils/colored_puts"
5
+ task default: %i[]
6
+
7
+ # @private
8
+ def current_version
9
+ require_relative "lib/discorb/common"
10
+ tag = `git tag --points-at HEAD`.force_encoding("utf-8").strip
11
+ tag.empty? ? "main" : Discorb::VERSION
12
+ end
13
+
14
+ desc "Run spec with parallel_rspec"
15
+ task :spec do
16
+ sh "parallel_rspec spec/*.spec.rb spec/**/*.spec.rb"
17
+ end
18
+
19
+ desc "Build emoji_table.rb"
20
+ task :emoji_table do
21
+ require_relative "lib/discorb"
22
+
23
+ iputs "Building emoji_table.rb"
24
+ res = {}
25
+ Discorb::EmojiTable::DISCORD_TO_UNICODE.each do |discord, unicode|
26
+ res[unicode] ||= []
27
+ res[unicode] << discord
28
+ end
29
+
30
+ res_text = +""
31
+ res.each do |unicode, discord|
32
+ res_text << %(#{unicode.unpack("C*").pack("C*").inspect} => %w[#{discord.join(" ")}],\n)
33
+ end
34
+
35
+ table_script = File.read("lib/discorb/emoji_table.rb")
36
+
37
+ table_script.gsub!(
38
+ /(?<=UNICODE_TO_DISCORD = {\n)[\s\S]+(?=}\.freeze)/,
39
+ res_text
40
+ )
41
+
42
+ File.open("lib/discorb/emoji_table.rb", "w") { |f| f.print(table_script) }
43
+ `rufo lib/discorb/emoji_table.rb`
44
+ sputs "Successfully made emoji_table.rb"
45
+ end
46
+
47
+ desc "Format files"
48
+ task :format do
49
+ Dir
50
+ .glob("**/*.rb")
51
+ .each do |file|
52
+ next if file.start_with?("vendor")
53
+
54
+ iputs "Formatting #{file}"
55
+ `rufo ./#{file}`
56
+ content = ""
57
+ File.open(file, "rb") { |f| content = f.read }
58
+ content.gsub!("\r\n", "\n")
59
+ File.open(file, "wb") { |f| f.print(content) }
60
+ end
61
+ end
62
+
63
+ desc "Generate document and replace"
64
+ namespace :document do
65
+ version = current_version
66
+ desc "Just generate document"
67
+ task :yard do
68
+ sh "yard -o doc/#{version} --locale #{ENV.fetch("rake_locale", nil) or "en"}"
69
+ end
70
+
71
+ desc "Replace files"
72
+ namespace :replace do
73
+ require "fileutils"
74
+
75
+ desc "Replace CSS"
76
+ task :css do
77
+ iputs "Replacing css"
78
+ Dir
79
+ .glob("template-replace/files/**/*.*")
80
+ .map { |f| f.delete_prefix("template-replace/files") }
81
+ .each do |file|
82
+ FileUtils.cp(
83
+ "template-replace/files#{file}",
84
+ "doc/#{version}/#{file}"
85
+ )
86
+ end
87
+ sputs "Successfully replaced css"
88
+ end
89
+
90
+ desc "Replace HTML"
91
+ task :html do
92
+ require_relative "template-replace/scripts/sidebar"
93
+ require_relative "template-replace/scripts/version"
94
+ require_relative "template-replace/scripts/index"
95
+ require_relative "template-replace/scripts/yard_replace"
96
+ require_relative "template-replace/scripts/favicon"
97
+ require_relative "template-replace/scripts/arrow"
98
+ iputs "Resetting changes"
99
+ Dir.glob("doc/#{version}/**/*.html") do |f|
100
+ if (m = f.match(/[0-9]+\.[0-9]+\.[0-9]+(-[a-z]+)?/)) && m[0] != version
101
+ next
102
+ end
103
+
104
+ content = File.read(f)
105
+ content.gsub!(/<!--od-->[\s\S]*<!--eod-->/, "")
106
+ File.write(f, content)
107
+ end
108
+ iputs "Adding version tab"
109
+ %w[file_list class_list method_list].each do |f|
110
+ replace_sidebar("doc/#{version}/#{f}.html")
111
+ end
112
+
113
+ iputs "Building version tab"
114
+ build_version_sidebar("doc/#{version}", version)
115
+ iputs "Replacing _index.html"
116
+ replace_index("doc/#{version}", version)
117
+ iputs "Replacing YARD credits"
118
+ yard_replace("doc/#{version}", version)
119
+ iputs "Adding favicon"
120
+ add_favicon("doc/#{version}")
121
+ iputs "Replacing arrow"
122
+ replace_arrow("doc/#{version}")
123
+ iputs "Successfully replaced htmls"
124
+ end
125
+
126
+ desc "Replace EOL"
127
+ task :eol do
128
+ iputs "Replacing CRLF with LF"
129
+ Dir.glob("doc/**/*.*") do |file|
130
+ next unless File.file?(file)
131
+ next unless %w[html css js].include? file.split(".").last
132
+
133
+ content = ""
134
+ File.open(file, "rb") { |f| content = f.read }
135
+ content.gsub!("\r\n", "\n")
136
+ File.open(file, "wb") { |f| f.print(content) }
137
+ end
138
+ sputs "Successfully replaced CRLF with LF"
139
+ end
140
+
141
+ desc "change locale of current document"
142
+ task :locale do
143
+ next if ENV["rake_locale"].nil?
144
+
145
+ require_relative "template-replace/scripts/locale_#{ENV.fetch("rake_locale", nil)}.rb"
146
+ replace_locale("doc/main")
147
+ end
148
+ end
149
+ task replace: %i[replace:css replace:html replace:eol]
150
+
151
+ desc "Build all versions"
152
+ task :build_all do
153
+ require "fileutils"
154
+
155
+ iputs "Building all versions"
156
+ begin
157
+ FileUtils.rm_rf("doc")
158
+ rescue StandardError
159
+ nil
160
+ end
161
+ FileUtils.cp_r("./template-replace/.", "./tmp-template-replace")
162
+ Rake::Task["document:yard"].execute
163
+ Rake::Task["document:replace:html"].execute
164
+ Rake::Task["document:replace:css"].execute
165
+ Rake::Task["document:replace:eol"].execute
166
+ Rake::Task["document:replace:locale"].execute
167
+ tags =
168
+ `git tag`.force_encoding("utf-8")
169
+ .split("\n")
170
+ .sort_by { |t| t[1..].split(".").map(&:to_i) }
171
+ tags.each do |tag|
172
+ sh "git checkout #{tag} -f"
173
+ iputs "Building #{tag}"
174
+ FileUtils.cp_r("./tmp-template-replace/.", "./template-replace")
175
+ version = tag.delete_prefix("v")
176
+ Rake::Task["document:yard"].execute
177
+ Rake::Task["document:replace:html"].execute
178
+ Rake::Task["document:replace:css"].execute
179
+ Rake::Task["document:replace:eol"].execute
180
+ Rake::Task["document:replace:locale"].execute
181
+ FileUtils.cp_r("./doc/.", "./tmp-doc")
182
+ FileUtils.rm_rf("doc")
183
+ end
184
+ sh "git switch main -f"
185
+ FileUtils.cp_r("./tmp-doc/.", "./doc")
186
+ FileUtils.cp_r("./doc/#{tags.last.delete_prefix("v")}/.", "./doc")
187
+ sputs "Successfully built all versions"
188
+ rescue StandardError => e
189
+ sh "git switch main -f"
190
+ raise e
191
+ end
192
+
193
+ desc "Push to discorb-lib/discorb-lib.github.io"
194
+ task :push do
195
+ iputs "Pushing documents"
196
+ Dir.chdir("doc") do
197
+ sh "git init"
198
+ sh "git remote add origin git@github.com:discorb-lib/discorb-lib.github.io"
199
+ sh "git add ."
200
+ sh "git commit -m \"Update: Update document\""
201
+ sh "git push -f"
202
+ end
203
+ sputs "Successfully pushed documents"
204
+ end
205
+
206
+ namespace :locale do
207
+ desc "Generate Japanese document"
208
+ task :ja do
209
+ require "crowdin-api"
210
+ require "zip"
211
+ crowdin =
212
+ Crowdin::Client.new do |config|
213
+ config.api_token = ENV.fetch("CROWDIN_PERSONAL_TOKEN", nil)
214
+ config.project_id = ENV["CROWDIN_PROJECT_ID"].to_i
215
+ end
216
+ build = crowdin.build_project_translation["data"]["id"]
217
+ crowdin.download_project_translations("./tmp.zip", build)
218
+
219
+ Zip::File.open("tmp.zip") do |zip|
220
+ zip.each { |entry| zip.extract(entry, entry.name) { true } }
221
+ end
222
+ ENV["rake_locale"] = "ja"
223
+ Rake::Task["document:yard"].execute
224
+ Rake::Task["document:replace"].execute
225
+ end
226
+
227
+ desc "Generate English document"
228
+ task :en do
229
+ Rake::Task["document"].execute("locale:en")
230
+ end
231
+ end
232
+ end
233
+
234
+ desc "Generate rbs file"
235
+ namespace :rbs do
236
+ desc "Generate event signature"
237
+ task :event do
238
+ require "syntax_tree/rbs"
239
+ client_rbs = File.read("sig/discorb/client.rbs")
240
+ extension_rbs = File.read("sig/discorb/extension.rbs")
241
+ event_document = File.read("./docs/events.md")
242
+ voice_event_document = File.read("./docs/voice_events.md")
243
+ event_reference = event_document.split("## Event reference")[1]
244
+ event_reference += voice_event_document.split("# Voice Events")[1]
245
+ event_reference.gsub!(/^### (.*)$/, "")
246
+ events = []
247
+ event_reference.split("#### `")[1..].each do |event|
248
+ header, content = event.split("`\n", 2)
249
+ name = header.split("(")[0]
250
+ description = content.split("| Parameter", 2)[0].strip
251
+ parameters =
252
+ if content.include?("| Parameter")
253
+ content.scan(/\| `(.*?)` +\| (.*?) +\| (.*?) +\|/)
254
+ else
255
+ []
256
+ end
257
+ events << {
258
+ name: name,
259
+ description: description,
260
+ parameters:
261
+ parameters.map { |p| { name: p[0], type: p[1], description: p[2] } }
262
+ }
263
+ end
264
+ event_sig = +""
265
+ event_lock_sig = +""
266
+ extension_sig = +""
267
+ events.each do |event|
268
+ args = []
269
+ event[:parameters].each do |parameter|
270
+ args << {
271
+ name: parameter[:name],
272
+ type:
273
+ if parameter[:type].start_with?("?")
274
+ parameter[:type][1..]
275
+ else
276
+ parameter[:type]
277
+ end.tr("{}`", "")
278
+ .tr("<>", "[]")
279
+ .gsub(", ", " | ")
280
+ .then do |t|
281
+ if event[:name] == "event_receive"
282
+ case t
283
+ when "Hash"
284
+ next "Discorb::json"
285
+ end
286
+ end
287
+ t
288
+ end
289
+ }
290
+ end
291
+ sig = args.map { |a| "#{a[:type]} #{a[:name]}" }.join(", ")
292
+ tuple_sig = args.map { |a| a[:type] }.join(", ")
293
+ tuple_sig = "[#{tuple_sig}]" if args.length > 1
294
+ tuple_sig = "void" if args.length.zero?
295
+ event_sig << <<~RBS
296
+ | (:#{event[:name]} event_name, ?id: Symbol?, **untyped metadata) { (#{sig}) -> void } -> Discorb::EventHandler
297
+ RBS
298
+ event_lock_sig << <<~RBS
299
+ | (:#{event[:name]} event, ?Integer? timeout) { (#{sig}) -> boolish } -> Async::Task[#{tuple_sig}]
300
+ RBS
301
+ extension_sig << <<~RBS
302
+ | (:#{event[:name]} event_name, ?id: Symbol?, **untyped metadata) { (#{sig}) -> void } -> void
303
+ RBS
304
+ end
305
+ event_sig << <<~RBS
306
+ | (Symbol event_name, ?id: Symbol?, **untyped metadata) { (*untyped) -> void } -> Discorb::EventHandler
307
+ RBS
308
+ event_lock_sig << <<~RBS
309
+ | (Symbol event, ?Integer? timeout) { (*untyped) -> boolish } -> Async::Task[untyped]
310
+ RBS
311
+ extension_sig << <<~RBS
312
+ | (Symbol event_name, ?id: Symbol?, **untyped metadata) { (*untyped) -> void } -> void
313
+ RBS
314
+ event_sig.sub!("| ", " ").rstrip!
315
+ event_lock_sig.sub!("| ", " ").rstrip!
316
+ extension_sig.sub!("| ", " ").rstrip!
317
+ res = client_rbs.gsub!(/(?<=def on:\n)(?:[\s\S]*?)(?=\n\n)/, event_sig)
318
+ raise "Failed to generate Client#on" unless res
319
+
320
+ res = client_rbs.gsub!(/(?<=def once:\n)(?:[\s\S]*?)(?=\n\n)/, event_sig)
321
+ raise "Failed to generate Client#once" unless res
322
+
323
+ res =
324
+ client_rbs.gsub!(
325
+ /(?<=def event_lock:\n)(?:[\s\S]*?)(?=\n\n)/,
326
+ event_lock_sig
327
+ )
328
+ raise "Failed to generate Client#event_lock" unless res
329
+
330
+ res =
331
+ extension_rbs.gsub!(
332
+ /(?<=def event:\n)(?:[\s\S]*?)(?=\n\n)/,
333
+ extension_sig
334
+ )
335
+ raise "Failed to generate Extension.event" unless res
336
+
337
+ res =
338
+ extension_rbs.gsub!(
339
+ /(?<=def once_event:\n)(?:[\s\S]*?)(?=\n\n)/,
340
+ extension_sig
341
+ )
342
+ raise "Failed to generate Extension.once_event" unless res
343
+
344
+ File.write(
345
+ "sig/discorb/client.rbs",
346
+ SyntaxTree::RBS.format(client_rbs),
347
+ mode: "wb"
348
+ )
349
+ File.write(
350
+ "sig/discorb/extension.rbs",
351
+ SyntaxTree::RBS.format(extension_rbs),
352
+ mode: "wb"
353
+ )
354
+ end
355
+
356
+ desc "Generate rbs file using sord"
357
+ task :sord do
358
+ require "open3"
359
+ type_errors = {
360
+ "SORD_ERROR_SymbolSymbolSymbolInteger" =>
361
+ "{ r: Integer, g: Integer, b: Integer}",
362
+ "SORD_ERROR_DiscorbRoleDiscorbMemberDiscorbPermissionOverwrite" =>
363
+ "Hash[Discorb::Role | Discorb::Member, Discorb::PermissionOverwrite]",
364
+ "SORD_ERROR_DiscorbRoleDiscorbMemberPermissionOverwrite" =>
365
+ "Hash[Discorb::Role | Discorb::Member, Discorb::PermissionOverwrite]",
366
+ "SORD_ERROR_f | SORD_ERROR_F | SORD_ERROR_d | SORD_ERROR_D | SORD_ERROR_t | SORD_ERROR_T | SORD_ERROR_R" =>
367
+ '"f" | "F" | "d" | "D" | "t" | "T" | "R"',
368
+ "SORD_ERROR_dark | SORD_ERROR_light" => '"dark" | "light"',
369
+ "SORD_ERROR_SymbolStringSymbolboolSymbolObject" =>
370
+ "String | Integer | Float"
371
+ }
372
+ regenerate = ARGV.include?("--regenerate") || ARGV.include?("-r")
373
+
374
+ sh(
375
+ "sord gen sig/discorb.rbs --keep-original-comments " \
376
+ "--no-sord-comments#{regenerate ? " --regenerate" : " --no-regenerate"}"
377
+ )
378
+ base = File.read("sig/discorb.rbs")
379
+ base.gsub!(/\n +def _set_data: \(.+\) -> untyped\n\n/, "\n")
380
+ # base.gsub!(/( )?( *)# @private.+?(?:\n\n(?=\1\2#)|(?=\n\2end))/sm, "")
381
+ base.gsub!(/untyped ([a-z_]*id)/, "_ToS \\1")
382
+ # #region rbs dictionary
383
+ base.gsub!(/ class Dictionary.+?end\n/ms, <<-RBS)
384
+ class Dictionary[K, V]
385
+ #
386
+ # Initialize a new Dictionary.
387
+ #
388
+ # @param [Hash] hash A hash of items to add to the dictionary.
389
+ # @param [Integer] limit The maximum number of items in the dictionary.
390
+ # @param [false, Proc] sort Whether to sort the items in the dictionary.
391
+ def initialize: (?::Hash[untyped, untyped] hash, ?limit: Integer?, ?sort: (bool | Proc)) -> void
392
+
393
+ #
394
+ # Registers a new item in the dictionary.
395
+ #
396
+ # @param [#to_s] id The ID of the item.
397
+ # @param [Object] body The item to register.
398
+ #
399
+ # @return [self] The dictionary.
400
+ def register: (_ToS id, Object body) -> self
401
+
402
+ #
403
+ # Merges another dictionary into this one.
404
+ #
405
+ # @param [Discorb::Dictionary] other The dictionary to merge.
406
+ def merge: (Discorb::Dictionary other) -> untyped
407
+
408
+ #
409
+ # Removes an item from the dictionary.
410
+ #
411
+ # @param [#to_s] id The ID of the item to remove.
412
+ def remove: (_ToS id) -> untyped
413
+
414
+ #
415
+ # Get an item from the dictionary.
416
+ #
417
+ # @param [#to_s] id The ID of the item.
418
+ # @return [Object] The item.
419
+ # @return [nil] if the item was not found.
420
+ #
421
+ # @overload get(index)
422
+ # @param [Integer] index The index of the item.
423
+ #
424
+ # @return [Object] The item.
425
+ # @return [nil] if the item is not found.
426
+ def get: (K id) -> V?
427
+
428
+ #
429
+ # Returns the values of the dictionary.
430
+ #
431
+ # @return [Array] The values of the dictionary.
432
+ def values: () -> ::Array[V]
433
+
434
+ #
435
+ # Checks if the dictionary has an ID.
436
+ #
437
+ # @param [#to_s] id The ID to check.
438
+ #
439
+ # @return [Boolean] `true` if the dictionary has the ID, `false` otherwise.
440
+ def has?: (_ToS id) -> bool
441
+
442
+ #
443
+ # Send a message to the array of values.
444
+ def method_missing: (untyped name) -> untyped
445
+
446
+ def respond_to_missing?: (untyped name, untyped args, untyped kwargs) -> bool
447
+
448
+ def inspect: () -> String
449
+
450
+ # @return [Integer] The maximum number of items in the dictionary.
451
+ attr_accessor limit: Integer
452
+ end
453
+ RBS
454
+ # #endregion
455
+ type_errors.each { |error, type| base.gsub!(error, type) }
456
+ base.gsub!("end\n\n\nend", "end\n")
457
+ base.gsub!(/ +$/m, "")
458
+ File.write("sig/discorb.rbs", base)
459
+ end
460
+
461
+ desc "Lint rbs with stree"
462
+ task :lint do
463
+ sh "stree check --plugins=rbs sig/**/*.rbs"
464
+ end
465
+
466
+ desc "Autofix rbs with stree"
467
+ task "lint:fix" do
468
+ sh "stree write --plugins=rbs sig/**/*.rbs"
469
+ end
470
+ end
471
+
472
+ task document: %i[document:yard document:replace]
473
+
474
+ desc "Lint code with rubocop"
475
+ task :lint do
476
+ sh "rubocop lib spec Rakefile"
477
+ end
478
+
479
+ desc "Autofix code with rubocop"
480
+ task "lint:fix" do
481
+ sh "rubocop lib spec Rakefile -A"
482
+ end