twilight_http/request/channel/thread/create_forum_thread/
message.rs1use super::{CreateForumThread, ForumThread};
2use crate::{
3 Error,
4 request::{AuditLogReason, Nullable, TryIntoRequest, attachment::PartialAttachment},
5 response::{Response, ResponseFuture},
6};
7use serde::Serialize;
8use std::{future::IntoFuture, mem};
9use twilight_model::{
10 channel::message::{AllowedMentions, Component, Embed, MessageFlags},
11 http::attachment::Attachment,
12 id::{Id, marker::StickerMarker},
13};
14use twilight_validate::{
15 message::{
16 MessageValidationError, attachment_filename as validate_attachment_filename,
17 components as validate_components, content as validate_content, embeds as validate_embeds,
18 sticker_ids as validate_sticker_ids,
19 },
20 request::audit_reason as validate_audit_reason,
21};
22
23#[derive(Serialize)]
25pub(super) struct CreateForumThreadMessageFields<'a> {
26 #[serde(skip_serializing_if = "Option::is_none")]
27 pub(super) allowed_mentions: Option<Nullable<&'a AllowedMentions>>,
28 #[serde(skip_serializing_if = "Option::is_none")]
29 pub(super) attachments: Option<Vec<PartialAttachment<'a>>>,
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub(super) components: Option<&'a [Component]>,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 pub(super) content: Option<&'a str>,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub(super) embeds: Option<&'a [Embed]>,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 pub(super) flags: Option<MessageFlags>,
38 #[serde(skip_serializing_if = "Option::is_none")]
39 pub(super) payload_json: Option<&'a [u8]>,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 pub(super) sticker_ids: Option<&'a [Id<StickerMarker>]>,
42}
43
44#[must_use = "requests must be configured and executed"]
45pub struct CreateForumThreadMessage<'a>(Result<CreateForumThread<'a>, MessageValidationError>);
46
47impl<'a> CreateForumThreadMessage<'a> {
48 pub(super) const fn new(inner: CreateForumThread<'a>) -> Self {
49 Self(Ok(inner))
50 }
51
52 pub const fn allowed_mentions(mut self, allowed_mentions: Option<&'a AllowedMentions>) -> Self {
57 if let Ok(inner) = self.0.as_mut() {
58 inner.fields.message.allowed_mentions = Some(Nullable(allowed_mentions));
59 }
60
61 self
62 }
63
64 pub fn attachments(mut self, attachments: &'a [Attachment]) -> Self {
75 if self.0.is_ok() {
76 let validation = attachments
77 .iter()
78 .try_for_each(|attachment| validate_attachment_filename(&attachment.filename));
79
80 if let Err(source) = validation {
81 self.0 = Err(source);
82 } else if let Ok(inner) = self.0.as_mut() {
83 let mut manager = mem::take(&mut inner.attachment_manager);
84 manager = manager.set_files(attachments.iter().collect());
85
86 inner.attachment_manager = manager;
87 }
88 }
89
90 self
91 }
92
93 pub fn components(mut self, components: &'a [Component]) -> Self {
105 self.0 = self.0.and_then(|mut inner| {
106 validate_components(
107 components,
108 inner
109 .fields
110 .message
111 .flags
112 .is_some_and(|f| f.contains(MessageFlags::IS_COMPONENTS_V2)),
113 )?;
114 inner.fields.message.components = Some(components);
115
116 Ok(inner)
117 });
118
119 self
120 }
121
122 pub fn content(mut self, content: &'a str) -> Self {
133 self.0 = self.0.and_then(|mut inner| {
134 validate_content(content)?;
135 inner.fields.message.content = Some(content);
136
137 Ok(inner)
138 });
139
140 self
141 }
142
143 pub fn embeds(mut self, embeds: &'a [Embed]) -> Self {
164 self.0 = self.0.and_then(|mut inner| {
165 validate_embeds(embeds)?;
166 inner.fields.message.embeds = Some(embeds);
167
168 Ok(inner)
169 });
170
171 self
172 }
173
174 pub const fn flags(mut self, flags: MessageFlags) -> Self {
182 if let Ok(inner) = self.0.as_mut() {
183 inner.fields.message.flags = Some(flags);
184 }
185
186 self
187 }
188
189 pub const fn payload_json(mut self, payload_json: &'a [u8]) -> Self {
202 if let Ok(inner) = self.0.as_mut() {
203 inner.fields.message.payload_json = Some(payload_json);
204 }
205
206 self
207 }
208
209 pub fn sticker_ids(mut self, sticker_ids: &'a [Id<StickerMarker>]) -> Self {
217 self.0 = self.0.and_then(|mut inner| {
218 validate_sticker_ids(sticker_ids)?;
219 inner.fields.message.sticker_ids = Some(sticker_ids);
220
221 Ok(inner)
222 });
223
224 self
225 }
226}
227
228impl<'a> AuditLogReason<'a> for CreateForumThreadMessage<'a> {
229 fn reason(mut self, reason: &'a str) -> Self {
230 if let Ok(inner) = self.0.as_mut() {
231 inner.reason = validate_audit_reason(reason).and(Ok(Some(reason)));
232 }
233
234 self
235 }
236}
237
238impl IntoFuture for CreateForumThreadMessage<'_> {
239 type Output = Result<Response<ForumThread>, Error>;
240
241 type IntoFuture = ResponseFuture<ForumThread>;
242
243 fn into_future(self) -> Self::IntoFuture {
244 match self.0 {
245 Ok(inner) => inner.exec(),
246 Err(source) => ResponseFuture::error(Error::validation(source)),
247 }
248 }
249}
250
251impl TryIntoRequest for CreateForumThreadMessage<'_> {
252 fn try_into_request(self) -> Result<crate::request::Request, Error> {
253 self.0
254 .map_err(Error::validation)
255 .and_then(CreateForumThread::try_into_request)
256 }
257}