twilight_http/request/channel/thread/
update_thread.rs1use crate::{
2 client::Client,
3 error::Error,
4 request::{self, AuditLogReason, Nullable, Request, TryIntoRequest},
5 response::{Response, ResponseFuture},
6 routing::Route,
7};
8use serde::Serialize;
9use std::future::IntoFuture;
10use twilight_model::{
11 channel::{thread::AutoArchiveDuration, Channel},
12 id::{
13 marker::{ChannelMarker, TagMarker},
14 Id,
15 },
16};
17use twilight_validate::{
18 channel::{
19 name as validate_name, rate_limit_per_user as validate_rate_limit_per_user,
20 ChannelValidationError,
21 },
22 request::{audit_reason as validate_audit_reason, ValidationError},
23};
24
25#[derive(Serialize)]
26struct UpdateThreadFields<'a> {
27 #[serde(skip_serializing_if = "Option::is_none")]
28 applied_tags: Option<Nullable<&'a [Id<TagMarker>]>>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 archived: Option<bool>,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 auto_archive_duration: Option<AutoArchiveDuration>,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 invitable: Option<bool>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 locked: Option<bool>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 name: Option<&'a str>,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 rate_limit_per_user: Option<u16>,
41}
42
43#[must_use = "requests must be configured and executed"]
48pub struct UpdateThread<'a> {
49 channel_id: Id<ChannelMarker>,
50 fields: Result<UpdateThreadFields<'a>, ChannelValidationError>,
51 http: &'a Client,
52 reason: Result<Option<&'a str>, ValidationError>,
53}
54
55impl<'a> UpdateThread<'a> {
56 pub(crate) const fn new(http: &'a Client, channel_id: Id<ChannelMarker>) -> Self {
57 Self {
58 channel_id,
59 fields: Ok(UpdateThreadFields {
60 applied_tags: None,
61 archived: None,
62 auto_archive_duration: None,
63 invitable: None,
64 locked: None,
65 name: None,
66 rate_limit_per_user: None,
67 }),
68 http,
69 reason: Ok(None),
70 }
71 }
72
73 pub fn applied_tags(mut self, applied_tags: Option<&'a [Id<TagMarker>]>) -> Self {
75 if let Ok(fields) = self.fields.as_mut() {
76 fields.applied_tags = Some(Nullable(applied_tags));
77 }
78
79 self
80 }
81
82 pub fn archived(mut self, archived: bool) -> Self {
90 if let Ok(fields) = self.fields.as_mut() {
91 fields.archived = Some(archived);
92 }
93
94 self
95 }
96
97 pub fn auto_archive_duration(mut self, auto_archive_duration: AutoArchiveDuration) -> Self {
102 if let Ok(fields) = self.fields.as_mut() {
103 fields.auto_archive_duration = Some(auto_archive_duration);
104 }
105
106 self
107 }
108
109 pub fn invitable(mut self, invitable: bool) -> Self {
111 if let Ok(fields) = self.fields.as_mut() {
112 fields.invitable = Some(invitable);
113 }
114
115 self
116 }
117
118 pub fn locked(mut self, locked: bool) -> Self {
125 if let Ok(fields) = self.fields.as_mut() {
126 fields.locked = Some(locked);
127 }
128
129 self
130 }
131
132 pub fn name(mut self, name: &'a str) -> Self {
142 self.fields = self.fields.and_then(|mut fields| {
143 validate_name(name)?;
144 fields.name = Some(name);
145
146 Ok(fields)
147 });
148
149 self
150 }
151
152 pub fn rate_limit_per_user(mut self, rate_limit_per_user: u16) -> Self {
166 self.fields = self.fields.and_then(|mut fields| {
167 validate_rate_limit_per_user(rate_limit_per_user)?;
168 fields.rate_limit_per_user = Some(rate_limit_per_user);
169
170 Ok(fields)
171 });
172
173 self
174 }
175}
176
177impl<'a> AuditLogReason<'a> for UpdateThread<'a> {
178 fn reason(mut self, reason: &'a str) -> Self {
179 self.reason = validate_audit_reason(reason).and(Ok(Some(reason)));
180
181 self
182 }
183}
184
185impl IntoFuture for UpdateThread<'_> {
186 type Output = Result<Response<Channel>, Error>;
187
188 type IntoFuture = ResponseFuture<Channel>;
189
190 fn into_future(self) -> Self::IntoFuture {
191 let http = self.http;
192
193 match self.try_into_request() {
194 Ok(request) => http.request(request),
195 Err(source) => ResponseFuture::error(source),
196 }
197 }
198}
199
200impl TryIntoRequest for UpdateThread<'_> {
201 fn try_into_request(self) -> Result<Request, Error> {
202 let fields = self.fields.map_err(Error::validation)?;
203 let mut request = Request::builder(&Route::UpdateChannel {
204 channel_id: self.channel_id.get(),
205 })
206 .json(&fields);
207
208 if let Some(reason) = self.reason.map_err(Error::validation)? {
209 request = request.headers(request::audit_header(reason)?);
210 }
211
212 request.build()
213 }
214}
215
216#[cfg(test)]
217mod tests {
218 use super::{UpdateThread, UpdateThreadFields};
219 use crate::{
220 request::{Request, TryIntoRequest},
221 routing::Route,
222 Client,
223 };
224 use std::error::Error;
225 use twilight_model::id::Id;
226
227 #[test]
228 fn request() -> Result<(), Box<dyn Error>> {
229 let client = Client::new("token".to_string());
230 let channel_id = Id::new(123);
231
232 let actual = UpdateThread::new(&client, channel_id)
233 .rate_limit_per_user(60)
234 .try_into_request()?;
235
236 let expected = Request::builder(&Route::UpdateChannel {
237 channel_id: channel_id.get(),
238 })
239 .json(&UpdateThreadFields {
240 applied_tags: None,
241 archived: None,
242 auto_archive_duration: None,
243 invitable: None,
244 locked: None,
245 name: None,
246 rate_limit_per_user: Some(60),
247 })
248 .build()?;
249
250 assert_eq!(expected.body(), actual.body());
251 assert_eq!(expected.path(), actual.path());
252 assert_eq!(expected.ratelimit_path(), actual.ratelimit_path());
253
254 Ok(())
255 }
256}