discorb 0.19.0 → 0.20.0

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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build_version.yml +2 -2
  3. data/.rubocop.yml +12 -75
  4. data/Changelog.md +10 -0
  5. data/Rakefile +482 -454
  6. data/lib/discorb/allowed_mentions.rb +68 -72
  7. data/lib/discorb/app_command/command.rb +466 -398
  8. data/lib/discorb/app_command/common.rb +65 -25
  9. data/lib/discorb/app_command/handler.rb +304 -266
  10. data/lib/discorb/app_command.rb +5 -5
  11. data/lib/discorb/application.rb +198 -197
  12. data/lib/discorb/asset.rb +101 -101
  13. data/lib/discorb/attachment.rb +134 -119
  14. data/lib/discorb/audit_logs.rb +412 -385
  15. data/lib/discorb/automod.rb +279 -269
  16. data/lib/discorb/channel/base.rb +107 -108
  17. data/lib/discorb/channel/category.rb +32 -32
  18. data/lib/discorb/channel/container.rb +44 -44
  19. data/lib/discorb/channel/dm.rb +26 -28
  20. data/lib/discorb/channel/guild.rb +311 -246
  21. data/lib/discorb/channel/stage.rb +156 -140
  22. data/lib/discorb/channel/text.rb +430 -336
  23. data/lib/discorb/channel/thread.rb +374 -325
  24. data/lib/discorb/channel/voice.rb +85 -79
  25. data/lib/discorb/channel.rb +5 -5
  26. data/lib/discorb/client.rb +635 -621
  27. data/lib/discorb/color.rb +178 -182
  28. data/lib/discorb/common.rb +168 -164
  29. data/lib/discorb/components/button.rb +107 -106
  30. data/lib/discorb/components/select_menu.rb +157 -145
  31. data/lib/discorb/components/text_input.rb +103 -106
  32. data/lib/discorb/components.rb +68 -66
  33. data/lib/discorb/dictionary.rb +135 -135
  34. data/lib/discorb/embed.rb +404 -398
  35. data/lib/discorb/emoji.rb +309 -302
  36. data/lib/discorb/emoji_table.rb +16099 -8857
  37. data/lib/discorb/error.rb +131 -131
  38. data/lib/discorb/event.rb +360 -314
  39. data/lib/discorb/event_handler.rb +39 -39
  40. data/lib/discorb/exe/about.rb +17 -17
  41. data/lib/discorb/exe/irb.rb +72 -67
  42. data/lib/discorb/exe/new.rb +323 -315
  43. data/lib/discorb/exe/run.rb +69 -68
  44. data/lib/discorb/exe/setup.rb +57 -55
  45. data/lib/discorb/exe/show.rb +12 -12
  46. data/lib/discorb/extend.rb +25 -45
  47. data/lib/discorb/extension.rb +89 -83
  48. data/lib/discorb/flag.rb +126 -128
  49. data/lib/discorb/gateway.rb +984 -804
  50. data/lib/discorb/gateway_events.rb +670 -638
  51. data/lib/discorb/gateway_requests.rb +45 -48
  52. data/lib/discorb/guild.rb +2115 -1626
  53. data/lib/discorb/guild_template.rb +280 -241
  54. data/lib/discorb/http.rb +247 -232
  55. data/lib/discorb/image.rb +42 -42
  56. data/lib/discorb/integration.rb +169 -161
  57. data/lib/discorb/intents.rb +161 -163
  58. data/lib/discorb/interaction/autocomplete.rb +76 -62
  59. data/lib/discorb/interaction/command.rb +279 -224
  60. data/lib/discorb/interaction/components.rb +114 -104
  61. data/lib/discorb/interaction/modal.rb +36 -32
  62. data/lib/discorb/interaction/response.rb +379 -336
  63. data/lib/discorb/interaction/root.rb +271 -257
  64. data/lib/discorb/interaction.rb +5 -5
  65. data/lib/discorb/invite.rb +154 -153
  66. data/lib/discorb/member.rb +344 -311
  67. data/lib/discorb/message.rb +615 -544
  68. data/lib/discorb/message_meta.rb +197 -186
  69. data/lib/discorb/modules.rb +371 -290
  70. data/lib/discorb/permission.rb +305 -291
  71. data/lib/discorb/presence.rb +352 -346
  72. data/lib/discorb/rate_limit.rb +81 -76
  73. data/lib/discorb/reaction.rb +55 -54
  74. data/lib/discorb/role.rb +272 -240
  75. data/lib/discorb/shard.rb +76 -74
  76. data/lib/discorb/sticker.rb +193 -171
  77. data/lib/discorb/user.rb +205 -188
  78. data/lib/discorb/utils/colored_puts.rb +16 -16
  79. data/lib/discorb/utils.rb +12 -16
  80. data/lib/discorb/voice_state.rb +305 -281
  81. data/lib/discorb/webhook.rb +537 -507
  82. data/lib/discorb.rb +62 -56
  83. data/sig/discorb/application.rbs +2 -0
  84. data/sig/discorb/automod.rbs +10 -1
  85. data/sig/discorb/guild.rbs +2 -0
  86. data/sig/discorb/message.rbs +2 -0
  87. data/sig/discorb/user.rbs +22 -20
  88. metadata +2 -2
data/lib/discorb/guild.rb CHANGED
@@ -1,1626 +1,2115 @@
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}]
25
- # A dictionary of custom emojis in the guild.
26
- attr_reader :emojis
27
- # @return [Array<Symbol>] features that are enabled in the guild.
28
- # @see https://discord.com/developers/docs/resources/guild#guild-object-guild-features Official Discord API docs
29
- attr_reader :features
30
- # @return [:none, :elevated] The MFA level of the guild.
31
- attr_reader :mfa_level
32
- # @return [Discorb::SystemChannelFlag] The flag for the system channel.
33
- attr_reader :system_channel_flags
34
- # @return [Time] Time that representing when bot has joined the guild.
35
- attr_reader :joined_at
36
- # @return [Boolean] Whether the guild is unavailable.
37
- attr_reader :unavailable
38
- # @return [Integer] The amount of members in the guild.
39
- attr_reader :member_count
40
- # @return [Discorb::Asset] The icon of the guild.
41
- attr_reader :icon
42
- # @return [Discorb::Dictionary{Discorb::User => Discorb::VoiceState}] A dictionary of voice states in the guild.
43
- attr_reader :voice_states
44
- # @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::Member}] A dictionary of members in the guild.
45
- # @macro members_intent
46
- attr_reader :members
47
- # @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::GuildChannel}] A dictionary of channels in the guild.
48
- attr_reader :channels
49
- # @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::ThreadChannel}] A dictionary of threads in the guild.
50
- attr_reader :threads
51
- # @return [Discorb::Dictionary{Discorb::User => Discorb::Presence}] A dictionary of presence in the guild.
52
- attr_reader :presences
53
- # @return [Integer] Number of online members in the guild.
54
- attr_reader :max_presences
55
- # @return [String] The vanity invite URL for the guild.
56
- # @return [nil] If the guild does not have a vanity invite URL.
57
- attr_reader :vanity_url_code
58
- # @return [String] The description of the guild.
59
- attr_reader :description
60
- # @return [Discorb::Asset] The banner of the guild.
61
- # @return [nil] If the guild does not have a banner.
62
- attr_reader :banner
63
- # @return [Integer] The premium tier (Boost Level) of the guild.
64
- attr_reader :premium_tier
65
- # @return [Integer] The amount of premium subscriptions (Server Boosts) the guild has.
66
- attr_reader :premium_subscription_count
67
- # @return [Symbol] The preffered language of the guild.
68
- # @note This modifies the language code, `-` will be replaced with `_`.
69
- attr_reader :preferred_locale
70
- # @return [Integer] The maximum amount of users in a video channel.
71
- attr_reader :max_video_channel_users
72
- # @return [Integer] The approxmate amount of members in the guild.
73
- attr_reader :approximate_member_count
74
- # @return [Integer] The approxmate amount of non-offline members in the guild.
75
- attr_reader :approximate_presence_count
76
- # @return [Discorb::WelcomeScreen] The welcome screen of the guild.
77
- attr_reader :welcome_screen
78
- # @return [:default, :explicit, :safe, :age_restricted] The nsfw level of the guild.
79
- attr_reader :nsfw_level
80
- # @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::StageInstance}]
81
- # A dictionary of stage instances in the guild.
82
- attr_reader :stage_instances
83
- # @return [:none, :low, :medium, :high, :very_high] The verification level of the guild.
84
- attr_reader :verification_level
85
- # @return [:all_messages, :only_mentions] The default message notification level of the guild.
86
- attr_reader :default_message_notifications
87
- # @return [:disabled_in_text, :members_without_roles, :all_members] The explict content filter level of the guild.
88
- attr_reader :explicit_content_filter
89
- # @return [Boolean] Whether the client is the owner of the guild.
90
- attr_reader :owner
91
- alias owner? owner
92
- # @return [Boolean] Whether the guild is large.
93
- attr_reader :large
94
- alias large? large
95
- # @return [Boolean] Whether the guild enabled the widget.
96
- attr_reader :widget_enabled
97
- alias widget_enabled? widget_enabled
98
- # @return [Boolean] Whether the guild is available.
99
- attr_reader :available
100
- alias available? available
101
- # @return [Dictionary{Discorb::Snowflake => Discorb::ScheduledEvent}] A dictionary of scheduled events in the guild.
102
- attr_reader :scheduled_events
103
- alias events scheduled_events
104
-
105
- include Discorb::ChannelContainer
106
-
107
- # @!attribute [r] afk_channel
108
- # @return [Discorb::VoiceChannel] The AFK channel for this guild.
109
- # @macro client_cache
110
- # @!attribute [r] system_channel
111
- # @return [Discorb::TextChannel] The system message channel for this guild.
112
- # @macro client_cache
113
- # @!attribute [r] rules_channel
114
- # @return [Discorb::TextChannel] The rules channel for this guild.
115
- # @macro client_cache
116
- # @!attribute [r] public_updates_channel
117
- # @return [Discorb::TextChannel] The public updates channel (`#moderator-only`) for this guild.
118
- # @macro client_cache
119
- # @!attribute [r] me
120
- # @return [Discorb::Member] The client's member in the guild.
121
-
122
- # @private
123
- # @return [Array<Symbol>] The mapping of mfa_level.
124
- MFA_LEVELS = %i[none elevated].freeze
125
- # @private
126
- # @return [Array<Symbol>] The mapping of nsfw_level.
127
- NSFW_LEVELS = %i[default explicit safe age_restricted].freeze
128
- # @private
129
- # @return [Array<Symbol>] The mapping of verification_level.
130
- VERIFICATION_LEVELS = %i[none low medium high very_high].freeze
131
- # @private
132
- # @return [Array<Symbol>] The mapping of default_message_notifications.
133
- DEFAULT_MESSAGE_NOTIFICATIONS = %i[all_messages only_mentions].freeze
134
- # @private
135
- # @return [Array<Symbol>] The mapping of explicit_content_filter.
136
- EXPLICIT_CONTENT_FILTER = %i[disabled_in_text members_without_roles all_members].freeze
137
-
138
- #
139
- # Creates a new guild object.
140
- # @private
141
- #
142
- # @param [Discorb::Client] client The client that owns this guild.
143
- # @param [Hash] data The data of the guild.
144
- # @param [Boolean] is_create_event Whether the guild is created by a `GUILD_CREATE` event.
145
- #
146
- def initialize(client, data, is_create_event)
147
- @client = client
148
- @data = {}
149
- _set_data(data, is_create_event)
150
- end
151
-
152
- def afk_channel
153
- @client.channels[@afk_channel_id]
154
- end
155
-
156
- def system_channel
157
- @client.channels[@system_channel_id]
158
- end
159
-
160
- def rules_channel
161
- @client.channels[@rules_channel_id]
162
- end
163
-
164
- def public_updates_channel
165
- @client.channels[@public_updates_channel_id]
166
- end
167
-
168
- def inspect
169
- "#<#{self.class} \"#{@name}\" id=#{@id}>"
170
- end
171
-
172
- def me
173
- @members[@client.user.id]
174
- end
175
-
176
- #
177
- # Leave the guild.
178
- # @async
179
- #
180
- # @return [Async::Task<void>] The task.
181
- #
182
- def leave
183
- Async do
184
- @client.http.request(Route.new("/users/@me/guilds/#{@id}", "//users/@me/guilds/:guild_id", :delete)).wait
185
- @client.guilds.delete(@id)
186
- end
187
- end
188
-
189
- #
190
- # Fetch scheduled events for the guild.
191
- # @async
192
- #
193
- # @param [Boolean] with_user_count Whether to include the user count in the events.
194
- # Defaults to `true`.
195
- #
196
- # @return [Array<Discorb::ScheduledEvent>] The events for the guild.
197
- #
198
- def fetch_scheduled_events(with_user_count: true)
199
- Async do
200
- _resp, events = @client.http.request(
201
- Route.new(
202
- "/guilds/#{@id}/scheduled-events?with_user_count=#{with_user_count}",
203
- "//guilds/:guild_id/scheduled-events",
204
- :get
205
- )
206
- ).wait
207
- @scheduled_events = events.map { |e| ScheduledEvent.new(@client, e) }
208
- end
209
- end
210
-
211
- #
212
- # Fetch the scheduled event by ID.
213
- # @async
214
- #
215
- # @param [#to_s] id The ID of the scheduled event.
216
- #
217
- # @return [Async::Task<Discorb::ScheduledEvent>] The event with the given ID.
218
- # @return [Async::Task<nil>] If no event with the given ID exists.
219
- #
220
- def fetch_scheduled_event(id)
221
- Async do
222
- _resp, event = @client.http.request(
223
- Route.new(
224
- "/guilds/#{@id}/scheduled-events/#{id}",
225
- "//guilds/:guild_id/scheduled-events/:scheduled_event_id",
226
- :get
227
- )
228
- ).wait
229
- ScheduledEvent.new(@client, event)
230
- end
231
- end
232
-
233
- #
234
- # Create a scheduled event for the guild.
235
- # @async
236
- #
237
- # @param [:stage_instance, :voice, :external] type The type of event to create.
238
- # @param [String] name The name of the event.
239
- # @param [String] description The description of the event.
240
- # @param [Time] start_time The start time of the event.
241
- # @param [Time, nil] end_time The end time of the event. Defaults to `nil`.
242
- # @param [Discorb::Channel, Discorb::Snowflake, nil] channel The channel to run the event in.
243
- # @param [String, nil] location The location of the event. Defaults to `nil`.
244
- # @param [:guild_only] privacy_level The privacy level of the event. This must be `:guild_only`.
245
- #
246
- # @return [Async::Task<Discorb::ScheduledEvent>] The created event.
247
- #
248
- def create_scheduled_event(
249
- type,
250
- name,
251
- description,
252
- start_time,
253
- end_time = nil,
254
- privacy_level: :guild_only,
255
- location: nil,
256
- channel: nil
257
- )
258
- Async do
259
- payload = case type
260
- when :stage_instance
261
- raise ArgumentError, "channel must be provided for stage_instance events" unless channel
262
-
263
- {
264
- name: name,
265
- description: description,
266
- scheduled_start_time: start_time.iso8601,
267
- scheduled_end_time: end_time&.iso8601,
268
- privacy_level: Discorb::ScheduledEvent::PRIVACY_LEVEL.key(privacy_level),
269
- channel_id: channel&.id,
270
- entity_type: Discorb::ScheduledEvent::ENTITY_TYPE.key(:stage_instance),
271
- }
272
- when :voice
273
- raise ArgumentError, "channel must be provided for voice events" unless channel
274
-
275
- {
276
- name: name,
277
- description: description,
278
- scheduled_start_time: start_time.iso8601,
279
- scheduled_end_time: end_time&.iso8601,
280
- privacy_level: Discorb::ScheduledEvent::PRIVACY_LEVEL.key(privacy_level),
281
- channel_id: channel&.id,
282
- entity_type: Discorb::ScheduledEvent::ENTITY_TYPE.key(:voice),
283
- }
284
- when :external
285
- raise ArgumentError, "location must be provided for external events" unless location
286
- raise ArgumentError, "end_time must be provided for external events" unless end_time
287
-
288
- {
289
- name: name,
290
- description: description,
291
- scheduled_start_time: start_time.iso8601,
292
- scheduled_end_time: end_time.iso8601,
293
- privacy_level: Discorb::ScheduledEvent::PRIVACY_LEVEL.key(privacy_level),
294
- entity_type: Discorb::ScheduledEvent::ENTITY_TYPE.key(:external),
295
- entity_metadata: {
296
- location: location,
297
- },
298
- }
299
- else
300
- raise ArgumentError, "Invalid scheduled event type: #{type}"
301
- end
302
- _resp, event = @client.http.request(
303
- Route.new("/guilds/#{@id}/scheduled-events", "//guilds/:guild_id/scheduled-events", :post), payload
304
- ).wait
305
- Discorb::ScheduledEvent.new(@client, event)
306
- end
307
- end
308
-
309
- #
310
- # Fetch emoji list of the guild.
311
- # @async
312
- # @note This querys the API every time. We recommend using {#emojis} instead.
313
- #
314
- # @return [Async::Task<Discorb::Dictionary{Discorb::Snowflake => Discorb::CustomEmoji}>]
315
- # A dictionary of emoji in the guild.
316
- #
317
- def fetch_emoji_list
318
- Async do
319
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/emojis", "//guilds/:guild_id/emojis", :get)).wait
320
- @emojis = Dictionary.new
321
- ids = @emojis.map(&:id).map(&:to_s)
322
- data.map do |e|
323
- next if ids.include?(e[:id])
324
-
325
- @emojis[e[:id]] = CustomEmoji.new(@client, self, e)
326
- end
327
- @emojis
328
- end
329
- end
330
-
331
- alias fetch_emojis fetch_emoji_list
332
-
333
- #
334
- # Fetch emoji id of the guild.
335
- # @async
336
- # @note This querys the API every time. We recommend using {#emojis} instead.
337
- #
338
- # @param [#to_s] id The emoji id.
339
- #
340
- # @return [Async::Task<Discorb::CustomEmoji>] The emoji with the given id.
341
- #
342
- def fetch_emoji(id)
343
- Async do
344
- _resp, data = @client.http.request(
345
- Route.new(
346
- "/guilds/#{@id}/emojis/#{id}",
347
- "//guilds/:guild_id/emojis/:emoji_id",
348
- :get
349
- )
350
- ).wait
351
- @emojis[e[:id]] = CustomEmoji.new(@client, self, data)
352
- end
353
- end
354
-
355
- #
356
- # Create a custom emoji.
357
- # @async
358
- #
359
- # @param [#to_s] name The name of the emoji.
360
- # @param [Discorb::Image] image The image of the emoji.
361
- # @param [Array<Discorb::Role>] roles A list of roles to give the emoji.
362
- #
363
- # @return [Async::Task<Discorb::CustomEmoji>] The created emoji.
364
- #
365
- def create_emoji(name, image, roles: [])
366
- Async do
367
- _resp, data = @client.http.request(
368
- Route.new("/guilds/#{@id}/emojis", "//guilds/:guild_id/emojis", :post),
369
- {
370
- name: name,
371
- image: image.to_s,
372
- roles: roles.map { |r| Discorb::Utils.try(r, :id) },
373
- }
374
- ).wait
375
- @emojis[data[:id]] = CustomEmoji.new(@client, self, data)
376
- end
377
- end
378
-
379
- #
380
- # Fetch webhooks of the guild.
381
- # @async
382
- #
383
- # @return [Async::Task<Array<Discorb::Webhook>>] A list of webhooks in the guild.
384
- #
385
- def fetch_webhooks
386
- Async do
387
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/webhooks", "//guilds/:guild_id/webhooks",
388
- :get)).wait
389
- data.map { |webhook| Webhook.from_data(@client, webhook) }
390
- end
391
- end
392
-
393
- #
394
- # Fetch audit log of the guild.
395
- # @async
396
- #
397
- # @return [Async::Task<Discorb::AuditLog>] The audit log of the guild.
398
- #
399
- def fetch_audit_log
400
- Async do
401
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/audit-logs", "//guilds/:guild_id/audit-logs",
402
- :get)).wait
403
- AuditLog.new(@client, data, self)
404
- end
405
- end
406
-
407
- #
408
- # Fetch channels of the guild.
409
- # @async
410
- #
411
- # @return [Async::Task<Array<Discorb::Channel>>] A list of channels in the guild.
412
- #
413
- def fetch_channels
414
- Async do
415
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/channels", "//guilds/:guild_id/channels",
416
- :get)).wait
417
- data.map { |c| Channel.make_channel(@client, c) }
418
- end
419
- end
420
-
421
- #
422
- # Create a new text channel.
423
- # @async
424
- #
425
- # @param [String] name The name of the channel.
426
- # @param [String] topic The topic of the channel.
427
- # @param [Integer] rate_limit_per_user The rate limit per user in the channel.
428
- # @param [Integer] slowmode Alias for `rate_limit_per_user`.
429
- # @param [Integer] position The position of the channel.
430
- # @param [Boolean] nsfw Whether the channel is nsfw.
431
- # @param [Hash{Discorb::Role, Discorb::Member => Discorb::PermissionOverwrite}] permission_overwrites
432
- # A list of permission overwrites.
433
- # @param [Discorb::CategoryChannel] parent The parent of the channel.
434
- # @param [String] reason The reason for creating the channel.
435
- #
436
- # @return [Async::Task<Discorb::TextChannel>] The created text channel.
437
- #
438
- def create_text_channel(
439
- name,
440
- topic: nil,
441
- rate_limit_per_user: nil,
442
- slowmode: nil,
443
- position: nil,
444
- nsfw: nil,
445
- permission_overwrites: nil,
446
- parent: nil,
447
- reason: nil
448
- )
449
- Async do
450
- payload = { type: TextChannel.channel_type }
451
- payload[:name] = name
452
- payload[:topic] = topic if topic
453
- rate_limit_per_user ||= slowmode
454
- payload[:rate_limit_per_user] = rate_limit_per_user if rate_limit_per_user
455
- payload[:nsfw] = nsfw if nsfw
456
- payload[:position] = position if position
457
- if permission_overwrites
458
- payload[:permission_overwrites] = permission_overwrites.map do |target, overwrite|
459
- {
460
- type: target.is_a?(Role) ? 0 : 1,
461
- id: target.id,
462
- allow: overwrite.allow_value,
463
- deny: overwrite.deny_value,
464
- }
465
- end
466
- end
467
- payload[:parent_id] = parent.id if parent
468
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/channels", "//guilds/:guild_id/channels", :post),
469
- payload, audit_log_reason: reason).wait
470
- payload[:parent_id] = parent&.id
471
- Channel.make_channel(@client, data)
472
- end
473
- end
474
-
475
- #
476
- # Create a new voice channel.
477
- # @async
478
- #
479
- # @param [String] name The name of the channel.
480
- # @param [Integer] bitrate The bitrate of the channel.
481
- # @param [Integer] user_limit The user limit of the channel.
482
- # @param [Integer] position The position of the channel.
483
- # @param [Hash{Discorb::Role, Discorb::Member => Discorb::PermissionOverwrite}] permission_overwrites
484
- # A list of permission overwrites.
485
- # @param [Discorb::CategoryChannel] parent The parent of the channel.
486
- # @param [String] reason The reason for creating the channel.
487
- #
488
- # @return [Async::Task<Discorb::VoiceChannel>] The created voice channel.
489
- #
490
- def create_voice_channel(
491
- name, bitrate: 64, user_limit: nil, position: nil, permission_overwrites: nil, parent: nil, reason: nil
492
- )
493
- Async do
494
- payload = { type: VoiceChannel.channel_type }
495
- payload[:name] = name
496
- payload[:bitrate] = bitrate * 1000 if bitrate
497
- payload[:user_limit] = user_limit if user_limit
498
- payload[:position] = position if position
499
- if permission_overwrites
500
- payload[:permission_overwrites] = permission_overwrites.map do |target, overwrite|
501
- {
502
- type: target.is_a?(Role) ? 0 : 1,
503
- id: target.id,
504
- allow: overwrite.allow_value,
505
- deny: overwrite.deny_value,
506
- }
507
- end
508
- end
509
- payload[:parent_id] = parent.id if parent
510
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/channels", "//guilds/:guild_id/channels", :post),
511
- payload, audit_log_reason: reason).wait
512
- payload[:parent_id] = parent&.id
513
- Channel.make_channel(@client, data)
514
- end
515
- end
516
-
517
- # Create a new category channel.
518
- # @async
519
- #
520
- # @param [String] name The name of the channel.
521
- # @param [Integer] position The position of the channel.
522
- # @param [Hash{Discorb::Role, Discorb::Member => Discorb::PermissionOverwrite}] permission_overwrites
523
- # A list of permission overwrites.
524
- # @param [Discorb::CategoryChannel] parent The parent of the channel.
525
- # @param [String] reason The reason for creating the channel.
526
- #
527
- # @return [Async::Task<Discorb::CategoryChannel>] The created category channel.
528
- #
529
- def create_category_channel(name, position: nil, permission_overwrites: nil, parent: nil, reason: nil)
530
- Async do
531
- payload = { type: CategoryChannel.channel_type }
532
- payload[:name] = name
533
- payload[:position] = position if position
534
- if permission_overwrites
535
- payload[:permission_overwrites] = permission_overwrites.map do |target, overwrite|
536
- {
537
- type: target.is_a?(Role) ? 0 : 1,
538
- id: target.id,
539
- allow: overwrite.allow_value,
540
- deny: overwrite.deny_value,
541
- }
542
- end
543
- end
544
- payload[:parent_id] = parent&.id
545
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/channels", "//guilds/:guild_id/channels", :post),
546
- payload, audit_log_reason: reason).wait
547
- Channel.make_channel(@client, data)
548
- end
549
- end
550
-
551
- alias create_category create_category_channel
552
-
553
- #
554
- # Create a new stage channel.
555
- # @async
556
- #
557
- # @param [String] name The name of the channel.
558
- # @param [Integer] bitrate The bitrate of the channel.
559
- # @param [Integer] position The position of the channel.
560
- # @param [Hash{Discorb::Role, Discorb::Member => Discorb::PermissionOverwrite}] permission_overwrites
561
- # A list of permission overwrites.
562
- # @param [Discorb::CategoryChannel] parent The parent of the channel.
563
- # @param [String] reason The reason for creating the channel.
564
- #
565
- # @return [Async::Task<Discorb::StageChannel>] The created stage channel.
566
- #
567
- def create_stage_channel(name, bitrate: 64, position: nil, permission_overwrites: nil, parent: nil, reason: nil)
568
- Async do
569
- payload = { type: StageChannel.channel_type }
570
- payload[:name] = name
571
- payload[:bitrate] = bitrate * 1000 if bitrate
572
- payload[:position] = position if position
573
- if permission_overwrites
574
- payload[:permission_overwrites] = permission_overwrites.map do |target, overwrite|
575
- {
576
- type: target.is_a?(Role) ? 0 : 1,
577
- id: target.id,
578
- allow: overwrite.allow_value,
579
- deny: overwrite.deny_value,
580
- }
581
- end
582
- end
583
- payload[:parent_id] = parent&.id
584
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/channels", "//guilds/:guild_id/channels", :post),
585
- payload, audit_log_reason: reason).wait
586
- Channel.make_channel(@client, data)
587
- end
588
- end
589
-
590
- #
591
- # Create a new news channel.
592
- # @async
593
- #
594
- # @param [String] name The name of the channel.
595
- # @param [String] topic The topic of the channel.
596
- # @param [Integer] rate_limit_per_user The rate limit per user in the channel.
597
- # @param [Integer] slowmode Alias for `rate_limit_per_user`.
598
- # @param [Integer] position The position of the channel.
599
- # @param [Boolean] nsfw Whether the channel is nsfw.
600
- # @param [Hash{Discorb::Role, Discorb::Member => Discorb::PermissionOverwrite}] permission_overwrites
601
- # A list of permission overwrites.
602
- # @param [Discorb::CategoryChannel] parent The parent of the channel.
603
- # @param [String] reason The reason for creating the channel.
604
- #
605
- # @return [Async::Task<Discorb::NewsChannel>] The created news channel.
606
- #
607
- def create_news_channel(
608
- name,
609
- topic: nil,
610
- rate_limit_per_user: nil,
611
- slowmode: nil,
612
- position: nil,
613
- nsfw: nil,
614
- permission_overwrites: nil,
615
- parent: nil,
616
- reason: nil
617
- )
618
- Async do
619
- payload = { type: NewsChannel.channel_type }
620
- payload[:name] = name
621
- payload[:topic] = topic if topic
622
- rate_limit_per_user ||= slowmode
623
- payload[:rate_limit_per_user] = rate_limit_per_user if rate_limit_per_user
624
- payload[:position] = position if position
625
- if permission_overwrites
626
- payload[:permission_overwrites] = permission_overwrites.map do |target, overwrite|
627
- {
628
- type: target.is_a?(Role) ? 0 : 1,
629
- id: target.id,
630
- allow: overwrite.allow_value,
631
- deny: overwrite.deny_value,
632
- }
633
- end
634
- end
635
- payload[:nsfw] = nsfw unless nsfw.nil?
636
- payload[:parent_id] = parent&.id
637
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/channels", "//guilds/:guild_id/channels", :post),
638
- payload, audit_log_reason: reason).wait
639
- Channel.make_channel(@client, data)
640
- end
641
- end
642
-
643
- #
644
- # Fetch a list of active threads in the guild.
645
- # @async
646
- #
647
- # @return [Async::Task<Array<Discorb::ThreadChannel>>] The list of threads.
648
- #
649
- def fetch_active_threads
650
- Async do
651
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/threads/active",
652
- "//guilds/:guild_id/threads/active", :get)).wait
653
- data[:threads].map { |t| Channel.make_thread(@client, t) }
654
- end
655
- end
656
-
657
- #
658
- # Fetch a member in the guild.
659
- # @async
660
- #
661
- # @param [#to_s] id The ID of the member to fetch.
662
- #
663
- # @return [Async::Task<Discorb::Member>] The member.
664
- # @return [Async::Task<nil>] If the member is not found.
665
- #
666
- def fetch_member(id)
667
- Async do
668
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/members/#{id}",
669
- "//guilds/:guild_id/members/:user_id", :get)).wait
670
- rescue Discorb::NotFoundError
671
- nil
672
- else
673
- Member.new(@client, @id, data[:user], data)
674
- end
675
- end
676
-
677
- # Fetch members in the guild.
678
- # @async
679
- # @macro members_intent
680
- #
681
- # @param [Integer] limit The maximum number of members to fetch, 0 for all.
682
- # @param [Integer] after The ID of the member to start fetching after.
683
- #
684
- # @return [Async::Task<Array<Discorb::Member>>] The list of members.
685
- #
686
- def fetch_members(limit: 0, after: nil)
687
- Async do
688
- unless limit.zero?
689
- _resp, data = @client.http.request(
690
- Route.new(
691
- "/guilds/#{@id}/members?#{URI.encode_www_form(
692
- {
693
- after: after,
694
- limit: limit,
695
- }
696
- )}", "//guilds/:guild_id/members", :get
697
- )
698
- ).wait
699
- next data[:members].map { |m| Member.new(@client, @id, m[:user], m) }
700
- end
701
- ret = []
702
- after = 0
703
- loop do
704
- params = { after: after, limit: 100 }
705
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/members?#{URI.encode_www_form(params)}",
706
- "//guilds/:guild_id/members", :get)).wait
707
- ret += data.map { |m| Member.new(@client, @id, m[:user], m) }
708
- after = data.last[:user][:id]
709
- break if data.length != 100
710
- end
711
- ret
712
- end
713
- end
714
-
715
- alias fetch_member_list fetch_members
716
-
717
- #
718
- # Search for members by name in the guild.
719
- # @async
720
- #
721
- # @param [String] name The name of the member to search for.
722
- # @param [Integer] limit The maximum number of members to return.
723
- #
724
- # @return [Async::Task<Array<Discorb::Member>>] The list of members.
725
- #
726
- def fetch_members_named(name, limit: 1)
727
- Async do
728
- _resp, data = @client.http.request(
729
- Route.new(
730
- "/guilds/#{@id}/members/search?#{URI.encode_www_form(
731
- {
732
- query: name,
733
- limit: limit,
734
- }
735
- )}", "//guilds/:guild_id/members/search", :get
736
- )
737
- ).wait
738
- data.map { |d| Member.new(@client, @id, d[:user], d) }
739
- end
740
- end
741
-
742
- #
743
- # Almost the same as {#fetch_members_named}, but returns a single member.
744
- # @async
745
- #
746
- # @return [Async::Task<Discorb::Member>] The member.
747
- # @return [Async::Task<nil>] If the member is not found.
748
- #
749
- def fetch_member_named(...)
750
- Async do
751
- fetch_members_named(...).first
752
- end
753
- end
754
-
755
- #
756
- # Change nickname of client member.
757
- # @async
758
- #
759
- # @param [String] nickname The nickname to set.
760
- # @param [String] reason The reason for changing the nickname.
761
- #
762
- # @return [Async::Task<void>] The task.
763
- #
764
- def edit_nickname(nickname, reason: nil)
765
- Async do
766
- @client.http.request(
767
- Route.new("/guilds/#{@id}/members/@me/nick", "//guilds/:guild_id/members/@me/nick",
768
- :patch), { nick: nickname }, audit_log_reason: reason,
769
- ).wait
770
- end
771
- end
772
-
773
- alias edit_nick edit_nickname
774
- alias modify_nickname edit_nickname
775
- alias modify_nick modify_nickname
776
-
777
- #
778
- # Kick a member from the guild.
779
- # @async
780
- #
781
- # @param [Discorb::Member] member The member to kick.
782
- # @param [String] reason The reason for kicking the member.
783
- #
784
- # @return [Async::Task<void>] The task.
785
- #
786
- def kick_member(member, reason: nil)
787
- Async do
788
- @client.http.request(
789
- Route.new("/guilds/#{@id}/members/#{member.id}", "//guilds/:guild_id/members/:user_id",
790
- :delete), {}, audit_log_reason: reason,
791
- ).wait
792
- end
793
- end
794
-
795
- #
796
- # Fetch a list of bans in the guild.
797
- # @async
798
- #
799
- # @param [Integer] limit The number of bans to fetch.
800
- # @param [Discorb::Snowflake] before The ID of the ban to fetch before.
801
- # @param [Discorb::Snowflake] after The ID of the ban to fetch after.
802
- # @param [Discorb::Snowflake] around The ID of the ban to fetch around.
803
- #
804
- # @return [Async::Task<Array<Discorb::Guild::Ban>>] The list of bans.
805
- #
806
- def fetch_bans(limit = 50, before: nil, after: nil, around: nil)
807
- Async do
808
- params = {
809
- limit: limit,
810
- before: Discorb::Utils.try(after, :id),
811
- after: Discorb::Utils.try(around, :id),
812
- around: Discorb::Utils.try(before, :id),
813
- }.filter { |_k, v| !v.nil? }.to_h
814
- _resp, bans = @client.http.request(Route.new("/guilds/#{@id}/bans?#{URI.encode_www_form(params)}",
815
- "//guilds/:guild_id/bans", :get)).wait
816
- bans.map { |d| Ban.new(@client, self, d) }
817
- end
818
- end
819
-
820
- #
821
- # Fetch a ban in the guild.
822
- # @async
823
- #
824
- # @param [Discorb::User] user The user to fetch.
825
- #
826
- # @return [Async::Task<Discorb::Guild::Ban>] The ban.
827
- # @return [Async::Task<nil>] If the ban is not found.
828
- #
829
- def fetch_ban(user)
830
- Async do
831
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/bans/#{user.id}",
832
- "//guilds/:guild_id/bans/:user_id", :get)).wait
833
- rescue Discorb::NotFoundError
834
- nil
835
- else
836
- Ban.new(@client, self, data)
837
- end
838
- end
839
-
840
- #
841
- # Checks the user was banned from the guild.
842
- # @async
843
- #
844
- # @param [Discorb::User] user The user to check.
845
- #
846
- # @return [Async::Task<Boolean>] Whether the user was banned.
847
- #
848
- def banned?(user)
849
- Async do
850
- !fetch_ban(user).wait.nil?
851
- end
852
- end
853
-
854
- #
855
- # Ban a member from the guild.
856
- # @async
857
- #
858
- # @param [Discorb::Member] member The member to ban.
859
- # @param [Integer] delete_message_days The number of days to delete messages.
860
- # @param [String] reason The reason for banning the member.
861
- #
862
- # @return [Async::Task<Discorb::Guild::Ban>] The ban.
863
- #
864
- def ban_member(member, delete_message_days: 0, reason: nil)
865
- Async do
866
- _resp, data = @client.http.request(
867
- Route.new("/guilds/#{@id}/bans",
868
- "//guilds/:guild_id/bans",
869
- :post),
870
- {
871
- user: member.id,
872
- delete_message_days: delete_message_days,
873
- }, audit_log_reason: reason,
874
- ).wait
875
- Ban.new(@client, self, data)
876
- end
877
- end
878
-
879
- #
880
- # Unban a user from the guild.
881
- # @async
882
- #
883
- # @param [Discorb::User] user The user to unban.
884
- # @param [String] reason The reason for unbanning the user.
885
- #
886
- # @return [Async::Task<void>] The task.
887
- #
888
- def unban_user(user, reason: nil)
889
- Async do
890
- @client.http.request(Route.new("/guilds/#{@id}/bans/#{user.id}", "//guilds/:guild_id/bans/:user_id", :delete),
891
- {}, audit_log_reason: reason).wait
892
- end
893
- end
894
-
895
- #
896
- # Fetch a list of roles in the guild.
897
- # @async
898
- #
899
- # @return [Async::Task<Array<Discorb::Role>>] The list of roles.
900
- #
901
- def fetch_roles
902
- Async do
903
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/roles", "//guilds/:guild_id/roles", :get)).wait
904
- data.map { |d| Role.new(@client, self, d) }
905
- end
906
- end
907
-
908
- #
909
- # Create a role in the guild.
910
- # @async
911
- #
912
- # @param [String] name The name of the role.
913
- # @param [Discorb::Color] color The color of the role.
914
- # @param [Boolean] hoist Whether the role should be hoisted.
915
- # @param [Boolean] mentionable Whether the role should be mentionable.
916
- # @param [String] reason The reason for creating the role.
917
- #
918
- # @return [Async::Task<Discorb::Role>] The role.
919
- #
920
- def create_role(name = nil, color: nil, hoist: nil, mentionable: nil, reason: nil)
921
- Async do
922
- payload = {}
923
- payload[:name] = name if name
924
- payload[:color] = color.to_i if color
925
- payload[:hoist] = hoist if hoist
926
- payload[:mentionable] = mentionable if mentionable
927
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/roles", "//guilds/:guild_id/roles", :post),
928
- payload, audit_log_reason: reason).wait
929
- Role.new(@client, self, data)
930
- end
931
- end
932
-
933
- #
934
- # Fetch how many members will be pruned.
935
- # @async
936
- #
937
- # @param [Integer] days The number of days to prune.
938
- # @param [Array<Discorb::Role>] roles The roles that include for pruning.
939
- #
940
- # @return [Async::Task<Integer>] The number of members that will be pruned.
941
- #
942
- def fetch_prune(days = 7, roles: [])
943
- Async do
944
- params = {
945
- days: days,
946
- include_roles: @id.to_s,
947
- }
948
- param[:include_roles] = roles.map(&:id).map(&:to_s).join(";") if roles.any?
949
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/prune?#{URI.encode_www_form(params)}",
950
- "//guilds/:guild_id/prune", :get)).wait
951
- data[:pruned]
952
- end
953
- end
954
-
955
- #
956
- # Prune members from the guild.
957
- # @async
958
- #
959
- # @param [Integer] days The number of days to prune.
960
- # @param [Array<Discorb::Role>] roles The roles that include for pruning.
961
- # @param [String] reason The reason for pruning.
962
- #
963
- # @return [Async::Task<Integer>] The number of members that were pruned.
964
- #
965
- def prune(days = 7, roles: [], reason: nil)
966
- Async do
967
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/prune", "//guilds/:guild_id/prune", :post),
968
- { days: days, roles: roles.map(&:id) }, audit_log_reason: reason).wait
969
- data[:pruned]
970
- end
971
- end
972
-
973
- #
974
- # Fetch voice regions that are available in the guild.
975
- # @async
976
- #
977
- # @return [Async::Task<Array<Discorb::VoiceRegion>>] The available voice regions.
978
- #
979
- def fetch_voice_regions
980
- Async do
981
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/voice", "//guilds/:guild_id/voice", :get)).wait
982
- data.map { |d| VoiceRegion.new(d) }
983
- end
984
- end
985
-
986
- #
987
- # Fetch invites in the guild.
988
- # @async
989
- #
990
- # @return [Async::Task<Array<Invite>>] The invites.
991
- #
992
- def fetch_invites
993
- Async do
994
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/invites", "//guilds/:guild_id/invites", :get)).wait
995
- data.map { |d| Invite.new(@client, d, false) }
996
- end
997
- end
998
-
999
- #
1000
- # Fetch integrations in the guild.
1001
- # @async
1002
- #
1003
- # @return [Async::Task<Array<Discorb::Integration>>] The integrations.
1004
- #
1005
- def fetch_integrations
1006
- Async do
1007
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/integrations", "//guilds/:guild_id/integrations",
1008
- :get)).wait
1009
- data.map { |d| Integration.new(@client, d, @id) }
1010
- end
1011
- end
1012
-
1013
- #
1014
- # Fetch the widget of the guild.
1015
- # @async
1016
- #
1017
- # @return [Async::Task<Discorb::Guild::Widget>] The widget.
1018
- #
1019
- def fetch_widget
1020
- Async do
1021
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/widget", "//guilds/:guild_id/widget", :get)).wait
1022
- Widget.new(@client, @id, data)
1023
- end
1024
- end
1025
-
1026
- #
1027
- # Fetch the vanity URL of the guild.
1028
- # @async
1029
- #
1030
- # @return [Async::Task<Discorb::Guild::VanityInvite>] The vanity URL.
1031
- #
1032
- def fetch_vanity_invite
1033
- Async do
1034
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/vanity-url", "//guilds/:guild_id/vanity-url",
1035
- :get)).wait
1036
- VanityInvite.new(@client, self, data)
1037
- end
1038
- end
1039
-
1040
- #
1041
- # Fetch the welcome screen of the guild.
1042
- # @async
1043
- #
1044
- # @return [Async::Task<Discorb::WelcomeScreen>] The welcome screen.
1045
- #
1046
- def fetch_welcome_screen
1047
- Async do
1048
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/welcome-screen",
1049
- "//guilds/:guild_id/welcome-screen", :get)).wait
1050
- WelcomeScreen.new(@client, self, data)
1051
- end
1052
- end
1053
-
1054
- #
1055
- # Fetch stickers in the guild.
1056
- # @async
1057
- #
1058
- # @return [Async::Task<Array<Discorb::Sticker::GuildSticker>>] The stickers.
1059
- #
1060
- def fetch_stickers
1061
- Async do
1062
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/stickers", "//guilds/:guild_id/stickers",
1063
- :get)).wait
1064
- data.map { |d| Sticker::GuildSticker.new(@client, d) }
1065
- end
1066
- end
1067
-
1068
- #
1069
- # Fetch the sticker by ID.
1070
- # @async
1071
- #
1072
- # @param [#to_s] id The ID of the sticker.
1073
- #
1074
- # @return [Async::Task<Discorb::Sticker::GuildSticker>] The sticker.
1075
- # @return [Async::Task<nil>] If the sticker does not exist.
1076
- #
1077
- def fetch_sticker(id)
1078
- Async do
1079
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/stickers/#{id}",
1080
- "//guilds/:guild_id/stickers/:sticker_id", :get)).wait
1081
- rescue Discorb::NotFoundError
1082
- nil
1083
- else
1084
- Sticker::GuildSticker.new(@client, data)
1085
- end
1086
- end
1087
-
1088
- #
1089
- # Fetch templates in the guild.
1090
- # @async
1091
- #
1092
- # @return [Async::Task<Discorb::GuildTemplate>] The templates.
1093
- #
1094
- def fetch_templates
1095
- Async do
1096
- _resp, data = @client.http.request(Route.new("/guilds/#{@id}/templates", "//guilds/:guild_id/templates",
1097
- :get)).wait
1098
- data.map { |d| GuildTemplate.new(@client, d) }
1099
- end
1100
- end
1101
-
1102
- #
1103
- # Almost the same as {#fetch_templates}, but returns a single template.
1104
- #
1105
- # @return [Discorb::GuildTemplate] The template.
1106
- # @return [Async::Task<nil>] If the template does not exist.
1107
- #
1108
- def fetch_template
1109
- Async do
1110
- fetch_templates.wait.first
1111
- end
1112
- end
1113
-
1114
- #
1115
- # Create a new template in the guild.
1116
- #
1117
- # @param [String] name The name of the template.
1118
- # @param [String] description The description of the template.
1119
- # @param [String] reason The reason for creating the template.
1120
- #
1121
- # @return [Async::Task<Discorb::GuildTemplate>] The template.
1122
- #
1123
- def create_template(name, description = nil, reason: nil)
1124
- Async do
1125
- _resp, data = @client.http.request(
1126
- Route.new("/guilds/#{@id}/templates", "//guilds/:guild_id/templates",
1127
- :post), { name: name, description: description }, audit_log_reason: reason,
1128
- ).wait
1129
- GuildTemplate.new(@client, data)
1130
- end
1131
- end
1132
-
1133
- #
1134
- # Fetch the automod rules in the guild.
1135
- # @async
1136
- #
1137
- # @return [Async::Task<Array<Discorb::AutoModRule>>] The automod rules.
1138
- #
1139
- def fetch_automod_rules
1140
- Async do
1141
- _resp, data = @client.http.request(
1142
- Route.new("/guilds/#{@id}/auto-moderation/rules", "//guilds/:guild_id/auto-moderation/rules", :get)
1143
- )
1144
- data.map { |d| AutoModRule.new(@client, d) }
1145
- end
1146
- end
1147
-
1148
- alias fetch_automod_rule_list fetch_automod_rules
1149
-
1150
- #
1151
- # Fetch the automod rule by ID.
1152
- #
1153
- # @param [#to_s] id The ID of the automod rule.
1154
- #
1155
- # @return [Async::Task<Array<Discord::AutoModRule>>] The automod rule.
1156
- #
1157
- def fetch_automod_rule(id)
1158
- Async do
1159
- _resp, data = @client.http.request(
1160
- Route.new(
1161
- "/guilds/#{@id}/auto-moderation/rules/#{id}",
1162
- "//guilds/:guild_id/auto-moderation/rules/:rule_id",
1163
- :get
1164
- )
1165
- ).wait
1166
- AutoModRule.new(@client, data)
1167
- end
1168
- end
1169
-
1170
- #
1171
- # Create a new automod rule in the guild.
1172
- # @async
1173
- #
1174
- # @param [String] name The name of the rule.
1175
- # @param [Symbol] trigger_type The trigger type of the rule. See {Discorb::AutoModRule::TRIGGER_TYPES}.
1176
- # @param [Array<Discorb::AutoModRule::Action>] actions The actions of the rule.
1177
- # @param [Symbol] event_type The event type of the rule. See {Discorb::AutoModRule::EVENT_TYPES}.
1178
- # @param [Boolean] enabled Whether the rule is enabled or not.
1179
- # @param [Array<Discorb::Role>] exempt_roles The roles that are exempt from the rule.
1180
- # @param [Array<Discorb::Channel>] exempt_channels The channels that are exempt from the rule.
1181
- # @param [Array<String>] keyword_filter The keywords to filter.
1182
- # @param [Symbol] presets The preset of the rule. See {Discorb::AutoModRule::PRESET_TYPES}.
1183
- # @param [String] reason The reason for creating the rule.
1184
- #
1185
- # @return [Async::Task<Discorb::AutoModRule>] The automod rule.
1186
- #
1187
- def create_automod_rule(
1188
- name,
1189
- trigger_type,
1190
- actions,
1191
- event_type = :message_send,
1192
- enabled: false,
1193
- exempt_roles: [],
1194
- exempt_channels: [],
1195
- keyword_filter: nil,
1196
- presets: nil,
1197
- reason: nil
1198
- )
1199
- Async do
1200
- payload = {
1201
- name: name,
1202
- event_type: Discorb::AutoModRule::EVENT_TYPES.key(event_type),
1203
- trigger_type: Discorb::AutoModRule::TRIGGER_TYPES.key(trigger_type),
1204
- metadata: {
1205
- keyword_filter: keyword_filter,
1206
- presets: presets && Discorb::AutoModRule::PRESET_TYPES.key(presets),
1207
- },
1208
- actions: actions.map(&:to_hash),
1209
- enabled: enabled,
1210
- exempt_roles: exempt_roles.map(&:id),
1211
- exempt_channels: exempt_channels.map(&:id),
1212
- }
1213
-
1214
- _resp, data = @client.http.request(
1215
- Route.new(
1216
- "/guilds/#{@id}/auto-moderation/rules",
1217
- "//guilds/:guild_id/auto-moderation/rules",
1218
- :post
1219
- ),
1220
- payload,
1221
- audit_log_reason: reason
1222
- )
1223
- Discorb::AutoModRule.new(@client, data)
1224
- end
1225
- end
1226
-
1227
- #
1228
- # Represents a vanity invite.
1229
- #
1230
- class VanityInvite < DiscordModel
1231
- # @return [String] The vanity invite code.
1232
- attr_reader :code
1233
- # @return [Integer] The number of uses.
1234
- attr_reader :uses
1235
-
1236
- # @!attribute [r] url
1237
- # @return [String] The vanity URL.
1238
-
1239
- #
1240
- # Initialize a new instance of the {VanityInvite} class.
1241
- # @private
1242
- #
1243
- # @param [Discorb::Client] client The client.
1244
- # @param [Discorb::Guild] guild The guild.
1245
- # @param [Hash] data The data of the invite.
1246
- #
1247
- def initialize(client, guild, data)
1248
- @client = client
1249
- @guild = guild
1250
- @code = data[:code]
1251
- @uses = data[:uses]
1252
- end
1253
-
1254
- def url
1255
- "https://discord.gg/#{@code}"
1256
- end
1257
- end
1258
-
1259
- #
1260
- # Represents a guild widget.
1261
- #
1262
- class Widget < DiscordModel
1263
- # @return [Discorb::Snowflake] The guild ID.
1264
- attr_reader :guild_id
1265
- # @return [Discorb::Snowflake] The channel ID.
1266
- attr_reader :channel_id
1267
- # @return [Boolean] Whether the widget is enabled.
1268
- attr_reader :enabled
1269
- alias enabled? enabled
1270
- alias enable? enabled
1271
-
1272
- # @!attribute [r] channel
1273
- # @macro client_cache
1274
- # @return [Discorb::Channel] The channel.
1275
- # @!attribute [r] guild
1276
- # @macro client_cache
1277
- # @return [Discorb::Guild] The guild.
1278
- # @!attribute [r] json_url
1279
- # @return [String] The JSON URL.
1280
-
1281
- #
1282
- # Initialize a new instance of the {Widget} class.
1283
- # @private
1284
- #
1285
- # @param [Discorb::Client] client The client.
1286
- # @param [Discorb::Snowflake] guild_id The guild ID.
1287
- # @param [Hash] data The data from Discord.
1288
- #
1289
- def initialize(client, guild_id, data)
1290
- @client = client
1291
- @enabled = data[:enabled]
1292
- @guild_id = Snowflake.new(guild_id)
1293
- @channel_id = Snowflake.new(data[:channel_id])
1294
- end
1295
-
1296
- def channel
1297
- @client.channels[@channel_id]
1298
- end
1299
-
1300
- #
1301
- # Edit the widget.
1302
- # @async
1303
- # @macro edit
1304
- #
1305
- # @param [Boolean] enabled Whether the widget is enabled.
1306
- # @param [Discorb::GuildChannel] channel The channel.
1307
- # @param [String] reason The reason for editing the widget.
1308
- #
1309
- # @return [Async::Task<void>] The task.
1310
- #
1311
- def edit(enabled: nil, channel: nil, reason: nil)
1312
- Async do
1313
- payload = {}
1314
- payload[:enabled] = enabled unless enabled.nil?
1315
- payload[:channel_id] = channel.id if channel_id
1316
- @client.http.request(Route.new("/guilds/#{@guild_id}/widget", "//guilds/:guild_id/widget", :patch), payload,
1317
- audit_log_reason: reason).wait
1318
- end
1319
- end
1320
-
1321
- alias modify edit
1322
-
1323
- def json_url
1324
- "#{Discorb::API_BASE_URL}/guilds/#{@guild_id}/widget.json"
1325
- end
1326
-
1327
- #
1328
- # Return iframe HTML of the widget.
1329
- #
1330
- # @param ["dark", "light"] theme The theme of the widget.
1331
- # @param [Integer] width The width of the widget.
1332
- # @param [Integer] height The height of the widget.
1333
- #
1334
- # @return [String] The iframe HTML.
1335
- #
1336
- def iframe(theme: "dark", width: 350, height: 500)
1337
- # rubocop:disable Layout/LineLength
1338
- [
1339
- %(<iframe src="https://canary.discord.com/widget?id=#{@guild_id}&theme=#{theme}" width="#{width}" height="#{height}"),
1340
- %(allowtransparency="true" frameborder="0" sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts"></iframe>),
1341
- ].join
1342
- # rubocop:enable Layout/LineLength
1343
- end
1344
- end
1345
-
1346
- #
1347
- # Represents a ban.
1348
- #
1349
- class Ban < DiscordModel
1350
- # @return [Discorb::User] The user.
1351
- attr_reader :user
1352
- # @return [String] The reason for the ban.
1353
- attr_reader :reason
1354
-
1355
- #
1356
- # Initialize a new instance of the {Ban} class.
1357
- # @private
1358
- #
1359
- # @param [Discorb::Client] client The client.
1360
- # @param [Discorb::Guild] guild The guild.
1361
- # @param [Hash] data The data from Discord.
1362
- #
1363
- def initialize(client, guild, data)
1364
- @client = client
1365
- @guild = guild
1366
- @reason = data[:reason]
1367
- @user = @client.users[data[:user][:id]] || User.new(@client, data[:user])
1368
- end
1369
-
1370
- def inspect
1371
- "<#{self.class.name} #{@user}>"
1372
- end
1373
- end
1374
-
1375
- class << self
1376
- #
1377
- # Returns a banner url from the guild's ID.
1378
- #
1379
- # @param [#to_s] guild_id The ID of the guild.
1380
- # @param [:shield, :banner1, :banner2, :banner3, :banner4] style The style of the banner.
1381
- #
1382
- # @return [String] The url of the banner.
1383
- #
1384
- def banner(guild_id, style: :banner)
1385
- "#{Discorb::API_BASE_URL}/guilds/#{guild_id}/widget.png&style=#{style}"
1386
- end
1387
- end
1388
-
1389
- private
1390
-
1391
- def _set_data(data, is_create_event)
1392
- @id = Snowflake.new(data[:id])
1393
- if data[:unavailable]
1394
- @unavailable = true
1395
- return
1396
- end
1397
- @client.guilds[@id] = self unless data[:no_cache]
1398
- @icon = data[:icon] && Asset.new(self, data[:icon])
1399
- @unavailable = false
1400
- @name = data[:name]
1401
- @members = Discorb::Dictionary.new
1402
- data[:members]&.each do |m|
1403
- Member.new(@client, @id, m[:user], m)
1404
- end
1405
- @splash = data[:splash] && Asset.new(self, data[:splash], path: "splashes/#{@id}")
1406
- @discovery_splash = data[:discovery_splash] && Asset.new(self, data[:discovery_splash],
1407
- path: "discovery-splashes/#{@id}")
1408
- @owner_id = data[:owner_id]
1409
- @permissions = Permission.new(data[:permissions].to_i)
1410
- @afk_channel_id = data[:afk_channel_id]
1411
- @afk_timeout = data[:afk_timeout]
1412
- @widget_enabled = data[:widget_enabled]
1413
- @widget_channel_id = data[:widget_channel_id]
1414
- @roles = Dictionary.new
1415
- data[:roles].each do |r|
1416
- @roles[r[:id]] = Role.new(@client, self, r)
1417
- end
1418
- @emojis = Dictionary.new
1419
- data[:emojis].map do |e|
1420
- @emojis[e[:id]] = CustomEmoji.new(@client, self, e)
1421
- end
1422
- @features = data[:features].map { |f| f.downcase.to_sym }
1423
- @mfa_level = MFA_LEVELS[data[:mfa_level]]
1424
- @verification_level = VERIFICATION_LEVELS[data[:verification_level]]
1425
- @default_message_notifications = DEFAULT_MESSAGE_NOTIFICATIONS[data[:default_message_notifications]]
1426
- @explicit_content_filter = EXPLICIT_CONTENT_FILTER[data[:explicit_content_filter]]
1427
- @system_channel_id = data[:system_channel_id]
1428
- @system_channel_flag = SystemChannelFlag.new(0b111 - data[:system_channel_flags])
1429
- @rules_channel_id = data[:rules_channel_id]
1430
- @vanity_url_code = data[:vanity_url_code]
1431
- @description = data[:description]
1432
- @banner = data[:banner] && Asset.new(self, data[:banner], path: "banners/#{@id}")
1433
- @premium_tier = data[:premium_tier]
1434
- @premium_subscription_count = data[:premium_tier_count].to_i
1435
- @preferred_locale = data[:preferred_locale].gsub("-", "_").to_sym
1436
- @public_updates_channel_id = data[:public_updates_channel_id]
1437
- @max_video_channel_users = data[:max_video_channel_users]
1438
- @approximate_member_count = data[:approximate_member_count]
1439
- @approximate_presence_count = data[:approximate_presence_count]
1440
- @welcome_screen = data[:welcome_screen].nil? ? nil : WelcomeScreen.new(@client, self, data[:welcome_screen])
1441
- @nsfw_level = NSFW_LEVELS[data[:nsfw_level]]
1442
- return unless is_create_event
1443
-
1444
- @stickers = data[:stickers].nil? ? [] : data[:stickers].map { |s| Sticker::GuildSticker.new(@client, s) }
1445
- @joined_at = Time.iso8601(data[:joined_at])
1446
- @large = data[:large]
1447
- @member_count = data[:member_count]
1448
- tmp_channels = data[:channels].filter { |c| !c.key?(:thread_metadata) }.map do |c|
1449
- Channel.make_channel(@client, c.merge({ guild_id: @id }))
1450
- end
1451
- @channels = Dictionary.new(tmp_channels.to_h { |c| [c.id, c] }, sort: ->(c) { c[1].position })
1452
- @voice_states = Dictionary.new(data[:voice_states].to_h do |v|
1453
- [Snowflake.new(v[:user_id]), VoiceState.new(@client, v.merge({ guild_id: @id }))]
1454
- end)
1455
- @threads = data[:threads] ? data[:threads].map { |t| Channel.make_channel(@client, t) } : []
1456
- @presences = Dictionary.new(data[:presences].to_h do |pr|
1457
- [Snowflake.new(pr[:user][:id]), Presence.new(@client, pr)]
1458
- end)
1459
- @max_presences = data[:max_presences]
1460
- @stage_instances = Dictionary.new(data[:stage_instances].to_h do |s|
1461
- [Snowflake.new(s[:id]), StageInstance.new(@client, s)]
1462
- end)
1463
- @scheduled_events = Dictionary.new(data[:guild_scheduled_events].to_h do |s|
1464
- [Snowflake.new(s[:id]), ScheduledEvent.new(@client, s)]
1465
- end)
1466
- @data.update(data)
1467
- end
1468
- end
1469
-
1470
- #
1471
- # Represents a system channel flag.
1472
- # ## Flag fields
1473
- # |Field|Value|
1474
- # |-|-|
1475
- # |`1 << 0`|`:member_join`|
1476
- # |`1 << 1`|`:server_boost`|
1477
- # |`1 << 2`|`:setup_tips`|
1478
- # |`1 << 3`|`:join_stickers`|
1479
- #
1480
- class SystemChannelFlag < Flag
1481
- @bits = {
1482
- member_join: 0,
1483
- server_boost: 1,
1484
- setup_tips: 2,
1485
- join_stickers: 3,
1486
- }.freeze
1487
- end
1488
-
1489
- #
1490
- # Represents a welcome screen.
1491
- #
1492
- class WelcomeScreen < DiscordModel
1493
- # @return [String] The description of the welcome screen.
1494
- attr_reader :description
1495
- # @return [Array<Discorb::WelcomeScreen::Channel>] The channels to display the welcome screen.
1496
- attr_reader :channels
1497
- # @return [Discorb::Guild] The guild the welcome screen belongs to.
1498
- attr_reader :guild
1499
-
1500
- #
1501
- # Initializes the welcome screen.
1502
- # @private
1503
- #
1504
- # @param [Discorb::Client] client The client.
1505
- # @param [Discorb::Guild] guild The guild the welcome screen belongs to.
1506
- # @param [Hash] data The data of the welcome screen.
1507
- #
1508
- def initialize(client, guild, data)
1509
- @client = client
1510
- @description = data[:description]
1511
- @guild = guild
1512
- @channels = data[:channels].map do |c|
1513
- WelcomeScreen::Channel.new(
1514
- client.channels[c[:channel_id]],
1515
- c,
1516
- c[:emoji_name] &&
1517
- if c[:emoji_id]
1518
- (client.emojis[c[:emoji_id]] ||
1519
- Discorb::PartialEmoji.new(
1520
- {
1521
- name: c[:emoji_name],
1522
- id: c[:emoji_id],
1523
- }
1524
- ))
1525
- else
1526
- Discorb::UnicodeEmoji.new(c[:emoji_name])
1527
- end
1528
- )
1529
- end
1530
- end
1531
-
1532
- #
1533
- # Represents a channel to display the welcome screen.
1534
- #
1535
- class Channel < DiscordModel
1536
- # @return [String] The channel's name.
1537
- attr_reader :description
1538
-
1539
- # @!attribute [r] emoji
1540
- # @return [Discorb::Emoji] The emoji to display.
1541
- # @!attribute [r] channel
1542
- # @macro client_cache
1543
- # @return [Discorb::Channel] The channel to display the welcome screen.
1544
-
1545
- #
1546
- # Initialize a new welcome screen channel.
1547
- #
1548
- # @param [Discorb::TextChannel] channel The channel to display the welcome screen.
1549
- # @param [String] description The channel's name.
1550
- # @param [Discorb::Emoji] emoji The emoji to display.
1551
- #
1552
- def initialize(channel, description, emoji)
1553
- if description.is_a?(Hash)
1554
- @screen = channel
1555
- data = description
1556
- @channel_id = Snowflake.new(data[:channel_id])
1557
- @description = data[:description]
1558
- @emoji_id = Snowflake.new(data[:emoji_id])
1559
- @emoji_name = data[:emoji_name]
1560
- else
1561
- @channel_id = channel.id
1562
- @description = description
1563
- if emoji.is_a?(UnicodeEmoji)
1564
- @emoji_id = nil
1565
- @emoji_name = emoji.value
1566
- else
1567
- @emoji_id = emoji.id
1568
- @emoji_name = emoji.name
1569
- end
1570
- end
1571
- end
1572
-
1573
- #
1574
- # Converts the channel to a hash.
1575
- #
1576
- # @return [Hash] The hash.
1577
- # @see https://discord.com/developers/docs/resources/guild#welcome-screen-object
1578
- #
1579
- def to_hash
1580
- {
1581
- channel_id: @channel_id,
1582
- description: @description,
1583
- emoji_id: @emoji_id,
1584
- emoji_name: @emoji_name,
1585
- }
1586
- end
1587
-
1588
- def channel
1589
- @screen.guild.channels[@channel_id]
1590
- end
1591
-
1592
- def emoji
1593
- if @emoji_id.nil?
1594
- UnicodeEmoji.new(@emoji_name)
1595
- else
1596
- @screen.guild.emojis[@emoji_id]
1597
- end
1598
- end
1599
-
1600
- #
1601
- # Edits the welcome screen.
1602
- # @async
1603
- # @macro edit
1604
- #
1605
- # @param [Boolean] enabled Whether the welcome screen is enabled.
1606
- # @param [Array<Discorb::WelcomeScreen::Channel>] channels The channels to display the welcome screen.
1607
- # @param [String] description The description of the welcome screen.
1608
- # @param [String] reason The reason for editing the welcome screen.
1609
- #
1610
- # @return [Async::Task<void>] The task.
1611
- #
1612
- def edit(enabled: Discorb::Unset, channels: Discorb::Unset, description: Discorb::Unset, reason: nil)
1613
- Async do
1614
- payload = {}
1615
- payload[:enabled] = enabled unless enabled == Discorb::Unset
1616
- payload[:welcome_channels] = channels.map(&:to_hash) unless channels == Discorb::Unset
1617
- payload[:description] = description unless description == Discorb::Unset
1618
- @client.http.request(
1619
- Route.new("/guilds/#{@guild.id}/welcome-screen", "//guilds/:guild_id/welcome-screen",
1620
- :patch), payload, audit_log_reason: reason,
1621
- ).wait
1622
- end
1623
- end
1624
- end
1625
- end
1626
- end
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}]
25
+ # A dictionary of custom emojis in the guild.
26
+ attr_reader :emojis
27
+ # @return [Array<Symbol>] features that are enabled in the guild.
28
+ # @see https://discord.com/developers/docs/resources/guild#guild-object-guild-features Official Discord API docs
29
+ attr_reader :features
30
+ # @return [:none, :elevated] The MFA level of the guild.
31
+ attr_reader :mfa_level
32
+ # @return [Discorb::SystemChannelFlag] The flag for the system channel.
33
+ attr_reader :system_channel_flags
34
+ # @return [Time] Time that representing when bot has joined the guild.
35
+ attr_reader :joined_at
36
+ # @return [Boolean] Whether the guild is unavailable.
37
+ attr_reader :unavailable
38
+ # @return [Integer] The amount of members in the guild.
39
+ attr_reader :member_count
40
+ # @return [Discorb::Asset] The icon of the guild.
41
+ attr_reader :icon
42
+ # @return [Discorb::Dictionary{Discorb::User => Discorb::VoiceState}] A dictionary of voice states in the guild.
43
+ attr_reader :voice_states
44
+ # @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::Member}] A dictionary of members in the guild.
45
+ # @macro members_intent
46
+ attr_reader :members
47
+ # @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::GuildChannel}] A dictionary of channels in the guild.
48
+ attr_reader :channels
49
+ # @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::ThreadChannel}] A dictionary of threads in the guild.
50
+ attr_reader :threads
51
+ # @return [Discorb::Dictionary{Discorb::User => Discorb::Presence}] A dictionary of presence in the guild.
52
+ attr_reader :presences
53
+ # @return [Integer] Number of online members in the guild.
54
+ attr_reader :max_presences
55
+ # @return [String] The vanity invite URL for the guild.
56
+ # @return [nil] If the guild does not have a vanity invite URL.
57
+ attr_reader :vanity_url_code
58
+ # @return [String] The description of the guild.
59
+ attr_reader :description
60
+ # @return [Discorb::Asset] The banner of the guild.
61
+ # @return [nil] If the guild does not have a banner.
62
+ attr_reader :banner
63
+ # @return [Integer] The premium tier (Boost Level) of the guild.
64
+ attr_reader :premium_tier
65
+ # @return [Integer] The amount of premium subscriptions (Server Boosts) the guild has.
66
+ attr_reader :premium_subscription_count
67
+ # @return [Symbol] The preffered language of the guild.
68
+ # @note This modifies the language code, `-` will be replaced with `_`.
69
+ attr_reader :preferred_locale
70
+ # @return [Integer] The maximum amount of users in a video channel.
71
+ attr_reader :max_video_channel_users
72
+ # @return [Integer] The approxmate amount of members in the guild.
73
+ attr_reader :approximate_member_count
74
+ # @return [Integer] The approxmate amount of non-offline members in the guild.
75
+ attr_reader :approximate_presence_count
76
+ # @return [Discorb::WelcomeScreen] The welcome screen of the guild.
77
+ attr_reader :welcome_screen
78
+ # @return [:default, :explicit, :safe, :age_restricted] The nsfw level of the guild.
79
+ attr_reader :nsfw_level
80
+ # @return [Discorb::Dictionary{Discorb::Snowflake => Discorb::StageInstance}]
81
+ # A dictionary of stage instances in the guild.
82
+ attr_reader :stage_instances
83
+ # @return [:none, :low, :medium, :high, :very_high] The verification level of the guild.
84
+ attr_reader :verification_level
85
+ # @return [:all_messages, :only_mentions] The default message notification level of the guild.
86
+ attr_reader :default_message_notifications
87
+ # @return [:disabled_in_text, :members_without_roles, :all_members] The explict content filter level of the guild.
88
+ attr_reader :explicit_content_filter
89
+ # @return [Boolean] Whether the client is the owner of the guild.
90
+ attr_reader :owner
91
+ alias owner? owner
92
+ # @return [Boolean] Whether the guild is large.
93
+ attr_reader :large
94
+ alias large? large
95
+ # @return [Boolean] Whether the guild enabled the widget.
96
+ attr_reader :widget_enabled
97
+ alias widget_enabled? widget_enabled
98
+ # @return [Boolean] Whether the guild is available.
99
+ attr_reader :available
100
+ alias available? available
101
+ # @return [Dictionary{Discorb::Snowflake => Discorb::ScheduledEvent}] A dictionary of scheduled events in the guild.
102
+ attr_reader :scheduled_events
103
+ alias events scheduled_events
104
+
105
+ include Discorb::ChannelContainer
106
+
107
+ # @!attribute [r] afk_channel
108
+ # @return [Discorb::VoiceChannel] The AFK channel for this guild.
109
+ # @macro client_cache
110
+ # @!attribute [r] system_channel
111
+ # @return [Discorb::TextChannel] The system message channel for this guild.
112
+ # @macro client_cache
113
+ # @!attribute [r] rules_channel
114
+ # @return [Discorb::TextChannel] The rules channel for this guild.
115
+ # @macro client_cache
116
+ # @!attribute [r] public_updates_channel
117
+ # @return [Discorb::TextChannel] The public updates channel (`#moderator-only`) for this guild.
118
+ # @macro client_cache
119
+ # @!attribute [r] me
120
+ # @return [Discorb::Member] The client's member in the guild.
121
+
122
+ # @private
123
+ # @return [Array<Symbol>] The mapping of mfa_level.
124
+ MFA_LEVELS = %i[none elevated].freeze
125
+ # @private
126
+ # @return [Array<Symbol>] The mapping of nsfw_level.
127
+ NSFW_LEVELS = %i[default explicit safe age_restricted].freeze
128
+ # @private
129
+ # @return [Array<Symbol>] The mapping of verification_level.
130
+ VERIFICATION_LEVELS = %i[none low medium high very_high].freeze
131
+ # @private
132
+ # @return [Array<Symbol>] The mapping of default_message_notifications.
133
+ DEFAULT_MESSAGE_NOTIFICATIONS = %i[all_messages only_mentions].freeze
134
+ # @private
135
+ # @return [Array<Symbol>] The mapping of explicit_content_filter.
136
+ EXPLICIT_CONTENT_FILTER = %i[
137
+ disabled_in_text
138
+ members_without_roles
139
+ all_members
140
+ ].freeze
141
+
142
+ #
143
+ # Creates a new guild object.
144
+ # @private
145
+ #
146
+ # @param [Discorb::Client] client The client that owns this guild.
147
+ # @param [Hash] data The data of the guild.
148
+ # @param [Boolean] is_create_event Whether the guild is created by a `GUILD_CREATE` event.
149
+ #
150
+ def initialize(client, data, is_create_event)
151
+ @client = client
152
+ @data = {}
153
+ _set_data(data, is_create_event)
154
+ end
155
+
156
+ def afk_channel
157
+ @client.channels[@afk_channel_id]
158
+ end
159
+
160
+ def system_channel
161
+ @client.channels[@system_channel_id]
162
+ end
163
+
164
+ def rules_channel
165
+ @client.channels[@rules_channel_id]
166
+ end
167
+
168
+ def public_updates_channel
169
+ @client.channels[@public_updates_channel_id]
170
+ end
171
+
172
+ def inspect
173
+ "#<#{self.class} \"#{@name}\" id=#{@id}>"
174
+ end
175
+
176
+ def me
177
+ @members[@client.user.id]
178
+ end
179
+
180
+ #
181
+ # Leave the guild.
182
+ # @async
183
+ #
184
+ # @return [Async::Task<void>] The task.
185
+ #
186
+ def leave
187
+ Async do
188
+ @client
189
+ .http
190
+ .request(
191
+ Route.new(
192
+ "/users/@me/guilds/#{@id}",
193
+ "//users/@me/guilds/:guild_id",
194
+ :delete
195
+ )
196
+ )
197
+ .wait
198
+ @client.guilds.delete(@id)
199
+ end
200
+ end
201
+
202
+ #
203
+ # Fetch scheduled events for the guild.
204
+ # @async
205
+ #
206
+ # @param [Boolean] with_user_count Whether to include the user count in the events.
207
+ # Defaults to `true`.
208
+ #
209
+ # @return [Array<Discorb::ScheduledEvent>] The events for the guild.
210
+ #
211
+ def fetch_scheduled_events(with_user_count: true)
212
+ Async do
213
+ _resp, events =
214
+ @client
215
+ .http
216
+ .request(
217
+ Route.new(
218
+ "/guilds/#{@id}/scheduled-events?with_user_count=#{with_user_count}",
219
+ "//guilds/:guild_id/scheduled-events",
220
+ :get
221
+ )
222
+ )
223
+ .wait
224
+ @scheduled_events = events.map { |e| ScheduledEvent.new(@client, e) }
225
+ end
226
+ end
227
+
228
+ #
229
+ # Fetch the scheduled event by ID.
230
+ # @async
231
+ #
232
+ # @param [#to_s] id The ID of the scheduled event.
233
+ #
234
+ # @return [Async::Task<Discorb::ScheduledEvent>] The event with the given ID.
235
+ # @return [Async::Task<nil>] If no event with the given ID exists.
236
+ #
237
+ def fetch_scheduled_event(id)
238
+ Async do
239
+ _resp, event =
240
+ @client
241
+ .http
242
+ .request(
243
+ Route.new(
244
+ "/guilds/#{@id}/scheduled-events/#{id}",
245
+ "//guilds/:guild_id/scheduled-events/:scheduled_event_id",
246
+ :get
247
+ )
248
+ )
249
+ .wait
250
+ ScheduledEvent.new(@client, event)
251
+ end
252
+ end
253
+
254
+ #
255
+ # Create a scheduled event for the guild.
256
+ # @async
257
+ #
258
+ # @param [:stage_instance, :voice, :external] type The type of event to create.
259
+ # @param [String] name The name of the event.
260
+ # @param [String] description The description of the event.
261
+ # @param [Time] start_time The start time of the event.
262
+ # @param [Time, nil] end_time The end time of the event. Defaults to `nil`.
263
+ # @param [Discorb::Channel, Discorb::Snowflake, nil] channel The channel to run the event in.
264
+ # @param [String, nil] location The location of the event. Defaults to `nil`.
265
+ # @param [:guild_only] privacy_level The privacy level of the event. This must be `:guild_only`.
266
+ #
267
+ # @return [Async::Task<Discorb::ScheduledEvent>] The created event.
268
+ #
269
+ def create_scheduled_event(
270
+ type,
271
+ name,
272
+ description,
273
+ start_time,
274
+ end_time = nil,
275
+ privacy_level: :guild_only,
276
+ location: nil,
277
+ channel: nil
278
+ )
279
+ Async do
280
+ payload =
281
+ case type
282
+ when :stage_instance
283
+ unless channel
284
+ raise ArgumentError,
285
+ "channel must be provided for stage_instance events"
286
+ end
287
+
288
+ {
289
+ name: name,
290
+ description: description,
291
+ scheduled_start_time: start_time.iso8601,
292
+ scheduled_end_time: end_time&.iso8601,
293
+ privacy_level:
294
+ Discorb::ScheduledEvent::PRIVACY_LEVEL.key(privacy_level),
295
+ channel_id: channel&.id,
296
+ entity_type:
297
+ Discorb::ScheduledEvent::ENTITY_TYPE.key(:stage_instance)
298
+ }
299
+ when :voice
300
+ unless channel
301
+ raise ArgumentError, "channel must be provided for voice events"
302
+ end
303
+
304
+ {
305
+ name: name,
306
+ description: description,
307
+ scheduled_start_time: start_time.iso8601,
308
+ scheduled_end_time: end_time&.iso8601,
309
+ privacy_level:
310
+ Discorb::ScheduledEvent::PRIVACY_LEVEL.key(privacy_level),
311
+ channel_id: channel&.id,
312
+ entity_type: Discorb::ScheduledEvent::ENTITY_TYPE.key(:voice)
313
+ }
314
+ when :external
315
+ unless location
316
+ raise ArgumentError,
317
+ "location must be provided for external events"
318
+ end
319
+ unless end_time
320
+ raise ArgumentError,
321
+ "end_time must be provided for external events"
322
+ end
323
+
324
+ {
325
+ name: name,
326
+ description: description,
327
+ scheduled_start_time: start_time.iso8601,
328
+ scheduled_end_time: end_time.iso8601,
329
+ privacy_level:
330
+ Discorb::ScheduledEvent::PRIVACY_LEVEL.key(privacy_level),
331
+ entity_type: Discorb::ScheduledEvent::ENTITY_TYPE.key(:external),
332
+ entity_metadata: {
333
+ location: location
334
+ }
335
+ }
336
+ else
337
+ raise ArgumentError, "Invalid scheduled event type: #{type}"
338
+ end
339
+ _resp, event =
340
+ @client
341
+ .http
342
+ .request(
343
+ Route.new(
344
+ "/guilds/#{@id}/scheduled-events",
345
+ "//guilds/:guild_id/scheduled-events",
346
+ :post
347
+ ),
348
+ payload
349
+ )
350
+ .wait
351
+ Discorb::ScheduledEvent.new(@client, event)
352
+ end
353
+ end
354
+
355
+ #
356
+ # Fetch emoji list of the guild.
357
+ # @async
358
+ # @note This querys the API every time. We recommend using {#emojis} instead.
359
+ #
360
+ # @return [Async::Task<Discorb::Dictionary{Discorb::Snowflake => Discorb::CustomEmoji}>]
361
+ # A dictionary of emoji in the guild.
362
+ #
363
+ def fetch_emoji_list
364
+ Async do
365
+ _resp, data =
366
+ @client
367
+ .http
368
+ .request(
369
+ Route.new(
370
+ "/guilds/#{@id}/emojis",
371
+ "//guilds/:guild_id/emojis",
372
+ :get
373
+ )
374
+ )
375
+ .wait
376
+ @emojis = Dictionary.new
377
+ ids = @emojis.map(&:id).map(&:to_s)
378
+ data.map do |e|
379
+ next if ids.include?(e[:id])
380
+
381
+ @emojis[e[:id]] = CustomEmoji.new(@client, self, e)
382
+ end
383
+ @emojis
384
+ end
385
+ end
386
+
387
+ alias fetch_emojis fetch_emoji_list
388
+
389
+ #
390
+ # Fetch emoji id of the guild.
391
+ # @async
392
+ # @note This querys the API every time. We recommend using {#emojis} instead.
393
+ #
394
+ # @param [#to_s] id The emoji id.
395
+ #
396
+ # @return [Async::Task<Discorb::CustomEmoji>] The emoji with the given id.
397
+ #
398
+ def fetch_emoji(id)
399
+ Async do
400
+ _resp, data =
401
+ @client
402
+ .http
403
+ .request(
404
+ Route.new(
405
+ "/guilds/#{@id}/emojis/#{id}",
406
+ "//guilds/:guild_id/emojis/:emoji_id",
407
+ :get
408
+ )
409
+ )
410
+ .wait
411
+ @emojis[e[:id]] = CustomEmoji.new(@client, self, data)
412
+ end
413
+ end
414
+
415
+ #
416
+ # Create a custom emoji.
417
+ # @async
418
+ #
419
+ # @param [#to_s] name The name of the emoji.
420
+ # @param [Discorb::Image] image The image of the emoji.
421
+ # @param [Array<Discorb::Role>] roles A list of roles to give the emoji.
422
+ #
423
+ # @return [Async::Task<Discorb::CustomEmoji>] The created emoji.
424
+ #
425
+ def create_emoji(name, image, roles: [])
426
+ Async do
427
+ _resp, data =
428
+ @client
429
+ .http
430
+ .request(
431
+ Route.new(
432
+ "/guilds/#{@id}/emojis",
433
+ "//guilds/:guild_id/emojis",
434
+ :post
435
+ ),
436
+ {
437
+ name: name,
438
+ image: image.to_s,
439
+ roles: roles.map { |r| Discorb::Utils.try(r, :id) }
440
+ }
441
+ )
442
+ .wait
443
+ @emojis[data[:id]] = CustomEmoji.new(@client, self, data)
444
+ end
445
+ end
446
+
447
+ #
448
+ # Fetch webhooks of the guild.
449
+ # @async
450
+ #
451
+ # @return [Async::Task<Array<Discorb::Webhook>>] A list of webhooks in the guild.
452
+ #
453
+ def fetch_webhooks
454
+ Async do
455
+ _resp, data =
456
+ @client
457
+ .http
458
+ .request(
459
+ Route.new(
460
+ "/guilds/#{@id}/webhooks",
461
+ "//guilds/:guild_id/webhooks",
462
+ :get
463
+ )
464
+ )
465
+ .wait
466
+ data.map { |webhook| Webhook.from_data(@client, webhook) }
467
+ end
468
+ end
469
+
470
+ #
471
+ # Fetch audit log of the guild.
472
+ # @async
473
+ #
474
+ # @return [Async::Task<Discorb::AuditLog>] The audit log of the guild.
475
+ #
476
+ def fetch_audit_log
477
+ Async do
478
+ _resp, data =
479
+ @client
480
+ .http
481
+ .request(
482
+ Route.new(
483
+ "/guilds/#{@id}/audit-logs",
484
+ "//guilds/:guild_id/audit-logs",
485
+ :get
486
+ )
487
+ )
488
+ .wait
489
+ AuditLog.new(@client, data, self)
490
+ end
491
+ end
492
+
493
+ #
494
+ # Fetch channels of the guild.
495
+ # @async
496
+ #
497
+ # @return [Async::Task<Array<Discorb::Channel>>] A list of channels in the guild.
498
+ #
499
+ def fetch_channels
500
+ Async do
501
+ _resp, data =
502
+ @client
503
+ .http
504
+ .request(
505
+ Route.new(
506
+ "/guilds/#{@id}/channels",
507
+ "//guilds/:guild_id/channels",
508
+ :get
509
+ )
510
+ )
511
+ .wait
512
+ data.map { |c| Channel.make_channel(@client, c) }
513
+ end
514
+ end
515
+
516
+ #
517
+ # Create a new text channel.
518
+ # @async
519
+ #
520
+ # @param [String] name The name of the channel.
521
+ # @param [String] topic The topic of the channel.
522
+ # @param [Integer] rate_limit_per_user The rate limit per user in the channel.
523
+ # @param [Integer] slowmode Alias for `rate_limit_per_user`.
524
+ # @param [Integer] position The position of the channel.
525
+ # @param [Boolean] nsfw Whether the channel is nsfw.
526
+ # @param [Hash{Discorb::Role, Discorb::Member => Discorb::PermissionOverwrite}] permission_overwrites
527
+ # A list of permission overwrites.
528
+ # @param [Discorb::CategoryChannel] parent The parent of the channel.
529
+ # @param [String] reason The reason for creating the channel.
530
+ #
531
+ # @return [Async::Task<Discorb::TextChannel>] The created text channel.
532
+ #
533
+ def create_text_channel(
534
+ name,
535
+ topic: nil,
536
+ rate_limit_per_user: nil,
537
+ slowmode: nil,
538
+ position: nil,
539
+ nsfw: nil,
540
+ permission_overwrites: nil,
541
+ parent: nil,
542
+ reason: nil
543
+ )
544
+ Async do
545
+ payload = { type: TextChannel.channel_type }
546
+ payload[:name] = name
547
+ payload[:topic] = topic if topic
548
+ rate_limit_per_user ||= slowmode
549
+ payload[
550
+ :rate_limit_per_user
551
+ ] = rate_limit_per_user if rate_limit_per_user
552
+ payload[:nsfw] = nsfw if nsfw
553
+ payload[:position] = position if position
554
+ if permission_overwrites
555
+ payload[
556
+ :permission_overwrites
557
+ ] = permission_overwrites.map do |target, overwrite|
558
+ {
559
+ type: target.is_a?(Role) ? 0 : 1,
560
+ id: target.id,
561
+ allow: overwrite.allow_value,
562
+ deny: overwrite.deny_value
563
+ }
564
+ end
565
+ end
566
+ payload[:parent_id] = parent.id if parent
567
+ _resp, data =
568
+ @client
569
+ .http
570
+ .request(
571
+ Route.new(
572
+ "/guilds/#{@id}/channels",
573
+ "//guilds/:guild_id/channels",
574
+ :post
575
+ ),
576
+ payload,
577
+ audit_log_reason: reason
578
+ )
579
+ .wait
580
+ payload[:parent_id] = parent&.id
581
+ Channel.make_channel(@client, data)
582
+ end
583
+ end
584
+
585
+ #
586
+ # Create a new voice channel.
587
+ # @async
588
+ #
589
+ # @param [String] name The name of the channel.
590
+ # @param [Integer] bitrate The bitrate of the channel.
591
+ # @param [Integer] user_limit The user limit of the channel.
592
+ # @param [Integer] position The position of the channel.
593
+ # @param [Hash{Discorb::Role, Discorb::Member => Discorb::PermissionOverwrite}] permission_overwrites
594
+ # A list of permission overwrites.
595
+ # @param [Discorb::CategoryChannel] parent The parent of the channel.
596
+ # @param [String] reason The reason for creating the channel.
597
+ #
598
+ # @return [Async::Task<Discorb::VoiceChannel>] The created voice channel.
599
+ #
600
+ def create_voice_channel(
601
+ name,
602
+ bitrate: 64,
603
+ user_limit: nil,
604
+ position: nil,
605
+ permission_overwrites: nil,
606
+ parent: nil,
607
+ reason: nil
608
+ )
609
+ Async do
610
+ payload = { type: VoiceChannel.channel_type }
611
+ payload[:name] = name
612
+ payload[:bitrate] = bitrate * 1000 if bitrate
613
+ payload[:user_limit] = user_limit if user_limit
614
+ payload[:position] = position if position
615
+ if permission_overwrites
616
+ payload[
617
+ :permission_overwrites
618
+ ] = permission_overwrites.map do |target, overwrite|
619
+ {
620
+ type: target.is_a?(Role) ? 0 : 1,
621
+ id: target.id,
622
+ allow: overwrite.allow_value,
623
+ deny: overwrite.deny_value
624
+ }
625
+ end
626
+ end
627
+ payload[:parent_id] = parent.id if parent
628
+ _resp, data =
629
+ @client
630
+ .http
631
+ .request(
632
+ Route.new(
633
+ "/guilds/#{@id}/channels",
634
+ "//guilds/:guild_id/channels",
635
+ :post
636
+ ),
637
+ payload,
638
+ audit_log_reason: reason
639
+ )
640
+ .wait
641
+ payload[:parent_id] = parent&.id
642
+ Channel.make_channel(@client, data)
643
+ end
644
+ end
645
+
646
+ # Create a new category channel.
647
+ # @async
648
+ #
649
+ # @param [String] name The name of the channel.
650
+ # @param [Integer] position The position of the channel.
651
+ # @param [Hash{Discorb::Role, Discorb::Member => Discorb::PermissionOverwrite}] permission_overwrites
652
+ # A list of permission overwrites.
653
+ # @param [Discorb::CategoryChannel] parent The parent of the channel.
654
+ # @param [String] reason The reason for creating the channel.
655
+ #
656
+ # @return [Async::Task<Discorb::CategoryChannel>] The created category channel.
657
+ #
658
+ def create_category_channel(
659
+ name,
660
+ position: nil,
661
+ permission_overwrites: nil,
662
+ parent: nil,
663
+ reason: nil
664
+ )
665
+ Async do
666
+ payload = { type: CategoryChannel.channel_type }
667
+ payload[:name] = name
668
+ payload[:position] = position if position
669
+ if permission_overwrites
670
+ payload[
671
+ :permission_overwrites
672
+ ] = permission_overwrites.map do |target, overwrite|
673
+ {
674
+ type: target.is_a?(Role) ? 0 : 1,
675
+ id: target.id,
676
+ allow: overwrite.allow_value,
677
+ deny: overwrite.deny_value
678
+ }
679
+ end
680
+ end
681
+ payload[:parent_id] = parent&.id
682
+ _resp, data =
683
+ @client
684
+ .http
685
+ .request(
686
+ Route.new(
687
+ "/guilds/#{@id}/channels",
688
+ "//guilds/:guild_id/channels",
689
+ :post
690
+ ),
691
+ payload,
692
+ audit_log_reason: reason
693
+ )
694
+ .wait
695
+ Channel.make_channel(@client, data)
696
+ end
697
+ end
698
+
699
+ alias create_category create_category_channel
700
+
701
+ #
702
+ # Create a new stage channel.
703
+ # @async
704
+ #
705
+ # @param [String] name The name of the channel.
706
+ # @param [Integer] bitrate The bitrate of the channel.
707
+ # @param [Integer] position The position of the channel.
708
+ # @param [Hash{Discorb::Role, Discorb::Member => Discorb::PermissionOverwrite}] permission_overwrites
709
+ # A list of permission overwrites.
710
+ # @param [Discorb::CategoryChannel] parent The parent of the channel.
711
+ # @param [String] reason The reason for creating the channel.
712
+ #
713
+ # @return [Async::Task<Discorb::StageChannel>] The created stage channel.
714
+ #
715
+ def create_stage_channel(
716
+ name,
717
+ bitrate: 64,
718
+ position: nil,
719
+ permission_overwrites: nil,
720
+ parent: nil,
721
+ reason: nil
722
+ )
723
+ Async do
724
+ payload = { type: StageChannel.channel_type }
725
+ payload[:name] = name
726
+ payload[:bitrate] = bitrate * 1000 if bitrate
727
+ payload[:position] = position if position
728
+ if permission_overwrites
729
+ payload[
730
+ :permission_overwrites
731
+ ] = permission_overwrites.map do |target, overwrite|
732
+ {
733
+ type: target.is_a?(Role) ? 0 : 1,
734
+ id: target.id,
735
+ allow: overwrite.allow_value,
736
+ deny: overwrite.deny_value
737
+ }
738
+ end
739
+ end
740
+ payload[:parent_id] = parent&.id
741
+ _resp, data =
742
+ @client
743
+ .http
744
+ .request(
745
+ Route.new(
746
+ "/guilds/#{@id}/channels",
747
+ "//guilds/:guild_id/channels",
748
+ :post
749
+ ),
750
+ payload,
751
+ audit_log_reason: reason
752
+ )
753
+ .wait
754
+ Channel.make_channel(@client, data)
755
+ end
756
+ end
757
+
758
+ #
759
+ # Create a new news channel.
760
+ # @async
761
+ #
762
+ # @param [String] name The name of the channel.
763
+ # @param [String] topic The topic of the channel.
764
+ # @param [Integer] rate_limit_per_user The rate limit per user in the channel.
765
+ # @param [Integer] slowmode Alias for `rate_limit_per_user`.
766
+ # @param [Integer] position The position of the channel.
767
+ # @param [Boolean] nsfw Whether the channel is nsfw.
768
+ # @param [Hash{Discorb::Role, Discorb::Member => Discorb::PermissionOverwrite}] permission_overwrites
769
+ # A list of permission overwrites.
770
+ # @param [Discorb::CategoryChannel] parent The parent of the channel.
771
+ # @param [String] reason The reason for creating the channel.
772
+ #
773
+ # @return [Async::Task<Discorb::NewsChannel>] The created news channel.
774
+ #
775
+ def create_news_channel(
776
+ name,
777
+ topic: nil,
778
+ rate_limit_per_user: nil,
779
+ slowmode: nil,
780
+ position: nil,
781
+ nsfw: nil,
782
+ permission_overwrites: nil,
783
+ parent: nil,
784
+ reason: nil
785
+ )
786
+ Async do
787
+ payload = { type: NewsChannel.channel_type }
788
+ payload[:name] = name
789
+ payload[:topic] = topic if topic
790
+ rate_limit_per_user ||= slowmode
791
+ payload[
792
+ :rate_limit_per_user
793
+ ] = rate_limit_per_user if rate_limit_per_user
794
+ payload[:position] = position if position
795
+ if permission_overwrites
796
+ payload[
797
+ :permission_overwrites
798
+ ] = permission_overwrites.map do |target, overwrite|
799
+ {
800
+ type: target.is_a?(Role) ? 0 : 1,
801
+ id: target.id,
802
+ allow: overwrite.allow_value,
803
+ deny: overwrite.deny_value
804
+ }
805
+ end
806
+ end
807
+ payload[:nsfw] = nsfw unless nsfw.nil?
808
+ payload[:parent_id] = parent&.id
809
+ _resp, data =
810
+ @client
811
+ .http
812
+ .request(
813
+ Route.new(
814
+ "/guilds/#{@id}/channels",
815
+ "//guilds/:guild_id/channels",
816
+ :post
817
+ ),
818
+ payload,
819
+ audit_log_reason: reason
820
+ )
821
+ .wait
822
+ Channel.make_channel(@client, data)
823
+ end
824
+ end
825
+
826
+ #
827
+ # Fetch a list of active threads in the guild.
828
+ # @async
829
+ #
830
+ # @return [Async::Task<Array<Discorb::ThreadChannel>>] The list of threads.
831
+ #
832
+ def fetch_active_threads
833
+ Async do
834
+ _resp, data =
835
+ @client
836
+ .http
837
+ .request(
838
+ Route.new(
839
+ "/guilds/#{@id}/threads/active",
840
+ "//guilds/:guild_id/threads/active",
841
+ :get
842
+ )
843
+ )
844
+ .wait
845
+ data[:threads].map { |t| Channel.make_thread(@client, t) }
846
+ end
847
+ end
848
+
849
+ #
850
+ # Fetch a member in the guild.
851
+ # @async
852
+ #
853
+ # @param [#to_s] id The ID of the member to fetch.
854
+ #
855
+ # @return [Async::Task<Discorb::Member>] The member.
856
+ # @return [Async::Task<nil>] If the member is not found.
857
+ #
858
+ def fetch_member(id)
859
+ Async do
860
+ _resp, data =
861
+ @client
862
+ .http
863
+ .request(
864
+ Route.new(
865
+ "/guilds/#{@id}/members/#{id}",
866
+ "//guilds/:guild_id/members/:user_id",
867
+ :get
868
+ )
869
+ )
870
+ .wait
871
+ rescue Discorb::NotFoundError
872
+ nil
873
+ else
874
+ Member.new(@client, @id, data[:user], data)
875
+ end
876
+ end
877
+
878
+ # Fetch members in the guild.
879
+ # @async
880
+ # @macro members_intent
881
+ #
882
+ # @param [Integer] limit The maximum number of members to fetch, 0 for all.
883
+ # @param [Integer] after The ID of the member to start fetching after.
884
+ #
885
+ # @return [Async::Task<Array<Discorb::Member>>] The list of members.
886
+ #
887
+ def fetch_members(limit: 0, after: nil)
888
+ Async do
889
+ unless limit.zero?
890
+ _resp, data =
891
+ @client
892
+ .http
893
+ .request(
894
+ Route.new(
895
+ "/guilds/#{@id}/members?#{
896
+ URI.encode_www_form({ after: after, limit: limit })
897
+ }",
898
+ "//guilds/:guild_id/members",
899
+ :get
900
+ )
901
+ )
902
+ .wait
903
+ next data[:members].map { |m| Member.new(@client, @id, m[:user], m) }
904
+ end
905
+ ret = []
906
+ after = 0
907
+ loop do
908
+ params = { after: after, limit: 100 }
909
+ _resp, data =
910
+ @client
911
+ .http
912
+ .request(
913
+ Route.new(
914
+ "/guilds/#{@id}/members?#{URI.encode_www_form(params)}",
915
+ "//guilds/:guild_id/members",
916
+ :get
917
+ )
918
+ )
919
+ .wait
920
+ ret += data.map { |m| Member.new(@client, @id, m[:user], m) }
921
+ after = data.last[:user][:id]
922
+ break if data.length != 100
923
+ end
924
+ ret
925
+ end
926
+ end
927
+
928
+ alias fetch_member_list fetch_members
929
+
930
+ #
931
+ # Search for members by name in the guild.
932
+ # @async
933
+ #
934
+ # @param [String] name The name of the member to search for.
935
+ # @param [Integer] limit The maximum number of members to return.
936
+ #
937
+ # @return [Async::Task<Array<Discorb::Member>>] The list of members.
938
+ #
939
+ def fetch_members_named(name, limit: 1)
940
+ Async do
941
+ _resp, data =
942
+ @client
943
+ .http
944
+ .request(
945
+ Route.new(
946
+ "/guilds/#{@id}/members/search?#{
947
+ URI.encode_www_form({ query: name, limit: limit })
948
+ }",
949
+ "//guilds/:guild_id/members/search",
950
+ :get
951
+ )
952
+ )
953
+ .wait
954
+ data.map { |d| Member.new(@client, @id, d[:user], d) }
955
+ end
956
+ end
957
+
958
+ #
959
+ # Almost the same as {#fetch_members_named}, but returns a single member.
960
+ # @async
961
+ #
962
+ # @return [Async::Task<Discorb::Member>] The member.
963
+ # @return [Async::Task<nil>] If the member is not found.
964
+ #
965
+ def fetch_member_named(...)
966
+ Async { fetch_members_named(...).first }
967
+ end
968
+
969
+ #
970
+ # Change nickname of client member.
971
+ # @async
972
+ #
973
+ # @param [String] nickname The nickname to set.
974
+ # @param [String] reason The reason for changing the nickname.
975
+ #
976
+ # @return [Async::Task<void>] The task.
977
+ #
978
+ def edit_nickname(nickname, reason: nil)
979
+ Async do
980
+ @client
981
+ .http
982
+ .request(
983
+ Route.new(
984
+ "/guilds/#{@id}/members/@me/nick",
985
+ "//guilds/:guild_id/members/@me/nick",
986
+ :patch
987
+ ),
988
+ { nick: nickname },
989
+ audit_log_reason: reason
990
+ )
991
+ .wait
992
+ end
993
+ end
994
+
995
+ alias edit_nick edit_nickname
996
+ alias modify_nickname edit_nickname
997
+ alias modify_nick modify_nickname
998
+
999
+ #
1000
+ # Kick a member from the guild.
1001
+ # @async
1002
+ #
1003
+ # @param [Discorb::Member] member The member to kick.
1004
+ # @param [String] reason The reason for kicking the member.
1005
+ #
1006
+ # @return [Async::Task<void>] The task.
1007
+ #
1008
+ def kick_member(member, reason: nil)
1009
+ Async do
1010
+ @client
1011
+ .http
1012
+ .request(
1013
+ Route.new(
1014
+ "/guilds/#{@id}/members/#{member.id}",
1015
+ "//guilds/:guild_id/members/:user_id",
1016
+ :delete
1017
+ ),
1018
+ {},
1019
+ audit_log_reason: reason
1020
+ )
1021
+ .wait
1022
+ end
1023
+ end
1024
+
1025
+ #
1026
+ # Fetch a list of bans in the guild.
1027
+ # @async
1028
+ #
1029
+ # @param [Integer] limit The number of bans to fetch.
1030
+ # @param [Discorb::Snowflake] before The ID of the ban to fetch before.
1031
+ # @param [Discorb::Snowflake] after The ID of the ban to fetch after.
1032
+ # @param [Discorb::Snowflake] around The ID of the ban to fetch around.
1033
+ #
1034
+ # @return [Async::Task<Array<Discorb::Guild::Ban>>] The list of bans.
1035
+ #
1036
+ def fetch_bans(limit = 50, before: nil, after: nil, around: nil)
1037
+ Async do
1038
+ params =
1039
+ {
1040
+ limit: limit,
1041
+ before: Discorb::Utils.try(after, :id),
1042
+ after: Discorb::Utils.try(around, :id),
1043
+ around: Discorb::Utils.try(before, :id)
1044
+ }.filter { |_k, v| !v.nil? }.to_h
1045
+ _resp, bans =
1046
+ @client
1047
+ .http
1048
+ .request(
1049
+ Route.new(
1050
+ "/guilds/#{@id}/bans?#{URI.encode_www_form(params)}",
1051
+ "//guilds/:guild_id/bans",
1052
+ :get
1053
+ )
1054
+ )
1055
+ .wait
1056
+ bans.map { |d| Ban.new(@client, self, d) }
1057
+ end
1058
+ end
1059
+
1060
+ #
1061
+ # Fetch a ban in the guild.
1062
+ # @async
1063
+ #
1064
+ # @param [Discorb::User] user The user to fetch.
1065
+ #
1066
+ # @return [Async::Task<Discorb::Guild::Ban>] The ban.
1067
+ # @return [Async::Task<nil>] If the ban is not found.
1068
+ #
1069
+ def fetch_ban(user)
1070
+ Async do
1071
+ _resp, data =
1072
+ @client
1073
+ .http
1074
+ .request(
1075
+ Route.new(
1076
+ "/guilds/#{@id}/bans/#{user.id}",
1077
+ "//guilds/:guild_id/bans/:user_id",
1078
+ :get
1079
+ )
1080
+ )
1081
+ .wait
1082
+ rescue Discorb::NotFoundError
1083
+ nil
1084
+ else
1085
+ Ban.new(@client, self, data)
1086
+ end
1087
+ end
1088
+
1089
+ #
1090
+ # Checks the user was banned from the guild.
1091
+ # @async
1092
+ #
1093
+ # @param [Discorb::User] user The user to check.
1094
+ #
1095
+ # @return [Async::Task<Boolean>] Whether the user was banned.
1096
+ #
1097
+ def banned?(user)
1098
+ Async { !fetch_ban(user).wait.nil? }
1099
+ end
1100
+
1101
+ #
1102
+ # Ban a member from the guild.
1103
+ # @async
1104
+ #
1105
+ # @param [Discorb::Member] member The member to ban.
1106
+ # @param [Integer] delete_message_days The number of days to delete messages.
1107
+ # @param [String] reason The reason for banning the member.
1108
+ #
1109
+ # @return [Async::Task<Discorb::Guild::Ban>] The ban.
1110
+ #
1111
+ def ban_member(member, delete_message_days: 0, reason: nil)
1112
+ Async do
1113
+ _resp, data =
1114
+ @client
1115
+ .http
1116
+ .request(
1117
+ Route.new(
1118
+ "/guilds/#{@id}/bans",
1119
+ "//guilds/:guild_id/bans",
1120
+ :post
1121
+ ),
1122
+ { user: member.id, delete_message_days: delete_message_days },
1123
+ audit_log_reason: reason
1124
+ )
1125
+ .wait
1126
+ Ban.new(@client, self, data)
1127
+ end
1128
+ end
1129
+
1130
+ #
1131
+ # Unban a user from the guild.
1132
+ # @async
1133
+ #
1134
+ # @param [Discorb::User] user The user to unban.
1135
+ # @param [String] reason The reason for unbanning the user.
1136
+ #
1137
+ # @return [Async::Task<void>] The task.
1138
+ #
1139
+ def unban_user(user, reason: nil)
1140
+ Async do
1141
+ @client
1142
+ .http
1143
+ .request(
1144
+ Route.new(
1145
+ "/guilds/#{@id}/bans/#{user.id}",
1146
+ "//guilds/:guild_id/bans/:user_id",
1147
+ :delete
1148
+ ),
1149
+ {},
1150
+ audit_log_reason: reason
1151
+ )
1152
+ .wait
1153
+ end
1154
+ end
1155
+
1156
+ #
1157
+ # Fetch a list of roles in the guild.
1158
+ # @async
1159
+ #
1160
+ # @return [Async::Task<Array<Discorb::Role>>] The list of roles.
1161
+ #
1162
+ def fetch_roles
1163
+ Async do
1164
+ _resp, data =
1165
+ @client
1166
+ .http
1167
+ .request(
1168
+ Route.new(
1169
+ "/guilds/#{@id}/roles",
1170
+ "//guilds/:guild_id/roles",
1171
+ :get
1172
+ )
1173
+ )
1174
+ .wait
1175
+ data.map { |d| Role.new(@client, self, d) }
1176
+ end
1177
+ end
1178
+
1179
+ #
1180
+ # Create a role in the guild.
1181
+ # @async
1182
+ #
1183
+ # @param [String] name The name of the role.
1184
+ # @param [Discorb::Color] color The color of the role.
1185
+ # @param [Boolean] hoist Whether the role should be hoisted.
1186
+ # @param [Boolean] mentionable Whether the role should be mentionable.
1187
+ # @param [String] reason The reason for creating the role.
1188
+ #
1189
+ # @return [Async::Task<Discorb::Role>] The role.
1190
+ #
1191
+ def create_role(
1192
+ name = nil,
1193
+ color: nil,
1194
+ hoist: nil,
1195
+ mentionable: nil,
1196
+ reason: nil
1197
+ )
1198
+ Async do
1199
+ payload = {}
1200
+ payload[:name] = name if name
1201
+ payload[:color] = color.to_i if color
1202
+ payload[:hoist] = hoist if hoist
1203
+ payload[:mentionable] = mentionable if mentionable
1204
+ _resp, data =
1205
+ @client
1206
+ .http
1207
+ .request(
1208
+ Route.new(
1209
+ "/guilds/#{@id}/roles",
1210
+ "//guilds/:guild_id/roles",
1211
+ :post
1212
+ ),
1213
+ payload,
1214
+ audit_log_reason: reason
1215
+ )
1216
+ .wait
1217
+ Role.new(@client, self, data)
1218
+ end
1219
+ end
1220
+
1221
+ #
1222
+ # Fetch how many members will be pruned.
1223
+ # @async
1224
+ #
1225
+ # @param [Integer] days The number of days to prune.
1226
+ # @param [Array<Discorb::Role>] roles The roles that include for pruning.
1227
+ #
1228
+ # @return [Async::Task<Integer>] The number of members that will be pruned.
1229
+ #
1230
+ def fetch_prune(days = 7, roles: [])
1231
+ Async do
1232
+ params = { days: days, include_roles: @id.to_s }
1233
+ param[:include_roles] = roles
1234
+ .map(&:id)
1235
+ .map(&:to_s)
1236
+ .join(";") if roles.any?
1237
+ _resp, data =
1238
+ @client
1239
+ .http
1240
+ .request(
1241
+ Route.new(
1242
+ "/guilds/#{@id}/prune?#{URI.encode_www_form(params)}",
1243
+ "//guilds/:guild_id/prune",
1244
+ :get
1245
+ )
1246
+ )
1247
+ .wait
1248
+ data[:pruned]
1249
+ end
1250
+ end
1251
+
1252
+ #
1253
+ # Prune members from the guild.
1254
+ # @async
1255
+ #
1256
+ # @param [Integer] days The number of days to prune.
1257
+ # @param [Array<Discorb::Role>] roles The roles that include for pruning.
1258
+ # @param [String] reason The reason for pruning.
1259
+ #
1260
+ # @return [Async::Task<Integer>] The number of members that were pruned.
1261
+ #
1262
+ def prune(days = 7, roles: [], reason: nil)
1263
+ Async do
1264
+ _resp, data =
1265
+ @client
1266
+ .http
1267
+ .request(
1268
+ Route.new(
1269
+ "/guilds/#{@id}/prune",
1270
+ "//guilds/:guild_id/prune",
1271
+ :post
1272
+ ),
1273
+ { days: days, roles: roles.map(&:id) },
1274
+ audit_log_reason: reason
1275
+ )
1276
+ .wait
1277
+ data[:pruned]
1278
+ end
1279
+ end
1280
+
1281
+ #
1282
+ # Fetch voice regions that are available in the guild.
1283
+ # @async
1284
+ #
1285
+ # @return [Async::Task<Array<Discorb::VoiceRegion>>] The available voice regions.
1286
+ #
1287
+ def fetch_voice_regions
1288
+ Async do
1289
+ _resp, data =
1290
+ @client
1291
+ .http
1292
+ .request(
1293
+ Route.new(
1294
+ "/guilds/#{@id}/voice",
1295
+ "//guilds/:guild_id/voice",
1296
+ :get
1297
+ )
1298
+ )
1299
+ .wait
1300
+ data.map { |d| VoiceRegion.new(d) }
1301
+ end
1302
+ end
1303
+
1304
+ #
1305
+ # Fetch invites in the guild.
1306
+ # @async
1307
+ #
1308
+ # @return [Async::Task<Array<Invite>>] The invites.
1309
+ #
1310
+ def fetch_invites
1311
+ Async do
1312
+ _resp, data =
1313
+ @client
1314
+ .http
1315
+ .request(
1316
+ Route.new(
1317
+ "/guilds/#{@id}/invites",
1318
+ "//guilds/:guild_id/invites",
1319
+ :get
1320
+ )
1321
+ )
1322
+ .wait
1323
+ data.map { |d| Invite.new(@client, d, false) }
1324
+ end
1325
+ end
1326
+
1327
+ #
1328
+ # Fetch integrations in the guild.
1329
+ # @async
1330
+ #
1331
+ # @return [Async::Task<Array<Discorb::Integration>>] The integrations.
1332
+ #
1333
+ def fetch_integrations
1334
+ Async do
1335
+ _resp, data =
1336
+ @client
1337
+ .http
1338
+ .request(
1339
+ Route.new(
1340
+ "/guilds/#{@id}/integrations",
1341
+ "//guilds/:guild_id/integrations",
1342
+ :get
1343
+ )
1344
+ )
1345
+ .wait
1346
+ data.map { |d| Integration.new(@client, d, @id) }
1347
+ end
1348
+ end
1349
+
1350
+ #
1351
+ # Fetch the widget of the guild.
1352
+ # @async
1353
+ #
1354
+ # @return [Async::Task<Discorb::Guild::Widget>] The widget.
1355
+ #
1356
+ def fetch_widget
1357
+ Async do
1358
+ _resp, data =
1359
+ @client
1360
+ .http
1361
+ .request(
1362
+ Route.new(
1363
+ "/guilds/#{@id}/widget",
1364
+ "//guilds/:guild_id/widget",
1365
+ :get
1366
+ )
1367
+ )
1368
+ .wait
1369
+ Widget.new(@client, @id, data)
1370
+ end
1371
+ end
1372
+
1373
+ #
1374
+ # Fetch the vanity URL of the guild.
1375
+ # @async
1376
+ #
1377
+ # @return [Async::Task<Discorb::Guild::VanityInvite>] The vanity URL.
1378
+ #
1379
+ def fetch_vanity_invite
1380
+ Async do
1381
+ _resp, data =
1382
+ @client
1383
+ .http
1384
+ .request(
1385
+ Route.new(
1386
+ "/guilds/#{@id}/vanity-url",
1387
+ "//guilds/:guild_id/vanity-url",
1388
+ :get
1389
+ )
1390
+ )
1391
+ .wait
1392
+ VanityInvite.new(@client, self, data)
1393
+ end
1394
+ end
1395
+
1396
+ #
1397
+ # Fetch the welcome screen of the guild.
1398
+ # @async
1399
+ #
1400
+ # @return [Async::Task<Discorb::WelcomeScreen>] The welcome screen.
1401
+ #
1402
+ def fetch_welcome_screen
1403
+ Async do
1404
+ _resp, data =
1405
+ @client
1406
+ .http
1407
+ .request(
1408
+ Route.new(
1409
+ "/guilds/#{@id}/welcome-screen",
1410
+ "//guilds/:guild_id/welcome-screen",
1411
+ :get
1412
+ )
1413
+ )
1414
+ .wait
1415
+ WelcomeScreen.new(@client, self, data)
1416
+ end
1417
+ end
1418
+
1419
+ #
1420
+ # Fetch stickers in the guild.
1421
+ # @async
1422
+ #
1423
+ # @return [Async::Task<Array<Discorb::Sticker::GuildSticker>>] The stickers.
1424
+ #
1425
+ def fetch_stickers
1426
+ Async do
1427
+ _resp, data =
1428
+ @client
1429
+ .http
1430
+ .request(
1431
+ Route.new(
1432
+ "/guilds/#{@id}/stickers",
1433
+ "//guilds/:guild_id/stickers",
1434
+ :get
1435
+ )
1436
+ )
1437
+ .wait
1438
+ data.map { |d| Sticker::GuildSticker.new(@client, d) }
1439
+ end
1440
+ end
1441
+
1442
+ #
1443
+ # Fetch the sticker by ID.
1444
+ # @async
1445
+ #
1446
+ # @param [#to_s] id The ID of the sticker.
1447
+ #
1448
+ # @return [Async::Task<Discorb::Sticker::GuildSticker>] The sticker.
1449
+ # @return [Async::Task<nil>] If the sticker does not exist.
1450
+ #
1451
+ def fetch_sticker(id)
1452
+ Async do
1453
+ _resp, data =
1454
+ @client
1455
+ .http
1456
+ .request(
1457
+ Route.new(
1458
+ "/guilds/#{@id}/stickers/#{id}",
1459
+ "//guilds/:guild_id/stickers/:sticker_id",
1460
+ :get
1461
+ )
1462
+ )
1463
+ .wait
1464
+ rescue Discorb::NotFoundError
1465
+ nil
1466
+ else
1467
+ Sticker::GuildSticker.new(@client, data)
1468
+ end
1469
+ end
1470
+
1471
+ #
1472
+ # Fetch templates in the guild.
1473
+ # @async
1474
+ #
1475
+ # @return [Async::Task<Discorb::GuildTemplate>] The templates.
1476
+ #
1477
+ def fetch_templates
1478
+ Async do
1479
+ _resp, data =
1480
+ @client
1481
+ .http
1482
+ .request(
1483
+ Route.new(
1484
+ "/guilds/#{@id}/templates",
1485
+ "//guilds/:guild_id/templates",
1486
+ :get
1487
+ )
1488
+ )
1489
+ .wait
1490
+ data.map { |d| GuildTemplate.new(@client, d) }
1491
+ end
1492
+ end
1493
+
1494
+ #
1495
+ # Almost the same as {#fetch_templates}, but returns a single template.
1496
+ #
1497
+ # @return [Discorb::GuildTemplate] The template.
1498
+ # @return [Async::Task<nil>] If the template does not exist.
1499
+ #
1500
+ def fetch_template
1501
+ Async { fetch_templates.wait.first }
1502
+ end
1503
+
1504
+ #
1505
+ # Create a new template in the guild.
1506
+ #
1507
+ # @param [String] name The name of the template.
1508
+ # @param [String] description The description of the template.
1509
+ # @param [String] reason The reason for creating the template.
1510
+ #
1511
+ # @return [Async::Task<Discorb::GuildTemplate>] The template.
1512
+ #
1513
+ def create_template(name, description = nil, reason: nil)
1514
+ Async do
1515
+ _resp, data =
1516
+ @client
1517
+ .http
1518
+ .request(
1519
+ Route.new(
1520
+ "/guilds/#{@id}/templates",
1521
+ "//guilds/:guild_id/templates",
1522
+ :post
1523
+ ),
1524
+ { name: name, description: description },
1525
+ audit_log_reason: reason
1526
+ )
1527
+ .wait
1528
+ GuildTemplate.new(@client, data)
1529
+ end
1530
+ end
1531
+
1532
+ #
1533
+ # Fetch the automod rules in the guild.
1534
+ # @async
1535
+ #
1536
+ # @return [Async::Task<Array<Discorb::AutoModRule>>] The automod rules.
1537
+ #
1538
+ def fetch_automod_rules
1539
+ Async do
1540
+ _resp, data =
1541
+ @client.http.request(
1542
+ Route.new(
1543
+ "/guilds/#{@id}/auto-moderation/rules",
1544
+ "//guilds/:guild_id/auto-moderation/rules",
1545
+ :get
1546
+ )
1547
+ )
1548
+ data.map { |d| AutoModRule.new(@client, d) }
1549
+ end
1550
+ end
1551
+
1552
+ alias fetch_automod_rule_list fetch_automod_rules
1553
+
1554
+ #
1555
+ # Fetch the automod rule by ID.
1556
+ #
1557
+ # @param [#to_s] id The ID of the automod rule.
1558
+ #
1559
+ # @return [Async::Task<Array<Discord::AutoModRule>>] The automod rule.
1560
+ #
1561
+ def fetch_automod_rule(id)
1562
+ Async do
1563
+ _resp, data =
1564
+ @client
1565
+ .http
1566
+ .request(
1567
+ Route.new(
1568
+ "/guilds/#{@id}/auto-moderation/rules/#{id}",
1569
+ "//guilds/:guild_id/auto-moderation/rules/:rule_id",
1570
+ :get
1571
+ )
1572
+ )
1573
+ .wait
1574
+ AutoModRule.new(@client, data)
1575
+ end
1576
+ end
1577
+
1578
+ #
1579
+ # Create a new automod rule in the guild.
1580
+ # @async
1581
+ #
1582
+ # @param [String] name The name of the rule.
1583
+ # @param [Symbol] trigger_type The trigger type of the rule. See {Discorb::AutoModRule::TRIGGER_TYPES}.
1584
+ # @param [Array<Discorb::AutoModRule::Action>] actions The actions of the rule.
1585
+ # @param [Symbol] event_type The event type of the rule. See {Discorb::AutoModRule::EVENT_TYPES}.
1586
+ # @param [Boolean] enabled Whether the rule is enabled or not.
1587
+ # @param [Array<Discorb::Role>] exempt_roles The roles that are exempt from the rule.
1588
+ # @param [Array<Discorb::Channel>] exempt_channels The channels that are exempt from the rule.
1589
+ # @param [Array<String>] keyword_filter The keywords to filter.
1590
+ # @param [Array<String>] allow_list Substrings which will be exempt from triggering the preset trigger type.
1591
+ # @param [Integer] mention_total_limit The total number of mentions allowed per message.
1592
+ # @param [Symbol] presets The preset of the rule. See {Discorb::AutoModRule::PRESET_TYPES}.
1593
+ # @param [String] reason The reason for creating the rule.
1594
+ #
1595
+ # @return [Async::Task<Discorb::AutoModRule>] The automod rule.
1596
+ #
1597
+ def create_automod_rule(
1598
+ name,
1599
+ trigger_type,
1600
+ actions,
1601
+ event_type = :message_send,
1602
+ enabled: false,
1603
+ exempt_roles: [],
1604
+ exempt_channels: [],
1605
+ keyword_filter: nil,
1606
+ mention_total_limit: nil,
1607
+ allow_list: nil,
1608
+ presets: nil,
1609
+ reason: nil
1610
+ )
1611
+ Async do
1612
+ payload = {
1613
+ name: name,
1614
+ event_type: Discorb::AutoModRule::EVENT_TYPES.key(event_type),
1615
+ trigger_type: Discorb::AutoModRule::TRIGGER_TYPES.key(trigger_type),
1616
+ metadata: {
1617
+ keyword_filter: keyword_filter,
1618
+ presets: presets && Discorb::AutoModRule::PRESET_TYPES.key(presets),
1619
+ allow_list: allow_list,
1620
+ mention_total_limit: mention_total_limit
1621
+ },
1622
+ actions: actions.map(&:to_hash),
1623
+ enabled: enabled,
1624
+ exempt_roles: exempt_roles.map(&:id),
1625
+ exempt_channels: exempt_channels.map(&:id)
1626
+ }
1627
+
1628
+ _resp, data =
1629
+ @client.http.request(
1630
+ Route.new(
1631
+ "/guilds/#{@id}/auto-moderation/rules",
1632
+ "//guilds/:guild_id/auto-moderation/rules",
1633
+ :post
1634
+ ),
1635
+ payload,
1636
+ audit_log_reason: reason
1637
+ )
1638
+ Discorb::AutoModRule.new(@client, data)
1639
+ end
1640
+ end
1641
+
1642
+ #
1643
+ # Represents a vanity invite.
1644
+ #
1645
+ class VanityInvite < DiscordModel
1646
+ # @return [String] The vanity invite code.
1647
+ attr_reader :code
1648
+ # @return [Integer] The number of uses.
1649
+ attr_reader :uses
1650
+
1651
+ # @!attribute [r] url
1652
+ # @return [String] The vanity URL.
1653
+
1654
+ #
1655
+ # Initialize a new instance of the {VanityInvite} class.
1656
+ # @private
1657
+ #
1658
+ # @param [Discorb::Client] client The client.
1659
+ # @param [Discorb::Guild] guild The guild.
1660
+ # @param [Hash] data The data of the invite.
1661
+ #
1662
+ def initialize(client, guild, data)
1663
+ @client = client
1664
+ @guild = guild
1665
+ @code = data[:code]
1666
+ @uses = data[:uses]
1667
+ end
1668
+
1669
+ def url
1670
+ "https://discord.gg/#{@code}"
1671
+ end
1672
+ end
1673
+
1674
+ #
1675
+ # Represents a guild widget.
1676
+ #
1677
+ class Widget < DiscordModel
1678
+ # @return [Discorb::Snowflake] The guild ID.
1679
+ attr_reader :guild_id
1680
+ # @return [Discorb::Snowflake] The channel ID.
1681
+ attr_reader :channel_id
1682
+ # @return [Boolean] Whether the widget is enabled.
1683
+ attr_reader :enabled
1684
+ alias enabled? enabled
1685
+ alias enable? enabled
1686
+
1687
+ # @!attribute [r] channel
1688
+ # @macro client_cache
1689
+ # @return [Discorb::Channel] The channel.
1690
+ # @!attribute [r] guild
1691
+ # @macro client_cache
1692
+ # @return [Discorb::Guild] The guild.
1693
+ # @!attribute [r] json_url
1694
+ # @return [String] The JSON URL.
1695
+
1696
+ #
1697
+ # Initialize a new instance of the {Widget} class.
1698
+ # @private
1699
+ #
1700
+ # @param [Discorb::Client] client The client.
1701
+ # @param [Discorb::Snowflake] guild_id The guild ID.
1702
+ # @param [Hash] data The data from Discord.
1703
+ #
1704
+ def initialize(client, guild_id, data)
1705
+ @client = client
1706
+ @enabled = data[:enabled]
1707
+ @guild_id = Snowflake.new(guild_id)
1708
+ @channel_id = Snowflake.new(data[:channel_id])
1709
+ end
1710
+
1711
+ def channel
1712
+ @client.channels[@channel_id]
1713
+ end
1714
+
1715
+ #
1716
+ # Edit the widget.
1717
+ # @async
1718
+ # @macro edit
1719
+ #
1720
+ # @param [Boolean] enabled Whether the widget is enabled.
1721
+ # @param [Discorb::GuildChannel] channel The channel.
1722
+ # @param [String] reason The reason for editing the widget.
1723
+ #
1724
+ # @return [Async::Task<void>] The task.
1725
+ #
1726
+ def edit(enabled: nil, channel: nil, reason: nil)
1727
+ Async do
1728
+ payload = {}
1729
+ payload[:enabled] = enabled unless enabled.nil?
1730
+ payload[:channel_id] = channel.id if channel_id
1731
+ @client
1732
+ .http
1733
+ .request(
1734
+ Route.new(
1735
+ "/guilds/#{@guild_id}/widget",
1736
+ "//guilds/:guild_id/widget",
1737
+ :patch
1738
+ ),
1739
+ payload,
1740
+ audit_log_reason: reason
1741
+ )
1742
+ .wait
1743
+ end
1744
+ end
1745
+
1746
+ alias modify edit
1747
+
1748
+ def json_url
1749
+ "#{Discorb::API_BASE_URL}/guilds/#{@guild_id}/widget.json"
1750
+ end
1751
+
1752
+ #
1753
+ # Return iframe HTML of the widget.
1754
+ #
1755
+ # @param ["dark", "light"] theme The theme of the widget.
1756
+ # @param [Integer] width The width of the widget.
1757
+ # @param [Integer] height The height of the widget.
1758
+ #
1759
+ # @return [String] The iframe HTML.
1760
+ #
1761
+ def iframe(theme: "dark", width: 350, height: 500)
1762
+ # rubocop:disable Layout/LineLength
1763
+ [
1764
+ %(<iframe src="https://canary.discord.com/widget?id=#{@guild_id}&theme=#{theme}" width="#{width}" height="#{height}"),
1765
+ %(allowtransparency="true" frameborder="0" sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts"></iframe>)
1766
+ ].join
1767
+ # rubocop:enable Layout/LineLength
1768
+ end
1769
+ end
1770
+
1771
+ #
1772
+ # Represents a ban.
1773
+ #
1774
+ class Ban < DiscordModel
1775
+ # @return [Discorb::User] The user.
1776
+ attr_reader :user
1777
+ # @return [String] The reason for the ban.
1778
+ attr_reader :reason
1779
+
1780
+ #
1781
+ # Initialize a new instance of the {Ban} class.
1782
+ # @private
1783
+ #
1784
+ # @param [Discorb::Client] client The client.
1785
+ # @param [Discorb::Guild] guild The guild.
1786
+ # @param [Hash] data The data from Discord.
1787
+ #
1788
+ def initialize(client, guild, data)
1789
+ @client = client
1790
+ @guild = guild
1791
+ @reason = data[:reason]
1792
+ @user =
1793
+ @client.users[data[:user][:id]] || User.new(@client, data[:user])
1794
+ end
1795
+
1796
+ def inspect
1797
+ "<#{self.class.name} #{@user}>"
1798
+ end
1799
+ end
1800
+
1801
+ class << self
1802
+ #
1803
+ # Returns a banner url from the guild's ID.
1804
+ #
1805
+ # @param [#to_s] guild_id The ID of the guild.
1806
+ # @param [:shield, :banner1, :banner2, :banner3, :banner4] style The style of the banner.
1807
+ #
1808
+ # @return [String] The url of the banner.
1809
+ #
1810
+ def banner(guild_id, style: :banner)
1811
+ "#{Discorb::API_BASE_URL}/guilds/#{guild_id}/widget.png&style=#{style}"
1812
+ end
1813
+ end
1814
+
1815
+ private
1816
+
1817
+ def _set_data(data, is_create_event)
1818
+ @id = Snowflake.new(data[:id])
1819
+ if data[:unavailable]
1820
+ @unavailable = true
1821
+ return
1822
+ end
1823
+ @client.guilds[@id] = self unless data[:no_cache]
1824
+ @icon = data[:icon] && Asset.new(self, data[:icon])
1825
+ @unavailable = false
1826
+ @name = data[:name]
1827
+ @members = Discorb::Dictionary.new
1828
+ data[:members]&.each { |m| Member.new(@client, @id, m[:user], m) }
1829
+ @splash =
1830
+ data[:splash] && Asset.new(self, data[:splash], path: "splashes/#{@id}")
1831
+ @discovery_splash =
1832
+ data[:discovery_splash] &&
1833
+ Asset.new(
1834
+ self,
1835
+ data[:discovery_splash],
1836
+ path: "discovery-splashes/#{@id}"
1837
+ )
1838
+ @owner_id = data[:owner_id]
1839
+ @permissions = Permission.new(data[:permissions].to_i)
1840
+ @afk_channel_id = data[:afk_channel_id]
1841
+ @afk_timeout = data[:afk_timeout]
1842
+ @widget_enabled = data[:widget_enabled]
1843
+ @widget_channel_id = data[:widget_channel_id]
1844
+ @roles = Dictionary.new
1845
+ data[:roles].each { |r| @roles[r[:id]] = Role.new(@client, self, r) }
1846
+ @emojis = Dictionary.new
1847
+ data[:emojis].map do |e|
1848
+ @emojis[e[:id]] = CustomEmoji.new(@client, self, e)
1849
+ end
1850
+ @features = data[:features].map { |f| f.downcase.to_sym }
1851
+ @mfa_level = MFA_LEVELS[data[:mfa_level]]
1852
+ @verification_level = VERIFICATION_LEVELS[data[:verification_level]]
1853
+ @default_message_notifications =
1854
+ DEFAULT_MESSAGE_NOTIFICATIONS[data[:default_message_notifications]]
1855
+ @explicit_content_filter =
1856
+ EXPLICIT_CONTENT_FILTER[data[:explicit_content_filter]]
1857
+ @system_channel_id = data[:system_channel_id]
1858
+ @system_channel_flag =
1859
+ SystemChannelFlag.new(0b111 - data[:system_channel_flags])
1860
+ @rules_channel_id = data[:rules_channel_id]
1861
+ @vanity_url_code = data[:vanity_url_code]
1862
+ @description = data[:description]
1863
+ @banner =
1864
+ data[:banner] && Asset.new(self, data[:banner], path: "banners/#{@id}")
1865
+ @premium_tier = data[:premium_tier]
1866
+ @premium_subscription_count = data[:premium_tier_count].to_i
1867
+ @preferred_locale = data[:preferred_locale].gsub("-", "_").to_sym
1868
+ @public_updates_channel_id = data[:public_updates_channel_id]
1869
+ @max_video_channel_users = data[:max_video_channel_users]
1870
+ @approximate_member_count = data[:approximate_member_count]
1871
+ @approximate_presence_count = data[:approximate_presence_count]
1872
+ @welcome_screen =
1873
+ (
1874
+ if data[:welcome_screen].nil?
1875
+ nil
1876
+ else
1877
+ WelcomeScreen.new(@client, self, data[:welcome_screen])
1878
+ end
1879
+ )
1880
+ @nsfw_level = NSFW_LEVELS[data[:nsfw_level]]
1881
+ return unless is_create_event
1882
+
1883
+ @stickers =
1884
+ (
1885
+ if data[:stickers].nil?
1886
+ []
1887
+ else
1888
+ data[:stickers].map { |s| Sticker::GuildSticker.new(@client, s) }
1889
+ end
1890
+ )
1891
+ @joined_at = Time.iso8601(data[:joined_at])
1892
+ @large = data[:large]
1893
+ @member_count = data[:member_count]
1894
+ tmp_channels =
1895
+ data[:channels]
1896
+ .filter { |c| !c.key?(:thread_metadata) }
1897
+ .map { |c| Channel.make_channel(@client, c.merge({ guild_id: @id })) }
1898
+ @channels =
1899
+ Dictionary.new(
1900
+ tmp_channels.to_h { |c| [c.id, c] },
1901
+ sort: ->(c) { c[1].position }
1902
+ )
1903
+ @voice_states =
1904
+ Dictionary.new(
1905
+ data[:voice_states].to_h do |v|
1906
+ [
1907
+ Snowflake.new(v[:user_id]),
1908
+ VoiceState.new(@client, v.merge({ guild_id: @id }))
1909
+ ]
1910
+ end
1911
+ )
1912
+ @threads =
1913
+ (
1914
+ if data[:threads]
1915
+ data[:threads].map { |t| Channel.make_channel(@client, t) }
1916
+ else
1917
+ []
1918
+ end
1919
+ )
1920
+ @presences =
1921
+ Dictionary.new(
1922
+ data[:presences].to_h do |pr|
1923
+ [Snowflake.new(pr[:user][:id]), Presence.new(@client, pr)]
1924
+ end
1925
+ )
1926
+ @max_presences = data[:max_presences]
1927
+ @stage_instances =
1928
+ Dictionary.new(
1929
+ data[:stage_instances].to_h do |s|
1930
+ [Snowflake.new(s[:id]), StageInstance.new(@client, s)]
1931
+ end
1932
+ )
1933
+ @scheduled_events =
1934
+ Dictionary.new(
1935
+ data[:guild_scheduled_events].to_h do |s|
1936
+ [Snowflake.new(s[:id]), ScheduledEvent.new(@client, s)]
1937
+ end
1938
+ )
1939
+ @data.update(data)
1940
+ end
1941
+ end
1942
+
1943
+ #
1944
+ # Represents a system channel flag.
1945
+ # ## Flag fields
1946
+ # |Field|Value|
1947
+ # |-|-|
1948
+ # |`1 << 0`|`:member_join`|
1949
+ # |`1 << 1`|`:server_boost`|
1950
+ # |`1 << 2`|`:setup_tips`|
1951
+ # |`1 << 3`|`:join_stickers`|
1952
+ #
1953
+ class SystemChannelFlag < Flag
1954
+ @bits = {
1955
+ member_join: 0,
1956
+ server_boost: 1,
1957
+ setup_tips: 2,
1958
+ join_stickers: 3
1959
+ }.freeze
1960
+ end
1961
+
1962
+ #
1963
+ # Represents a welcome screen.
1964
+ #
1965
+ class WelcomeScreen < DiscordModel
1966
+ # @return [String] The description of the welcome screen.
1967
+ attr_reader :description
1968
+ # @return [Array<Discorb::WelcomeScreen::Channel>] The channels to display the welcome screen.
1969
+ attr_reader :channels
1970
+ # @return [Discorb::Guild] The guild the welcome screen belongs to.
1971
+ attr_reader :guild
1972
+
1973
+ #
1974
+ # Initializes the welcome screen.
1975
+ # @private
1976
+ #
1977
+ # @param [Discorb::Client] client The client.
1978
+ # @param [Discorb::Guild] guild The guild the welcome screen belongs to.
1979
+ # @param [Hash] data The data of the welcome screen.
1980
+ #
1981
+ def initialize(client, guild, data)
1982
+ @client = client
1983
+ @description = data[:description]
1984
+ @guild = guild
1985
+ @channels =
1986
+ data[:channels].map do |c|
1987
+ WelcomeScreen::Channel.new(
1988
+ client.channels[c[:channel_id]],
1989
+ c,
1990
+ c[:emoji_name] &&
1991
+ if c[:emoji_id]
1992
+ (
1993
+ client.emojis[c[:emoji_id]] ||
1994
+ Discorb::PartialEmoji.new(
1995
+ { name: c[:emoji_name], id: c[:emoji_id] }
1996
+ )
1997
+ )
1998
+ else
1999
+ Discorb::UnicodeEmoji.new(c[:emoji_name])
2000
+ end
2001
+ )
2002
+ end
2003
+ end
2004
+
2005
+ #
2006
+ # Represents a channel to display the welcome screen.
2007
+ #
2008
+ class Channel < DiscordModel
2009
+ # @return [String] The channel's name.
2010
+ attr_reader :description
2011
+
2012
+ # @!attribute [r] emoji
2013
+ # @return [Discorb::Emoji] The emoji to display.
2014
+ # @!attribute [r] channel
2015
+ # @macro client_cache
2016
+ # @return [Discorb::Channel] The channel to display the welcome screen.
2017
+
2018
+ #
2019
+ # Initialize a new welcome screen channel.
2020
+ #
2021
+ # @param [Discorb::TextChannel] channel The channel to display the welcome screen.
2022
+ # @param [String] description The channel's name.
2023
+ # @param [Discorb::Emoji] emoji The emoji to display.
2024
+ #
2025
+ def initialize(channel, description, emoji)
2026
+ if description.is_a?(Hash)
2027
+ @screen = channel
2028
+ data = description
2029
+ @channel_id = Snowflake.new(data[:channel_id])
2030
+ @description = data[:description]
2031
+ @emoji_id = Snowflake.new(data[:emoji_id])
2032
+ @emoji_name = data[:emoji_name]
2033
+ else
2034
+ @channel_id = channel.id
2035
+ @description = description
2036
+ if emoji.is_a?(UnicodeEmoji)
2037
+ @emoji_id = nil
2038
+ @emoji_name = emoji.value
2039
+ else
2040
+ @emoji_id = emoji.id
2041
+ @emoji_name = emoji.name
2042
+ end
2043
+ end
2044
+ end
2045
+
2046
+ #
2047
+ # Converts the channel to a hash.
2048
+ #
2049
+ # @return [Hash] The hash.
2050
+ # @see https://discord.com/developers/docs/resources/guild#welcome-screen-object
2051
+ #
2052
+ def to_hash
2053
+ {
2054
+ channel_id: @channel_id,
2055
+ description: @description,
2056
+ emoji_id: @emoji_id,
2057
+ emoji_name: @emoji_name
2058
+ }
2059
+ end
2060
+
2061
+ def channel
2062
+ @screen.guild.channels[@channel_id]
2063
+ end
2064
+
2065
+ def emoji
2066
+ if @emoji_id.nil?
2067
+ UnicodeEmoji.new(@emoji_name)
2068
+ else
2069
+ @screen.guild.emojis[@emoji_id]
2070
+ end
2071
+ end
2072
+
2073
+ #
2074
+ # Edits the welcome screen.
2075
+ # @async
2076
+ # @macro edit
2077
+ #
2078
+ # @param [Boolean] enabled Whether the welcome screen is enabled.
2079
+ # @param [Array<Discorb::WelcomeScreen::Channel>] channels The channels to display the welcome screen.
2080
+ # @param [String] description The description of the welcome screen.
2081
+ # @param [String] reason The reason for editing the welcome screen.
2082
+ #
2083
+ # @return [Async::Task<void>] The task.
2084
+ #
2085
+ def edit(
2086
+ enabled: Discorb::Unset,
2087
+ channels: Discorb::Unset,
2088
+ description: Discorb::Unset,
2089
+ reason: nil
2090
+ )
2091
+ Async do
2092
+ payload = {}
2093
+ payload[:enabled] = enabled unless enabled == Discorb::Unset
2094
+ payload[:welcome_channels] = channels.map(
2095
+ &:to_hash
2096
+ ) unless channels == Discorb::Unset
2097
+ payload[:description] = description unless description ==
2098
+ Discorb::Unset
2099
+ @client
2100
+ .http
2101
+ .request(
2102
+ Route.new(
2103
+ "/guilds/#{@guild.id}/welcome-screen",
2104
+ "//guilds/:guild_id/welcome-screen",
2105
+ :patch
2106
+ ),
2107
+ payload,
2108
+ audit_log_reason: reason
2109
+ )
2110
+ .wait
2111
+ end
2112
+ end
2113
+ end
2114
+ end
2115
+ end