discorb 0.12.3 → 0.13.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build_main.yml +1 -0
  3. data/.github/workflows/build_version.yml +4 -3
  4. data/.github/workflows/crowdin.yml +32 -0
  5. data/.gitignore +3 -1
  6. data/.yardopts +2 -0
  7. data/Changelog.md +407 -372
  8. data/Gemfile +5 -1
  9. data/README.md +1 -1
  10. data/Rakefile +131 -1
  11. data/crowdin.yml +2 -0
  12. data/discorb.gemspec +1 -1
  13. data/docs/Examples.md +2 -0
  14. data/docs/application_command.md +17 -12
  15. data/docs/cli/irb.md +2 -0
  16. data/docs/cli/new.md +2 -0
  17. data/docs/cli/run.md +3 -1
  18. data/docs/cli/setup.md +4 -2
  19. data/docs/cli.md +2 -0
  20. data/docs/events.md +59 -5
  21. data/docs/extension.md +2 -2
  22. data/docs/faq.md +4 -2
  23. data/docs/license.md +2 -0
  24. data/docs/tutorial.md +4 -3
  25. data/docs/voice_events.md +2 -0
  26. data/lib/discorb/app_command.rb +13 -7
  27. data/lib/discorb/application.rb +32 -2
  28. data/lib/discorb/audit_logs.rb +28 -16
  29. data/lib/discorb/channel.rb +140 -81
  30. data/lib/discorb/client.rb +17 -19
  31. data/lib/discorb/common.rb +28 -1
  32. data/lib/discorb/components.rb +12 -0
  33. data/lib/discorb/dictionary.rb +1 -1
  34. data/lib/discorb/embed.rb +4 -0
  35. data/lib/discorb/emoji.rb +9 -7
  36. data/lib/discorb/emoji_table.rb +3774 -3689
  37. data/lib/discorb/event.rb +266 -24
  38. data/lib/discorb/event_handler.rb +39 -0
  39. data/lib/discorb/exe/show.rb +2 -0
  40. data/lib/discorb/extension.rb +5 -5
  41. data/lib/discorb/file.rb +4 -0
  42. data/lib/discorb/flag.rb +5 -1
  43. data/lib/discorb/gateway.rb +67 -15
  44. data/lib/discorb/gateway_requests.rb +4 -0
  45. data/lib/discorb/guild.rb +169 -82
  46. data/lib/discorb/guild_template.rb +12 -9
  47. data/lib/discorb/http.rb +82 -37
  48. data/lib/discorb/image.rb +7 -5
  49. data/lib/discorb/integration.rb +3 -0
  50. data/lib/discorb/intents.rb +8 -3
  51. data/lib/discorb/interaction/response.rb +27 -25
  52. data/lib/discorb/interaction/root.rb +8 -0
  53. data/lib/discorb/invite.rb +3 -2
  54. data/lib/discorb/log.rb +4 -0
  55. data/lib/discorb/member.rb +42 -13
  56. data/lib/discorb/message.rb +32 -17
  57. data/lib/discorb/modules.rb +19 -26
  58. data/lib/discorb/permission.rb +4 -0
  59. data/lib/discorb/rate_limit.rb +6 -2
  60. data/lib/discorb/role.rb +15 -11
  61. data/lib/discorb/sticker.rb +17 -12
  62. data/lib/discorb/user.rb +8 -7
  63. data/lib/discorb/voice_state.rb +8 -5
  64. data/lib/discorb/webhook.rb +38 -47
  65. data/lib/discorb.rb +2 -2
  66. data/po/yard.pot +7775 -5157
  67. data/sig/discorb.rbs +3317 -3820
  68. data/template-replace/scripts/locale_ja.rb +62 -0
  69. data/template-replace/scripts/yard_replace.rb +6 -0
  70. metadata +7 -4
data/lib/discorb/http.rb CHANGED
@@ -18,14 +18,14 @@ module Discorb
18
18
 
19
19
  #
20
20
  # Execute a GET request.
21
- # @macro async
21
+ # @async
22
22
  #
23
23
  # @param [String] path The path to the resource.
24
24
  # @param [Hash] headers The headers to send with the request.
25
25
  # @param [String] audit_log_reason The audit log reason to send with the request.
26
26
  # @param [Hash] kwargs The keyword arguments.
27
27
  #
28
- # @return [Array(Net::HTTPResponse, Hash)] The response and as JSON.
28
+ # @return [Async::Task<Array(Net::HTTPResponse, Hash)>] The response and as JSON.
29
29
  # @return [Async::Task<Array(Net::HTTPResponse, nil)>] The response was 204.
30
30
  #
31
31
  # @raise [Discorb::HTTPError] The request was failed.
@@ -42,7 +42,7 @@ module Discorb
42
42
 
43
43
  #
44
44
  # Execute a POST request.
45
- # @macro async
45
+ # @async
46
46
  #
47
47
  # @param [String] path The path to the resource.
48
48
  # @param [String, Hash] body The body of the request.
@@ -50,7 +50,7 @@ module Discorb
50
50
  # @param [String] audit_log_reason The audit log reason to send with the request.
51
51
  # @param [Hash] kwargs The keyword arguments.
52
52
  #
53
- # @return [Array(Net::HTTPResponse, Hash)] The response and as JSON.
53
+ # @return [Async::Task<Array(Net::HTTPResponse, Hash)>] The response and as JSON.
54
54
  # @return [Async::Task<Array(Net::HTTPResponse, nil)>] The response was 204.
55
55
  #
56
56
  # @raise [Discorb::HTTPError] The request was failed.
@@ -65,9 +65,46 @@ module Discorb
65
65
  end
66
66
  end
67
67
 
68
+ #
69
+ # Execute a multipart POST request.
70
+ # @async
71
+ #
72
+ # @param [String] path The path to the resource.
73
+ # @param [String, Hash] body The body of the request.
74
+ # @param [Array<Discorb::File>] files The files to upload.
75
+ # @param [Hash] headers The headers to send with the request.
76
+ # @param [String] audit_log_reason The audit log reason to send with the request.
77
+ # @param [Hash] kwargs The keyword arguments.
78
+ #
79
+ # @return [Async::Task<Array(Net::HTTPResponse, Hash)>] The response and as JSON.
80
+ # @return [Async::Task<Array(Net::HTTPResponse, nil)>] The response was 204.
81
+ #
82
+ # @raise [Discorb::HTTPError] The request was failed.
83
+ #
84
+ def multipart_post(path, body = "", files, headers: nil, audit_log_reason: nil, **kwargs)
85
+ Async do |task|
86
+ @ratelimit_handler.wait("POST", path)
87
+ req = Net::HTTP::Post.new(get_path(path), get_headers(headers, body, audit_log_reason), **kwargs)
88
+ data = [
89
+ ["payload_json", get_body(body)],
90
+ ]
91
+ files&.each_with_index do |file, i|
92
+ next if file.nil?
93
+ data << ["files[#{i}]", file.io, { filename: file.filename, content_type: file.content_type }]
94
+ end
95
+ req.set_form(data, "multipart/form-data")
96
+ session = Net::HTTP.new("discord.com", 443)
97
+ session.use_ssl = true
98
+ resp = session.request(req)
99
+ data = get_response_data(resp)
100
+ @ratelimit_handler.save("POST", path, resp)
101
+ handle_response(:post, resp, data, path, body, headers, audit_log_reason, kwargs)
102
+ end
103
+ end
104
+
68
105
  #
69
106
  # Execute a PATCH request.
70
- # @macro async
107
+ # @async
71
108
  #
72
109
  # @param [String] path The path to the resource.
73
110
  # @param [String, Hash] body The body of the request.
@@ -75,7 +112,7 @@ module Discorb
75
112
  # @param [String] audit_log_reason The audit log reason to send with the request.
76
113
  # @param [Hash] kwargs The keyword arguments.
77
114
  #
78
- # @return [Array(Net::HTTPResponse, Hash)] The response and as JSON.
115
+ # @return [Async::Task<Array(Net::HTTPResponse, Hash)>] The response and as JSON.
79
116
  # @return [Async::Task<Array(Net::HTTPResponse, nil)>] The response was 204.
80
117
  #
81
118
  # @raise [Discorb::HTTPError] The request was failed.
@@ -90,9 +127,44 @@ module Discorb
90
127
  end
91
128
  end
92
129
 
130
+ #
131
+ # Execute a PATCH request.
132
+ # @async
133
+ #
134
+ # @param [String] path The path to the resource.
135
+ # @param [String, Hash] body The body of the request.
136
+ # @param [Hash] headers The headers to send with the request.
137
+ # @param [String] audit_log_reason The audit log reason to send with the request.
138
+ # @param [Hash] kwargs The keyword arguments.
139
+ #
140
+ # @return [Async::Task<Array(Net::HTTPResponse, Hash)>] The response and as JSON.
141
+ # @return [Async::Task<Array(Net::HTTPResponse, nil)>] The response was 204.
142
+ #
143
+ # @raise [Discorb::HTTPError] The request was failed.
144
+ #
145
+ def multipart_patch(path, body = "", headers: nil, audit_log_reason: nil, **kwargs)
146
+ Async do |task|
147
+ @ratelimit_handler.wait("PATCH", path)
148
+ req = Net::HTTP::Patch.new(get_path(path), get_headers(headers, body, audit_log_reason), **kwargs)
149
+ data = [
150
+ ["payload_json", get_body(body)],
151
+ ]
152
+ files&.each_with_index do |file, i|
153
+ data << ["files[#{i}]", file.io, { filename: file.filename, content_type: file.content_type }]
154
+ end
155
+ req.set_form(data, "multipart/form-data")
156
+ session = Net::HTTP.new("discord.com", 443)
157
+ session.use_ssl = true
158
+ resp = session.request(req)
159
+ data = get_response_data(resp)
160
+ @ratelimit_handler.save("PATCH", path, resp)
161
+ handle_response(:patch, resp, data, path, body, headers, audit_log_reason, kwargs)
162
+ end
163
+ end
164
+
93
165
  #
94
166
  # Execute a PUT request.
95
- # @macro async
167
+ # @async
96
168
  #
97
169
  # @param [String] path The path to the resource.
98
170
  # @param [String, Hash] body The body of the request.
@@ -100,7 +172,7 @@ module Discorb
100
172
  # @param [String] audit_log_reason The audit log reason to send with the request.
101
173
  # @param [Hash] kwargs The keyword arguments.
102
174
  #
103
- # @return [Array(Net::HTTPResponse, Hash)] The response and as JSON.
175
+ # @return [Async::Task<Array(Net::HTTPResponse, Hash)>] The response and as JSON.
104
176
  # @return [Async::Task<Array(Net::HTTPResponse, nil)>] The response was 204.
105
177
  #
106
178
  # @raise [Discorb::HTTPError] The request was failed.
@@ -117,14 +189,14 @@ module Discorb
117
189
 
118
190
  #
119
191
  # Execute a DELETE request.
120
- # @macro async
192
+ # @async
121
193
  #
122
194
  # @param [String] path The path to the resource.
123
195
  # @param [Hash] headers The headers to send with the request.
124
196
  # @param [String] audit_log_reason The audit log reason to send with the request.
125
197
  # @param [Hash] kwargs The keyword arguments.
126
198
  #
127
- # @return [Array(Net::HTTPResponse, Hash)] The response and as JSON.
199
+ # @return [Async::Task<Array(Net::HTTPResponse, Hash)>] The response and as JSON.
128
200
  # @return [Async::Task<Array(Net::HTTPResponse, nil)>] The response was 204.
129
201
  #
130
202
  # @raise [Discorb::HTTPError] The request was failed.
@@ -143,33 +215,6 @@ module Discorb
143
215
  "#<#{self.class} client=#{@client}>"
144
216
  end
145
217
 
146
- #
147
- # A helper method to send multipart/form-data requests.
148
- #
149
- # @param [Hash] payload The payload to send.
150
- # @param [Array<Discorb::File>] files The files to send.
151
- #
152
- # @return [Array(String, String)] The boundary and body.
153
- #
154
- def self.multipart(payload, files)
155
- boundary = "DiscorbBySevenC7CMultipartFormData#{Time.now.to_f}"
156
- str_payloads = [<<~HTTP]
157
- Content-Disposition: form-data; name="payload_json"
158
- Content-Type: application/json
159
-
160
- #{payload.to_json}
161
- HTTP
162
- files.each do |single_file|
163
- str_payloads << <<~HTTP
164
- Content-Disposition: form-data; name="file"; filename="#{single_file.filename}"
165
- Content-Type: #{single_file.content_type}
166
-
167
- #{single_file.io.read}
168
- HTTP
169
- end
170
- [boundary, "--#{boundary}\n#{str_payloads.join("\n--#{boundary}\n")}\n--#{boundary}--"]
171
- end
172
-
173
218
  private
174
219
 
175
220
  def handle_response(method, resp, data, path, body, headers, audit_log_reason, kwargs)
data/lib/discorb/image.rb CHANGED
@@ -16,12 +16,10 @@ module Discorb
16
16
  #
17
17
  def initialize(source, type = nil)
18
18
  if source.respond_to?(:read)
19
- @bytes = source.read
19
+ @io = source
20
20
  @type = type || MIME::Types.type_for(source.path).first.content_type
21
21
  elsif ::File.exist?(source)
22
- ::File.open(source, "rb") do |file|
23
- @bytes = file.read
24
- end
22
+ @io = ::File.open(source, "rb")
25
23
  @type = MIME::Types.type_for(source).first.to_s
26
24
  else
27
25
  raise ArgumentError, "Couldn't read file."
@@ -34,7 +32,11 @@ module Discorb
34
32
  # @return [String] The image as a Discord style.
35
33
  #
36
34
  def to_s
37
- "data:#{@type};base64,#{Base64.strict_encode64(@bytes)}"
35
+ "data:#{@type};base64,#{Base64.strict_encode64(@io.read)}"
36
+ end
37
+
38
+ def inspect
39
+ "#<#{self.class} #{@type}>"
38
40
  end
39
41
  end
40
42
  end
@@ -58,9 +58,12 @@ module Discorb
58
58
 
59
59
  #
60
60
  # Delete the integration.
61
+ # @async
61
62
  #
62
63
  # @param [String] reason The reason for deleting the integration.
63
64
  #
65
+ # @return [Async::Task<void>] The task.
66
+ #
64
67
  def delete!(reason: nil)
65
68
  Async do
66
69
  @client.http.delete("/guilds/#{@guild}/integrations/#{@id}", audit_log_reason: reason).wait
@@ -19,6 +19,7 @@ module Discorb
19
19
  dm_messages: 1 << 12,
20
20
  dm_reactions: 1 << 13,
21
21
  dm_typing: 1 << 14,
22
+ scheduled_events: 1 << 16,
22
23
  }.freeze
23
24
 
24
25
  #
@@ -38,6 +39,7 @@ module Discorb
38
39
  # @param dm_messages [Boolean] Whether dm messages related events are enabled.
39
40
  # @param dm_reactions [Boolean] Whether dm reactions related events are enabled.
40
41
  # @param dm_typing [Boolean] Whether dm typing related events are enabled.
42
+ # @param scheduled_events [Boolean] Whether events related scheduled events are enabled.
41
43
  #
42
44
  # @note You must enable privileged intents to use `members` and/or `presences` intents.
43
45
  #
@@ -55,7 +57,8 @@ module Discorb
55
57
  typing: true,
56
58
  dm_messages: true,
57
59
  dm_reactions: true,
58
- dm_typing: true)
60
+ dm_typing: true,
61
+ scheduled_events: true)
59
62
  @raw_value = {
60
63
  guilds: guilds,
61
64
  members: members,
@@ -72,6 +75,7 @@ module Discorb
72
75
  dm_messages: dm_messages,
73
76
  dm_reactions: dm_reactions,
74
77
  dm_typing: dm_typing,
78
+ scheduled_events: scheduled_events,
75
79
  }
76
80
  end
77
81
 
@@ -124,13 +128,14 @@ module Discorb
124
128
  end
125
129
 
126
130
  # Create new intent object with default values.
131
+ # This will return intents without members and presence.
127
132
  def default
128
- from_value(32509)
133
+ from_value(@intent_bits.values.reduce(:+) - @intent_bits[:members] - @intent_bits[:presences])
129
134
  end
130
135
 
131
136
  # Create new intent object with all intents.
132
137
  def all
133
- from_value(32767)
138
+ from_value(@intent_bits.values.reduce(:+))
134
139
  end
135
140
 
136
141
  # Create new intent object with no intents.
@@ -7,11 +7,12 @@ module Discorb
7
7
  #
8
8
  # Response with `DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE`(`5`).
9
9
  #
10
- # @macro async
11
- # @macro http
10
+ # @async
12
11
  #
13
12
  # @param [Boolean] ephemeral Whether to make the response ephemeral.
14
13
  #
14
+ # @return [Async::Task<void>] The task.
15
+ #
15
16
  def defer_source(ephemeral: false)
16
17
  Async do
17
18
  @client.http.post("/interactions/#{@id}/#{@token}/callback", {
@@ -27,8 +28,7 @@ module Discorb
27
28
  #
28
29
  # Response with `CHANNEL_MESSAGE_WITH_SOURCE`(`4`).
29
30
  #
30
- # @macro async
31
- # @macro http
31
+ # @async
32
32
  #
33
33
  # @param [String] content The content of the response.
34
34
  # @param [Boolean] tts Whether to send the message as text-to-speech.
@@ -77,8 +77,7 @@ module Discorb
77
77
 
78
78
  #
79
79
  # Edits the callback message.
80
- # @macro async
81
- # @macro http
80
+ # @async
82
81
  # @macro edit
83
82
  #
84
83
  # @param [String] content The new content of the message.
@@ -88,27 +87,23 @@ module Discorb
88
87
  # @param [Discorb::File] file The file to send.
89
88
  # @param [Array<Discorb::File>] files The files to send.
90
89
  #
90
+ # @return [Async::Task<void>] The task.
91
+ #
91
92
  def edit(
92
- content = :unset,
93
- embed: :unset, embeds: :unset,
94
- file: :unset, files: :unset,
95
- attachments: :unset
93
+ content = Discorb::Unset,
94
+ embed: Discorb::Unset, embeds: Discorb::Unset,
95
+ file: Discorb::Unset, files: Discorb::Unset,
96
+ attachments: Discorb::Unset
96
97
  )
97
98
  Async do
98
99
  payload = {}
99
- payload[:content] = content if content != :unset
100
- payload[:embeds] = embed ? [embed.to_hash] : [] if embed != :unset
101
- payload[:embeds] = embeds.map(&:to_hash) if embeds != :unset
102
- payload[:attachments] = attachments.map(&:to_hash) if attachments != :unset
103
- files = [file] if file != :unset
104
- if files == :unset
105
- headers = {
106
- "Content-Type" => "application/json",
107
- }
108
- else
109
- headers, payload = HTTP.multipart(payload, files)
110
- end
111
- @client.http.patch("/webhooks/#{@application_id}/#{@token}/messages/@original", payload, headers: headers).wait
100
+ payload[:content] = content if content != Discorb::Unset
101
+ payload[:embeds] = embed ? [embed.to_hash] : [] if embed != Discorb::Unset
102
+ payload[:embeds] = embeds.map(&:to_hash) if embeds != Discorb::Unset
103
+ payload[:attachments] = attachments.map(&:to_hash) if attachments != Discorb::Unset
104
+ files = [file] if file != Discorb::Unset
105
+ files = [] if files == Discorb::Unset
106
+ @client.http.multipart_patch("/webhooks/#{@application_id}/#{@token}/messages/@original", payload, files, headers: headers).wait
112
107
  end
113
108
  end
114
109
 
@@ -116,8 +111,11 @@ module Discorb
116
111
 
117
112
  #
118
113
  # Deletes the callback message.
114
+ # @async
119
115
  # @note This will fail if the message is ephemeral.
120
116
  #
117
+ # @return [Async::Task<void>] The task.
118
+ #
121
119
  def delete!
122
120
  Async do
123
121
  @client.http.delete("/webhooks/#{@application_id}/#{@token}/messages/@original").wait
@@ -132,9 +130,12 @@ module Discorb
132
130
  module UpdateResponse
133
131
  #
134
132
  # Response with `DEFERRED_UPDATE_MESSAGE`(`6`).
133
+ # @async
135
134
  #
136
135
  # @param [Boolean] ephemeral Whether to make the response ephemeral.
137
136
  #
137
+ # @return [Async::Task<void>] The task.
138
+ #
138
139
  def defer_update(ephemeral: false)
139
140
  Async do
140
141
  @client.http.post("/interactions/#{@id}/#{@token}/callback", {
@@ -149,8 +150,7 @@ module Discorb
149
150
  #
150
151
  # Response with `UPDATE_MESSAGE`(`7`).
151
152
  #
152
- # @macro async
153
- # @macro http
153
+ # @async
154
154
  #
155
155
  # @param [String] content The content of the response.
156
156
  # @param [Boolean] tts Whether to send the message as text-to-speech.
@@ -160,6 +160,8 @@ module Discorb
160
160
  # @param [Array<Discorb::Component>, Array<Array<Discorb::Component>>] components The components to send.
161
161
  # @param [Boolean] ephemeral Whether to make the response ephemeral.
162
162
  #
163
+ # @return [Async::Task<void>] The task.
164
+ #
163
165
  def edit(content, tts: false, embed: nil, embeds: nil, allowed_mentions: nil, components: nil, ephemeral: false)
164
166
  Async do
165
167
  payload = {}
@@ -18,6 +18,12 @@ module Discorb
18
18
  attr_reader :version
19
19
  # @return [String] The token for the interaction.
20
20
  attr_reader :token
21
+ # @return [Symbol] The locale of the user that created the interaction.
22
+ # @note This modifies the language code, `-` will be replaced with `_`.
23
+ attr_reader :locale
24
+ # @return [Symbol] The locale of the guild that created the interaction.
25
+ # @note This modifies the language code, `-` will be replaced with `_`.
26
+ attr_reader :guild_locale
21
27
 
22
28
  # @!attribute [r] guild
23
29
  # @macro client_cache
@@ -43,6 +49,8 @@ module Discorb
43
49
  @member = guild.members[data[:member][:id]] || Member.new(@client, @guild_id, data[:member][:user], data[:member]) if data[:member]
44
50
  @user = @client.users[data[:user][:id]] || User.new(@client, data[:user]) if data[:user]
45
51
  @token = data[:token]
52
+ @locale = data[:locale].to_s.gsub("-", "_").to_sym
53
+ @guild_locale = data[:guild_locale].to_s.gsub("-", "_").to_sym
46
54
  @version = data[:version]
47
55
  @defered = false
48
56
  @responded = false
@@ -100,8 +100,9 @@ module Discorb
100
100
  end
101
101
 
102
102
  # Delete the invite.
103
- # @macro async
104
- # @macro http
103
+ # @async
104
+ # @return [Async::Task<void>] The task.
105
+ #
105
106
  def delete!(reason: nil)
106
107
  Async do
107
108
  @client.http.delete("/invites/#{@code}", audit_log_reason: reason)
data/lib/discorb/log.rb CHANGED
@@ -13,6 +13,10 @@ module Discorb
13
13
  @colorize_log = colorize_log
14
14
  end
15
15
 
16
+ def inspect
17
+ "#<#{self.class} level=#{level}>"
18
+ end
19
+
16
20
  def level
17
21
  self.class.levels[@level]
18
22
  end
@@ -143,12 +143,13 @@ module Discorb
143
143
 
144
144
  #
145
145
  # Add a role to the member.
146
- # @macro http
147
- # @macro async
146
+ # @async
148
147
  #
149
148
  # @param [Discorb::Role] role The role to add.
150
149
  # @param [String] reason The reason for the action.
151
150
  #
151
+ # @return [Async::Task<void>] The task.
152
+ #
152
153
  def add_role(role, reason: nil)
153
154
  Async do
154
155
  @client.http.put("/guilds/#{@guild_id}/members/#{@id}/roles/#{role.is_a?(Role) ? role.id : role}", nil, audit_log_reason: reason).wait
@@ -157,12 +158,13 @@ module Discorb
157
158
 
158
159
  #
159
160
  # Remove a role to the member.
160
- # @macro http
161
- # @macro async
161
+ # @async
162
162
  #
163
163
  # @param [Discorb::Role] role The role to add.
164
164
  # @param [String] reason The reason for the action.
165
165
  #
166
+ # @return [Async::Task<void>] The task.
167
+ #
166
168
  def remove_role(role, reason: nil)
167
169
  Async do
168
170
  @client.http.delete("/guilds/#{@guild_id}/members/#{@id}/roles/#{role.is_a?(Role) ? role.id : role}", audit_log_reason: reason).wait
@@ -171,8 +173,7 @@ module Discorb
171
173
 
172
174
  #
173
175
  # Edit the member.
174
- # @macro http
175
- # @macro async
176
+ # @async
176
177
  # @macro edit
177
178
  #
178
179
  # @param [String] nick The nickname of the member.
@@ -180,27 +181,54 @@ module Discorb
180
181
  # @param [Boolean] mute Whether the member is muted.
181
182
  # @param [Boolean] deaf Whether the member is deafened.
182
183
  # @param [Discorb::StageChannel] channel The channel the member is moved to.
184
+ # @param [Time, nil] communication_disabled_until The time the member is timed out. Set to `nil` to end the timeout.
185
+ # @param [Time, nil] timeout_until Alias of `communication_disabled_until`.
183
186
  # @param [String] reason The reason for the action.
184
187
  #
185
- def edit(nick: :unset, role: :unset, mute: :unset, deaf: :unset, channel: :unset, reason: nil)
188
+ # @return [Async::Task<void>] The task.
189
+ #
190
+ def edit(
191
+ nick: Discorb::Unset, role: Discorb::Unset, mute: Discorb::Unset, deaf: Discorb::Unset, channel: Discorb::Unset, communication_disabled_until: Discorb::Unset, timeout_until: Discorb::Unset,
192
+ reason: nil
193
+ )
186
194
  Async do
187
195
  payload = {}
188
- payload[:nick] = nick if nick != :unset
189
- payload[:roles] = role if role != :unset
190
- payload[:mute] = mute if mute != :unset
191
- payload[:deaf] = deaf if deaf != :unset
192
- payload[:channel_id] = channel&.id if channel != :unset
196
+ payload[:nick] = nick if nick != Discorb::Unset
197
+ payload[:roles] = role if role != Discorb::Unset
198
+ payload[:mute] = mute if mute != Discorb::Unset
199
+ payload[:deaf] = deaf if deaf != Discorb::Unset
200
+ communication_disabled_until = timeout_until if timeout_until != Discorb::Unset
201
+ payload[:communication_disabled_until] = communication_disabled_until&.iso8601 if communication_disabled_until != Discorb::Unset
202
+ payload[:channel_id] = channel&.id if channel != Discorb::Unset
193
203
  @client.http.patch("/guilds/#{@guild_id}/members/#{@id}", payload, audit_log_reason: reason).wait
194
204
  end
195
205
  end
196
206
 
197
207
  alias modify edit
198
208
 
209
+ #
210
+ # Timeout the member.
211
+ # @async
212
+ #
213
+ # @param [Time] time The time until the member is timeout.
214
+ # @param [String] reason The reason for the action.
215
+ #
216
+ # @return [Async::Task<void>] The task.
217
+ #
218
+ def timeout(time, reason: nil)
219
+ edit(communication_disabled_until: time, reason: reason)
220
+ end
221
+
222
+ alias disable_communication timeout
223
+
199
224
  #
200
225
  # Kick the member.
226
+ # @async
201
227
  #
202
228
  # @param [String] reason The reason for the action.
203
229
  #
230
+ # @return [Async::Task<void>] The task.
231
+ #
204
232
  def kick(reason: nil)
205
233
  Async do
206
234
  guild.kick_member(self, reason: reason).wait
@@ -209,6 +237,7 @@ module Discorb
209
237
 
210
238
  #
211
239
  # Ban the member.
240
+ # @async
212
241
  #
213
242
  # @param [Integer] delete_message_days The number of days to delete messages.
214
243
  # @param [String] reason The reason for the action.
@@ -233,7 +262,7 @@ module Discorb
233
262
  @joined_at = member_data[:joined_at] && Time.iso8601(member_data[:joined_at])
234
263
  @hoisted_role_id = member_data[:hoisted_role]
235
264
  @deaf = member_data[:deaf]
236
- @custom_avatar = member_data[:avatar] && Asset.new(member_data[:avatar])
265
+ @custom_avatar = member_data[:avatar] && Asset.new(self, member_data[:avatar])
237
266
  super(user_data)
238
267
  @display_avatar = @avatar || @custom_avatar
239
268
  @client.guilds[@guild_id].members[@id] = self unless @guild_id.nil? || @client.guilds[@guild_id].nil?