discorb 0.14.0 → 0.16.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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build_version.yml +1 -1
  3. data/.github/workflows/lint-push.yml +4 -2
  4. data/.rubocop.yml +6 -2
  5. data/Changelog.md +27 -0
  6. data/Rakefile +6 -0
  7. data/docs/events.md +71 -5
  8. data/docs/faq.md +8 -8
  9. data/examples/simple/rolepanel.rb +1 -1
  10. data/examples/simple/shard.rb +17 -0
  11. data/lib/discorb/allowed_mentions.rb +7 -0
  12. data/lib/discorb/app_command/command.rb +64 -2
  13. data/lib/discorb/app_command/handler.rb +1 -1
  14. data/lib/discorb/application.rb +16 -7
  15. data/lib/discorb/asset.rb +9 -0
  16. data/lib/discorb/{file.rb → attachment.rb} +55 -33
  17. data/lib/discorb/audit_logs.rb +42 -4
  18. data/lib/discorb/channel.rb +47 -12
  19. data/lib/discorb/client.rb +135 -51
  20. data/lib/discorb/common.rb +18 -4
  21. data/lib/discorb/components/button.rb +5 -6
  22. data/lib/discorb/components/select_menu.rb +2 -16
  23. data/lib/discorb/dictionary.rb +2 -0
  24. data/lib/discorb/embed.rb +71 -38
  25. data/lib/discorb/emoji.rb +29 -2
  26. data/lib/discorb/emoji_table.rb +1 -1
  27. data/lib/discorb/error.rb +7 -1
  28. data/lib/discorb/event.rb +27 -17
  29. data/lib/discorb/exe/new.rb +5 -5
  30. data/lib/discorb/exe/run.rb +1 -15
  31. data/lib/discorb/gateway.rb +262 -161
  32. data/lib/discorb/gateway_requests.rb +4 -7
  33. data/lib/discorb/guild.rb +67 -33
  34. data/lib/discorb/guild_template.rb +24 -3
  35. data/lib/discorb/http.rb +25 -3
  36. data/lib/discorb/integration.rb +23 -8
  37. data/lib/discorb/intents.rb +15 -10
  38. data/lib/discorb/interaction/autocomplete.rb +4 -4
  39. data/lib/discorb/interaction/command.rb +34 -5
  40. data/lib/discorb/interaction/components.rb +15 -2
  41. data/lib/discorb/interaction/response.rb +12 -0
  42. data/lib/discorb/interaction/root.rb +16 -1
  43. data/lib/discorb/invite.rb +11 -7
  44. data/lib/discorb/member.rb +21 -0
  45. data/lib/discorb/message.rb +59 -3
  46. data/lib/discorb/message_meta.rb +36 -55
  47. data/lib/discorb/modules.rb +38 -14
  48. data/lib/discorb/permission.rb +14 -5
  49. data/lib/discorb/presence.rb +41 -8
  50. data/lib/discorb/rate_limit.rb +7 -2
  51. data/lib/discorb/reaction.rb +6 -0
  52. data/lib/discorb/role.rb +12 -0
  53. data/lib/discorb/shard.rb +74 -0
  54. data/lib/discorb/sticker.rb +22 -14
  55. data/lib/discorb/user.rb +11 -0
  56. data/lib/discorb/voice_state.rb +20 -2
  57. data/lib/discorb/webhook.rb +53 -2
  58. data/lib/discorb.rb +5 -3
  59. data/sig/discorb.rbs +7234 -6714
  60. metadata +5 -4
  61. data/lib/discorb/log.rb +0 -81
@@ -122,22 +122,8 @@ module Discorb
122
122
  }
123
123
  end
124
124
 
125
- # @private
126
- def hash_emoji(emoji)
127
- case emoji
128
- when UnicodeEmoji
129
- {
130
- id: nil,
131
- name: emoji.to_s,
132
- animated: false,
133
- }
134
- when CustomEmoji
135
- {
136
- id: emoji.id,
137
- name: emoji.name,
138
- animated: emoji.animated?,
139
- }
140
- end
125
+ def inspect
126
+ "#<#{self.class} #{@label}: #{@value}>"
141
127
  end
142
128
 
143
129
  class << self
@@ -55,6 +55,8 @@ module Discorb
55
55
  @cache.delete(id.to_s)
56
56
  end
57
57
 
58
+ alias delete remove
59
+
58
60
  #
59
61
  # Get an item from the dictionary.
60
62
  #
data/lib/discorb/embed.rb CHANGED
@@ -45,37 +45,43 @@ module Discorb
45
45
  # @param [Discorb::Embed::Thumbnail, String] thumbnail The thumbnail of embed.
46
46
  #
47
47
  def initialize(title = nil, description = nil, color: nil, url: nil, timestamp: nil, author: nil,
48
- fields: nil, footer: nil, image: nil, thumbnail: nil, data: nil)
49
- if data.nil?
50
- @title = title
51
- @description = description
52
- @url = url
53
- @timestamp = timestamp
54
- @color = color
55
- @author = author
56
- @fields = fields || []
57
- @footer = footer
58
- @image = image && (image.is_a?(String) ? Image.new(image) : image)
59
- @thumbnail = thumbnail && (thumbnail.is_a?(String) ? Thumbnail.new(thumbnail) : thumbnail)
60
- @type = "rich"
61
- else
62
- @title = data[:title]
63
- @description = data[:description]
64
- @url = data[:url]
65
- @timestamp = data[:timestamp] && Time.iso8601(data[:timestamp])
66
- @type = data[:type]
67
- @color = data[:color] && Color.new(data[:color])
68
- @footer = data[:footer] && Footer.new(data[:footer][:text], icon: data[:footer][:icon_url])
69
- @author = if data[:author]
70
- Author.new(data[:author][:name], icon: data[:author][:icon_url],
71
- url: data[:author][:url])
72
- end
73
- @thumbnail = data[:thumbnail] && Thumbnail.new(data[:thumbnail])
74
- @image = data[:image] && Image.new(data[:image])
75
- @video = data[:video] && Video.new(data[:video])
76
- @provider = data[:provider] && Provider.new(data[:provider])
77
- @fields = data[:fields] ? data[:fields].map { |f| Field.new(f[:name], f[:value], inline: f[:inline]) } : []
78
- end
48
+ fields: nil, footer: nil, image: nil, thumbnail: nil)
49
+ @title = title
50
+ @description = description
51
+ @url = url
52
+ @timestamp = timestamp
53
+ @color = color
54
+ @author = author
55
+ @fields = fields || []
56
+ @footer = footer
57
+ @image = image && (image.is_a?(String) ? Image.new(image) : image)
58
+ @thumbnail = thumbnail && (thumbnail.is_a?(String) ? Thumbnail.new(thumbnail) : thumbnail)
59
+ @type = "rich"
60
+ end
61
+
62
+ #
63
+ # Initialize embed from hash.
64
+ # @private
65
+ #
66
+ # @param [Hash] data The hash data to initialize embed.
67
+ #
68
+ def initialize_hash(data)
69
+ @title = data[:title]
70
+ @description = data[:description]
71
+ @url = data[:url]
72
+ @timestamp = data[:timestamp] && Time.iso8601(data[:timestamp])
73
+ @type = data[:type]
74
+ @color = data[:color] && Color.new(data[:color])
75
+ @footer = data[:footer] && Footer.new(data[:footer][:text], icon: data[:footer][:icon_url])
76
+ @author = if data[:author]
77
+ Author.new(data[:author][:name], icon: data[:author][:icon_url],
78
+ url: data[:author][:url])
79
+ end
80
+ @thumbnail = data[:thumbnail] && Thumbnail.new(data[:thumbnail])
81
+ @image = data[:image] && Image.new(data[:image])
82
+ @video = data[:video] && Video.new(data[:video])
83
+ @provider = data[:provider] && Provider.new(data[:provider])
84
+ @fields = data[:fields] ? data[:fields].map { |f| Field.new(f[:name], f[:value], inline: f[:inline]) } : []
79
85
  end
80
86
 
81
87
  def image=(value)
@@ -111,10 +117,27 @@ module Discorb
111
117
  ret
112
118
  end
113
119
 
120
+ def self.from_hash(data)
121
+ inst = allocate
122
+ inst.initialize_hash(data)
123
+ inst
124
+ end
125
+
126
+ #
127
+ # Represents an entry in embed.
128
+ # @abstract
129
+ # @private
130
+ #
131
+ class Entry
132
+ def inspect
133
+ "#<#{self.class}>"
134
+ end
135
+ end
136
+
114
137
  #
115
138
  # Represents an author of embed.
116
139
  #
117
- class Author
140
+ class Author < Entry
118
141
  # @return [String] The name of author.
119
142
  attr_accessor :name
120
143
  # @return [String, nil] The url of author.
@@ -153,7 +176,7 @@ module Discorb
153
176
  #
154
177
  # Represemts a footer of embed.
155
178
  #
156
- class Footer
179
+ class Footer < Entry
157
180
  attr_accessor :text, :icon
158
181
 
159
182
  #
@@ -184,7 +207,7 @@ module Discorb
184
207
  #
185
208
  # Represents a field of embed.
186
209
  #
187
- class Field
210
+ class Field < Entry
188
211
  # @return [String] The name of field.
189
212
  attr_accessor :name
190
213
  # @return [String] The value of field.
@@ -223,7 +246,7 @@ module Discorb
223
246
  #
224
247
  # Represents an image of embed.
225
248
  #
226
- class Image
249
+ class Image < Entry
227
250
  # @return [String] The url of image.
228
251
  attr_accessor :url
229
252
  # @return [String] The proxy url of image.
@@ -267,7 +290,7 @@ module Discorb
267
290
  #
268
291
  # Represents a thumbnail of embed.
269
292
  #
270
- class Thumbnail
293
+ class Thumbnail < Entry
271
294
  # @return [String] The url of thumbnail.
272
295
  attr_accessor :url
273
296
  # @return [String] The proxy url of thumbnail.
@@ -311,7 +334,7 @@ module Discorb
311
334
  #
312
335
  # Represents a video of embed.
313
336
  #
314
- class Video
337
+ class Video < Entry
315
338
  # @return [String] The url of video.
316
339
  attr_reader :url
317
340
  # @return [String] The proxy url of video.
@@ -321,7 +344,12 @@ module Discorb
321
344
  # @return [Integer] The width of video.
322
345
  attr_reader :width
323
346
 
347
+ #
348
+ # Initialize a new Video object.
324
349
  # @private
350
+ #
351
+ # @param [Hash] data The data of video.
352
+ #
325
353
  def initialize(data)
326
354
  @url = data[:url]
327
355
  @proxy_url = data[:proxy_url]
@@ -333,13 +361,18 @@ module Discorb
333
361
  #
334
362
  # Represents a provider of embed.
335
363
  #
336
- class Provider
364
+ class Provider < Entry
337
365
  # @return [String] The name of provider.
338
366
  attr_reader :name
339
367
  # @return [String] The url of provider.
340
368
  attr_reader :url
341
369
 
370
+ #
371
+ # Initialize a new Provider object.
342
372
  # @private
373
+ #
374
+ # @param [Hash] data The data of provider.
375
+ #
343
376
  def initialize(data)
344
377
  @name = data[:name]
345
378
  @url = data[:url]
data/lib/discorb/emoji.rb CHANGED
@@ -44,7 +44,14 @@ module Discorb
44
44
  # @!attribute [r] roles?
45
45
  # @return [Boolean] whether or not this emoji is restricted to certain roles.
46
46
 
47
+ #
48
+ # Initialize a new custom emoji.
47
49
  # @private
50
+ #
51
+ # @param [Discorb::Client] client The client that owns this emoji.
52
+ # @param [Discorb::Guild] guild The guild that owns this emoji.
53
+ # @param [Hash] data The data of the emoji.
54
+ #
48
55
  def initialize(client, guild, data)
49
56
  @client = client
50
57
  @guild = guild
@@ -121,7 +128,12 @@ module Discorb
121
128
 
122
129
  alias destroy! delete!
123
130
 
131
+ #
132
+ # Converts the object to a hash.
124
133
  # @private
134
+ #
135
+ # @return [Hash] The hash represents the object.
136
+ #
125
137
  def to_hash
126
138
  {
127
139
  name: @name,
@@ -135,7 +147,7 @@ module Discorb
135
147
  def _set_data(data)
136
148
  @id = Snowflake.new(data[:id])
137
149
  @name = data[:name]
138
- @roles = data[:role] ? data[:role].map { |r| Role.new(@client, r) } : []
150
+ @roles = data[:role] ? data[:role].map { |r| Role.new(@client, guild, r) } : []
139
151
  @user = User.new(@client, data[:user]) if data[:user]
140
152
  @require_colons = data[:require_colons]
141
153
  @managed = data[:managed]
@@ -158,7 +170,12 @@ module Discorb
158
170
  attr_reader :deleted
159
171
  alias deleted? deleted
160
172
 
173
+ #
174
+ # Initialize a new partial custom emoji.
161
175
  # @private
176
+ #
177
+ # @param [Hash] data The data of the emoji.
178
+ #
162
179
  def initialize(data)
163
180
  @id = Snowflake.new(data[:id])
164
181
  @name = data[:name]
@@ -200,7 +217,12 @@ module Discorb
200
217
  # @return [Integer] The skin tone of the emoji.
201
218
  attr_reader :skin_tone
202
219
 
203
- # @private
220
+ #
221
+ # Initialize a new unicode emoji.
222
+ #
223
+ # @param [String] name The name of the emoji.
224
+ # @param [Integer] tone The skin tone of the emoji.
225
+ #
204
226
  def initialize(name, tone: 0)
205
227
  if EmojiTable::DISCORD_TO_UNICODE.key?(name)
206
228
  @name = name
@@ -232,7 +254,12 @@ module Discorb
232
254
  "#<#{self.class} :#{@name}:>"
233
255
  end
234
256
 
257
+ #
258
+ # Converts the object to a hash.
235
259
  # @private
260
+ #
261
+ # @return [Hash] The hash represents the object.
262
+ #
236
263
  def to_hash
237
264
  {
238
265
  name: @value,
@@ -3885,7 +3885,7 @@ module Discorb
3885
3885
  "\xf0\x9f\x8f\xbc",
3886
3886
  "\xf0\x9f\x8f\xbd",
3887
3887
  "\xf0\x9f\x8f\xbe",
3888
- "\xf0\x9f\x8f\xbf"
3888
+ "\xf0\x9f\x8f\xbf",
3889
3889
  ].freeze
3890
3890
  end
3891
3891
  end
data/lib/discorb/error.rb CHANGED
@@ -42,7 +42,10 @@ module Discorb
42
42
  # @return [Net::HTTPResponse] the HTTP response.
43
43
  attr_reader :response
44
44
 
45
+ #
46
+ # Initialize a new instance of the HTTPError class.
45
47
  # @private
48
+ #
46
49
  def initialize(resp, data)
47
50
  @code = data[:code]
48
51
  @response = resp
@@ -54,7 +57,10 @@ module Discorb
54
57
  # Represents a 400 error.
55
58
  #
56
59
  class BadRequestError < HTTPError
60
+ #
61
+ # Initialize a new instance of the BadRequestError class.
57
62
  # @private
63
+ #
58
64
  def initialize(resp, data)
59
65
  @code = data[:code]
60
66
  @response = resp
@@ -62,7 +68,7 @@ module Discorb
62
68
  [
63
69
  data[:message] + " (#{@code})", enumerate_errors(data[:errors])
64
70
  .map { |ek, ev| "#{ek}=>#{ev}" }
65
- .join("\n")
71
+ .join("\n"),
66
72
  ].join("\n")
67
73
  )
68
74
  end
data/lib/discorb/event.rb CHANGED
@@ -4,20 +4,26 @@ module Discorb
4
4
  # Represents an event in guild.
5
5
  #
6
6
  class ScheduledEvent < DiscordModel
7
- @privacy_level = {
7
+ # @private
8
+ # @return [{Integer => Symbol}] The mapping of privacy level.
9
+ PRIVACY_LEVEL = {
8
10
  2 => :guild_only,
9
- }
10
- @status = {
11
+ }.freeze
12
+ # @private
13
+ # @return [{Integer => Symbol}] The mapping of status.
14
+ STATUS = {
11
15
  1 => :scheduled,
12
16
  2 => :active,
13
17
  3 => :completed,
14
18
  4 => :canceled,
15
- }
16
- @entity_type = {
19
+ }.freeze
20
+ # @private
21
+ # @return [{Integer => Symbol}] The mapping of entity_type.
22
+ ENTITY_TYPE = {
17
23
  1 => :stage_instance,
18
24
  2 => :voice,
19
25
  3 => :external,
20
- }
26
+ }.freeze
21
27
 
22
28
  # @!visibility private
23
29
  def initialize(client, data)
@@ -36,6 +42,10 @@ module Discorb
36
42
  def initialize(data)
37
43
  @location = data[:location]
38
44
  end
45
+
46
+ def inspect
47
+ "#<#{self.class.name} #{@name}>"
48
+ end
39
49
  end
40
50
 
41
51
  # @return [Discorb::Snowflake] The ID of the event.
@@ -132,10 +142,10 @@ module Discorb
132
142
  description: description,
133
143
  scheduled_start_time: start_time.iso8601,
134
144
  scheduled_end_time: end_time&.iso8601,
135
- privacy_level: Discorb::ScheduledEvent.privacy_level.key(privacy_level) || Discorb::Unset,
145
+ privacy_level: Discorb::ScheduledEvent::PRIVACY_LEVEL.key(privacy_level) || Discorb::Unset,
136
146
  channel_id: channel&.id,
137
- entity_type: Discorb::ScheduledEvent.entity_type.key(:stage_instance),
138
- status: Discorb::ScheduledEvent.status.key(status) || Discorb::Unset,
147
+ entity_type: Discorb::ScheduledEvent::ENTITY_TYPE.key(:stage_instance),
148
+ status: Discorb::ScheduledEvent::STATUS.key(status) || Discorb::Unset,
139
149
  }.reject { |_, v| v == Discorb::Unset }
140
150
  when :voice
141
151
  raise ArgumentError, "channel must be provided for voice events" unless channel
@@ -144,10 +154,10 @@ module Discorb
144
154
  description: description,
145
155
  scheduled_start_time: start_time.iso8601,
146
156
  scheduled_end_time: end_time&.iso8601,
147
- privacy_level: Discorb::ScheduledEvent.privacy_level.key(privacy_level) || Discorb::Unset,
157
+ privacy_level: Discorb::ScheduledEvent::PRIVACY_LEVEL.key(privacy_level) || Discorb::Unset,
148
158
  channel_id: channel&.id,
149
- entity_type: Discorb::ScheduledEvent.entity_type.key(:voice),
150
- status: Discorb::ScheduledEvent.status.key(status) || Discorb::Unset,
159
+ entity_type: Discorb::ScheduledEvent::ENTITY_TYPE.key(:voice),
160
+ status: Discorb::ScheduledEvent::STATUS.key(status) || Discorb::Unset,
151
161
  }.reject { |_, v| v == Discorb::Unset }
152
162
  when :external
153
163
  raise ArgumentError, "location must be provided for external events" unless location
@@ -158,12 +168,12 @@ module Discorb
158
168
  channel_id: nil,
159
169
  scheduled_start_time: start_time.iso8601,
160
170
  scheduled_end_time: end_time.iso8601,
161
- privacy_level: Discorb::ScheduledEvent.privacy_level.key(privacy_level) || Discorb::Unset,
162
- entity_type: Discorb::ScheduledEvent.entity_type.key(:external),
171
+ privacy_level: Discorb::ScheduledEvent::PRIVACY_LEVEL.key(privacy_level) || Discorb::Unset,
172
+ entity_type: Discorb::ScheduledEvent::ENTITY_TYPE.key(:external),
163
173
  entity_metadata: {
164
174
  location: location,
165
175
  },
166
- status: Discorb::ScheduledEvent.status.key(status) || Discorb::Unset,
176
+ status: Discorb::ScheduledEvent::STATUS.key(status) || Discorb::Unset,
167
177
  }.reject { |_, v| v == Discorb::Unset }
168
178
  else
169
179
  raise ArgumentError, "Invalid scheduled event type: #{type}"
@@ -264,8 +274,8 @@ module Discorb
264
274
  @scheduled_start_time = Time.iso8601(data[:scheduled_start_time])
265
275
  @scheduled_end_time = data[:scheduled_end_time] && Time.iso8601(data[:scheduled_end_time])
266
276
  @privacy_level = :guild_only # data[:privacy_level]
267
- @status = self.class.status[data[:status]]
268
- @entity_type = self.class.entity_type[data[:entity_type]]
277
+ @status = STATUS[data[:status]]
278
+ @entity_type = ENTITY_TYPE[data[:entity_type]]
269
279
  @entity_id = data[:entity_id] && Snowflake.new(data[:entity_id])
270
280
  @entity_metadata = data[:entity_metadata] && Metadata.new(data[:entity_metadata])
271
281
  @creator = @client.users[@creator_id] || (data[:creator] && User.new(@client, data[:creator]))
@@ -164,8 +164,8 @@ def git_init
164
164
  system "git add ."
165
165
  system "git commit -m \"Initial commit\""
166
166
  sputs "Initialized repository, use " \
167
- "\e[32mgit commit --amend -m '...'\e[92m" \
168
- " to change commit message of initial commit.\n"
167
+ "\e[32mgit commit --amend -m '...'\e[92m" \
168
+ " to change commit message of initial commit.\n"
169
169
  end
170
170
 
171
171
  # @private
@@ -228,9 +228,9 @@ if (dir = ARGV[0])
228
228
  iputs "Found \e[30m#{dir}\e[90m and empty, using this directory."
229
229
  elsif $values[:force]
230
230
  iputs "Found \e[30m#{dir}\e[90m and not empty, but force is on, using this directory."
231
- else
232
- eputs "Directory \e[31m#{dir}\e[91m already exists and not empty. Use \e[31m-f\e[91m to force."
233
- exit
231
+ else
232
+ eputs "Directory \e[31m#{dir}\e[91m already exists and not empty. Use \e[31m-f\e[91m to force."
233
+ exit
234
234
  end
235
235
  else
236
236
  Dir.mkdir($path)
@@ -4,10 +4,9 @@ require "optparse"
4
4
  require "json"
5
5
  require "discorb/utils/colored_puts"
6
6
  require "io/console"
7
+ require "discorb"
7
8
 
8
9
  ARGV.delete_at 0
9
- # @private
10
- LOG_LEVELS = %w[none debug info warn error fatal].freeze
11
10
 
12
11
  opt = OptionParser.new <<~BANNER
13
12
  This command will run a client.
@@ -18,23 +17,10 @@ opt = OptionParser.new <<~BANNER
18
17
  BANNER
19
18
  options = {
20
19
  title: nil,
21
- log_level: nil,
22
- log_file: nil,
23
- log_color: nil,
24
20
  setup: nil,
25
21
  token: false,
26
22
  bundler: :default,
27
23
  }
28
- opt.on("-l", "--log-level LEVEL", "Log level.") do |v|
29
- unless LOG_LEVELS.include? v.downcase
30
- eputs "Invalid log level: \e[31m#{v}\e[91m"
31
- eputs "Valid log levels: \e[31m#{LOG_LEVELS.join("\e[91m, \e[31m")}\e[91m"
32
- exit 1
33
- end
34
- options[:log_level] = v.downcase
35
- end
36
- opt.on("-f", "--log-file FILE", "File to write log to.") { |v| options[:log_file] = v }
37
- opt.on("-c", "--[no-]log-color", "Whether to colorize log output.") { |v| options[:log_color] = v }
38
24
  opt.on("-s", "--setup", "Whether to setup application commands.") { |v| options[:setup] = v }
39
25
  opt.on("-e", "--env [ENV]", "The name of the environment variable to use for token, or just `-e` or `--env` for intractive prompt.") { |v| options[:token] = v }
40
26
  opt.on("-t", "--title TITLE", "The title of process.") { |v| options[:title] = v }