discorb 0.14.0 → 0.16.0

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