1use crate::{config::ResourceType, CacheableModels, InMemoryCache, UpdateCache};
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 if let (Some(member), Some(guild_id)) = (&self.member, self.guild_id) {
12 if let Some(user) = &member.user {
13 cache.cache_user(Cow::Borrowed(user), self.guild_id);
14
15 cache.cache_borrowed_partial_member(guild_id, member, user.id);
16 }
17 }
18 }
19
20 if cache.wants(ResourceType::USER) {
22 if let Some(user) = &self.user {
23 cache.cache_user(Cow::Borrowed(user), None);
24 }
25 }
26
27 if let Some(InteractionData::ApplicationCommand(data)) = &self.data {
29 if let Some(resolved) = &data.resolved {
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 if let Some(guild_id) = self.guild_id {
44 cache.cache_borrowed_interaction_member(guild_id, member, u.id);
45 }
46 }
47 }
48
49 if cache.wants(ResourceType::ROLE) {
51 if let Some(guild_id) = self.guild_id {
52 cache.cache_roles(guild_id, resolved.roles.values().cloned());
53 }
54 }
55 }
56 }
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use crate::DefaultInMemoryCache;
63 use std::collections::HashMap;
64 use twilight_model::{
65 application::{
66 command::CommandType,
67 interaction::{
68 application_command::CommandData, Interaction, InteractionData,
69 InteractionDataResolved, InteractionMember, InteractionType,
70 },
71 },
72 channel::{
73 message::{
74 sticker::{MessageSticker, StickerFormatType},
75 MessageFlags, MessageType,
76 },
77 Channel, ChannelType, Message,
78 },
79 gateway::payload::incoming::InteractionCreate,
80 guild::{MemberFlags, PartialMember, Permissions, Role, RoleFlags},
81 id::Id,
82 oauth::ApplicationIntegrationMap,
83 user::User,
84 util::{image_hash::ImageHashParseError, ImageHash, Timestamp},
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 communication_disabled_until: None,
158 flags,
159 joined_at: Some(timestamp),
160 nick: None,
161 pending: false,
162 permissions: Permissions::empty(),
163 premium_since: None,
164 roles: vec![Id::new(8)],
165 },
166 )]),
167 messages: HashMap::from([(
168 Id::new(4),
169 Message {
170 activity: None,
171 application: None,
172 application_id: None,
173 attachments: Vec::new(),
174 author: User {
175 accent_color: None,
176 avatar: Some(avatar3),
177 avatar_decoration: None,
178 avatar_decoration_data: None,
179 banner: None,
180 bot: false,
181 discriminator: 1,
182 email: None,
183 flags: None,
184 global_name: Some("test".to_owned()),
185 id: Id::new(3),
186 locale: None,
187 mfa_enabled: None,
188 name: "test".to_owned(),
189 premium_type: None,
190 public_flags: None,
191 system: None,
192 verified: None,
193 },
194 call: None,
195 channel_id: Id::new(2),
196 components: Vec::new(),
197 content: "ping".to_owned(),
198 edited_timestamp: None,
199 embeds: Vec::new(),
200 flags: Some(MessageFlags::empty()),
201 guild_id: Some(Id::new(1)),
202 id: Id::new(4),
203 interaction: None,
204 interaction_metadata: None,
205 kind: MessageType::Regular,
206 member: Some(PartialMember {
207 avatar: None,
208 communication_disabled_until: None,
209 deaf: false,
210 flags,
211 joined_at: Some(timestamp),
212 mute: false,
213 nick: Some("member nick".to_owned()),
214 permissions: None,
215 premium_since: None,
216 roles: Vec::new(),
217 user: None,
218 }),
219 mention_channels: Vec::new(),
220 mention_everyone: false,
221 mention_roles: Vec::new(),
222 mentions: Vec::new(),
223 message_snapshots: Vec::new(),
224 pinned: false,
225 poll: None,
226 reactions: Vec::new(),
227 reference: None,
228 referenced_message: None,
229 role_subscription_data: None,
230 sticker_items: vec![MessageSticker {
231 format_type: StickerFormatType::Png,
232 id: Id::new(1),
233 name: "sticker name".to_owned(),
234 }],
235 timestamp,
236 thread: None,
237 tts: false,
238 webhook_id: None,
239 },
240 )]),
241 roles: HashMap::from([(
242 Id::new(8),
243 Role {
244 color: 0u32,
245 hoist: false,
246 icon: None,
247 id: Id::new(8),
248 managed: false,
249 mentionable: true,
250 name: "role name".into(),
251 permissions: Permissions::empty(),
252 position: 2i64,
253 flags: RoleFlags::empty(),
254 tags: None,
255 unicode_emoji: None,
256 },
257 )]),
258 users: HashMap::from([(
259 Id::new(7),
260 User {
261 accent_color: None,
262 avatar: Some(avatar2),
263 avatar_decoration: None,
264 avatar_decoration_data: None,
265 banner: None,
266 bot: false,
267 discriminator: 5678,
268 email: None,
269 flags: None,
270 global_name: Some("different name".to_owned()),
271 id: Id::new(7),
272 locale: None,
273 mfa_enabled: None,
274 name: "different name".into(),
275 premium_type: None,
276 public_flags: None,
277 system: None,
278 verified: None,
279 },
280 )]),
281 }),
282 target_id: None,
283 }))),
284 entitlements: Vec::new(),
285 guild: None,
286 guild_id: Some(Id::new(3)),
287 guild_locale: None,
288 id: Id::new(4),
289 kind: InteractionType::ApplicationCommand,
290 locale: Some("en-GB".to_owned()),
291 member: Some(PartialMember {
292 avatar: None,
293 communication_disabled_until: None,
294 deaf: false,
295 flags,
296 joined_at: Some(timestamp),
297 mute: false,
298 nick: None,
299 permissions: Some(Permissions::empty()),
300 premium_since: None,
301 roles: Vec::new(),
302 user: Some(User {
303 accent_color: None,
304 avatar: Some(avatar3),
305 avatar_decoration: None,
306 avatar_decoration_data: None,
307 banner: None,
308 bot: false,
309 discriminator: 1234,
310 email: None,
311 flags: None,
312 global_name: Some("test".to_owned()),
313 id: Id::new(6),
314 locale: None,
315 mfa_enabled: None,
316 name: "username".into(),
317 premium_type: None,
318 public_flags: None,
319 system: None,
320 verified: None,
321 }),
322 }),
323 message: None,
324 token: "token".into(),
325 user: None,
326 }));
327
328 {
329 let guild_members = cache.guild_members(Id::new(3)).unwrap();
330 assert_eq!(guild_members.len(), 2);
331 }
332
333 {
334 let member = cache.member(Id::new(3), Id::new(6)).unwrap();
335 let user = cache.user(member.user_id).unwrap();
336 assert_eq!(user.avatar.as_ref().unwrap(), &avatar3);
337 }
338
339 {
340 let member = cache.member(Id::new(3), Id::new(7)).unwrap();
341 let user = cache.user(member.user_id).unwrap();
342 assert_eq!(user.avatar.as_ref().unwrap(), &avatar2);
343 }
344
345 {
346 let guild_roles = cache.guild_roles(Id::new(3)).unwrap();
347 assert_eq!(guild_roles.len(), 1);
348 }
349
350 Ok(())
351 }
352}