discorb 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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