discorb 0.18.0 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
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