sparkle_impostor/
attachment_sticker.rs1#[cfg(feature = "reqwest")]
4use reqwest::Client;
5use twilight_model::channel::message::sticker::{MessageSticker, StickerFormatType};
6use twilight_validate::message::MESSAGE_CONTENT_LENGTH_MAX;
7
8use crate::{error::Error, MessageSource};
9
10#[derive(Clone, Debug, PartialEq)]
12pub struct Info<'a> {
13 pub stickers: &'a [MessageSticker],
15 pub attachments: &'a [twilight_model::channel::Attachment],
17 #[cfg(feature = "upload")]
19 pub attachments_upload: Vec<twilight_model::http::attachment::Attachment>,
20}
21
22impl MessageSource<'_> {
23 pub fn handle_attachment_link(mut self) -> Result<Self, Error> {
36 self.append_urls(
37 self.attachment_sticker_info
38 .attachments
39 .iter()
40 .map(|attachment| attachment.url.as_str()),
41 )?;
42
43 Ok(self)
44 }
45
46 pub fn handle_sticker_link(mut self) -> Result<Self, Error> {
60 let mut sticker_urls = vec![];
61 for sticker in self.attachment_sticker_info.stickers {
62 sticker_urls.push(format!(
63 "https://cdn.discordapp.com/stickers/{}.{}",
64 sticker.id,
65 match sticker.format_type {
66 StickerFormatType::Gif => "gif",
67 StickerFormatType::Png | StickerFormatType::Apng => "png",
68 _ => return Err(Error::StickerLinkInvalid),
69 }
70 ));
71 }
72
73 self.append_urls(sticker_urls.iter().map(String::as_str))?;
74
75 Ok(self)
76 }
77
78 #[allow(single_use_lifetimes)]
79 fn append_urls<'a>(
80 &mut self,
81 urls: impl Iterator<Item = &'a str> + Clone,
82 ) -> Result<(), Error> {
83 if self
84 .content
85 .chars()
86 .count()
87 .saturating_add(
88 urls.clone()
89 .map(|url| url.chars().count().saturating_add(1))
91 .reduce(usize::saturating_add)
92 .unwrap_or(0),
93 )
94 .saturating_add(1)
96 > MESSAGE_CONTENT_LENGTH_MAX
97 {
98 return Err(Error::ContentInvalid);
99 }
100
101 self.content.push('\n');
102 for url in urls {
103 self.content.push('\n');
104 self.content.push_str(url);
105 }
106
107 Ok(())
108 }
109}
110
111#[cfg(feature = "upload")]
112impl<'a> MessageSource<'a> {
113 pub async fn handle_attachment_upload(mut self) -> Result<MessageSource<'a>, Error> {
130 if self
131 .attachment_sticker_info
132 .attachments
133 .iter()
134 .map(|attachment| attachment.size)
135 .sum::<u64>()
136 > 25 * 1024 * 1024
137 {
138 return Err(Error::AttachmentTooLarge);
139 }
140
141 let client = Client::new();
142 for attachment in self.attachment_sticker_info.attachments {
143 self.attachment_sticker_info.attachments_upload.push(
144 twilight_model::http::attachment::Attachment {
145 description: attachment.description.clone(),
146 file: client
147 .get(&attachment.url)
148 .send()
149 .await?
150 .bytes()
151 .await?
152 .to_vec(),
153 filename: attachment.filename.clone(),
154 id: attachment.id.get(),
155 },
156 );
157 }
158
159 Ok(self)
160 }
161}