A third party crate for Twilight to execute Discord webhooks that clone an existing message
This has grown to be a more complicated (and painful) project than expected, so let me list what it does
Opt-in features for edge-cases:
- Clone attachments or stickers by linking to them or re-uploading them
- Clone URL components
- Clone messages sent after the original message, even combining them to reduce webhook executions
- Clone reactions
- Clone references by putting an embed
- Clone messages in a thread/forum post or messages used to start a thread/forum post
- Sanitize invalid usernames
- Delete the original message and messages sent after
General features:
- Replicate the author's user or member avatar, embeds, anything possible
- Change any info about the new message, for example to clone to another channel
- Handle rate-limit retries
- Builder-pattern to keep your code clean
- Avoid clones and unnecessary deserialization
- Widely tested with integration tests (Almost 1:1 LOC for source and tests)
This also serves as the example, since it includes most of the API surface
let mut source = MessageSource::from_message(&message, &http)
.expect("message really can't be cloned (voice message etc)");
// example error handling
if let Err(_) = source.check_component() {
panic!("invalid components scare me");
}
let later_messages = source.later_messages_batched().await?;
// a lot of edge cases
source
.webhook_name("custom modified exclusive webhook name".to_owned())
.handle_attachment_link()?
.handle_sticker_link()?
.handle_reaction()
.await?
.handle_reference()?
.handle_thread()
.await?
.sanitize_username("?", "????")
.create()
.await?
.handle_thread_created()
.await?;
for later_message in later_messages {
// create every message sent later
later_message?.create().await?;
}
upload
: Enables methods for re-uploading attachments
Although widely tested, there may still be bugs, or you might have feature suggestions, please create issues for these!
The crate uses integration tests as opposed to unit tests to test real-world usage. It creates a message and clones it, then the tester checks if the message is cloned as expected
Before starting, set these environment variables, you can also put them in a .env
file:
BOT_TOKEN
: The token of the bot to use for testingCHANNEL_ID
: The channel in which the messages and webhooks will be cratedFORUM_CHANNEL_ID
: The forum channel in which cloning messages/threads in forum channels will be testedNOT_LAST_SOURCE_THREAD_ID
: The bot will create a thread and spam to 200 in it the first time the tests are ran, to avoid doing this again, set this to the ID of this threadGUILD_EMOJI_ID
: ID of an emoji that's in the guildCHANNEL_ID
is in
Required permissions in CHANNEL_ID
and FORUM_CHANNEL_ID
:
VIEW_CHANNEL
MANAGE_WEBHOOKS
SEND_MESSAGES
Required additional permissions in FORUM_CHANNEL_ID
:
CREATE_POSTS
SEND_MESSAGES_IN_POSTS
Test with a single thread to avoid race conditions: cargo test --all-features -- --test-threads=1