discorb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +56 -0
  3. data/.yardopts +6 -0
  4. data/Changelog.md +5 -0
  5. data/Gemfile +23 -0
  6. data/Gemfile.lock +70 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +53 -0
  9. data/Rakefile +46 -0
  10. data/bin/console +15 -0
  11. data/bin/setup +8 -0
  12. data/discorb.gemspec +37 -0
  13. data/docs/Examples.md +26 -0
  14. data/docs/events.md +480 -0
  15. data/docs/voice_events.md +283 -0
  16. data/examples/components/authorization_button.rb +43 -0
  17. data/examples/components/select_menu.rb +61 -0
  18. data/examples/extension/main.rb +12 -0
  19. data/examples/extension/message_expander.rb +41 -0
  20. data/examples/simple/eval.rb +32 -0
  21. data/examples/simple/ping_pong.rb +16 -0
  22. data/examples/simple/rolepanel.rb +65 -0
  23. data/examples/simple/wait_for_message.rb +30 -0
  24. data/lib/discorb/application.rb +157 -0
  25. data/lib/discorb/asset.rb +57 -0
  26. data/lib/discorb/audit_logs.rb +323 -0
  27. data/lib/discorb/channel.rb +1101 -0
  28. data/lib/discorb/client.rb +363 -0
  29. data/lib/discorb/color.rb +173 -0
  30. data/lib/discorb/common.rb +123 -0
  31. data/lib/discorb/components.rb +290 -0
  32. data/lib/discorb/dictionary.rb +119 -0
  33. data/lib/discorb/embed.rb +345 -0
  34. data/lib/discorb/emoji.rb +218 -0
  35. data/lib/discorb/emoji_table.rb +3799 -0
  36. data/lib/discorb/error.rb +98 -0
  37. data/lib/discorb/event.rb +35 -0
  38. data/lib/discorb/extend.rb +18 -0
  39. data/lib/discorb/extension.rb +54 -0
  40. data/lib/discorb/file.rb +69 -0
  41. data/lib/discorb/flag.rb +109 -0
  42. data/lib/discorb/gateway.rb +967 -0
  43. data/lib/discorb/gateway_requests.rb +47 -0
  44. data/lib/discorb/guild.rb +1244 -0
  45. data/lib/discorb/guild_template.rb +211 -0
  46. data/lib/discorb/image.rb +43 -0
  47. data/lib/discorb/integration.rb +111 -0
  48. data/lib/discorb/intents.rb +137 -0
  49. data/lib/discorb/interaction.rb +333 -0
  50. data/lib/discorb/internet.rb +285 -0
  51. data/lib/discorb/invite.rb +145 -0
  52. data/lib/discorb/log.rb +70 -0
  53. data/lib/discorb/member.rb +232 -0
  54. data/lib/discorb/message.rb +583 -0
  55. data/lib/discorb/modules.rb +138 -0
  56. data/lib/discorb/permission.rb +270 -0
  57. data/lib/discorb/presence.rb +308 -0
  58. data/lib/discorb/reaction.rb +48 -0
  59. data/lib/discorb/role.rb +189 -0
  60. data/lib/discorb/sticker.rb +157 -0
  61. data/lib/discorb/user.rb +163 -0
  62. data/lib/discorb/utils.rb +16 -0
  63. data/lib/discorb/voice_state.rb +251 -0
  64. data/lib/discorb/webhook.rb +420 -0
  65. data/lib/discorb.rb +51 -0
  66. metadata +120 -0
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discorb
4
+ #
5
+ # Represents an activity for Gateway Command.
6
+ #
7
+ class Activity
8
+ @types = {
9
+ playing: 0,
10
+ streaming: 1,
11
+ listening: 2,
12
+ watching: 3,
13
+ competing: 5,
14
+ }.freeze
15
+
16
+ #
17
+ # Initializes a new Activity.
18
+ #
19
+ # @param [String] name The name of the activity.
20
+ # @param [:playing, :streaming, :listening, :watching, :competing] type The type of activity.
21
+ # @param [String] url The URL of the activity.
22
+ #
23
+ def initialize(name, type = :playing, url = nil)
24
+ @name = name
25
+ @type = self.class.types[type]
26
+ @url = url
27
+ end
28
+
29
+ #
30
+ # Converts the activity to a hash.
31
+ #
32
+ # @return [Hash] A hash representation of the activity.
33
+ #
34
+ def to_hash
35
+ {
36
+ name: @name,
37
+ type: @type,
38
+ url: @url,
39
+ }
40
+ end
41
+
42
+ class << self
43
+ # @!visibility private
44
+ attr_reader :types
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,1244 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discorb
4
+ #
5
+ # Represents a guild in the Discord.
6
+ #
7
+ class Guild < DiscordModel
8
+ # @return [Discorb::Snowflake] ID of the guild.
9
+ attr_reader :id
10
+ # @return [String] The name of the guild.
11
+ attr_reader :name
12
+ # @return [Discorb::Asset] The splash of the guild.
13
+ attr_reader :splash
14
+ # @return [Discorb::Asset] The discovery splash of the guild.
15
+ attr_reader :discovery_splash
16
+ # @return [Discorb::Snowflake] ID of the guild owner.
17
+ attr_reader :owner_id
18
+ # @return [Discorb::Permission] The bot's permission in the guild.
19
+ attr_reader :permissions
20
+ # @return [Integer] The AFK timeout of the guild.
21
+ attr_reader :afk_timeout
22
+ # @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::Role}] A dictionary of roles in the guild.
23
+ attr_reader :roles
24
+ # @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::CustomEmoji}] A dictionary of custom emojis in the guild.
25
+ attr_reader :emojis
26
+ # @return [Array<Symbol>] features that are enabled in the guild.
27
+ # @see https://discord.com/developers/docs/resources/guild#guild-object-guild-features Official Discord API docs
28
+ attr_reader :features
29
+ # @return [:none, :elevated] The MFA level of the guild.
30
+ attr_reader :mfa_level
31
+ # @return [Discorb::Guild::SystemChannelFlag] The flag for the system channel.
32
+ attr_reader :system_channel_flags
33
+ # @return [Time] Time that representing when bot has joined the guild.
34
+ attr_reader :joined_at
35
+ # @return [Boolean] Whether the guild is unavailable.
36
+ attr_reader :unavailable
37
+ # @return [Integer] The amount of members in the guild.
38
+ attr_reader :member_count
39
+ # @return [Discorb::Asset] The icon of the guild.
40
+ attr_reader :icon
41
+ # @return [Discorb::Dictionary{Discorb::User => Discorb::VoiceState}] A dictionary of voice states in the guild.
42
+ attr_reader :voice_states
43
+ # @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::Member}] A dictionary of members in the guild.
44
+ # @macro members_intent
45
+ attr_reader :members
46
+ # @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::GuildChannel}] A dictionary of channels in the guild.
47
+ attr_reader :channels
48
+ # @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::ThreadChannel}] A dictionary of threads in the guild.
49
+ attr_reader :threads
50
+ # @return [Discorb::Dictionary{Discorb::User => Discorb::Presence}] A dictionary of presence in the guild.
51
+ attr_reader :presences
52
+ # @return [Integer] Number of online members in the guild.
53
+ attr_reader :max_presences
54
+ # @return [String] The vanity invite URL for the guild.
55
+ # @return [nil] If the guild does not have a vanity invite URL.
56
+ attr_reader :vanity_url_code
57
+ # @return [String] The description of the guild.
58
+ attr_reader :description
59
+ # @return [Discorb::Asset] The banner of the guild.
60
+ # @return [nil] If the guild does not have a banner.
61
+ attr_reader :banner
62
+ # @return [Integer] The premium tier (Boost Level) of the guild.
63
+ attr_reader :premium_tier
64
+ # @return [Integer] The amount of premium subscriptions (Server Boosts) the guild has.
65
+ attr_reader :premium_subscription_count
66
+ # @return [Symbol] The preffered language of the guild.
67
+ # @note This modifies the language code, `-` will be replaced with `_`.
68
+ attr_reader :preferred_locale
69
+ # @return [Integer] The maximum amount of users in a video channel.
70
+ attr_reader :max_video_channel_users
71
+ # @return [Integer] The approxmate amount of members in the guild.
72
+ attr_reader :approximate_member_count
73
+ # @return [Integer] The approxmate amount of non-offline members in the guild.
74
+ attr_reader :approximate_presence_count
75
+ # @return [Discorb::WelcomeScreen] The welcome screen of the guild.
76
+ attr_reader :welcome_screen
77
+ # @return [:default, :explicit, :safe, :age_restricted] The nsfw level of the guild.
78
+ attr_reader :nsfw_level
79
+ # @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::StageInstance}] A dictionary of stage instances in the guild.
80
+ attr_reader :stage_instances
81
+ # @return [:none, :low, :medium, :high, :very_high] The verification level of the guild.
82
+ attr_reader :verification_level
83
+ # @return [:all_messages, :only_mentions] The default message notification level of the guild.
84
+ attr_reader :default_message_notifications
85
+ # @return [:disabled_in_text, :members_without_roles, :all_members] The explict content filter level of the guild.
86
+ attr_reader :explicit_content_filter
87
+ # @return [Boolean] Whether the client is the owner of the guild.
88
+ attr_reader :owner
89
+ alias owner? owner
90
+ # @return [Boolean] Whether the guild is large.
91
+ attr_reader :large
92
+ alias large? large
93
+ # @return [Boolean] Whether the guild enabled the widget.
94
+ attr_reader :widget_enabled
95
+ alias widget_enabled? widget_enabled
96
+ # @return [Boolean] Whether the guild is available.
97
+ attr_reader :available
98
+ alias available? available
99
+
100
+ # @!attribute [r] afk_channel
101
+ # @return [Discorb::VoiceChannel] The AFK channel for this guild.
102
+ # @macro client_cache
103
+ # @!attribute [r] system_channel
104
+ # @return [Discorb::TextChannel] The system message channel for this guild.
105
+ # @macro client_cache
106
+ # @!attribute [r] rules_channel
107
+ # @return [Discorb::TextChannel] The rules channel for this guild.
108
+ # @macro client_cache
109
+ # @!attribute [r] public_updates_channel
110
+ # @return [Discorb::TextChannel] The public updates channel (`#moderator-only`) for this guild.
111
+ # @macro client_cache
112
+ # @!attribute [r] me
113
+ # @return [Discorb::Member] The client's member in the guild.
114
+
115
+ @mfa_levels = %i[none elevated].freeze
116
+ @nsfw_levels = %i[default explicit safe age_restricted].freeze
117
+ @verification_levels = %i[none low medium high very_high].freeze
118
+ @default_message_notifications = %i[all_messages only_mentions].freeze
119
+ @explicit_content_filter = %i[disabled_in_text members_without_roles all_members].freeze
120
+
121
+ # @!visibility private
122
+ def initialize(client, data, is_create_event)
123
+ @client = client
124
+ @data = {}
125
+ _set_data(data, is_create_event)
126
+ end
127
+
128
+ # @!visibility private
129
+ def update!
130
+ Async do
131
+ _, data = @client.get("/guilds/#{@id}").wait
132
+ _set_data(data, false)
133
+ end
134
+ end
135
+
136
+ def afk_channel
137
+ @client.channels[@afk_channel_id]
138
+ end
139
+
140
+ def system_channel
141
+ @client.channels[@system_channel_id]
142
+ end
143
+
144
+ def rules_channel
145
+ @client.channels[@rules_channel_id]
146
+ end
147
+
148
+ def public_updates_channel
149
+ @client.channels[@public_updates_channel_id]
150
+ end
151
+
152
+ def inspect
153
+ "#<#{self.class} \"#{@name}\" id=#{@id}>"
154
+ end
155
+
156
+ def me
157
+ @members[@client.user.id]
158
+ end
159
+
160
+ #
161
+ # Leave the guild.
162
+ # @macro async
163
+ # @macro http
164
+ #
165
+ def leave!
166
+ Async do
167
+ @client.internet.delete("/users/@me/guilds/#{@id}").wait
168
+ @client.guilds.delete(@id)
169
+ end
170
+ end
171
+
172
+ #
173
+ # Fetch emoji list of the guild.
174
+ # @macro async
175
+ # @macro http
176
+ # @note This querys the API every time. We recommend using {#emojis} instead.
177
+ #
178
+ # @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::CustomEmoji}] A dictionary of emoji in the guild.
179
+ #
180
+ def fetch_emoji_list
181
+ Async do
182
+ _resp, data = @client.internet.get("/guilds/#{@id}/emojis").wait
183
+ @emojis = Dictionary.new
184
+ ids = @emojis.map(&:id).map(&:to_s)
185
+ data.map do |e|
186
+ next if ids.include?(e[:id])
187
+
188
+ @emojis[e[:id]] = CustomEmoji.new(@client, self, e)
189
+ end
190
+ @emojis
191
+ end
192
+ end
193
+
194
+ alias fetch_emojis fetch_emoji_list
195
+
196
+ #
197
+ # Fetch emoji id of the guild.
198
+ # @macro async
199
+ # @macro http
200
+ # @note This querys the API every time. We recommend using {#emojis} instead.
201
+ #
202
+ # @param [#to_s] id The emoji id.
203
+ #
204
+ # @return [Discorb::CustomEmoji] The emoji with the given id.
205
+ #
206
+ def fetch_emoji(id)
207
+ _resp, data = @client.internet.get("/guilds/#{@id}/emojis/#{id}").wait
208
+ @emojis[e[:id]] = CustomEmoji.new(@client, self, data)
209
+ end
210
+
211
+ #
212
+ # Create a custom emoji.
213
+ # @macro async
214
+ # @macro http
215
+ #
216
+ # @param [#to_s] name The name of the emoji.
217
+ # @param [Discorb::Image] image The image of the emoji.
218
+ # @param [Array<Discorb::Role>] roles A list of roles to give the emoji.
219
+ #
220
+ # @return [Discorb::CustomEmoji] The created emoji.
221
+ #
222
+ def create_emoji(name, image, roles: [])
223
+ _resp, data = @client.internet.post(
224
+ "/guilds/#{@id}/emojis",
225
+ {
226
+ name: name,
227
+ image: image.to_s,
228
+ roles: roles.map { |r| Discorb::Utils.try(r, :id) },
229
+ }
230
+ ).wait
231
+ @emojis[data[:id]] = CustomEmoji.new(@client, self, data)
232
+ end
233
+
234
+ #
235
+ # Fetch webhooks of the guild.
236
+ # @macro async
237
+ # @macro http
238
+ #
239
+ # @return [Array<Discorb::Webhook>] A list of webhooks in the guild.
240
+ #
241
+ def fetch_webhooks
242
+ Async do
243
+ _resp, data = @client.internet.get("/guilds/#{@id}/webhooks").wait
244
+ data.map { |webhook| Webhook.new([@client, webhook]) }
245
+ end
246
+ end
247
+
248
+ #
249
+ # Fetch audit log of the guild.
250
+ # @macro async
251
+ # @macro http
252
+ #
253
+ # @return [Discorb::AuditLog] The audit log of the guild.
254
+ #
255
+ def fetch_audit_log
256
+ Async do
257
+ _resp, data = @client.internet.get("/guilds/#{@id}/audit-logs").wait
258
+ AuditLog.new(@client, data, self)
259
+ end
260
+ end
261
+
262
+ #
263
+ # Fetch channels of the guild.
264
+ # @macro async
265
+ # @macro http
266
+ #
267
+ # @return [Array<Discorb::Channel>] A list of channels in the guild.
268
+ #
269
+ def fetch_channels
270
+ Async do
271
+ _resp, data = @client.internet.get("/guilds/#{@id}/channels").wait
272
+ data.map { |c| Channel.make_channel(@client, c) }
273
+ end
274
+ end
275
+
276
+ #
277
+ # Create a new text channel.
278
+ # @macro async
279
+ # @macro http
280
+ #
281
+ # @param [String] name The name of the channel.
282
+ # @param [String] topic The topic of the channel.
283
+ # @param [Integer] rate_limit_per_user The rate limit per user in the channel.
284
+ # @param [Integer] slowmode Alias for `rate_limit_per_user`.
285
+ # @param [Integer] position The position of the channel.
286
+ # @param [Boolean] nsfw Whether the channel is nsfw.
287
+ # @param [Hash{Discorb::Role, Discorb::Member => Discorb::PermissionOverwrite}] permission_overwrites A list of permission overwrites.
288
+ # @param [Discorb::CategoryChannel] parent The parent of the channel.
289
+ # @param [String] reason The reason for creating the channel.
290
+ #
291
+ # @return [Discorb::TextChannel] The created text channel.
292
+ #
293
+ def create_text_channel(
294
+ name, topic: nil, rate_limit_per_user: nil, slowmode: nil, position: nil, nsfw: nil, permission_overwrites: nil, parent: nil, reason: nil
295
+ )
296
+ Async do
297
+ payload = { type: TextChannel.channel_type }
298
+ payload[:name] = name
299
+ payload[:topic] = topic if topic
300
+ rate_limit_per_user ||= slowmode
301
+ payload[:rate_limit_per_user] = rate_limit_per_user if rate_limit_per_user
302
+ payload[:nsfw] = nsfw if nsfw
303
+ payload[:position] = position if position
304
+ if permission_overwrites
305
+ payload[:permission_overwrites] = permission_overwrites.map do |target, overwrite|
306
+ {
307
+ type: target.is_a?(Role) ? 0 : 1,
308
+ id: target.id,
309
+ allow: overwrite.allow_value,
310
+ deny: overwrite.deny_value,
311
+ }
312
+ end
313
+ end
314
+ payload[:parent_id] = parent.id if parent
315
+ _resp, data = @client.internet.post(
316
+ "/guilds/#{@id}/channels", payload, audit_log_reason: reason,
317
+ ).wait
318
+ payload[:parent_id] = parent&.id
319
+ Channel.make_channel(@client, data)
320
+ end
321
+ end
322
+
323
+ #
324
+ # Create a new voice channel.
325
+ # @macro async
326
+ # @macro http
327
+ #
328
+ # @param [String] name The name of the channel.
329
+ # @param [Integer] bitrate The bitrate of the channel.
330
+ # @param [Integer] user_limit The user limit of the channel.
331
+ # @param [Integer] position The position of the channel.
332
+ # @param [Hash{Discorb::Role, Discorb::Member => Discorb::PermissionOverwrite}] permission_overwrites A list of permission overwrites.
333
+ # @param [Discorb::CategoryChannel] parent The parent of the channel.
334
+ # @param [String] reason The reason for creating the channel.
335
+ #
336
+ # @return [Discorb::VoiceChannel] The created voice channel.
337
+ #
338
+ def create_voice_channel(
339
+ name, bitrate: 64, user_limit: nil, position: nil, permission_overwrites: nil, parent: nil, reason: nil
340
+ )
341
+ Async do
342
+ payload = { type: VoiceChannel.channel_type }
343
+ payload[:name] = name
344
+ payload[:bitrate] = bitrate * 1000 if bitrate
345
+ payload[:user_limit] = user_limit if user_limit
346
+ payload[:position] = position if position
347
+ if permission_overwrites
348
+ payload[:permission_overwrites] = permission_overwrites.map do |target, overwrite|
349
+ {
350
+ type: target.is_a?(Role) ? 0 : 1,
351
+ id: target.id,
352
+ allow: overwrite.allow_value,
353
+ deny: overwrite.deny_value,
354
+ }
355
+ end
356
+ end
357
+ payload[:parent_id] = parent.id if parent
358
+ _resp, data = @client.internet.post(
359
+ "/guilds/#{@id}/channels", payload, audit_log_reason: reason,
360
+ ).wait
361
+ payload[:parent_id] = parent&.id
362
+ Channel.make_channel(@client, data)
363
+ end
364
+ end
365
+
366
+ # Create a new category channel.
367
+ # @macro async
368
+ # @macro http
369
+ #
370
+ # @param [String] name The name of the channel.
371
+ # @param [Integer] position The position of the channel.
372
+ # @param [Hash{Discorb::Role, Discorb::Member => Discorb::PermissionOverwrite}] permission_overwrites A list of permission overwrites.
373
+ # @param [Discorb::CategoryChannel] parent The parent of the channel.
374
+ # @param [String] reason The reason for creating the channel.
375
+ #
376
+ # @return [Discorb::CategoryChannel] The created category channel.
377
+ #
378
+ def create_category_channel(name, position: nil, permission_overwrites: nil, parent: nil, reason: nil)
379
+ Async do
380
+ payload = { type: CategoryChannel.channel_type }
381
+ payload[:name] = name
382
+ payload[:position] = position if position
383
+ if permission_overwrites
384
+ payload[:permission_overwrites] = permission_overwrites.map do |target, overwrite|
385
+ {
386
+ type: target.is_a?(Role) ? 0 : 1,
387
+ id: target.id,
388
+ allow: overwrite.allow_value,
389
+ deny: overwrite.deny_value,
390
+ }
391
+ end
392
+ end
393
+ payload[:parent_id] = parent&.id
394
+ _resp, data = @client.internet.post(
395
+ "/guilds/#{@id}/channels", payload, audit_log_reason: reason,
396
+ ).wait
397
+ Channel.make_channel(@client, data)
398
+ end
399
+ end
400
+
401
+ alias create_category create_category_channel
402
+
403
+ #
404
+ # Create a new stage channel.
405
+ # @macro async
406
+ # @macro http
407
+ #
408
+ # @param [String] name The name of the channel.
409
+ # @param [Integer] bitrate The bitrate of the channel.
410
+ # @param [Integer] position The position of the channel.
411
+ # @param [Hash{Discorb::Role, Discorb::Member => Discorb::PermissionOverwrite}] permission_overwrites A list of permission overwrites.
412
+ # @param [Discorb::CategoryChannel] parent The parent of the channel.
413
+ # @param [String] reason The reason for creating the channel.
414
+ #
415
+ # @return [Discorb::StageChannel] The created stage channel.
416
+ #
417
+ def create_stage_channel(name, bitrate: 64, position: nil, permission_overwrites: nil, parent: nil, reason: nil)
418
+ Async do
419
+ payload = { type: StageChannel.channel_type }
420
+ payload[:name] = name
421
+ payload[:bitrate] = bitrate * 1000 if bitrate
422
+ payload[:position] = position if position
423
+ if permission_overwrites
424
+ payload[:permission_overwrites] = permission_overwrites.map do |target, overwrite|
425
+ {
426
+ type: target.is_a?(Role) ? 0 : 1,
427
+ id: target.id,
428
+ allow: overwrite.allow_value,
429
+ deny: overwrite.deny_value,
430
+ }
431
+ end
432
+ end
433
+ payload[:parent_id] = parent&.id
434
+ _resp, data = @client.internet.post(
435
+ "/guilds/#{@id}/channels", payload, audit_log_reason: reason,
436
+ ).wait
437
+ Channel.make_channel(@client, data)
438
+ end
439
+ end
440
+
441
+ #
442
+ # Create a new news channel.
443
+ # @macro async
444
+ # @macro http
445
+ #
446
+ # @param [String] name The name of the channel.
447
+ # @param [String] topic The topic of the channel.
448
+ # @param [Integer] rate_limit_per_user The rate limit per user in the channel.
449
+ # @param [Integer] slowmode Alias for `rate_limit_per_user`.
450
+ # @param [Integer] position The position of the channel.
451
+ # @param [Boolean] nsfw Whether the channel is nsfw.
452
+ # @param [Hash{Discorb::Role, Discorb::Member => Discorb::PermissionOverwrite}] permission_overwrites A list of permission overwrites.
453
+ # @param [Discorb::CategoryChannel] parent The parent of the channel.
454
+ # @param [String] reason The reason for creating the channel.
455
+ #
456
+ # @return [Discorb::NewsChannel] The created news channel.
457
+ #
458
+ def create_news_channel(
459
+ name, topic: nil, rate_limit_per_user: nil, slowmode: nil, position: nil, nsfw: nil, permission_overwrites: nil, parent: nil, reason: nil
460
+ )
461
+ Async do
462
+ payload = { type: NewsChannel.channel_type }
463
+ payload[:name] = name
464
+ payload[:topic] = topic if topic
465
+ rate_limit_per_user ||= slowmode
466
+ payload[:rate_limit_per_user] = rate_limit_per_user if rate_limit_per_user
467
+ payload[:position] = position if position
468
+ if permission_overwrites
469
+ payload[:permission_overwrites] = permission_overwrites.map do |target, overwrite|
470
+ {
471
+ type: target.is_a?(Role) ? 0 : 1,
472
+ id: target.id,
473
+ allow: overwrite.allow_value,
474
+ deny: overwrite.deny_value,
475
+ }
476
+ end
477
+ end
478
+ payload[:nsfw] = nsfw unless nsfw.nil?
479
+ payload[:parent_id] = parent&.id
480
+ _resp, data = @client.internet.post(
481
+ "/guilds/#{@id}/channels", payload, audit_log_reason: reason,
482
+ ).wait
483
+ Channel.make_channel(@client, data)
484
+ end
485
+ end
486
+
487
+ #
488
+ # Fetch a list of active threads in the guild.
489
+ # @macro async
490
+ # @macro http
491
+ #
492
+ # @return [Array<Discorb::ThreadChannel>] The list of threads.
493
+ #
494
+ def fetch_active_threads
495
+ Async do
496
+ _resp, data = @client.internet.get("/guilds/#{@id}/threads/active").wait
497
+ data[:threads].map { |t| Channel.make_thread(@client, t) }
498
+ end
499
+ end
500
+
501
+ #
502
+ # Fetch a member in the guild.
503
+ # @macro async
504
+ # @macro http
505
+ # @macro members_intent
506
+ #
507
+ # @param [#to_s] id The ID of the member to fetch.
508
+ #
509
+ # @return [Discorb::Member] The member.
510
+ # @return [nil] If the member is not found.
511
+ #
512
+ def fetch_member(id)
513
+ Async do
514
+ _resp, data = @client.internet.get("/guilds/#{@id}/members/#{id}").wait
515
+ rescue Discorb::NotFoundError
516
+ nil
517
+ else
518
+ Member.new(@client, @id, data[:user], data)
519
+ end
520
+ end
521
+
522
+ #
523
+ # Search for members by name in the guild.
524
+ # @macro async
525
+ # @macro http
526
+ #
527
+ # @param [String] name The name of the member to search for.
528
+ # @param [Integer] limit The maximum number of members to return.
529
+ #
530
+ # @return [Array<Discorb::Member>] The list of members.
531
+ #
532
+ def fetch_members_named(name, limit: 1)
533
+ Async do
534
+ _resp, data = @client.internet.get("/guilds/#{@id}/members/search?#{URI.encode_www_form({ query: name, limit: limit })}").wait
535
+ data.map { |d| Member.new(@client, @id, d[:user], d) }
536
+ end
537
+ end
538
+
539
+ #
540
+ # Almost the same as {#fetch_members_named}, but returns a single member.
541
+ # @macro async
542
+ # @macro http
543
+ #
544
+ # @return [Discorb::Member] The member.
545
+ # @return [nil] If the member is not found.
546
+ #
547
+ def fetch_member_named(...)
548
+ Async do
549
+ fetch_members_named(...).first
550
+ end
551
+ end
552
+
553
+ #
554
+ # Change nickname of client member.
555
+ #
556
+ # @param [String] nickname The nickname to set.
557
+ # @param [String] reason The reason for changing the nickname.
558
+ #
559
+ def edit_nickname(nickname, reason: nil)
560
+ Async do
561
+ @client.internet.patch("/guilds/#{@id}/members/@me/nick", { nick: nickname }, audit_log_reason: reason).wait
562
+ end
563
+ end
564
+
565
+ alias edit_nick edit_nickname
566
+ alias modify_nickname edit_nickname
567
+ alias modify_nick modify_nickname
568
+
569
+ #
570
+ # Kick a member from the guild.
571
+ # @macro async
572
+ # @macro http
573
+ #
574
+ # @param [Discorb::Member] member The member to kick.
575
+ # @param [String] reason The reason for kicking the member.
576
+ #
577
+ def kick_member(member, reason: nil)
578
+ Async do
579
+ @client.internet.delete("/guilds/#{@id}/members/#{member.id}", audit_log_reason: reason).wait
580
+ end
581
+ end
582
+
583
+ #
584
+ # Fetch a list of bans in the guild.
585
+ # @macro async
586
+ # @macro http
587
+ #
588
+ # @return [Array<Discorb::Guild::Ban>] The list of bans.
589
+ #
590
+ def fetch_bans
591
+ Async do
592
+ _resp, data = @client.internet.get("/guilds/#{@id}/bans").wait
593
+ data.map { |d| Ban.new(@client, self, d) }
594
+ end
595
+ end
596
+
597
+ #
598
+ # Fetch a ban in the guild.
599
+ # @macro async
600
+ # @macro http
601
+ #
602
+ # @param [Discorb::User] user The user to fetch.
603
+ #
604
+ # @return [Discorb::Guild::Ban] The ban.
605
+ # @return [nil] If the ban is not found.
606
+ #
607
+ def fetch_ban(user)
608
+ Async do
609
+ _resp, data = @client.internet.get("/guilds/#{@id}/bans/#{user.id}").wait
610
+ rescue Discorb::NotFoundError
611
+ nil
612
+ else
613
+ Ban.new(@client, self, data)
614
+ end
615
+ end
616
+
617
+ #
618
+ # Checks the user was banned from the guild.
619
+ # @macro async
620
+ # @macro http
621
+ #
622
+ # @param [Discorb::User] user The user to check.
623
+ #
624
+ # @return [Boolean] Whether the user was banned.
625
+ #
626
+ def banned?(user)
627
+ Async do
628
+ !fetch_ban(user).wait.nil?
629
+ end
630
+ end
631
+
632
+ #
633
+ # Ban a member from the guild.
634
+ # @macro async
635
+ # @macro http
636
+ #
637
+ # @param [Discorb::Member] member The member to ban.
638
+ # @param [Integer] delete_message_days The number of days to delete messages.
639
+ # @param [String] reason The reason for banning the member.
640
+ #
641
+ # @return [Discorb::Guild::Ban] The ban.
642
+ #
643
+ def ban_member(member, delete_message_days: 0, reason: nil)
644
+ Async do
645
+ _resp, data = @client.internet.post(
646
+ "/guilds/#{@id}/bans", { user: member.id, delete_message_days: delete_message_days }, audit_log_reason: reason,
647
+ ).wait
648
+ Ban.new(@client, self, data)
649
+ end
650
+ end
651
+
652
+ #
653
+ # Unban a user from the guild.
654
+ # @macro async
655
+ # @macro http
656
+ #
657
+ # @param [Discorb::User] user The user to unban.
658
+ # @param [String] reason The reason for unbanning the user.
659
+ #
660
+ def unban_user(user, reason: nil)
661
+ Async do
662
+ @client.internet.delete("/guilds/#{@id}/bans/#{user.id}", audit_log_reason: reason).wait
663
+ end
664
+ end
665
+
666
+ #
667
+ # Fetch a list of roles in the guild.
668
+ # @macro async
669
+ # @macro http
670
+ #
671
+ # @return [Array<Discorb::Role>] The list of roles.
672
+ #
673
+ def fetch_roles
674
+ Async do
675
+ _resp, data = @client.internet.get("/guilds/#{@id}/roles").wait
676
+ data.map { |d| Role.new(@client, self, d) }
677
+ end
678
+ end
679
+
680
+ #
681
+ # Create a role in the guild.
682
+ # @macro async
683
+ # @macro http
684
+ #
685
+ # @param [String] name The name of the role.
686
+ # @param [Discorb::Color] color The color of the role.
687
+ # @param [Boolean] hoist Whether the role should be hoisted.
688
+ # @param [Boolean] mentionable Whether the role should be mentionable.
689
+ # @param [String] reason The reason for creating the role.
690
+ #
691
+ # @return [Discorb::Role] The role.
692
+ #
693
+ def create_role(name = nil, color: nil, hoist: nil, mentionable: nil, reason: nil)
694
+ Async do
695
+ payload = {}
696
+ payload[:name] = name if name
697
+ payload[:color] = color.to_i if color
698
+ payload[:hoist] = hoist if hoist
699
+ payload[:mentionable] = mentionable if mentionable
700
+ _resp, data = @client.internet.post(
701
+ "/guilds/#{@id}/roles", payload, audit_log_reason: reason,
702
+ ).wait
703
+ Role.new(@client, self, data)
704
+ end
705
+ end
706
+
707
+ #
708
+ # Fetch how many members will be pruned.
709
+ # @macro async
710
+ # @macro http
711
+ #
712
+ # @param [Integer] days The number of days to prune.
713
+ # @param [Array<Discorb::Role>] roles The roles that include for pruning.
714
+ #
715
+ # @return [Integer] The number of members that will be pruned.
716
+ #
717
+ def fetch_prune(days = 7, roles: [])
718
+ Async do
719
+ params = {
720
+ days: days,
721
+ include_roles: @id.to_s,
722
+ }
723
+ param[:include_roles] = roles.map(&:id).map(&:to_s).join(";") if roles.any?
724
+ _resp, data = @client.internet.get("/guilds/#{@id}/prune?#{URI.encode_www_form(params)}").wait
725
+ data[:pruned]
726
+ end
727
+ end
728
+
729
+ #
730
+ # Prune members from the guild.
731
+ # @macro async
732
+ # @macro http
733
+ #
734
+ # @param [Integer] days The number of days to prune.
735
+ # @param [Array<Discorb::Role>] roles The roles that include for pruning.
736
+ # @param [String] reason The reason for pruning.
737
+ #
738
+ # @return [Integer] The number of members that were pruned.
739
+ #
740
+ def prune(days = 7, roles: [], reason: nil)
741
+ Async do
742
+ _resp, data = @client.internet.post(
743
+ "/guilds/#{@id}/prune", { days: days, roles: roles.map(&:id) }, audit_log_reason: reason,
744
+ ).wait
745
+ data[:pruned]
746
+ end
747
+ end
748
+
749
+ #
750
+ # Fetch voice regions that are available in the guild.
751
+ # @macro async
752
+ # @macro http
753
+ #
754
+ # @return [Array<Discorb::VoiceRegion>] The available voice regions.
755
+ #
756
+ def fetch_voice_regions
757
+ Async do
758
+ _resp, data = @client.internet.get("/guilds/#{@id}/voice").wait
759
+ data.map { |d| VoiceRegion.new(@client, d) }
760
+ end
761
+ end
762
+
763
+ #
764
+ # Fetch invites in the guild.
765
+ # @macro async
766
+ # @macro http
767
+ #
768
+ # @return [Array<Invite>] The invites.
769
+ #
770
+ def fetch_invites
771
+ Async do
772
+ _resp, data = @client.internet.get("/guilds/#{@id}/invites").wait
773
+ data.map { |d| Invite.new(@client, d) }
774
+ end
775
+ end
776
+
777
+ #
778
+ # Fetch integrations in the guild.
779
+ # @macro async
780
+ # @macro http
781
+ #
782
+ # @return [Array<Discorb::Integration>] The integrations.
783
+ #
784
+ def fetch_integrations
785
+ Async do
786
+ _resp, data = @client.internet.get("/guilds/#{@id}/integrations").wait
787
+ data.map { |d| Integration.new(@client, d) }
788
+ end
789
+ end
790
+
791
+ #
792
+ # Fetch the widget of the guild.
793
+ # @macro async
794
+ # @macro http
795
+ #
796
+ # @return [Discorb::Guild::Widget] The widget.
797
+ #
798
+ def fetch_widget
799
+ Async do
800
+ _resp, data = @client.internet.get("/guilds/#{@id}/widget").wait
801
+ Widget.new(@client, @id, data)
802
+ end
803
+ end
804
+
805
+ #
806
+ # Fetch the vanity URL of the guild.
807
+ # @macro async
808
+ # @macro http
809
+ #
810
+ # @return [Discorb::Guild::VanityInvite] The vanity URL.
811
+ #
812
+ def fetch_vanity_invite
813
+ Async do
814
+ _resp, data = @client.internet.get("/guilds/#{@id}/vanity-url").wait
815
+ VanityInvite.new(@client, self, data)
816
+ end
817
+ end
818
+
819
+ #
820
+ # Fetch the welcome screen of the guild.
821
+ # @macro async
822
+ # @macro http
823
+ #
824
+ # @return [Discorb::Guild::WelcomeScreen] The welcome screen.
825
+ #
826
+ def fetch_welcome_screen
827
+ Async do
828
+ _resp, data = @client.internet.get("/guilds/#{@id}/welcome-screen").wait
829
+ WelcomeScreen.new(@client, self, data)
830
+ end
831
+ end
832
+
833
+ #
834
+ # Fetch stickers in the guild.
835
+ # @macro async
836
+ # @macro http
837
+ #
838
+ # @return [Array<Discorb::Sticker::GuildSticker>] The stickers.
839
+ #
840
+ def fetch_stickers
841
+ Async do
842
+ _resp, data = @client.internet.get("/guilds/#{@id}/stickers").wait
843
+ data.map { |d| Sticker::GuildSticker.new(@client, d) }
844
+ end
845
+ end
846
+
847
+ #
848
+ # Fetch the sticker by ID.
849
+ # @macro async
850
+ # @macro http
851
+ #
852
+ # @param [#to_s] id The ID of the sticker.
853
+ #
854
+ # @return [Discorb::Sticker::GuildSticker] The sticker.
855
+ # @return [nil] If the sticker does not exist.
856
+ #
857
+ def fetch_sticker(id)
858
+ Async do
859
+ _resp, data = @client.internet.get("/guilds/#{@id}/stickers/#{id}").wait
860
+ rescue Discorb::NotFoundError
861
+ nil
862
+ else
863
+ Sticker::GuildSticker.new(@client, data)
864
+ end
865
+ end
866
+
867
+ #
868
+ # Fetch templates in the guild.
869
+ # @macro async
870
+ # @macro http
871
+ #
872
+ # @return [Discorb::GuildTemplate] The templates.
873
+ #
874
+ def fetch_templates
875
+ Async do
876
+ _resp, data = @client.internet.get("/guilds/#{@id}/templates").wait
877
+ data.map { |d| GuildTemplate.new(@client, d) }
878
+ end
879
+ end
880
+
881
+ #
882
+ # Almost the same as {#fetch_templates}, but returns a single template.
883
+ #
884
+ # @return [Discorb::GuildTemplate] The template.
885
+ # @return [nil] If the template does not exist.
886
+ #
887
+ def fetch_template
888
+ Async do
889
+ fetch_templates.wait.first
890
+ end
891
+ end
892
+
893
+ #
894
+ # Create a new template in the guild.
895
+ #
896
+ # @param [String] name The name of the template.
897
+ # @param [String] description The description of the template.
898
+ # @param [String] reason The reason for creating the template.
899
+ #
900
+ # @return [Discorb::GuildTemplate] The template.
901
+ #
902
+ def create_template(name, description = nil, reason: nil)
903
+ Async do
904
+ _resp, data = @client.internet.post(
905
+ "/guilds/#{@id}/templates", { name: name, description: description }, audit_log_reason: reason,
906
+ ).wait
907
+ GuildTemplate.new(@client, data)
908
+ end
909
+ end
910
+
911
+ #
912
+ # Represents a vanity invite.
913
+ #
914
+ class VanityInvite < DiscordModel
915
+ # @return [String] The vanity invite code.
916
+ attr_reader :code
917
+ # @return [Integer] The number of uses.
918
+ attr_reader :uses
919
+
920
+ # @!attribute [r] url
921
+ # @return [String] The vanity URL.
922
+
923
+ # @!visibility private
924
+ def initialize(client, guild, data)
925
+ @client = client
926
+ @guild = guild
927
+ @code = data[:code]
928
+ @uses = data[:uses]
929
+ end
930
+
931
+ def url
932
+ "https://discord.gg/#{@code}"
933
+ end
934
+ end
935
+
936
+ #
937
+ # Represents a guild widget.
938
+ #
939
+ class Widget < DiscordModel
940
+ # @return [Discorb::Snowflake] The guild ID.
941
+ attr_reader :guild_id
942
+ # @return [Discorb::Snowflake] The channel ID.
943
+ attr_reader :channel_id
944
+ # @return [Boolean] Whether the widget is enabled.
945
+ attr_reader :enabled
946
+ alias enabled? enabled
947
+ alias enable? enabled
948
+
949
+ # @!attribute [r] channel
950
+ # @macro client_cache
951
+ # @return [Discorb::Channel] The channel.
952
+ # @!attribute [r] guild
953
+ # @macro client_cache
954
+ # @return [Discorb::Guild] The guild.
955
+ # @!attribute [r] json_url
956
+ # @return [String] The JSON URL.
957
+
958
+ # @!visibility private
959
+ def initialize(client, guild_id, data)
960
+ @client = client
961
+ @enabled = data[:enabled]
962
+ @guild_id = Snowflake.new(guild_id)
963
+ @channel_id = Snowflake.new(data[:channel_id])
964
+ end
965
+
966
+ def channel
967
+ @client.channels[@channel_id]
968
+ end
969
+
970
+ #
971
+ # Edit the widget.
972
+ # @macro async
973
+ # @macro http
974
+ # @macro edit
975
+ #
976
+ # @param [Boolean] enabled Whether the widget is enabled.
977
+ # @param [Discorb::GuildChannel] channel The channel.
978
+ # @param [String] reason The reason for editing the widget.
979
+ #
980
+ def edit(enabled: nil, channel: nil, reason: nil)
981
+ Async do
982
+ payload = {}
983
+ payload[:enabled] = enabled unless enabled.nil?
984
+ payload[:channel_id] = channel.id if channel_id
985
+ @client.internet.patch("/guilds/#{@guild_id}/widget", payload, audit_log_reason: reason).wait
986
+ end
987
+ end
988
+
989
+ alias modify edit
990
+
991
+ def json_url
992
+ "#{Discorb::API_BASE_URL}/guilds/#{@guild_id}/widget.json"
993
+ end
994
+
995
+ #
996
+ # Return iframe HTML of the widget.
997
+ #
998
+ # @param ["dark", "light"] theme The theme of the widget.
999
+ # @param [Integer] width The width of the widget.
1000
+ # @param [Integer] height The height of the widget.
1001
+ #
1002
+ # @return [String] The iframe HTML.
1003
+ #
1004
+ def iframe(theme: "dark", width: 350, height: 500)
1005
+ [
1006
+ %(<iframe src="https://canary.discord.com/widget?id=#{@guild_id}&theme=#{theme}" width="#{width}" height="#{height}"),
1007
+ %(allowtransparency="true" frameborder="0" sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts"></iframe>),
1008
+ ].join
1009
+ end
1010
+ end
1011
+
1012
+ #
1013
+ # Represents a ban.
1014
+ #
1015
+ class Ban < DiscordModel
1016
+ # @return [Discorb::User] The user.
1017
+ attr_reader :user
1018
+ # @return [String] The reason for the ban.
1019
+ attr_reader :reason
1020
+
1021
+ # @!visibility private
1022
+ def initialize(client, guild, data)
1023
+ @client = client
1024
+ @guild = guild
1025
+ @reason = data[:reason]
1026
+ @user = @client.users[data[:user][:id]] || User.new(@client, data[:user])
1027
+ end
1028
+ end
1029
+
1030
+ class << self
1031
+ # @!visibility private
1032
+ attr_reader :nsfw_levels, :mfa_levels, :verification_levels, :default_message_notifications, :explicit_content_filter
1033
+
1034
+ #
1035
+ # Returns a banner url from the guild's ID.
1036
+ #
1037
+ # @param [#to_s] guild_id The ID of the guild.
1038
+ # @param [:shield, :banner1, :banner2, :banner3, :banner4] style The style of the banner.
1039
+ #
1040
+ # @return [String] The url of the banner.
1041
+ #
1042
+ def banner(guild_id, style: "banner")
1043
+ "#{Discorb::API_BASE_URL}/guilds/#{guild_id}/widget.png&style=#{style}"
1044
+ end
1045
+ end
1046
+
1047
+ private
1048
+
1049
+ def _set_data(data, is_create_event)
1050
+ @id = Snowflake.new(data[:id])
1051
+ if data[:unavailable]
1052
+ @unavailable = true
1053
+ return
1054
+ end
1055
+ @client.guilds[@id] = self unless data[:no_cache]
1056
+ @icon = data[:icon] && Asset.new(self, data[:icon])
1057
+ @unavailable = false
1058
+ @name = data[:name]
1059
+ @members = Discorb::Dictionary.new
1060
+ data[:members].each do |m|
1061
+ Member.new(@client, @id, m[:user], m)
1062
+ end
1063
+ @splash = data[:splash] && Asset.new(self, data[:splash], path: "splashes/#{@id}")
1064
+ @discovery_splash = data[:discovery_splash] && Asset.new(self, data[:discovery_splash], path: "discovery-splashes/#{@id}")
1065
+ @owner_id = data[:owner_id]
1066
+ @permissions = Permission.new(data[:permissions].to_i)
1067
+ @afk_channel_id = data[:afk_channel_id]
1068
+ @afk_timeout = data[:afk_timeout]
1069
+ @widget_enabled = data[:widget_enabled]
1070
+ @widget_channel_id = data[:widget_channel_id]
1071
+ @roles = Dictionary.new
1072
+ data[:roles].each do |r|
1073
+ @roles[r[:id]] = Role.new(@client, self, r)
1074
+ end
1075
+ @emojis = Dictionary.new
1076
+ data[:emojis].map do |e|
1077
+ @emojis[e[:id]] = CustomEmoji.new(@client, self, e)
1078
+ end
1079
+ @features = data[:features].map { |f| f.downcase.to_sym }
1080
+ @mfa_level = self.class.mfa_levels[data[:mfa_level]]
1081
+ @verification_level = self.class.verification_levels[data[:verification_level]]
1082
+ @default_message_notifications = self.class.default_message_notifications[data[:default_message_notifications]]
1083
+ @explicit_content_filter = self.class.explicit_content_filter[data[:explicit_content_filter]]
1084
+ @system_channel_id = data[:system_channel_id]
1085
+ @system_channel_flag = SystemChannelFlag.new(0b111 - data[:system_channel_flags])
1086
+ @rules_channel_id = data[:rules_channel_id]
1087
+ @vanity_url_code = data[:vanity_url_code]
1088
+ @description = data[:description]
1089
+ @banner = data[:banner] && Asset.new(self, data[:banner], path: "banners/#{@id}")
1090
+ @premium_tier = data[:premium_tier]
1091
+ @premium_subscription_count = data[:premium_tier_count].to_i
1092
+ @preferred_locale = data[:preferred_locale].gsub("-", "_").to_sym
1093
+ @public_updates_channel_id = data[:public_updates_channel_id]
1094
+ @max_video_channel_users = data[:max_video_channel_users]
1095
+ @approximate_member_count = data[:approximate_member_count]
1096
+ @approximate_presence_count = data[:approximate_presence_count]
1097
+ @welcome_screen = data[:welcome_screen].nil? ? nil : WelcomeScreen.new(@client, self, data[:welcome_screen])
1098
+ @nsfw_level = self.class.nsfw_levels[data[:nsfw_level]]
1099
+ return unless is_create_event
1100
+
1101
+ @stickers = data[:stickers].nil? ? [] : data[:stickers].map { |s| Sticker::GuildSticker.new(self, s) }
1102
+ @joined_at = Time.iso8601(data[:joined_at])
1103
+ @large = data[:large]
1104
+ @member_count = data[:member_count]
1105
+ tmp_channels = data[:channels].filter { |c| !c.key?(:thread_metadata) }.map do |c|
1106
+ Channel.make_channel(@client, c.merge({ guild_id: @id }))
1107
+ end
1108
+ @channels = Dictionary.new(tmp_channels.map { |c| [c.id, c] }.to_h, sort: ->(c) { c[1].position })
1109
+ @voice_states = Dictionary.new(data[:voice_states].map { |v| [Snowflake.new(v[:user_id]), VoiceState.new(@client, v.merge({ guild_id: @id }))] }.to_h)
1110
+ @threads = data[:threads] ? data[:threads].map { |t| Channel.make_channel(@client, t) } : []
1111
+ @presences = Dictionary.new(data[:presences].map { |pr| [Snowflake.new(pr[:user][:id]), Presence.new(@client, pr)] }.to_h)
1112
+ @max_presences = data[:max_presences]
1113
+ @stage_instances = Dictionary.new(data[:stage_instances].map { |s| [Snowflake.new(s[:id]), StageInstance.new(@client, s)] }.to_h)
1114
+ @data.update(data)
1115
+ end
1116
+ end
1117
+
1118
+ #
1119
+ # Represents a system channel flag.
1120
+ # ## Flag fields
1121
+ # |Field|Value|
1122
+ # |-|-|
1123
+ # |`1 << 0`|`:member_join`|
1124
+ # |`1 << 1`|`:server_boost`|
1125
+ # |`1 << 2`|`:setup_tips`|
1126
+ #
1127
+ class SystemChannelFlag < Flag
1128
+ @bits = {
1129
+ member_join: 0,
1130
+ server_boost: 1,
1131
+ setup_tips: 2,
1132
+ }.freeze
1133
+ end
1134
+
1135
+ #
1136
+ # Represents a welcome screen.
1137
+ #
1138
+ class WelcomeScreen < DiscordModel
1139
+ # @return [String] The description of the welcome screen.
1140
+ attr_reader :description
1141
+ # @return [Array<Discorb::WelcomeScreen::Channel>] The channels to display the welcome screen.
1142
+ attr_reader :channels
1143
+ # @return [Discorb::Guild] The guild the welcome screen belongs to.
1144
+ attr_reader :guild
1145
+
1146
+ # @!visibility private
1147
+ def initialize(client, guild, data)
1148
+ @client = client
1149
+ @description = data[:description]
1150
+ @guild = guild
1151
+ @channels = data[:channels].map { |c| WelcomeScreen::Channel.new(client, c, nil) }
1152
+ end
1153
+
1154
+ #
1155
+ # Represents a channel to display the welcome screen.
1156
+ #
1157
+ class Channel < DiscordModel
1158
+ # @return [String] The channel's name.
1159
+ attr_reader :description
1160
+
1161
+ # @!attribute [r] emoji
1162
+ # @return [Discorb::Emoji] The emoji to display.
1163
+ # @!attribute [r] channel
1164
+ # @macro client_cache
1165
+ # @return [Discorb::Channel] The channel to display the welcome screen.
1166
+
1167
+ #
1168
+ # Initialize a new welcome screen channel.
1169
+ #
1170
+ # @param [Discorb::TextChannel] channel The channel to display the welcome screen.
1171
+ # @param [String] description The channel's name.
1172
+ # @param [Discorb::Emoji] emoji The emoji to display.
1173
+ #
1174
+ def initialize(channel, description, emoji)
1175
+ if description.is_a?(Hash)
1176
+ @screen = channel
1177
+ data = description
1178
+ @channel_id = Snowflake.new(data[:channel_id])
1179
+ @description = data[:description]
1180
+ @emoji_id = Snowflake.new(data[:emoji_id])
1181
+ @emoji_name = data[:emoji_name]
1182
+ else
1183
+ @channel_id = channel.id
1184
+ @description = description
1185
+ if emoji.is_a?(UnicodeEmoji)
1186
+ @emoji_id = nil
1187
+ @emoji_name = emoji.value
1188
+ else
1189
+ @emoji_id = emoji.id
1190
+ @emoji_name = emoji.name
1191
+ end
1192
+ end
1193
+ end
1194
+
1195
+ #
1196
+ # Converts the channel to a hash.
1197
+ #
1198
+ # @return [Hash] The hash.
1199
+ # @see https://discord.com/developers/docs/resources/guild#welcome-screen-object
1200
+ #
1201
+ def to_hash
1202
+ {
1203
+ channel_id: @channel_id,
1204
+ description: @description,
1205
+ emoji_id: @emoji_id,
1206
+ emoji_name: @emoji_name,
1207
+ }
1208
+ end
1209
+
1210
+ def channel
1211
+ @screen.guild.channels[@channel_id]
1212
+ end
1213
+
1214
+ def emoji
1215
+ if @emoji_id.nil?
1216
+ UnicodeEmoji.new(@emoji_name)
1217
+ else
1218
+ @screen.guild.emojis[@emoji_id]
1219
+ end
1220
+ end
1221
+
1222
+ #
1223
+ # Edits the welcome screen.
1224
+ # @macro async
1225
+ # @macro http
1226
+ # @macro edit
1227
+ #
1228
+ # @param [Boolean] enabled Whether the welcome screen is enabled.
1229
+ # @param [Array<Discorb::WelcomeScreen::Channel>] channels The channels to display the welcome screen.
1230
+ # @param [String] description The description of the welcome screen.
1231
+ # @param [String] reason The reason for editing the welcome screen.
1232
+ #
1233
+ def edit(enabled: :unset, channels: :unset, description: :unset, reason: nil)
1234
+ Async do
1235
+ payload = {}
1236
+ payload[:enabled] = enabled unless enabled == :unset
1237
+ payload[:welcome_channels] = channels.map(&:to_hash) unless channels == :unset
1238
+ payload[:description] = description unless description == :unset
1239
+ @client.internet.patch("/guilds/#{@guild.id}/welcome-screen", payload, audit_log_reason: reason).wait
1240
+ end
1241
+ end
1242
+ end
1243
+ end
1244
+ end