twilight_http/request/channel/
update_channel.rs1#[cfg(not(target_os = "wasi"))]
2use crate::response::{Response, ResponseFuture};
3use crate::{
4 client::Client,
5 error::Error,
6 request::{self, AuditLogReason, Nullable, Request, TryIntoRequest},
7 routing::Route,
8};
9use serde::Serialize;
10use std::future::IntoFuture;
11use twilight_model::{
12 channel::{
13 Channel, ChannelFlags, ChannelType, VideoQualityMode,
14 forum::{DefaultReaction, ForumLayout, ForumSortOrder, ForumTag},
15 permission_overwrite::PermissionOverwrite,
16 },
17 id::{Id, marker::ChannelMarker},
18};
19use twilight_validate::{
20 channel::{
21 ChannelValidationError, bitrate as validate_bitrate, forum_topic as validate_forum_topic,
22 name as validate_name, topic as validate_topic, user_limit as validate_user_limit,
23 },
24 request::{ValidationError, audit_reason as validate_audit_reason},
25};
26
27#[derive(Serialize)]
30struct UpdateChannelFields<'a> {
31 #[serde(skip_serializing_if = "Option::is_none")]
32 available_tags: Option<&'a [ForumTag]>,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 bitrate: Option<u32>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 default_forum_layout: Option<ForumLayout>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 default_reaction_emoji: Option<Nullable<&'a DefaultReaction>>,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 default_sort_order: Option<Nullable<ForumSortOrder>>,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 default_thread_rate_limit_per_user: Option<Nullable<u16>>,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 flags: Option<ChannelFlags>,
45 #[serde(rename = "type")]
46 #[serde(skip_serializing_if = "Option::is_none")]
47 kind: Option<ChannelType>,
48 #[serde(skip_serializing_if = "Option::is_none")]
49 name: Option<&'a str>,
50 #[serde(skip_serializing_if = "Option::is_none")]
51 nsfw: Option<bool>,
52 #[serde(skip_serializing_if = "Option::is_none")]
53 parent_id: Option<Nullable<Id<ChannelMarker>>>,
54 #[serde(skip_serializing_if = "Option::is_none")]
55 permission_overwrites: Option<&'a [PermissionOverwrite]>,
56 #[serde(skip_serializing_if = "Option::is_none")]
57 position: Option<u64>,
58 #[serde(skip_serializing_if = "Option::is_none")]
59 rate_limit_per_user: Option<u16>,
60 #[serde(skip_serializing_if = "Option::is_none")]
61 rtc_region: Option<Nullable<&'a str>>,
62 #[serde(skip_serializing_if = "Option::is_none")]
63 topic: Option<&'a str>,
64 #[serde(skip_serializing_if = "Option::is_none")]
65 user_limit: Option<u16>,
66 #[serde(skip_serializing_if = "Option::is_none")]
67 video_quality_mode: Option<VideoQualityMode>,
68}
69
70#[must_use = "requests must be configured and executed"]
75pub struct UpdateChannel<'a> {
76 channel_id: Id<ChannelMarker>,
77 fields: Result<UpdateChannelFields<'a>, ChannelValidationError>,
78 http: &'a Client,
79 reason: Result<Option<&'a str>, ValidationError>,
80}
81
82impl<'a> UpdateChannel<'a> {
83 pub(crate) const fn new(http: &'a Client, channel_id: Id<ChannelMarker>) -> Self {
84 Self {
85 channel_id,
86 fields: Ok(UpdateChannelFields {
87 available_tags: None,
88 bitrate: None,
89 default_forum_layout: None,
90 default_reaction_emoji: None,
91 default_sort_order: None,
92 default_thread_rate_limit_per_user: None,
93 flags: None,
94 kind: None,
95 name: None,
96 nsfw: None,
97 parent_id: None,
98 permission_overwrites: None,
99 position: None,
100 rate_limit_per_user: None,
101 rtc_region: None,
102 topic: None,
103 user_limit: None,
104 video_quality_mode: None,
105 }),
106 http,
107 reason: Ok(None),
108 }
109 }
110
111 pub const fn available_tags(mut self, available_tags: &'a [ForumTag]) -> Self {
113 if let Ok(fields) = self.fields.as_mut() {
114 fields.available_tags = Some(available_tags);
115 }
116
117 self
118 }
119
120 pub fn bitrate(mut self, bitrate: u32) -> Self {
130 self.fields = self.fields.and_then(|mut fields| {
131 validate_bitrate(bitrate)?;
132 fields.bitrate = Some(bitrate);
133
134 Ok(fields)
135 });
136
137 self
138 }
139
140 pub const fn default_forum_layout(mut self, default_forum_layout: ForumLayout) -> Self {
142 if let Ok(fields) = self.fields.as_mut() {
143 fields.default_forum_layout = Some(default_forum_layout);
144 }
145
146 self
147 }
148
149 pub const fn default_reaction_emoji(
151 mut self,
152 default_reaction_emoji: Option<&'a DefaultReaction>,
153 ) -> Self {
154 if let Ok(fields) = self.fields.as_mut() {
155 fields.default_reaction_emoji = Some(Nullable(default_reaction_emoji));
156 }
157
158 self
159 }
160
161 pub const fn default_sort_order(mut self, default_sort_order: Option<ForumSortOrder>) -> Self {
163 if let Ok(fields) = self.fields.as_mut() {
164 fields.default_sort_order = Some(Nullable(default_sort_order));
165 }
166
167 self
168 }
169
170 pub fn default_thread_rate_limit_per_user(
184 mut self,
185 default_thread_rate_limit_per_user: Option<u16>,
186 ) -> Self {
187 self.fields = self.fields.and_then(|mut fields| {
188 if let Some(default_thread_rate_limit_per_user) = default_thread_rate_limit_per_user {
189 twilight_validate::channel::rate_limit_per_user(
190 default_thread_rate_limit_per_user,
191 )?;
192 }
193
194 fields.default_thread_rate_limit_per_user =
195 Some(Nullable(default_thread_rate_limit_per_user));
196
197 Ok(fields)
198 });
199
200 self
201 }
202
203 pub const fn flags(mut self, flags: ChannelFlags) -> Self {
205 if let Ok(fields) = self.fields.as_mut() {
206 fields.flags = Some(flags);
207 }
208
209 self
210 }
211
212 pub fn forum_topic(mut self, topic: Option<&'a str>) -> Self {
226 self.fields = self.fields.and_then(|mut fields| {
227 if let Some(topic) = topic {
228 validate_forum_topic(topic)?;
229 }
230
231 fields.topic = topic;
232
233 Ok(fields)
234 });
235
236 self
237 }
238
239 pub fn name(mut self, name: &'a str) -> Self {
250 self.fields = self.fields.and_then(|mut fields| {
251 validate_name(name)?;
252 fields.name = Some(name);
253
254 Ok(fields)
255 });
256
257 self
258 }
259
260 pub const fn nsfw(mut self, nsfw: bool) -> Self {
262 if let Ok(fields) = self.fields.as_mut() {
263 fields.nsfw = Some(nsfw);
264 }
265
266 self
267 }
268
269 pub const fn parent_id(mut self, parent_id: Option<Id<ChannelMarker>>) -> Self {
272 if let Ok(fields) = self.fields.as_mut() {
273 fields.parent_id = Some(Nullable(parent_id));
274 }
275
276 self
277 }
278
279 pub const fn permission_overwrites(
282 mut self,
283 permission_overwrites: &'a [PermissionOverwrite],
284 ) -> Self {
285 if let Ok(fields) = self.fields.as_mut() {
286 fields.permission_overwrites = Some(permission_overwrites);
287 }
288
289 self
290 }
291
292 pub const fn position(mut self, position: u64) -> Self {
297 if let Ok(fields) = self.fields.as_mut() {
298 fields.position = Some(position);
299 }
300
301 self
302 }
303
304 pub fn rate_limit_per_user(mut self, rate_limit_per_user: u16) -> Self {
318 self.fields = self.fields.and_then(|mut fields| {
319 twilight_validate::channel::rate_limit_per_user(rate_limit_per_user)?;
320 fields.rate_limit_per_user = Some(rate_limit_per_user);
321
322 Ok(fields)
323 });
324
325 self
326 }
327
328 pub const fn rtc_region(mut self, rtc_region: Option<&'a str>) -> Self {
332 if let Ok(fields) = self.fields.as_mut() {
333 fields.rtc_region = Some(Nullable(rtc_region));
334 }
335
336 self
337 }
338
339 pub fn topic(mut self, topic: &'a str) -> Self {
351 self.fields = self.fields.and_then(|mut fields| {
352 validate_topic(topic)?;
353 fields.topic.replace(topic);
354
355 Ok(fields)
356 });
357
358 self
359 }
360
361 pub fn user_limit(mut self, user_limit: u16) -> Self {
373 self.fields = self.fields.and_then(|mut fields| {
374 validate_user_limit(user_limit)?;
375 fields.user_limit = Some(user_limit);
376
377 Ok(fields)
378 });
379
380 self
381 }
382
383 pub const fn video_quality_mode(mut self, video_quality_mode: VideoQualityMode) -> Self {
385 if let Ok(fields) = self.fields.as_mut() {
386 fields.video_quality_mode = Some(video_quality_mode);
387 }
388
389 self
390 }
391
392 pub const fn kind(mut self, kind: ChannelType) -> Self {
400 if let Ok(fields) = self.fields.as_mut() {
401 fields.kind = Some(kind);
402 }
403
404 self
405 }
406}
407
408impl<'a> AuditLogReason<'a> for UpdateChannel<'a> {
409 fn reason(mut self, reason: &'a str) -> Self {
410 self.reason = validate_audit_reason(reason).and(Ok(Some(reason)));
411
412 self
413 }
414}
415
416#[cfg(not(target_os = "wasi"))]
417impl IntoFuture for UpdateChannel<'_> {
418 type Output = Result<Response<Channel>, Error>;
419
420 type IntoFuture = ResponseFuture<Channel>;
421
422 fn into_future(self) -> Self::IntoFuture {
423 let http = self.http;
424
425 match self.try_into_request() {
426 Ok(request) => http.request(request),
427 Err(source) => ResponseFuture::error(source),
428 }
429 }
430}
431
432impl TryIntoRequest for UpdateChannel<'_> {
433 fn try_into_request(self) -> Result<Request, Error> {
434 let fields = self.fields.map_err(Error::validation)?;
435 let mut request = Request::builder(&Route::UpdateChannel {
436 channel_id: self.channel_id.get(),
437 })
438 .json(&fields);
439
440 if let Some(reason) = self.reason.map_err(Error::validation)? {
441 request = request.headers(request::audit_header(reason)?);
442 }
443
444 request.build()
445 }
446}