1use crate::{CacheableModels, InMemoryCache, UpdateCache, config::ResourceType};
2use std::borrow::Cow;
3use twilight_model::{
4 application::interaction::InteractionData, gateway::payload::incoming::InteractionCreate,
5};
6
7impl<CacheModels: CacheableModels> UpdateCache<CacheModels> for InteractionCreate {
8 fn update(&self, cache: &InMemoryCache<CacheModels>) {
9 if cache.wants(ResourceType::MEMBER)
11 && let (Some(member), Some(guild_id)) = (&self.member, self.guild_id)
12 && let Some(user) = &member.user
13 {
14 cache.cache_user(Cow::Borrowed(user), self.guild_id);
15
16 cache.cache_borrowed_partial_member(guild_id, member, user.id);
17 }
18
19 if cache.wants(ResourceType::USER)
21 && let Some(user) = &self.user
22 {
23 cache.cache_user(Cow::Borrowed(user), None);
24 }
25
26 if let Some(InteractionData::ApplicationCommand(data)) = &self.data
28 && let Some(resolved) = &data.resolved
29 {
30 for u in resolved.users.values() {
32 if cache.wants(ResourceType::USER) {
33 cache.cache_user(Cow::Borrowed(u), self.guild_id);
34 }
35
36 if !cache.wants(ResourceType::MEMBER) || self.guild_id.is_none() {
37 continue;
38 }
39
40 if let Some(member) = &resolved.members.get(&u.id)
43 && let Some(guild_id) = self.guild_id
44 {
45 cache.cache_borrowed_interaction_member(guild_id, member, u.id);
46 }
47 }
48
49 if cache.wants(ResourceType::ROLE)
51 && let Some(guild_id) = self.guild_id
52 {
53 cache.cache_roles(guild_id, resolved.roles.values().cloned());
54 }
55 }
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use crate::DefaultInMemoryCache;
62 use std::collections::HashMap;
63 use twilight_model::guild::RoleColors;
64 use twilight_model::{
65 application::{
66 command::CommandType,
67 interaction::{
68 Interaction, InteractionData, InteractionDataResolved, InteractionMember,
69 InteractionType, application_command::CommandData,
70 },
71 },
72 channel::{
73 Channel, ChannelType, Message,
74 message::{
75 MessageFlags, MessageType,
76 sticker::{MessageSticker, StickerFormatType},
77 },
78 },
79 gateway::payload::incoming::InteractionCreate,
80 guild::{MemberFlags, PartialMember, Permissions, Role, RoleFlags},
81 id::Id,
82 oauth::ApplicationIntegrationMap,
83 user::User,
84 util::{ImageHash, Timestamp, image_hash::ImageHashParseError},
85 };
86
87 #[allow(clippy::too_many_lines, deprecated)]
88 #[test]
89 fn interaction_create() -> Result<(), ImageHashParseError> {
90 let timestamp = Timestamp::from_secs(1_632_072_645).expect("non zero");
91 let avatar2 = ImageHash::parse(b"3a43231a99f4dfcf0fd94d1d8defd301")?;
93 let avatar3 = ImageHash::parse(b"5e23c298295ad37936cfe24ad314774f")?;
94 let flags = MemberFlags::BYPASSES_VERIFICATION | MemberFlags::DID_REJOIN;
95
96 let cache = DefaultInMemoryCache::new();
97
98 cache.update(&InteractionCreate(Interaction {
99 app_permissions: Some(Permissions::SEND_MESSAGES),
100 application_id: Id::new(1),
101 authorizing_integration_owners: ApplicationIntegrationMap {
102 guild: None,
103 user: None,
104 },
105 channel: Some(Channel {
106 bitrate: None,
107 guild_id: None,
108 id: Id::new(400),
109 kind: ChannelType::GuildText,
110 last_message_id: None,
111 last_pin_timestamp: None,
112 name: None,
113 nsfw: None,
114 owner_id: None,
115 parent_id: None,
116 permission_overwrites: None,
117 position: None,
118 rate_limit_per_user: None,
119 recipients: None,
120 rtc_region: None,
121 topic: None,
122 user_limit: None,
123 application_id: None,
124 applied_tags: None,
125 available_tags: None,
126 default_auto_archive_duration: None,
127 default_forum_layout: None,
128 default_reaction_emoji: None,
129 default_sort_order: None,
130 default_thread_rate_limit_per_user: None,
131 flags: None,
132 icon: None,
133 invitable: None,
134 managed: None,
135 member: None,
136 member_count: None,
137 message_count: None,
138 newly_created: None,
139 thread_metadata: None,
140 video_quality_mode: None,
141 }),
142 channel_id: Some(Id::new(2)),
143 context: None,
144 data: Some(InteractionData::ApplicationCommand(Box::new(CommandData {
145 guild_id: None,
146 id: Id::new(5),
147 name: "command name".into(),
148 kind: CommandType::ChatInput, options: Vec::new(),
150 resolved: Some(InteractionDataResolved {
151 attachments: HashMap::new(),
152 channels: HashMap::new(),
153 members: HashMap::from([(
154 Id::new(7),
155 InteractionMember {
156 avatar: None,
157 avatar_decoration_data: None,
158 banner: None,
159 communication_disabled_until: None,
160 flags,
161 joined_at: Some(timestamp),
162 nick: None,
163 pending: false,
164 permissions: Permissions::empty(),
165 premium_since: None,
166 roles: vec![Id::new(8)],
167 },
168 )]),
169 messages: HashMap::from([(
170 Id::new(4),
171 Message {
172 activity: None,
173 application: None,
174 application_id: None,
175 attachments: Vec::new(),
176 author: User {
177 accent_color: None,
178 avatar: Some(avatar3),
179 avatar_decoration: None,
180 avatar_decoration_data: None,
181 banner: None,
182 bot: false,
183 discriminator: 1,
184 email: None,
185 flags: None,
186 global_name: Some("test".to_owned()),
187 id: Id::new(3),
188 locale: None,
189 mfa_enabled: None,
190 name: "test".to_owned(),
191 premium_type: None,
192 primary_guild: None,
193 public_flags: None,
194 system: None,
195 verified: None,
196 },
197 call: None,
198 channel_id: Id::new(2),
199 components: Vec::new(),
200 content: "ping".to_owned(),
201 edited_timestamp: None,
202 embeds: Vec::new(),
203 flags: Some(MessageFlags::empty()),
204 guild_id: Some(Id::new(1)),
205 id: Id::new(4),
206 interaction: None,
207 interaction_metadata: None,
208 kind: MessageType::Regular,
209 member: Some(PartialMember {
210 avatar: None,
211 avatar_decoration_data: None,
212 banner: None,
213 communication_disabled_until: None,
214 deaf: false,
215 flags,
216 joined_at: Some(timestamp),
217 mute: false,
218 nick: Some("member nick".to_owned()),
219 permissions: None,
220 premium_since: None,
221 roles: Vec::new(),
222 user: None,
223 }),
224 mention_channels: Vec::new(),
225 mention_everyone: false,
226 mention_roles: Vec::new(),
227 mentions: Vec::new(),
228 message_snapshots: Vec::new(),
229 pinned: false,
230 poll: None,
231 reactions: Vec::new(),
232 reference: None,
233 referenced_message: None,
234 role_subscription_data: None,
235 sticker_items: vec![MessageSticker {
236 format_type: StickerFormatType::Png,
237 id: Id::new(1),
238 name: "sticker name".to_owned(),
239 }],
240 timestamp,
241 thread: None,
242 tts: false,
243 webhook_id: None,
244 },
245 )]),
246 roles: HashMap::from([(
247 Id::new(8),
248 Role {
249 color: 0u32,
250 colors: RoleColors {
251 primary_color: 0,
252 secondary_color: None,
253 tertiary_color: None,
254 },
255 hoist: false,
256 icon: None,
257 id: Id::new(8),
258 managed: false,
259 mentionable: true,
260 name: "role name".into(),
261 permissions: Permissions::empty(),
262 position: 2i64,
263 flags: RoleFlags::empty(),
264 tags: None,
265 unicode_emoji: None,
266 },
267 )]),
268 users: HashMap::from([(
269 Id::new(7),
270 User {
271 accent_color: None,
272 avatar: Some(avatar2),
273 avatar_decoration: None,
274 avatar_decoration_data: None,
275 banner: None,
276 bot: false,
277 discriminator: 5678,
278 email: None,
279 flags: None,
280 global_name: Some("different name".to_owned()),
281 id: Id::new(7),
282 locale: None,
283 mfa_enabled: None,
284 name: "different name".into(),
285 premium_type: None,
286 primary_guild: None,
287 public_flags: None,
288 system: None,
289 verified: None,
290 },
291 )]),
292 }),
293 target_id: None,
294 }))),
295 entitlements: Vec::new(),
296 guild: None,
297 guild_id: Some(Id::new(3)),
298 guild_locale: None,
299 id: Id::new(4),
300 kind: InteractionType::ApplicationCommand,
301 locale: Some("en-GB".to_owned()),
302 member: Some(PartialMember {
303 avatar: None,
304 avatar_decoration_data: None,
305 banner: None,
306 communication_disabled_until: None,
307 deaf: false,
308 flags,
309 joined_at: Some(timestamp),
310 mute: false,
311 nick: None,
312 permissions: Some(Permissions::empty()),
313 premium_since: None,
314 roles: Vec::new(),
315 user: Some(User {
316 accent_color: None,
317 avatar: Some(avatar3),
318 avatar_decoration: None,
319 avatar_decoration_data: None,
320 banner: None,
321 bot: false,
322 discriminator: 1234,
323 email: None,
324 flags: None,
325 global_name: Some("test".to_owned()),
326 id: Id::new(6),
327 locale: None,
328 mfa_enabled: None,
329 name: "username".into(),
330 premium_type: None,
331 primary_guild: None,
332 public_flags: None,
333 system: None,
334 verified: None,
335 }),
336 }),
337 message: None,
338 token: "token".into(),
339 user: None,
340 }));
341
342 {
343 let guild_members = cache.guild_members(Id::new(3)).unwrap();
344 assert_eq!(guild_members.len(), 2);
345 }
346
347 {
348 let member = cache.member(Id::new(3), Id::new(6)).unwrap();
349 let user = cache.user(member.user_id).unwrap();
350 assert_eq!(user.avatar.as_ref().unwrap(), &avatar3);
351 }
352
353 {
354 let member = cache.member(Id::new(3), Id::new(7)).unwrap();
355 let user = cache.user(member.user_id).unwrap();
356 assert_eq!(user.avatar.as_ref().unwrap(), &avatar2);
357 }
358
359 {
360 let guild_roles = cache.guild_roles(Id::new(3)).unwrap();
361 assert_eq!(guild_roles.len(), 1);
362 }
363
364 Ok(())
365 }
366}