pub struct MessageSource<'a> {Show 22 fields
pub source_id: Id<MessageMarker>,
pub source_channel_id: Id<ChannelMarker>,
pub source_thread_id: Option<Id<ChannelMarker>>,
pub content: String,
pub embeds: Vec<Embed>,
pub tts: bool,
pub flags: Option<MessageFlags>,
pub channel_id: Id<ChannelMarker>,
pub guild_id: Id<GuildMarker>,
pub guild_emoji_ids: Option<Vec<Id<EmojiMarker>>>,
pub username: String,
pub webhook_name: String,
pub avatar_info: Info,
pub reference_info: Info<'a>,
pub reaction_info: Info<'a>,
pub attachment_sticker_info: Info<'a>,
pub component_info: Info,
pub thread_info: Info,
pub later_messages: Info,
pub webhook: Option<(Id<WebhookMarker>, String)>,
pub response: Option<MaybeDeserialized<Message>>,
pub http: &'a Client,
}Expand description
A message that can be cloned
§Mutation
Can be mutated to override some fields, for example to clone it to another channel
Since most methods mutate the source, it’s recommend to mutate the message
right before calling MessageSource::create
Fields starting with source shouldn’t be mutated, in other
words, “message” refers to the created message while “source message” refers
to the message to be cloned from
You can also provide some of the fields, for example from your cache, so that they won’t be received over the HTTP API
§Warnings
Many of the fields here are stateful, there are no guarantees on the validity of these since this doesn’t have access to the gateway, this means you should use and drop this struct as fast as you can
Fields§
§source_id: Id<MessageMarker>Source message’s ID
source_channel_id: Id<ChannelMarker>ID of the channel the source message is in
source_thread_id: Option<Id<ChannelMarker>>ID of the thread the source message is in
content: StringContent of the message
embeds: Vec<Embed>Embeds in the message
tts: boolWhether the message has text-to-speech enabled
flags: Option<MessageFlags>Flags of the message
channel_id: Id<ChannelMarker>ID of the channel the message is in
If the message is in a thread, this should be the parent thread’s ID
guild_id: Id<GuildMarker>ID of the guild the message is in
guild_emoji_ids: Option<Vec<Id<EmojiMarker>>>Emoji IDs of the guild the message is in
None if it has never been needed
username: StringUsername of the message’s author
webhook_name: StringName to be used for the webhook that will be used to create the message
avatar_info: InfoInfo about the message’s avatar
reference_info: Info<'a>Info about the message’s reference
reaction_info: Info<'a>Info about the message’s reactions
attachment_sticker_info: Info<'a>Info about the message’s attachments
component_info: InfoInfo about the message’s components
thread_info: InfoInfo about the message’s thread
later_messages: InfoMessages sent after the source
webhook: Option<(Id<WebhookMarker>, String)>Webhook ID and token to execute to clone messages with
response: Option<MaybeDeserialized<Message>>Cloned message’s response
None if MessageSource::create wasn’t called
http: &'a ClientThe client to use for requests
Implementations§
Source§impl MessageSource<'_>
impl MessageSource<'_>
Sourcepub fn handle_attachment_link(self) -> Result<Self, Error>
pub fn handle_attachment_link(self) -> Result<Self, Error>
Append links to the attachments into the message content
If the attachment is an image, it’s embedded in the client
§Warnings
The link will die after the source message is deleted
§Errors
Returns Error::ContentInvalid if the message content becomes
too long after adding the links
Sourcepub fn handle_sticker_link(self) -> Result<Self, Error>
pub fn handle_sticker_link(self) -> Result<Self, Error>
Append links to the stickers into the message content
The stickers are embedded in the client, but StickerFormatType::Apng
stickers aren’t animated
§Errors
Returns Error::StickerLinkInvalid if a sticker’s
StickerFormatType is StickerFormatType::Lottie or
StickerFormatType::Unknown
Returns Error::ContentInvalid if the message content becomes
too long after adding the links
Source§impl MessageSource<'_>
impl MessageSource<'_>
Sourcepub const fn check_component(&self) -> Result<(), Error>
pub const fn check_component(&self) -> Result<(), Error>
Check that the message has no non-URL components
URL components can be replicated, so they’re allowed
§Errors
Returns Error::Component if the message has a non-URL
component
Source§impl<'a> MessageSource<'a>
impl<'a> MessageSource<'a>
Sourcepub fn from_message(
message: &'a Message,
http: &'a Client,
) -> Result<Self, Error>
pub fn from_message( message: &'a Message, http: &'a Client, ) -> Result<Self, Error>
Create MessageSource from a Message
§Warnings
message.guild_id is usually None even if the message is in a guild,
make sure this field is actually passed
§Errors
Returns Error::NotInGuild if the message is not in a guild,
Returns Error::RichPresence if the message is related
to rich presence, which can’t be recreated by bots
Returns Error::Voice if the message is a voice message, which
bots currently can’t create
Returns Error::System if the message’s type isn’t
MessageType::Regular or MessageType::Reply or has role
subscription data, which are edge-cases that can’t be replicated
correctly
Returns Error::ContentInvalid if the message’s content is
invalid, this may happen when the author has used Nitro perks to send a
message with over 2000 characters
Source§impl<'a> MessageSource<'a>
impl<'a> MessageSource<'a>
Sourcepub fn check_delete_request_count_in(&self, n: u16) -> Result<(), Error>
pub fn check_delete_request_count_in(&self, n: u16) -> Result<(), Error>
Check if MessageSource::delete would use more than n requests
If MessageSource::later_messages or
MessageSource::later_messages_batched wasn’t called, n is always 1
Each message older than 2 weeks uses 1 request, others use
other_message_count divided by
twilight_validate::channel::CHANNEL_BULK_DELETE_MESSAGES_MAX rounded
up requests
§Errors
Returns Error::DeleteRequestCountAboveLimit if
MessageSource::delete would use more than n requests
Sourcepub async fn delete(self) -> Result<MessageSource<'a>, Error>
pub async fn delete(self) -> Result<MessageSource<'a>, Error>
Delete the original message
If MessageSource::later_messages or
MessageSource::later_messages_batched was called, later messages
will also be deleted
If there is a message older than two weeks, they’ll be
deleted individually since bulk delete isn’t valid for these messages,
see MessageSource::check_delete_request_count_in if this is not the
expected behavior
§Errors
Returns Error::Http if deleting the messages fails
§Panics
If two weeks ago or the time a message was sent can’t be represented
with SystemTime on the current platform
Source§impl<'a> MessageSource<'a>
impl<'a> MessageSource<'a>
Sourcepub async fn check_is_in_last(&mut self, n: u16) -> Result<(), Error>
pub async fn check_is_in_last(&mut self, n: u16) -> Result<(), Error>
Check if this is in the last n messages in the channel, return
Error::SourceAboveLimit if not
Make sure the bot has these additional permissions
§Warnings
If MessageSource::create was called before this method, don’t
account for that message when setting the limit
If the bot doesn’t have Permissions::READ_MESSAGE_HISTORY, it’ll act
as if this is the last message, since that’s what Discord responds with
§Errors
Returns Error::SourceAboveLimit if the message isn’t in the last n
messages
Returns Error::Http if getting channel messages fails
Returns Error::DeserializeBody if deserializing channel messages
fails
Sourcepub async fn later_messages(
&mut self,
) -> Result<Vec<Result<MessageSource<'_>, Error>>, Error>
pub async fn later_messages( &mut self, ) -> Result<Vec<Result<MessageSource<'_>, Error>>, Error>
Return MessageSource for messages sent after this
Make sure the bot has these additional permissions
Returned message sources don’t implicitly call the same methods as
self, this is intentional so that you can choose what to handle
yourself, if you want to handle each one the same way, simply extract
it to a function
§Warnings
This method is potentially very expensive unless
MessageSource::check_is_in_last was called
If the bot doesn’t have Permissions::READ_MESSAGE_HISTORY, it’ll
always return an empty vector, since that’s what Discord responds with
Should not be combined with MessageSource::later_messages_batched
§Errors
The vector element will be an error if the message can’t be resent (See
MessageSource::from_message)
Returns Error::Http if getting channel messages fails
Returns Error::DeserializeBody if deserializing channel messages
fails
Sourcepub async fn later_messages_batched(
&mut self,
) -> Result<Vec<Result<MessageSource<'_>, Error>>, Error>
pub async fn later_messages_batched( &mut self, ) -> Result<Vec<Result<MessageSource<'_>, Error>>, Error>
Return MessageSource for messages sent after this after combining
messages from the same author to the same message
This combines the messages’ content separated with a newline, it’s provided to reduce the number of webhook executions
See MessageSource::later_messages for more
§Warnings
Should not be combined with MessageSource::later_messages
§Errors
Returns Error::Http if getting channel messages fails
Returns Error::DeserializeBody if deserializing channel messages
fails
Source§impl<'a> MessageSource<'a>
impl<'a> MessageSource<'a>
Sourcepub async fn check_reaction(
&mut self,
behavior: CheckBehavior,
) -> Result<(), Error>
pub async fn check_reaction( &mut self, behavior: CheckBehavior, ) -> Result<(), Error>
Check that the message has no reactions
You can call the same function repeatedly with different
CheckBehaviors
This function is only async if CheckBehavior::NotExternal was passed
§Warnings
Super reactions currently can’t be received, so they’re ignored
§Errors
Returns Error::Reaction if CheckBehavior::None was passed
and the message has a reaction
Returns Error::ReactionAboveLimit if CheckBehavior::Limit
was passed and the message has more reactions than the limit
Returns Error::ReactionCountMultiple if
CheckBehavior::CountOne was passed and the message has a reaction
emoji with count higher than 1
Returns Error::ReactionCustom if
CheckBehavior::Unicode was passed and the message has a non-unicode
reaction emoji
Returns Error::ReactionExternal if
CheckBehavior::NotExternal was passed and and the message has an
external reaction emoji
Returns Error::Http if CheckBehavior::NotExternal was passed and
getting guild emojis fails
Returns Error::DeserializeBody if CheckBehavior::NotExternal was
passed and deserializing guild emojis fails
Sourcepub async fn handle_reaction(self) -> Result<MessageSource<'a>, Error>
pub async fn handle_reaction(self) -> Result<MessageSource<'a>, Error>
Re-create the reactions
The reaction authors and counts will naturally be lost, their author will be the bot and counts will be 1
Guild emojis will have to be requested if any reaction emoji isn’t unicode to check if the emoji is external
Make sure the bot has these additional permissions:
§Warnings
Super reactions currently can’t be received, so they’re ignored
Using this without MessageSource::check_reaction may cause loss in
reactions
§Errors
Returns Error::NotCreated if MessageSource::create wasn’t called
yet
Returns Error::Http if getting guild emojis fails
Returns Error::DeserializeBody if deserializing the message or guild
emojis failed
Source§impl MessageSource<'_>
impl MessageSource<'_>
Sourcepub fn handle_reference(self) -> Result<Self, Error>
pub fn handle_reference(self) -> Result<Self, Error>
Handle the message having a reference
This adds an embed with the reference message’s info to the message
§Warnings
Must be called before MessageSource::create
§Errors
Returns Error::MessageValidation if the message already has
EMBED_COUNT_LIMIT embeds
Source§impl<'a> MessageSource<'a>
impl<'a> MessageSource<'a>
Sourcepub async fn handle_thread(self) -> Result<MessageSource<'a>, Error>
pub async fn handle_thread(self) -> Result<MessageSource<'a>, Error>
Handle the message being in a thread
This requires getting the channel with another HTTP request
§Warnings
Must be called before MessageSource::create
§Errors
Returns Error::Http if getting the channel fails
Returns Error::DeserializeBody if deserializing the channel fails
Sourcepub async fn handle_thread_created(self) -> Result<MessageSource<'a>, Error>
pub async fn handle_thread_created(self) -> Result<MessageSource<'a>, Error>
Handle a thread being created from the message
§Errors
Returns Error::ChannelValidation if the thread is invalid, shouldn’t
happen unless the it was mutated
Returns Error::Http if creating the thread fails
Returns Error::DeserializeBody if deserializing the thread fails
§Panics
If called before MessageSource::create
Source§impl MessageSource<'_>
impl MessageSource<'_>
Sourcepub fn sanitize_username(self, append: &str, replace: &str) -> Self
pub fn sanitize_username(self, append: &str, replace: &str) -> Self
Sanitize the username if it’s invalid
This is necessary because usernames or nicks don’t have the same requirements as webhook usernames
If the username is under WEBHOOK_USERNAME_LIMIT_MIN, appends
append to it, make sure append is under 32 characters and is not
empty
If the username is over WEBHOOK_USERNAME_LIMIT_MAX, trims it and
ends it with “…”
Replaces invalid substrings with replace, make sure it’s over
WEBHOOK_USERNAME_LIMIT_MIN characters and under 6 characters
Source§impl<'a> MessageSource<'a>
impl<'a> MessageSource<'a>
Sourcepub async fn create(self) -> Result<MessageSource<'a>, Error>
pub async fn create(self) -> Result<MessageSource<'a>, Error>
Executes a webhook using the given source
If a webhook called the set name or Message Cloner in the channel doesn’t exist, creates it
Make sure the bot has these required permissions:
Permissions::SEND_TTS_MESSAGESPermissions::MENTION_EVERYONEPermissions::USE_EXTERNAL_EMOJISPermissions::MANAGE_WEBHOOKS
Because rate-limits for webhook executions can’t be handled beforehand, retries each execution up to 5 times, if all of these are rate-limited, returns the HTTP error
§Warnings
Other methods on MessageSource are provided to handle edge-cases,
not calling them before this may make this method fail
If calling this on the same webhook repeatedly, it’s rate-limited on every try after the 50th execution in tests, though Discord may change this in the future
§Errors
Returns Error::Http if getting, creating or executing the webhook
fails
Returns Error::DeserializeBody if deserializing the webhook
Returns Error::Validation if the webhook name is invalid
Returns Error::MessageValidation if the given message is invalid,
shouldn’t happen unless the message was mutated
Sourcepub fn webhook_name(self, name: String) -> Self
pub fn webhook_name(self, name: String) -> Self
Set the name of the webhook to use for creating messages
Defaults to Message Cloner if not called