discorb 0.18.0 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) 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 +25 -0
  5. data/Gemfile +4 -4
  6. data/README.md +2 -1
  7. data/Rakefile +482 -459
  8. data/Steepfile +8 -6
  9. data/docs/application_command.md +1 -0
  10. data/docs/events.md +2 -2
  11. data/docs/voice_events.md +6 -6
  12. data/lib/discorb/allowed_mentions.rb +68 -72
  13. data/lib/discorb/app_command/command.rb +466 -394
  14. data/lib/discorb/app_command/common.rb +65 -25
  15. data/lib/discorb/app_command/handler.rb +304 -265
  16. data/lib/discorb/app_command.rb +5 -5
  17. data/lib/discorb/application.rb +198 -197
  18. data/lib/discorb/asset.rb +101 -101
  19. data/lib/discorb/attachment.rb +134 -119
  20. data/lib/discorb/audit_logs.rb +412 -385
  21. data/lib/discorb/automod.rb +279 -269
  22. data/lib/discorb/channel/base.rb +107 -108
  23. data/lib/discorb/channel/category.rb +32 -32
  24. data/lib/discorb/channel/container.rb +44 -44
  25. data/lib/discorb/channel/dm.rb +26 -28
  26. data/lib/discorb/channel/guild.rb +311 -246
  27. data/lib/discorb/channel/stage.rb +156 -140
  28. data/lib/discorb/channel/text.rb +430 -336
  29. data/lib/discorb/channel/thread.rb +374 -325
  30. data/lib/discorb/channel/voice.rb +85 -79
  31. data/lib/discorb/channel.rb +5 -5
  32. data/lib/discorb/client.rb +635 -623
  33. data/lib/discorb/color.rb +178 -182
  34. data/lib/discorb/common.rb +168 -164
  35. data/lib/discorb/components/button.rb +107 -106
  36. data/lib/discorb/components/select_menu.rb +157 -145
  37. data/lib/discorb/components/text_input.rb +103 -106
  38. data/lib/discorb/components.rb +68 -66
  39. data/lib/discorb/dictionary.rb +135 -135
  40. data/lib/discorb/embed.rb +404 -398
  41. data/lib/discorb/emoji.rb +309 -302
  42. data/lib/discorb/emoji_table.rb +16099 -8857
  43. data/lib/discorb/error.rb +131 -131
  44. data/lib/discorb/event.rb +360 -314
  45. data/lib/discorb/event_handler.rb +39 -39
  46. data/lib/discorb/exe/about.rb +17 -17
  47. data/lib/discorb/exe/irb.rb +72 -67
  48. data/lib/discorb/exe/new.rb +323 -315
  49. data/lib/discorb/exe/run.rb +69 -68
  50. data/lib/discorb/exe/setup.rb +57 -55
  51. data/lib/discorb/exe/show.rb +12 -12
  52. data/lib/discorb/extend.rb +25 -45
  53. data/lib/discorb/extension.rb +89 -83
  54. data/lib/discorb/flag.rb +126 -128
  55. data/lib/discorb/gateway.rb +984 -794
  56. data/lib/discorb/gateway_events.rb +670 -638
  57. data/lib/discorb/gateway_requests.rb +45 -48
  58. data/lib/discorb/guild.rb +2115 -1626
  59. data/lib/discorb/guild_template.rb +280 -241
  60. data/lib/discorb/http.rb +247 -232
  61. data/lib/discorb/image.rb +42 -42
  62. data/lib/discorb/integration.rb +169 -161
  63. data/lib/discorb/intents.rb +161 -163
  64. data/lib/discorb/interaction/autocomplete.rb +76 -62
  65. data/lib/discorb/interaction/command.rb +279 -224
  66. data/lib/discorb/interaction/components.rb +114 -104
  67. data/lib/discorb/interaction/modal.rb +36 -32
  68. data/lib/discorb/interaction/response.rb +379 -330
  69. data/lib/discorb/interaction/root.rb +271 -118
  70. data/lib/discorb/interaction.rb +5 -5
  71. data/lib/discorb/invite.rb +154 -153
  72. data/lib/discorb/member.rb +344 -311
  73. data/lib/discorb/message.rb +615 -544
  74. data/lib/discorb/message_meta.rb +197 -186
  75. data/lib/discorb/modules.rb +371 -290
  76. data/lib/discorb/permission.rb +305 -289
  77. data/lib/discorb/presence.rb +352 -346
  78. data/lib/discorb/rate_limit.rb +81 -76
  79. data/lib/discorb/reaction.rb +55 -54
  80. data/lib/discorb/role.rb +272 -240
  81. data/lib/discorb/shard.rb +76 -74
  82. data/lib/discorb/sticker.rb +193 -171
  83. data/lib/discorb/user.rb +205 -188
  84. data/lib/discorb/utils/colored_puts.rb +16 -16
  85. data/lib/discorb/utils.rb +12 -16
  86. data/lib/discorb/voice_state.rb +305 -281
  87. data/lib/discorb/webhook.rb +537 -507
  88. data/lib/discorb.rb +62 -56
  89. data/sig/discorb/activity.rbs +1 -0
  90. data/sig/discorb/allowed_mentions.rbs +1 -0
  91. data/sig/discorb/app_command/base.rbs +7 -1
  92. data/sig/discorb/application.rbs +6 -0
  93. data/sig/discorb/asset.rbs +2 -0
  94. data/sig/discorb/attachment.rbs +8 -0
  95. data/sig/discorb/audit_log.rbs +7 -0
  96. data/sig/discorb/automod.rbs +32 -6
  97. data/sig/discorb/avatar.rbs +1 -0
  98. data/sig/discorb/channel/base.rbs +8 -1
  99. data/sig/discorb/channel/category.rbs +1 -0
  100. data/sig/discorb/channel/container.rbs +4 -0
  101. data/sig/discorb/channel/stage.rbs +4 -0
  102. data/sig/discorb/channel/text.rbs +2 -2
  103. data/sig/discorb/channel/thread.rbs +11 -0
  104. data/sig/discorb/channel/voice.rbs +2 -0
  105. data/sig/discorb/client.rbs +21 -20
  106. data/sig/discorb/color.rbs +6 -0
  107. data/sig/discorb/component/base.rbs +1 -0
  108. data/sig/discorb/component/button.rbs +2 -0
  109. data/sig/discorb/component/select_menu.rbs +4 -0
  110. data/sig/discorb/component/text_input.rbs +1 -0
  111. data/sig/discorb/custom_emoji.rbs +5 -1
  112. data/sig/discorb/dictionary.rbs +2 -0
  113. data/sig/discorb/discord_model.rbs +2 -0
  114. data/sig/discorb/embed.rbs +7 -0
  115. data/sig/discorb/emoji.rbs +1 -0
  116. data/sig/discorb/event_handler.rbs +2 -1
  117. data/sig/discorb/extension.rbs +13 -12
  118. data/sig/discorb/flag.rbs +2 -0
  119. data/sig/discorb/gateway.rbs +5 -0
  120. data/sig/discorb/guild.rbs +8 -4
  121. data/sig/discorb/guild_template.rbs +1 -1
  122. data/sig/discorb/http.rbs +4 -1
  123. data/sig/discorb/image.rbs +2 -0
  124. data/sig/discorb/integration.rbs +1 -1
  125. data/sig/discorb/intents.rbs +4 -3
  126. data/sig/discorb/interaction/base.rbs +36 -0
  127. data/sig/discorb/interaction/message_component.rbs +1 -2
  128. data/sig/discorb/interaction/modal.rbs +1 -2
  129. data/sig/discorb/interaction/responder.rbs +49 -49
  130. data/sig/discorb/invite.rbs +1 -1
  131. data/sig/discorb/member.rbs +2 -0
  132. data/sig/discorb/message.rbs +8 -1
  133. data/sig/discorb/messageable.rbs +1 -4
  134. data/sig/discorb/partial_emoji.rbs +3 -0
  135. data/sig/discorb/permissions.rbs +7 -0
  136. data/sig/discorb/presence.rbs +2 -0
  137. data/sig/discorb/reaction.rbs +5 -1
  138. data/sig/discorb/role.rbs +7 -1
  139. data/sig/discorb/scheduled_event.rbs +2 -1
  140. data/sig/discorb/shard.rbs +2 -1
  141. data/sig/discorb/snowflake.rbs +2 -0
  142. data/sig/discorb/stage_instance.rbs +9 -3
  143. data/sig/discorb/sticker.rbs +1 -1
  144. data/sig/discorb/unicode_emoji.rbs +4 -0
  145. data/sig/discorb/user.rbs +24 -20
  146. data/sig/discorb/webhook.rbs +17 -6
  147. data/sig/discorb/welcome_screen.rbs +1 -0
  148. data/sig/override.rbs +2 -0
  149. metadata +3 -3
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 = :send_message,
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: 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