1use twilight_model::{
2 channel::{
3 embed::{Embed, EmbedField},
4 message::{
5 sticker::{MessageSticker, StickerFormatType},
6 MessageActivityType, MessageFlags, MessageType,
7 },
8 Attachment, Message,
9 },
10 gateway::payload::incoming::MessageUpdate,
11 id::{
12 marker::{
13 ApplicationMarker, AttachmentMarker, ChannelMarker, GenericMarker, GuildMarker,
14 MessageMarker, StickerMarker, UserMarker, WebhookMarker,
15 },
16 Id,
17 },
18 util::{ImageHash, Timestamp},
19};
20
21use crate::unique_id;
22
23#[derive(Clone, Debug)]
29pub struct CachedEmbedField {
30 pub embed_id: Id<GenericMarker>,
31 pub inline: bool,
32 pub name: String,
33 pub value: String,
34}
35
36impl CachedEmbedField {
37 #[allow(clippy::missing_const_for_fn)]
39 #[must_use]
40 pub fn from_embed_field(embed_field: EmbedField, embed_id: Id<GenericMarker>) -> Self {
41 Self {
42 embed_id,
43 inline: embed_field.inline,
44 name: embed_field.name,
45 value: embed_field.value,
46 }
47 }
48}
49
50#[derive(Clone, Debug)]
63pub struct CachedEmbed {
64 pub id: Id<GenericMarker>,
65 pub message_id: Id<MessageMarker>,
66 pub author_icon_url: Option<String>,
67 pub author_name: Option<String>,
68 pub author_proxy_icon_url: Option<String>,
69 pub author_url: Option<String>,
70 pub color: Option<u32>,
71 pub description: Option<String>,
72 pub footer_icon_url: Option<String>,
73 pub footer_proxy_icon_url: Option<String>,
74 pub footer_text: Option<String>,
75 pub image_height: Option<u64>,
76 pub image_proxy_url: Option<String>,
77 pub image_url: Option<String>,
78 pub image_width: Option<u64>,
79 pub kind: String,
80 pub provider_name: Option<String>,
81 pub provider_url: Option<String>,
82 pub thumbnail_height: Option<u64>,
83 pub thumbnail_proxy_url: Option<String>,
84 pub thumbnail_url: Option<String>,
85 pub thumbnail_width: Option<u64>,
86 pub timestamp: Option<Timestamp>,
87 pub title: Option<String>,
88 pub url: Option<String>,
89 pub video_height: Option<u64>,
90 pub video_proxy_url: Option<String>,
91 pub video_url: Option<String>,
92 pub video_width: Option<u64>,
93}
94
95impl CachedEmbed {
96 #[allow(clippy::cast_sign_loss, clippy::as_conversions)]
98 #[must_use]
99 pub fn from_embed(embed: Embed, message_id: Id<MessageMarker>) -> Self {
100 Self {
101 id: Id::new(unique_id() as u64),
102 message_id,
103 author_icon_url: embed
104 .author
105 .as_ref()
106 .and_then(|author| author.icon_url.clone()),
107 author_name: embed.author.as_ref().map(|author| author.name.clone()),
108 author_proxy_icon_url: embed
109 .author
110 .as_ref()
111 .and_then(|author| author.icon_url.clone()),
112 author_url: embed.author.as_ref().and_then(|author| author.url.clone()),
113 color: embed.color,
114 description: embed.description,
115 footer_icon_url: embed
116 .footer
117 .as_ref()
118 .and_then(|footer| footer.icon_url.clone()),
119 footer_proxy_icon_url: embed
120 .footer
121 .as_ref()
122 .and_then(|footer| footer.proxy_icon_url.clone()),
123 footer_text: embed.footer.as_ref().map(|footer| footer.text.clone()),
124 image_height: embed.image.as_ref().and_then(|image| image.height),
125 image_proxy_url: embed
126 .image
127 .as_ref()
128 .and_then(|image| image.proxy_url.clone()),
129 image_url: embed.image.as_ref().map(|image| image.url.clone()),
130 image_width: embed.image.as_ref().and_then(|image| image.width),
131 kind: embed.kind,
132 provider_name: embed
133 .provider
134 .as_ref()
135 .and_then(|provider| provider.name.clone()),
136 provider_url: embed
137 .provider
138 .as_ref()
139 .and_then(|provider| provider.url.clone()),
140 thumbnail_height: embed
141 .thumbnail
142 .as_ref()
143 .and_then(|thumbnail| thumbnail.height),
144 thumbnail_proxy_url: embed
145 .thumbnail
146 .as_ref()
147 .and_then(|thumbnail| thumbnail.proxy_url.clone()),
148 thumbnail_url: embed
149 .thumbnail
150 .as_ref()
151 .map(|thumbnail| thumbnail.url.clone()),
152 thumbnail_width: embed
153 .thumbnail
154 .as_ref()
155 .and_then(|thumbnail| thumbnail.width),
156 timestamp: embed.timestamp,
157 title: embed.title,
158 url: embed.url,
159 video_height: embed.video.as_ref().and_then(|video| video.height),
160 video_proxy_url: embed
161 .video
162 .as_ref()
163 .and_then(|video| video.proxy_url.clone()),
164 video_url: embed.video.as_ref().and_then(|video| video.url.clone()),
165 video_width: embed.video.as_ref().and_then(|video| video.width),
166 }
167 }
168}
169
170#[derive(Clone, Debug)]
177pub struct CachedAttachment {
178 pub message_id: Id<MessageMarker>,
179 pub content_type: Option<String>,
180 pub ephemeral: bool,
181 pub filename: String,
182 pub description: Option<String>,
183 pub height: Option<u64>,
184 pub id: Id<AttachmentMarker>,
185 pub proxy_url: String,
186 pub size: u64,
187 pub url: String,
188 pub width: Option<u64>,
189}
190
191impl CachedAttachment {
192 #[allow(clippy::missing_const_for_fn)]
194 #[must_use]
195 pub fn from_attachment(attachment: Attachment, message_id: Id<MessageMarker>) -> Self {
196 Self {
197 message_id,
198 content_type: attachment.content_type,
199 ephemeral: attachment.ephemeral,
200 filename: attachment.filename,
201 description: attachment.description,
202 height: attachment.height,
203 id: attachment.id,
204 proxy_url: attachment.proxy_url,
205 size: attachment.size,
206 url: attachment.url,
207 width: attachment.width,
208 }
209 }
210}
211
212#[derive(Clone, Debug)]
220pub struct CachedMessageSticker {
221 pub message_id: Id<MessageMarker>,
222 pub format_type: StickerFormatType,
223 pub id: Id<StickerMarker>,
224 pub name: String,
225}
226
227impl CachedMessageSticker {
228 #[allow(clippy::missing_const_for_fn)]
230 #[must_use]
231 pub fn from_sticker(sticker: MessageSticker, message_id: Id<MessageMarker>) -> Self {
232 Self {
233 message_id,
234 format_type: sticker.format_type,
235 id: sticker.id,
236 name: sticker.name,
237 }
238 }
239}
240
241#[derive(Clone, Debug)]
258pub struct CachedMessage {
259 pub activity_type: Option<MessageActivityType>,
260 pub activity_party_id: Option<String>,
261 pub application_cover_image: Option<ImageHash>,
262 pub application_description: Option<String>,
263 pub application_icon: Option<ImageHash>,
264 pub application_id: Option<Id<ApplicationMarker>>,
265 pub application_name: Option<String>,
266 pub interaction_application_id: Option<Id<ApplicationMarker>>,
267 pub author: Id<UserMarker>,
268 pub channel_id: Id<ChannelMarker>,
269 pub content: String,
270 pub edited_timestamp: Option<Timestamp>,
271 pub flags: Option<MessageFlags>,
272 pub guild_id: Option<Id<GuildMarker>>,
273 pub id: Id<MessageMarker>,
274 pub kind: MessageType,
275 pub mention_everyone: bool,
276 pub pinned: bool,
277 pub reference_channel_id: Option<Id<ChannelMarker>>,
278 pub reference_guild_id: Option<Id<GuildMarker>>,
279 pub reference_message_id: Option<Id<MessageMarker>>,
280 pub reference_fail_if_not_exists: Option<bool>,
281 pub referenced_message: Option<Id<MessageMarker>>,
282 pub timestamp: Timestamp,
283 pub thread: Option<Id<ChannelMarker>>,
284 pub tts: bool,
285 pub webhook_id: Option<Id<WebhookMarker>>,
286}
287
288impl CachedMessage {
289 pub fn update(&mut self, message: &MessageUpdate) {
291 if let Some(content) = &message.content {
292 self.content.clone_from(content);
293 }
294 if message.edited_timestamp.is_some() {
295 self.edited_timestamp = message.edited_timestamp;
296 }
297 if let Some(mentions) = message.mention_everyone {
298 self.mention_everyone = mentions;
299 }
300 if let Some(pinned) = message.pinned {
301 self.pinned = pinned;
302 }
303 }
304}
305
306impl From<&Message> for CachedMessage {
307 fn from(message: &Message) -> Self {
308 Self {
309 activity_type: message.activity.as_ref().map(|activity| activity.kind),
310 activity_party_id: message
311 .activity
312 .as_ref()
313 .and_then(|activity| activity.party_id.clone()),
314 application_cover_image: message
315 .application
316 .as_ref()
317 .and_then(|application| application.cover_image),
318 application_description: message
319 .application
320 .as_ref()
321 .map(|application| application.description.clone()),
322 application_icon: message
323 .application
324 .as_ref()
325 .and_then(|application| application.icon),
326 application_id: message
327 .application
328 .as_ref()
329 .map(|application| application.id),
330 application_name: message
331 .application
332 .as_ref()
333 .map(|application| application.name.clone()),
334 interaction_application_id: message.application_id,
335 author: message.author.id,
336 channel_id: message.channel_id,
337 content: message.content.clone(),
338 edited_timestamp: message.edited_timestamp,
339 guild_id: message.guild_id,
340 id: message.id,
341 kind: message.kind,
342 mention_everyone: message.mention_everyone,
343 pinned: message.pinned,
344 reference_channel_id: message
345 .reference
346 .as_ref()
347 .and_then(|reference| reference.channel_id),
348 reference_guild_id: message
349 .reference
350 .as_ref()
351 .and_then(|reference| reference.guild_id),
352 reference_message_id: message
353 .reference
354 .as_ref()
355 .and_then(|reference| reference.message_id),
356 reference_fail_if_not_exists: message
357 .reference
358 .as_ref()
359 .and_then(|reference| reference.fail_if_not_exists),
360 referenced_message: message
361 .referenced_message
362 .as_ref()
363 .map(|reference| reference.id),
364 timestamp: message.timestamp,
365 thread: message.thread.as_ref().map(|thread| thread.id),
366 tts: message.tts,
367 flags: message.flags,
368 webhook_id: message.webhook_id,
369 }
370 }
371}