MessageSource

Struct MessageSource 

Source
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: String

Content of the message

§embeds: Vec<Embed>

Embeds in the message

§tts: bool

Whether 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: String

Username of the message’s author

§webhook_name: String

Name to be used for the webhook that will be used to create the message

§avatar_info: Info

Info 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: Info

Info about the message’s components

§thread_info: Info

Info about the message’s thread

§later_messages: Info

Messages 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 Client

The client to use for requests

Implementations§

Source§

impl MessageSource<'_>

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

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<'_>

Source

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>

Source

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>

Source

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

Source

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>

Source

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

Source

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

Source

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>

Source

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

Source

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<'_>

Source

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>

Source

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

Source

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<'_>

Source

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>

Source

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:

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

Source

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

Trait Implementations§

Source§

impl<'a> Debug for MessageSource<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> !Freeze for MessageSource<'a>

§

impl<'a> !RefUnwindSafe for MessageSource<'a>

§

impl<'a> Send for MessageSource<'a>

§

impl<'a> Sync for MessageSource<'a>

§

impl<'a> Unpin for MessageSource<'a>

§

impl<'a> !UnwindSafe for MessageSource<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more