discorb 0.0.8 → 0.2.3

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.
data/lib/discorb/http.rb CHANGED
@@ -227,7 +227,7 @@ module Discorb
227
227
  end
228
228
 
229
229
  def get_headers(headers, body = "", audit_log_reason = nil)
230
- ret = if body.nil? || body.empty?
230
+ ret = if body.nil? || body == ""
231
231
  { "User-Agent" => USER_AGENT, "authorization" => "Bot #{@client.token}" }
232
232
  else
233
233
  { "User-Agent" => USER_AGENT, "authorization" => "Bot #{@client.token}",
@@ -75,11 +75,15 @@ module Discorb
75
75
 
76
76
  # @!visibility private
77
77
  def make_interaction(client, data)
78
+ interaction = nil
78
79
  descendants.each do |klass|
79
- return klass.make_interaction(client, data) if !klass.interaction_type.nil? && klass.interaction_type == data[:type]
80
+ interaction = klass.make_interaction(client, data) if !klass.interaction_type.nil? && klass.interaction_type == data[:type]
80
81
  end
81
- client.log.warn("Unknown interaction type #{data[:type]}, initialized Interaction")
82
- Interaction.new(client, data)
82
+ if interaction.nil?
83
+ client.log.warn("Unknown interaction type #{data[:type]}, initialized Interaction")
84
+ interaction = Interaction.new(client, data)
85
+ end
86
+ interaction
83
87
  end
84
88
 
85
89
  # @!visibility private
@@ -95,14 +99,14 @@ module Discorb
95
99
  #
96
100
  # Response with `DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE`(`5`).
97
101
  #
98
- # @param [Boolean] hide Whether to hide the response (ephemeral).
102
+ # @param [Boolean] ephemeral Whether to make the response ephemeral.
99
103
  #
100
- def defer_source(hide: false)
104
+ def defer_source(ephemeral: false)
101
105
  Async do
102
106
  @client.http.post("/interactions/#{@id}/#{@token}/callback", {
103
107
  type: 5,
104
108
  data: {
105
- flags: (hide ? 1 << 6 : 0),
109
+ flags: (ephemeral ? 1 << 6 : 0),
106
110
  },
107
111
  }).wait
108
112
  @defered = true
@@ -118,9 +122,9 @@ module Discorb
118
122
  # @param [Array<Discorb::Embed>] embeds The embeds to send. (max: 10)
119
123
  # @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions to send.
120
124
  # @param [Array<Discorb::Components>, Array<Array<Discorb::Components>>] components The components to send.
121
- # @param [Boolean] hide Whether to hide the response (ephemeral).
125
+ # @param [Boolean] ephemeral Whether to make the response ephemeral.
122
126
  #
123
- def post(content, tts: false, embed: nil, embeds: nil, allowed_mentions: nil, components: nil, hide: false)
127
+ def post(content = nil, tts: false, embed: nil, embeds: nil, allowed_mentions: nil, components: nil, ephemeral: false)
124
128
  payload = {}
125
129
  payload[:content] = content if content
126
130
  payload[:tts] = tts
@@ -151,7 +155,7 @@ module Discorb
151
155
  tmp_components << tmp_row
152
156
  payload[:components] = tmp_components.filter { |c| c.length.positive? }.map { |c| { type: 1, components: c.map(&:to_hash) } }
153
157
  end
154
- payload[:flags] = (hide ? 1 << 6 : 0)
158
+ payload[:flags] = (ephemeral ? 1 << 6 : 0)
155
159
  if @responded
156
160
  @client.http.post("/webhooks/#{@id}/#{@token}", { type: 4, data: payload }).wait
157
161
  elsif @defered
@@ -170,14 +174,14 @@ module Discorb
170
174
  #
171
175
  # Response with `DEFERRED_UPDATE_MESSAGE`(`6`).
172
176
  #
173
- # @param [Boolean] hide Whether to hide the response (ephemeral).
177
+ # @param [Boolean] ephemeral Whether to make the response ephemeral.
174
178
  #
175
- def defer_update(hide: false)
179
+ def defer_update(ephemeral: false)
176
180
  Async do
177
181
  @client.http.post("/interactions/#{@id}/#{@token}/callback", {
178
182
  type: 7,
179
183
  data: {
180
- flags: (hide ? 1 << 6 : 0),
184
+ flags: (ephemeral ? 1 << 6 : 0),
181
185
  },
182
186
  }).wait
183
187
  end
@@ -192,9 +196,9 @@ module Discorb
192
196
  # @param [Array<Discorb::Embed>] embeds The embeds to send. (max: 10)
193
197
  # @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions to send.
194
198
  # @param [Array<Discorb::Components>, Array<Array<Discorb::Components>>] components The components to send.
195
- # @param [Boolean] hide Whether to hide the response (ephemeral).
199
+ # @param [Boolean] ephemeral Whether to make the response ephemeral.
196
200
  #
197
- def edit(content, tts: false, embed: nil, embeds: nil, allowed_mentions: nil, components: nil, hide: false)
201
+ def edit(content, tts: false, embed: nil, embeds: nil, allowed_mentions: nil, components: nil, ephemeral: false)
198
202
  payload = {}
199
203
  payload[:content] = content if content
200
204
  payload[:tts] = tts
@@ -225,7 +229,7 @@ module Discorb
225
229
  tmp_components << tmp_row
226
230
  payload[:components] = tmp_components.filter { |c| c.length.positive? }.map { |c| { type: 1, components: c.map(&:to_hash) } }
227
231
  end
228
- payload[:flags] = (hide ? 1 << 6 : 0)
232
+ payload[:flags] = (ephemeral ? 1 << 6 : 0)
229
233
  @client.http.post("/interactions/#{@id}/#{@token}/callback", { type: 6, data: payload }).wait
230
234
  end
231
235
  end
@@ -238,15 +242,123 @@ module Discorb
238
242
  end
239
243
 
240
244
  #
241
- # Represents a slash command interaction.
245
+ # Represents a command interaction.
242
246
  # @todo Implement this.
243
247
  #
244
- class SlashCommandInteraction < Interaction
248
+ class CommandInteraction < Interaction
245
249
  @interaction_type = 2
246
- @interaction_name = :slash_command
250
+ @interaction_name = :application_command
251
+ include Interaction::SourceResponse
252
+
253
+ #
254
+ # Represents a slash command interaction.
255
+ #
256
+ class SlashCommand < CommandInteraction
257
+ @command_type = 1
258
+
259
+ def _set_data(data)
260
+ super
261
+ Sync do
262
+ name = data[:name]
263
+ options = nil
264
+ if (option = data[:options]&.first)
265
+ case option[:type]
266
+ when 1
267
+ name += " #{option[:name]}"
268
+ options = option[:options]
269
+ when 2
270
+ name += " #{option[:name]}"
271
+ if (option_sub = option[:options]&.first)
272
+ if option_sub[:type] == 1
273
+ name += " #{option_sub[:name]}"
274
+ options = option_sub[:options]
275
+ else
276
+ options = option[:options]
277
+ end
278
+ end
279
+ else
280
+ options = data[:options]
281
+ end
282
+ end
283
+ options ||= []
284
+ options.map! do |option|
285
+ case option[:type]
286
+ when 3, 4, 5, 10
287
+ option[:value]
288
+ when 6
289
+ guild.members[option[:value]] || guild.fetch_member(option[:value]).wait
290
+ when 7
291
+ guild.channels[option[:value]] || guild.fetch_channels.wait.find { |channel| channel.id == option[:value] }
292
+ when 8
293
+ guild.roles[option[:value]] || guild.fetch_roles.wait.find { |role| role.id == option[:value] }
294
+ when 9
295
+ guild.members[option[:value]] || guild.roles[option[:value]] || guild.fetch_member(option[:value]).wait || guild.fetch_roles.wait.find { |role| role.id == option[:value] }
296
+ end
297
+ end
298
+
299
+ unless (command = @client.commands.find { |c| c.to_s == name })
300
+ @client.log.warn "Unknown command name #{name}, ignoreing"
301
+ next
302
+ end
303
+
304
+ command.block.call(self, *options)
305
+ end
306
+ end
307
+ end
308
+
309
+ #
310
+ # Represents a user context menu interaction.
311
+ #
312
+ class UserMenuCommand < CommandInteraction
313
+ @command_type = 2
314
+
315
+ # @return [Discorb::Member, Discorb::User] The target user.
316
+ attr_reader :target
317
+
318
+ def _set_data(data)
319
+ @target = guild.members[data[:target_id]] || Discorb::Member.new(@client, @guild_id, data[:resolved][:users][data[:target_id].to_sym], data[:resolved][:members][data[:target_id].to_sym])
320
+ @client.commands.find { |c| c.name == data[:name] && c.type_raw == 2 }.block.call(self, @target)
321
+ end
322
+ end
323
+
324
+ #
325
+ # Represents a message context menu interaction.
326
+ #
327
+ class MessageMenuCommand < CommandInteraction
328
+ @command_type = 3
329
+
330
+ # @return [Discorb::Message] The target message.
331
+ attr_reader :target
332
+
333
+ def _set_data(data)
334
+ @target = Message.new(@client, data[:resolved][:messages][data[:target_id].to_sym].merge({ guild_id: @guild_id.to_s }))
335
+ @client.commands.find { |c| c.name == data[:name] && c.type_raw == 3 }.block.call(self, @target)
336
+ end
337
+ end
338
+
339
+ private
247
340
 
248
341
  def _set_data(data)
249
- p data
342
+ @name = data[:name]
343
+ end
344
+
345
+ class << self
346
+ # @!visibility private
347
+ attr_reader :command_type
348
+
349
+ # @!visibility private
350
+ def make_interaction(client, data)
351
+ nested_classes.each do |klass|
352
+ return klass.new(client, data) if !klass.command_type.nil? && klass.command_type == data[:data][:type]
353
+ end
354
+ client.log.warn("Unknown command type #{data[:type]}, initialized CommandInteraction")
355
+ CommandInteraction.new(client, data)
356
+ end
357
+
358
+ # @!visibility private
359
+ def nested_classes
360
+ constants.select { |c| const_get(c).is_a? Class }.map { |c| const_get(c) }
361
+ end
250
362
  end
251
363
  end
252
364
 
data/lib/discorb/log.rb CHANGED
@@ -61,7 +61,7 @@ module Discorb
61
61
  return unless @out
62
62
 
63
63
  if @colorize_log
64
- @out.puts("[#{Time.now.iso8601}] #{color}#{name}\e[m -- #{message}")
64
+ @out.puts("\e[2;90m[#{Time.now.iso8601}] #{color}#{name}\e[m -- #{message}")
65
65
  else
66
66
  @out.puts("[#{Time.now.iso8601}] #{name} -- #{message}")
67
67
  end
@@ -78,6 +78,15 @@ module Discorb
78
78
  "@#{name}"
79
79
  end
80
80
 
81
+ #
82
+ # Format the member to `Username#Discriminator` style.
83
+ #
84
+ # @return [String] The formatted member.
85
+ #
86
+ def to_s_user
87
+ "#{username}##{discriminator}"
88
+ end
89
+
81
90
  def name
82
91
  @nick || @username
83
92
  end
@@ -223,8 +232,8 @@ module Discorb
223
232
  @hoisted_role_id = member_data[:hoisted_role]
224
233
  @deaf = member_data[:deaf]
225
234
  @custom_avatar = member_data[:avatar] && Asset.new(member_data[:avatar])
226
- @display_avatar = Asset.new(self, member_data[:avatar] || user_data[:avatar])
227
235
  super(user_data)
236
+ @display_avatar = @avatar || @custom_avatar
228
237
  @client.guilds[@guild_id].members[@id] = self unless @guild_id.nil?
229
238
  @_member_data.update(member_data)
230
239
  end
@@ -213,6 +213,33 @@ module Discorb
213
213
  !@updated_at.nil?
214
214
  end
215
215
 
216
+ #
217
+ # Edit the message.
218
+ #
219
+ # @param [String] content The message content.
220
+ # @param [Discorb::Embed] embed The embed to send.
221
+ # @param [Array<Discord::Embed>] embeds The embeds to send.
222
+ # @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions.
223
+ # @param [Array<Discorb::Component>, Array<Array<Discorb::Component>>] components The components to send.
224
+ # @param [Boolean] supress Whether to supress embeds.
225
+ #
226
+ def edit(...)
227
+ Async do
228
+ channel.edit_message(@id, ...).wait
229
+ end
230
+ end
231
+
232
+ #
233
+ # Delete the message.
234
+ #
235
+ # @param [String] reason The reason for deleting the message.
236
+ #
237
+ def delete!(reason: nil)
238
+ Async do
239
+ channel.delete_message!(@id, reason: reason).wait
240
+ end
241
+ end
242
+
216
243
  #
217
244
  # Convert the message to reference object.
218
245
  #
@@ -7,6 +7,8 @@ module Discorb
7
7
  module Messageable
8
8
  #
9
9
  # Post a message to the channel.
10
+ # @macro async
11
+ # @macro http
10
12
  #
11
13
  # @param [String] content The message content.
12
14
  # @param [Boolean] tts Whether the message is tts.
@@ -61,13 +63,82 @@ module Discorb
61
63
  else
62
64
  headers = {}
63
65
  end
64
- _resp, data = @client.http.post("#{base_url.wait}/messages", payload, headers: headers).wait
66
+ _resp, data = @client.http.post("/channels/#{channel_id.wait}/messages", payload, headers: headers).wait
65
67
  Message.new(@client, data.merge({ guild_id: @guild_id.to_s }))
66
68
  end
67
69
  end
68
70
 
71
+ #
72
+ # Edit a message.
73
+ # @macro async
74
+ # @macro http
75
+ #
76
+ # @param [#to_s] message_id The message id.
77
+ # @param [String] content The message content.
78
+ # @param [Discorb::Embed] embed The embed to send.
79
+ # @param [Array<Discord::Embed>] embeds The embeds to send.
80
+ # @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions.
81
+ # @param [Array<Discorb::Component>, Array<Array<Discorb::Component>>] components The components to send.
82
+ # @param [Boolean] supress Whether to supress embeds.
83
+ #
84
+ def edit_message(message_id, content = nil, embed: nil, embeds: nil, allowed_mentions: nil,
85
+ components: nil, supress: nil)
86
+ Async do
87
+ payload = {}
88
+ payload[:content] = content if content
89
+ tmp_embed = if embed
90
+ [embed]
91
+ elsif embeds
92
+ embeds
93
+ end
94
+ payload[:embeds] = tmp_embed.map(&:to_hash) if tmp_embed
95
+ payload[:allowed_mentions] =
96
+ allowed_mentions ? allowed_mentions.to_hash(@client.allowed_mentions) : @client.allowed_mentions.to_hash
97
+ if components
98
+ tmp_components = []
99
+ tmp_row = []
100
+ components.each do |c|
101
+ case c
102
+ when Array
103
+ tmp_components << tmp_row
104
+ tmp_row = []
105
+ tmp_components << c
106
+ when SelectMenu
107
+ tmp_components << tmp_row
108
+ tmp_row = []
109
+ tmp_components << [c]
110
+ else
111
+ tmp_row << c
112
+ end
113
+ end
114
+ tmp_components << tmp_row
115
+ payload[:flags] = (supress ? 1 << 2 : 0) unless flags.nil?
116
+ payload[:components] = tmp_components.filter { |c| c.length.positive? }.map { |c| { type: 1, components: c.map(&:to_hash) } }
117
+ end
118
+ @client.http.patch("/channels/#{channel_id.wait}/messages/#{message_id}", payload).wait
119
+ end
120
+ end
121
+
122
+ #
123
+ # Delete a message.
124
+ # @macro async
125
+ # @macro http
126
+ #
127
+ # @param [#to_s] message_id The message id.
128
+ # @param [String] reason The reason for deleting the message.
129
+ #
130
+ def delete_message!(message_id, reason: nil)
131
+ Async do
132
+ @client.http.delete("/channels/#{channel_id.wait}/messages/#{message_id}", reason: reason).wait
133
+ end
134
+ end
135
+
136
+ alias destroy_message! delete_message!
137
+
69
138
  #
70
139
  # Fetch a message from ID.
140
+ # @macro async
141
+ # @macro http
71
142
  #
72
143
  # @param [Discorb::Snowflake] id The ID of the message.
73
144
  #
@@ -76,13 +147,15 @@ module Discorb
76
147
  #
77
148
  def fetch_message(id)
78
149
  Async do
79
- _resp, data = @client.http.get("#{base_url.wait}/messages/#{id}").wait
150
+ _resp, data = @client.http.get("/channels/#{channel_id.wait}/messages/#{id}").wait
80
151
  Message.new(@client, data.merge({ guild_id: @guild_id.to_s }))
81
152
  end
82
153
  end
83
154
 
84
155
  #
85
156
  # Fetch a message history.
157
+ # @macro async
158
+ # @macro http
86
159
  #
87
160
  # @param [Integer] limit The number of messages to fetch.
88
161
  # @param [Discorb::Snowflake] before The ID of the message to fetch before.
@@ -99,7 +172,7 @@ module Discorb
99
172
  after: Discorb::Utils.try(around, :id),
100
173
  around: Discorb::Utils.try(before, :id),
101
174
  }.filter { |_k, v| !v.nil? }.to_h
102
- _resp, messages = @client.http.get("#{base_url.wait}/messages?#{URI.encode_www_form(params)}").wait
175
+ _resp, messages = @client.http.get("/channels/#{channel_id.wait}/messages?#{URI.encode_www_form(params)}").wait
103
176
  messages.map { |m| Message.new(@client, m.merge({ guild_id: @guild_id.to_s })) }
104
177
  end
105
178
  end
data/lib/discorb/user.rb CHANGED
@@ -21,6 +21,8 @@ module Discorb
21
21
  # @return [Boolean] Whether the user is a bot.
22
22
  attr_reader :bot
23
23
  alias bot? bot
24
+ # @return [Time] The time the user was created.
25
+ attr_reader :created_at
24
26
 
25
27
  include Discorb::Messageable
26
28
 
@@ -41,6 +43,8 @@ module Discorb
41
43
  "#{@username}##{@discriminator}"
42
44
  end
43
45
 
46
+ alias to_s_user to_s
47
+
44
48
  def inspect
45
49
  "#<#{self.class} #{self}>"
46
50
  end
@@ -70,13 +74,13 @@ module Discorb
70
74
  alias app_owner? bot_owner?
71
75
 
72
76
  # @!visibility private
73
- def base_url
77
+ def channel_id
74
78
  Async do
75
79
  next @dm_channel_id if @dm_channel_id
76
80
 
77
81
  dm_channel = @client.http.post("/users/#{@id}/channels", { recipient_id: @client.user.id }).wait
78
82
  @dm_channel_id = dm_channel[:id]
79
- "/channels/#{@dm_channel_id}"
83
+ @dm_channel_id
80
84
  end
81
85
  end
82
86
 
@@ -123,10 +127,11 @@ module Discorb
123
127
  @id = Snowflake.new(data[:id])
124
128
  @flag = User::Flag.new(data[:public_flags] | (data[:flags] || 0))
125
129
  @discriminator = data[:discriminator]
126
- @avatar = Asset.new(self, data[:avatar])
130
+ @avatar = data[:avatar] ? Asset.new(self, data[:avatar]) : DefaultAvatar.new(data[:discriminator])
127
131
  @bot = data[:bot]
128
132
  @raw_data = data
129
133
  @client.users[@id] = self if !data[:no_cache] && data.is_a?(User)
134
+ @created_at = @id.timestamp
130
135
  @data.update(data)
131
136
  end
132
137
  end