diff options
author | Ashelyn Rose <git@ashen.earth> | 2025-02-28 21:52:16 -0700 |
---|---|---|
committer | Ashelyn Rose <git@ashen.earth> | 2025-02-28 21:52:16 -0700 |
commit | e9253bd959bf5bf6e8bcc6de4db247895b015a16 (patch) | |
tree | 1817aed80c8255d1292007a81e7f0a16138d25cc /src/system/util.rs | |
parent | 5cb49a76c2cedb500b82f405af3cf1dcc0507f98 (diff) |
Partial refactor
Handles message prefixes and autoproxy
Diffstat (limited to 'src/system/util.rs')
-rw-r--r-- | src/system/util.rs | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/system/util.rs b/src/system/util.rs new file mode 100644 index 0000000..4b51c09 --- /dev/null +++ b/src/system/util.rs @@ -0,0 +1,113 @@ +use futures::future::join_all; +use twilight_http::Client; +use twilight_model::channel::{message::{AllowedMentions, MentionType, MessageType}, Message}; +use std::sync::Arc; +use tokio::sync::Mutex; +use twilight_model::http::attachment::Attachment; + +pub enum ProxyError { + InvalidMessage(twilight_validate::message::MessageValidationError), + AttachmentRequest(reqwest::Error), + MessageCreate(twilight_http::error::Error), + ResponseDeserialization(twilight_http::response::DeserializeBodyError), +} + +impl From<twilight_validate::message::MessageValidationError> for ProxyError { + fn from(value: twilight_validate::message::MessageValidationError) -> Self { + ProxyError::InvalidMessage(value) + } +} + +impl From<reqwest::Error> for ProxyError{ + fn from(value: reqwest::Error) -> Self { + ProxyError::AttachmentRequest(value) + } +} + +impl From<twilight_http::error::Error> for ProxyError{ + fn from(value: twilight_http::error::Error) -> Self { + ProxyError::MessageCreate(value) + } +} + +impl From<twilight_http::response::DeserializeBodyError> for ProxyError{ + fn from(value: twilight_http::response::DeserializeBodyError) -> Self { + ProxyError::ResponseDeserialization(value) + } +} + +pub async fn duplicate_message(client: &Arc<Mutex<Client>>, message: &Message, content: &str) -> Result<Message, ProxyError> { + let client = client.lock().await; + + let mut create_message = client.create_message(message.channel_id).content(content)?; + + let mut allowed_mentions = AllowedMentions { + parse: Vec::new(), + replied_user: false, + roles: message.mention_roles.clone(), + users: message.mentions.iter().map(|user| user.id).collect(), + }; + + if message.mention_everyone { + allowed_mentions.parse.push(MentionType::Everyone); + } + + if message.kind == MessageType::Reply { + if let Some(ref_message) = message.referenced_message.as_ref() { + create_message = create_message.reply(ref_message.id); + + let pings_referenced_author = message + .mentions + .iter() + .any(|user| user.id == ref_message.author.id); + + if pings_referenced_author { + allowed_mentions.replied_user = true; + } else { + allowed_mentions.replied_user = false; + } + } else { + panic!("Cannot proxy message: Was reply but no referenced message"); + } + } + + let attachments = join_all(message.attachments.iter().map(|attachment| async { + let filename = attachment.filename.clone(); + let description_opt = attachment.description.clone(); + let bytes = reqwest::get(attachment.proxy_url.clone()) + .await? + .bytes() + .await?; + let mut new_attachment = + Attachment::from_bytes(filename, bytes.try_into().unwrap(), attachment.id.into()); + + if let Some(description) = description_opt { + new_attachment.description(description); + } + + Ok(new_attachment) + })) + .await + .iter() + .filter_map( + |result: &Result<Attachment, ProxyError>| match result { + Ok(attachment) => Some(attachment.clone()), + Err(_) => None, + }, + ) + .collect::<Vec<_>>(); + + if attachments.len() > 0 { + create_message = create_message.attachments(attachments.as_slice())?; + } + + if let Some(flags) = message.flags { + create_message = create_message.flags(flags); + } + + create_message = create_message.allowed_mentions(Some(&allowed_mentions)); + let new_message = create_message.await?.model().await?; + + Ok(new_message) +} + |