twilight_http/request/guild/
create_guild_channel.rs1use crate::{
2 client::Client,
3 error::Error,
4 request::{self, AuditLogReason, Request, TryIntoRequest},
5 response::{Response, ResponseFuture},
6 routing::Route,
7};
8use serde::Serialize;
9use std::future::IntoFuture;
10use twilight_model::{
11 channel::{
12 Channel, ChannelType, VideoQualityMode,
13 forum::{DefaultReaction, ForumLayout, ForumSortOrder, ForumTag},
14 permission_overwrite::PermissionOverwrite,
15 thread::AutoArchiveDuration,
16 },
17 id::{
18 Id,
19 marker::{ChannelMarker, GuildMarker},
20 },
21};
22use twilight_validate::{
23 channel::{
24 ChannelValidationError, bitrate as validate_bitrate, name as validate_name,
25 rate_limit_per_user as validate_rate_limit_per_user, topic as validate_topic,
26 },
27 request::{ValidationError, audit_reason as validate_audit_reason},
28};
29
30#[derive(Serialize)]
31struct CreateGuildChannelFields<'a> {
32 #[serde(skip_serializing_if = "Option::is_none")]
33 available_tags: Option<&'a [ForumTag]>,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 bitrate: Option<u32>,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 default_auto_archive_duration: Option<AutoArchiveDuration>,
38 #[serde(skip_serializing_if = "Option::is_none")]
39 default_forum_layout: Option<ForumLayout>,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 default_reaction_emoji: Option<&'a DefaultReaction>,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 default_sort_order: Option<ForumSortOrder>,
44 #[serde(skip_serializing_if = "Option::is_none")]
49 default_thread_rate_limit_per_user: Option<u16>,
50 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
51 kind: Option<ChannelType>,
52 name: &'a str,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 nsfw: Option<bool>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 parent_id: Option<Id<ChannelMarker>>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 permission_overwrites: Option<&'a [PermissionOverwrite]>,
59 #[serde(skip_serializing_if = "Option::is_none")]
60 position: Option<u64>,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 rate_limit_per_user: Option<u16>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 rtc_region: Option<&'a str>,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 topic: Option<&'a str>,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 user_limit: Option<u16>,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 video_quality_mode: Option<VideoQualityMode>,
71}
72
73#[must_use = "requests must be configured and executed"]
78pub struct CreateGuildChannel<'a> {
79 fields: Result<CreateGuildChannelFields<'a>, ChannelValidationError>,
80 guild_id: Id<GuildMarker>,
81 http: &'a Client,
82 reason: Result<Option<&'a str>, ValidationError>,
83}
84
85impl<'a> CreateGuildChannel<'a> {
86 pub(crate) fn new(http: &'a Client, guild_id: Id<GuildMarker>, name: &'a str) -> Self {
87 let fields = Ok(CreateGuildChannelFields {
88 available_tags: None,
89 bitrate: None,
90 default_auto_archive_duration: None,
91 default_forum_layout: None,
92 default_reaction_emoji: None,
93 default_sort_order: None,
94 default_thread_rate_limit_per_user: None,
95 kind: None,
96 name,
97 nsfw: None,
98 parent_id: None,
99 permission_overwrites: None,
100 position: None,
101 rate_limit_per_user: None,
102 rtc_region: None,
103 topic: None,
104 user_limit: None,
105 video_quality_mode: None,
106 })
107 .and_then(|fields| {
108 validate_name(name)?;
109
110 Ok(fields)
111 });
112
113 Self {
114 fields,
115 guild_id,
116 http,
117 reason: Ok(None),
118 }
119 }
120
121 pub const fn available_tags(mut self, available_tags: &'a [ForumTag]) -> Self {
123 if let Ok(fields) = self.fields.as_mut() {
124 fields.available_tags = Some(available_tags);
125 }
126
127 self
128 }
129
130 pub fn bitrate(mut self, bitrate: u32) -> Self {
140 self.fields = self.fields.and_then(|mut fields| {
141 validate_bitrate(bitrate)?;
142
143 fields.bitrate = Some(bitrate);
144
145 Ok(fields)
146 });
147
148 self
149 }
150
151 pub const fn default_auto_archive_duration(
157 mut self,
158 auto_archive_duration: AutoArchiveDuration,
159 ) -> Self {
160 if let Ok(fields) = self.fields.as_mut() {
161 fields.default_auto_archive_duration = Some(auto_archive_duration);
162 }
163
164 self
165 }
166
167 pub const fn default_forum_layout(mut self, default_forum_layout: ForumLayout) -> Self {
169 if let Ok(fields) = self.fields.as_mut() {
170 fields.default_forum_layout = Some(default_forum_layout);
171 }
172
173 self
174 }
175
176 pub const fn default_reaction_emoji(
178 mut self,
179 default_reaction_emoji: &'a DefaultReaction,
180 ) -> Self {
181 if let Ok(fields) = self.fields.as_mut() {
182 fields.default_reaction_emoji = Some(default_reaction_emoji);
183 }
184
185 self
186 }
187
188 pub const fn default_sort_order(mut self, default_sort_order: ForumSortOrder) -> Self {
190 if let Ok(fields) = self.fields.as_mut() {
191 fields.default_sort_order = Some(default_sort_order);
192 }
193
194 self
195 }
196
197 pub fn default_thread_rate_limit_per_user(
206 mut self,
207 default_thread_rate_limit_per_user: u16,
208 ) -> Self {
209 self.fields = self.fields.and_then(|mut fields| {
210 validate_rate_limit_per_user(default_thread_rate_limit_per_user)?;
211
212 fields.default_thread_rate_limit_per_user = Some(default_thread_rate_limit_per_user);
213
214 Ok(fields)
215 });
216
217 self
218 }
219
220 pub const fn kind(mut self, kind: ChannelType) -> Self {
222 if let Ok(fields) = self.fields.as_mut() {
223 fields.kind = Some(kind);
224 }
225
226 self
227 }
228
229 pub const fn nsfw(mut self, nsfw: bool) -> Self {
231 if let Ok(fields) = self.fields.as_mut() {
232 fields.nsfw = Some(nsfw);
233 }
234
235 self
236 }
237
238 pub const fn parent_id(mut self, parent_id: Id<ChannelMarker>) -> Self {
241 if let Ok(fields) = self.fields.as_mut() {
242 fields.parent_id = Some(parent_id);
243 }
244
245 self
246 }
247
248 pub const fn permission_overwrites(
250 mut self,
251 permission_overwrites: &'a [PermissionOverwrite],
252 ) -> Self {
253 if let Ok(fields) = self.fields.as_mut() {
254 fields.permission_overwrites = Some(permission_overwrites);
255 }
256
257 self
258 }
259
260 pub const fn position(mut self, position: u64) -> Self {
265 if let Ok(fields) = self.fields.as_mut() {
266 fields.position = Some(position);
267 }
268
269 self
270 }
271
272 pub fn rate_limit_per_user(mut self, rate_limit_per_user: u16) -> Self {
286 self.fields = self.fields.and_then(|mut fields| {
287 validate_rate_limit_per_user(rate_limit_per_user)?;
288
289 fields.rate_limit_per_user = Some(rate_limit_per_user);
290
291 Ok(fields)
292 });
293
294 self
295 }
296
297 pub const fn rtc_region(mut self, rtc_region: &'a str) -> Self {
299 if let Ok(fields) = self.fields.as_mut() {
300 fields.rtc_region = Some(rtc_region);
301 }
302
303 self
304 }
305
306 pub fn topic(mut self, topic: &'a str) -> Self {
319 self.fields = self.fields.and_then(|mut fields| {
320 validate_topic(topic)?;
321
322 fields.topic.replace(topic);
323
324 Ok(fields)
325 });
326
327 self
328 }
329
330 pub const fn user_limit(mut self, user_limit: u16) -> Self {
337 if let Ok(fields) = self.fields.as_mut() {
338 fields.user_limit = Some(user_limit);
339 }
340
341 self
342 }
343
344 pub const fn video_quality_mode(mut self, video_quality_mode: VideoQualityMode) -> Self {
346 if let Ok(fields) = self.fields.as_mut() {
347 fields.video_quality_mode = Some(video_quality_mode);
348 }
349
350 self
351 }
352}
353
354impl<'a> AuditLogReason<'a> for CreateGuildChannel<'a> {
355 fn reason(mut self, reason: &'a str) -> Self {
356 self.reason = validate_audit_reason(reason).and(Ok(Some(reason)));
357
358 self
359 }
360}
361
362impl IntoFuture for CreateGuildChannel<'_> {
363 type Output = Result<Response<Channel>, Error>;
364
365 type IntoFuture = ResponseFuture<Channel>;
366
367 fn into_future(self) -> Self::IntoFuture {
368 let http = self.http;
369
370 match self.try_into_request() {
371 Ok(request) => http.request(request),
372 Err(source) => ResponseFuture::error(source),
373 }
374 }
375}
376
377impl TryIntoRequest for CreateGuildChannel<'_> {
378 fn try_into_request(self) -> Result<Request, Error> {
379 let fields = self.fields.map_err(Error::validation)?;
380 let mut request = Request::builder(&Route::CreateChannel {
381 guild_id: self.guild_id.get(),
382 })
383 .json(&fields);
384
385 if let Some(reason) = self.reason.map_err(Error::validation)? {
386 request = request.headers(request::audit_header(reason)?);
387 }
388
389 request.build()
390 }
391}