Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -151,23 +151,18 @@ impl<'a> CreateFollowup<'a> {
///
/// Calling this method multiple times will clear previous calls.
///
/// Components are validated when the request is built so flags set after
/// this method are taken into account.
///
/// # Errors
///
/// Refer to the errors section of
/// [`twilight_validate::component::component`] for a list of errors that
/// may be returned as a result of validating each provided component.
pub fn components(mut self, components: &'a [Component]) -> Self {
self.fields = self.fields.and_then(|mut fields| {
validate_components(
components,
fields
.flags
.is_some_and(|flags| flags.contains(MessageFlags::IS_COMPONENTS_V2)),
)?;
pub const fn components(mut self, components: &'a [Component]) -> Self {
if let Ok(fields) = self.fields.as_mut() {
fields.components = Some(components);

Ok(fields)
});
}

self
}
Expand Down Expand Up @@ -296,6 +291,16 @@ impl IntoFuture for CreateFollowup<'_> {
impl TryIntoRequest for CreateFollowup<'_> {
fn try_into_request(self) -> Result<Request, Error> {
let mut fields = self.fields.map_err(Error::validation)?;

if let Some(components) = fields.components {
validate_components(
components,
fields
.flags
.is_some_and(|flags| flags.contains(MessageFlags::IS_COMPONENTS_V2)),
)
.map_err(Error::validation)?;
}
let mut request = Request::builder(&Route::ExecuteWebhook {
thread_id: None,
token: self.token,
Expand Down Expand Up @@ -349,6 +354,29 @@ mod tests {
use std::error::Error;
use twilight_model::id::Id;

#[test]
fn components_v2_before_flags() {
use twilight_model::channel::message::{Component, MessageFlags, component::TextDisplay};

let application_id = Id::new(1);
let client = Client::new(String::new());
let components = [Component::TextDisplay(TextDisplay {
content: "test".to_owned(),
id: None,
})];
let token = "foo".to_owned();

assert!(
client
.interaction(application_id)
.create_followup(&token)
.components(&components)
.flags(MessageFlags::IS_COMPONENTS_V2)
.try_into_request()
.is_ok()
);
}

#[test]
fn create_followup_message() -> Result<(), Box<dyn Error>> {
let application_id = Id::new(1);
Expand Down
63 changes: 50 additions & 13 deletions twilight-http/src/request/channel/message/create_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,23 +158,18 @@ impl<'a> CreateMessage<'a> {
///
/// Calling this method will clear previous calls.
///
/// Components are validated when the request is built so flags set after
/// this method are taken into account.
///
/// # Errors
///
/// Refer to the errors section of
/// [`twilight_validate::component::component`] for a list of errors that
/// may be returned as a result of validating each provided component.
pub fn components(mut self, components: &'a [Component]) -> Self {
self.fields = self.fields.and_then(|mut fields| {
validate_components(
components,
fields
.flags
.is_some_and(|flags| flags.contains(MessageFlags::IS_COMPONENTS_V2)),
)?;
pub const fn components(mut self, components: &'a [Component]) -> Self {
if let Ok(fields) = self.fields.as_mut() {
fields.components = Some(components);

Ok(fields)
});
}

self
}
Expand Down Expand Up @@ -263,11 +258,12 @@ impl<'a> CreateMessage<'a> {

/// Set the message's flags.
///
/// The only supported flags are [`SUPPRESS_EMBEDS`] and
/// [`SUPPRESS_NOTIFICATIONS`].
/// The only supported flags are [`SUPPRESS_EMBEDS`], [`SUPPRESS_NOTIFICATIONS`], and
/// [`IS_COMPONENTS_V2`].
///
/// [`SUPPRESS_EMBEDS`]: MessageFlags::SUPPRESS_EMBEDS
/// [`SUPPRESS_NOTIFICATIONS`]: MessageFlags::SUPPRESS_NOTIFICATIONS
/// [`IS_COMPONENTS_V2`]: MessageFlags::IS_COMPONENTS_V2
pub const fn flags(mut self, flags: MessageFlags) -> Self {
if let Ok(fields) = self.fields.as_mut() {
fields.flags = Some(flags);
Expand Down Expand Up @@ -407,6 +403,16 @@ impl IntoFuture for CreateMessage<'_> {
impl TryIntoRequest for CreateMessage<'_> {
fn try_into_request(self) -> Result<Request, Error> {
let mut fields = self.fields.map_err(Error::validation)?;

if let Some(components) = fields.components {
validate_components(
components,
fields
.flags
.is_some_and(|flags| flags.contains(MessageFlags::IS_COMPONENTS_V2)),
)
.map_err(Error::validation)?;
}
let mut request = Request::builder(&Route::CreateMessage {
channel_id: self.channel_id.get(),
});
Expand Down Expand Up @@ -441,3 +447,34 @@ impl TryIntoRequest for CreateMessage<'_> {
request.build()
}
}

#[cfg(test)]
mod tests {
use super::*;
use twilight_model::channel::message::component::TextDisplay;

#[test]
fn components_v2_before_flags() {
let client = Client::new(String::new());
let components = [Component::TextDisplay(TextDisplay {
content: "test".to_owned(),
id: None,
})];

assert!(
client
.create_message(Id::new(1))
.components(&components)
.flags(MessageFlags::IS_COMPONENTS_V2)
.try_into_request()
.is_ok()
);
assert!(
client
.create_message(Id::new(1))
.components(&components)
.try_into_request()
.is_err()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ use twilight_model::{
};
use twilight_validate::message::{
MessageValidationError, attachment_filename as validate_attachment_filename,
components as validate_components, content as validate_content, embeds as validate_embeds,
sticker_ids as validate_sticker_ids,
content as validate_content, embeds as validate_embeds, sticker_ids as validate_sticker_ids,
};

/// Contents of the first message in the new forum thread.
Expand Down Expand Up @@ -93,25 +92,18 @@ impl<'a> CreateForumThreadMessage<'a> {
///
/// Requires a webhook owned by the application.
///
/// Components are validated when the request is built so flags set after
/// this method are taken into account.
///
/// # Errors
///
/// Refer to the errors section of
/// [`twilight_validate::component::component`] for a list of errors that
/// may be returned as a result of validating each provided component.
pub fn components(mut self, components: &'a [Component]) -> Self {
self.0 = self.0.and_then(|mut inner| {
validate_components(
components,
inner
.fields
.message
.flags
.is_some_and(|f| f.contains(MessageFlags::IS_COMPONENTS_V2)),
)?;
pub const fn components(mut self, components: &'a [Component]) -> Self {
if let Ok(inner) = self.0.as_mut() {
inner.fields.message.components = Some(components);

Ok(inner)
});
}

self
}
Expand Down Expand Up @@ -170,11 +162,12 @@ impl<'a> CreateForumThreadMessage<'a> {

/// Set the message's flags.
///
/// The only supported flags are [`SUPPRESS_EMBEDS`] and
/// [`SUPPRESS_NOTIFICATIONS`].
/// The only supported flags are [`SUPPRESS_EMBEDS`], [`SUPPRESS_NOTIFICATIONS`], and
/// [`IS_COMPONENTS_V2`].
///
/// [`SUPPRESS_EMBEDS`]: MessageFlags::SUPPRESS_EMBEDS
/// [`SUPPRESS_NOTIFICATIONS`]: MessageFlags::SUPPRESS_NOTIFICATIONS
/// [`IS_COMPONENTS_V2`]: MessageFlags::IS_COMPONENTS_V2
pub const fn flags(mut self, flags: MessageFlags) -> Self {
if let Ok(inner) = self.0.as_mut() {
inner.fields.message.flags = Some(flags);
Expand Down Expand Up @@ -242,3 +235,29 @@ impl TryIntoRequest for CreateForumThreadMessage<'_> {
.and_then(CreateForumThread::try_into_request)
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::{client::Client, request::TryIntoRequest};
use twilight_model::channel::message::component::TextDisplay;

#[test]
fn components_v2_before_flags() {
let client = Client::new(String::new());
let components = [Component::TextDisplay(TextDisplay {
content: "test".to_owned(),
id: None,
})];

assert!(
client
.create_forum_thread(Id::new(1), "thread")
.message()
.components(&components)
.flags(MessageFlags::IS_COMPONENTS_V2)
.try_into_request()
.is_ok()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ use crate::{
};
use serde::{Deserialize, Serialize};
use twilight_model::{
channel::{Channel, Message, thread::AutoArchiveDuration},
channel::{Channel, Message, message::MessageFlags, thread::AutoArchiveDuration},
id::{
Id,
marker::{ChannelMarker, TagMarker},
},
};
use twilight_validate::message::components as validate_components;

#[derive(Deserialize, Serialize)]
pub struct ForumThread {
Expand Down Expand Up @@ -118,6 +119,17 @@ impl<'a> CreateForumThread<'a> {
}

fn try_into_request(mut self) -> Result<Request, Error> {
if let Some(components) = self.fields.message.components {
validate_components(
components,
self.fields
.message
.flags
.is_some_and(|flags| flags.contains(MessageFlags::IS_COMPONENTS_V2)),
)
.map_err(Error::validation)?;
}

let mut request = Request::builder(&Route::CreateForumThread {
channel_id: self.channel_id.get(),
});
Expand Down
51 changes: 40 additions & 11 deletions twilight-http/src/request/channel/webhook/execute_webhook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,23 +174,18 @@ impl<'a> ExecuteWebhook<'a> {
///
/// Requires a webhook owned by the application.
///
/// Components are validated when the request is built so flags set after
/// this method are taken into account.
///
/// # Errors
///
/// Refer to the errors section of
/// [`twilight_validate::component::component`] for a list of errors that
/// may be returned as a result of validating each provided component.
pub fn components(mut self, components: &'a [Component]) -> Self {
self.fields = self.fields.and_then(|mut fields| {
validate_components(
components,
fields
.flags
.is_some_and(|flags| flags.contains(MessageFlags::IS_COMPONENTS_V2)),
)?;
pub const fn components(mut self, components: &'a [Component]) -> Self {
if let Ok(fields) = self.fields.as_mut() {
fields.components = Some(components);

Ok(fields)
});
}

self
}
Expand Down Expand Up @@ -407,6 +402,16 @@ impl IntoFuture for ExecuteWebhook<'_> {
impl TryIntoRequest for ExecuteWebhook<'_> {
fn try_into_request(self) -> Result<Request, Error> {
let mut fields = self.fields.map_err(Error::validation)?;

if let Some(components) = fields.components {
validate_components(
components,
fields
.flags
.is_some_and(|flags| flags.contains(MessageFlags::IS_COMPONENTS_V2)),
)
.map_err(Error::validation)?;
}
let mut request = Request::builder(&Route::ExecuteWebhook {
thread_id: self.thread_id.map(Id::get),
token: self.token,
Expand Down Expand Up @@ -453,3 +458,27 @@ impl TryIntoRequest for ExecuteWebhook<'_> {
request.build()
}
}

#[cfg(test)]
mod tests {
use super::*;
use twilight_model::channel::message::component::TextDisplay;

#[test]
fn components_v2_before_flags() {
let client = Client::new(String::new());
let components = [Component::TextDisplay(TextDisplay {
content: "test".to_owned(),
id: None,
})];

assert!(
client
.execute_webhook(Id::new(1), "token")
.components(&components)
.flags(MessageFlags::IS_COMPONENTS_V2)
.try_into_request()
.is_ok()
);
}
}
Loading