1use std::collections::HashSet;
2
3use super::{Cache, CacheUpdate};
4use crate::model::channel::{GuildChannel, Message};
5use crate::model::event::{
6 ChannelCreateEvent,
7 ChannelDeleteEvent,
8 ChannelPinsUpdateEvent,
9 ChannelUpdateEvent,
10 GuildCreateEvent,
11 GuildDeleteEvent,
12 GuildEmojisUpdateEvent,
13 GuildMemberAddEvent,
14 GuildMemberRemoveEvent,
15 GuildMemberUpdateEvent,
16 GuildMembersChunkEvent,
17 GuildRoleCreateEvent,
18 GuildRoleDeleteEvent,
19 GuildRoleUpdateEvent,
20 GuildStickersUpdateEvent,
21 GuildUpdateEvent,
22 MessageCreateEvent,
23 MessageUpdateEvent,
24 PresenceUpdateEvent,
25 ReadyEvent,
26 ThreadCreateEvent,
27 ThreadDeleteEvent,
28 ThreadUpdateEvent,
29 UserUpdateEvent,
30 VoiceChannelStatusUpdateEvent,
31 VoiceStateUpdateEvent,
32};
33use crate::model::gateway::ShardInfo;
34use crate::model::guild::{Guild, GuildMemberFlags, Member, Role};
35use crate::model::id::ShardId;
36use crate::model::user::{CurrentUser, OnlineStatus};
37use crate::model::voice::VoiceState;
38
39impl CacheUpdate for ChannelCreateEvent {
40 type Output = GuildChannel;
41
42 fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
43 let old_channel = cache
44 .guilds
45 .get_mut(&self.channel.guild_id)
46 .and_then(|mut g| g.channels.insert(self.channel.id, self.channel.clone()));
47
48 cache.channels.insert(self.channel.id, self.channel.guild_id);
49 old_channel
50 }
51}
52
53impl CacheUpdate for ChannelDeleteEvent {
54 type Output = Vec<Message>;
55
56 fn update(&mut self, cache: &Cache) -> Option<Vec<Message>> {
57 let (channel_id, guild_id) = (self.channel.id, self.channel.guild_id);
58
59 cache.channels.remove(&channel_id);
60 cache.guilds.get_mut(&guild_id).map(|mut g| g.channels.remove(&channel_id));
61
62 cache.messages.remove(&channel_id).map(|(_, messages)| messages.into_values().collect())
64 }
65}
66
67impl CacheUpdate for ChannelUpdateEvent {
68 type Output = GuildChannel;
69
70 fn update(&mut self, cache: &Cache) -> Option<GuildChannel> {
71 cache.channels.insert(self.channel.id, self.channel.guild_id);
72
73 cache
74 .guilds
75 .get_mut(&self.channel.guild_id)
76 .and_then(|mut g| g.channels.insert(self.channel.id, self.channel.clone()))
77 }
78}
79
80impl CacheUpdate for ChannelPinsUpdateEvent {
81 type Output = ();
82
83 fn update(&mut self, cache: &Cache) -> Option<()> {
84 if let Some(guild_id) = self.guild_id {
85 if let Some(mut guild) = cache.guilds.get_mut(&guild_id) {
86 if let Some(channel) = guild.channels.get_mut(&self.channel_id) {
87 channel.last_pin_timestamp = self.last_pin_timestamp;
88 }
89 }
90 }
91
92 None
93 }
94}
95
96impl CacheUpdate for GuildCreateEvent {
97 type Output = ();
98
99 fn update(&mut self, cache: &Cache) -> Option<()> {
100 cache.unavailable_guilds.remove(&self.guild.id);
101 let mut guild = self.guild.clone();
102
103 for (user_id, member) in &mut guild.members {
104 cache.update_user_entry(&member.user);
105 if let Some(u) = cache.user(user_id) {
106 member.user = u.clone();
107 }
108 }
109
110 cache.guilds.insert(self.guild.id, guild);
111 for channel_id in self.guild.channels.keys() {
112 cache.channels.insert(*channel_id, self.guild.id);
113 }
114
115 None
116 }
117}
118
119impl CacheUpdate for GuildDeleteEvent {
120 type Output = Guild;
121
122 fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
123 if self.guild.unavailable {
124 cache.unavailable_guilds.insert(self.guild.id, ());
125 cache.guilds.remove(&self.guild.id);
126
127 return None;
128 }
129
130 match cache.guilds.remove(&self.guild.id) {
131 Some(guild) => {
132 for channel_id in guild.1.channels.keys() {
133 cache.channels.remove(channel_id);
135
136 cache.messages.remove(channel_id);
138 }
139
140 Some(guild.1)
141 },
142 None => None,
143 }
144 }
145}
146
147impl CacheUpdate for GuildEmojisUpdateEvent {
148 type Output = ();
149
150 fn update(&mut self, cache: &Cache) -> Option<()> {
151 if let Some(mut guild) = cache.guilds.get_mut(&self.guild_id) {
152 guild.emojis.clone_from(&self.emojis);
153 }
154
155 None
156 }
157}
158
159impl CacheUpdate for GuildMemberAddEvent {
160 type Output = ();
161
162 fn update(&mut self, cache: &Cache) -> Option<()> {
163 let user_id = self.member.user.id;
164 cache.update_user_entry(&self.member.user);
165 if let Some(u) = cache.user(user_id) {
166 self.member.user = u.clone();
167 }
168
169 if let Some(mut guild) = cache.guilds.get_mut(&self.member.guild_id) {
170 guild.member_count += 1;
171 guild.members.insert(user_id, self.member.clone());
172 }
173
174 None
175 }
176}
177
178impl CacheUpdate for GuildMemberRemoveEvent {
179 type Output = Member;
180
181 fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
182 if let Some(mut guild) = cache.guilds.get_mut(&self.guild_id) {
183 guild.member_count -= 1;
184 return guild.members.remove(&self.user.id);
185 }
186
187 None
188 }
189}
190
191impl CacheUpdate for GuildMemberUpdateEvent {
192 type Output = Member;
193
194 fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
195 cache.update_user_entry(&self.user);
196
197 if let Some(mut guild) = cache.guilds.get_mut(&self.guild_id) {
198 let item = if let Some(member) = guild.members.get_mut(&self.user.id) {
199 let item = Some(member.clone());
200
201 member.joined_at.clone_from(&Some(self.joined_at));
202 member.nick.clone_from(&self.nick);
203 member.roles.clone_from(&self.roles);
204 member.user.clone_from(&self.user);
205 member.pending.clone_from(&self.pending);
206 member.premium_since.clone_from(&self.premium_since);
207 member.deaf.clone_from(&self.deaf);
208 member.mute.clone_from(&self.mute);
209 member.avatar.clone_from(&self.avatar);
210 member.communication_disabled_until.clone_from(&self.communication_disabled_until);
211 member.unusual_dm_activity_until.clone_from(&self.unusual_dm_activity_until);
212
213 item
214 } else {
215 None
216 };
217
218 if item.is_none() {
219 guild.members.insert(self.user.id, Member {
220 deaf: false,
221 guild_id: self.guild_id,
222 joined_at: Some(self.joined_at),
223 mute: false,
224 nick: self.nick.clone(),
225 roles: self.roles.clone(),
226 user: self.user.clone(),
227 pending: self.pending,
228 premium_since: self.premium_since,
229 permissions: None,
230 avatar: self.avatar,
231 communication_disabled_until: self.communication_disabled_until,
232 flags: GuildMemberFlags::default(),
233 unusual_dm_activity_until: self.unusual_dm_activity_until,
234 });
235 }
236
237 item
238 } else {
239 None
240 }
241 }
242}
243
244impl CacheUpdate for GuildMembersChunkEvent {
245 type Output = ();
246
247 fn update(&mut self, cache: &Cache) -> Option<()> {
248 for member in self.members.values() {
249 cache.update_user_entry(&member.user);
250 }
251
252 if let Some(mut g) = cache.guilds.get_mut(&self.guild_id) {
253 g.members.extend(self.members.clone());
254 }
255
256 None
257 }
258}
259
260impl CacheUpdate for GuildRoleCreateEvent {
261 type Output = ();
262
263 fn update(&mut self, cache: &Cache) -> Option<()> {
264 cache
265 .guilds
266 .get_mut(&self.role.guild_id)
267 .map(|mut g| g.roles.insert(self.role.id, self.role.clone()));
268
269 None
270 }
271}
272
273impl CacheUpdate for GuildRoleDeleteEvent {
274 type Output = Role;
275
276 fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
277 cache.guilds.get_mut(&self.guild_id).and_then(|mut g| g.roles.remove(&self.role_id))
278 }
279}
280
281impl CacheUpdate for GuildRoleUpdateEvent {
282 type Output = Role;
283
284 fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
285 if let Some(mut guild) = cache.guilds.get_mut(&self.role.guild_id) {
286 if let Some(role) = guild.roles.get_mut(&self.role.id) {
287 return Some(std::mem::replace(role, self.role.clone()));
288 }
289 }
290
291 None
292 }
293}
294
295impl CacheUpdate for GuildStickersUpdateEvent {
296 type Output = ();
297
298 fn update(&mut self, cache: &Cache) -> Option<()> {
299 if let Some(mut guild) = cache.guilds.get_mut(&self.guild_id) {
300 guild.stickers.clone_from(&self.stickers);
301 }
302
303 None
304 }
305}
306
307impl CacheUpdate for GuildUpdateEvent {
308 type Output = ();
309
310 fn update(&mut self, cache: &Cache) -> Option<()> {
311 if let Some(mut guild) = cache.guilds.get_mut(&self.guild.id) {
312 guild.afk_metadata.clone_from(&self.guild.afk_metadata);
313 guild.banner.clone_from(&self.guild.banner);
314 guild.discovery_splash.clone_from(&self.guild.discovery_splash);
315 guild.features.clone_from(&self.guild.features);
316 guild.icon.clone_from(&self.guild.icon);
317 guild.name.clone_from(&self.guild.name);
318 guild.owner_id.clone_from(&self.guild.owner_id);
319 guild.roles.clone_from(&self.guild.roles);
320 guild.splash.clone_from(&self.guild.splash);
321 guild.vanity_url_code.clone_from(&self.guild.vanity_url_code);
322 guild.welcome_screen.clone_from(&self.guild.welcome_screen);
323 guild.default_message_notifications = self.guild.default_message_notifications;
324 guild.max_members = self.guild.max_members;
325 guild.max_presences = self.guild.max_presences;
326 guild.max_video_channel_users = self.guild.max_video_channel_users;
327 guild.mfa_level = self.guild.mfa_level;
328 guild.nsfw_level = self.guild.nsfw_level;
329 guild.premium_subscription_count = self.guild.premium_subscription_count;
330 guild.premium_tier = self.guild.premium_tier;
331 guild.public_updates_channel_id = self.guild.public_updates_channel_id;
332 guild.rules_channel_id = self.guild.rules_channel_id;
333 guild.system_channel_flags = self.guild.system_channel_flags;
334 guild.system_channel_id = self.guild.system_channel_id;
335 guild.verification_level = self.guild.verification_level;
336 guild.widget_channel_id = self.guild.widget_channel_id;
337 guild.widget_enabled = self.guild.widget_enabled;
338 }
339
340 None
341 }
342}
343
344impl CacheUpdate for MessageCreateEvent {
345 type Output = Message;
347
348 fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
349 let guild = self.message.guild_id.and_then(|g_id| cache.guilds.get_mut(&g_id));
351
352 if let Some(mut guild) = guild {
353 if let Some(channel) = guild.channels.get_mut(&self.message.channel_id) {
354 update_channel_last_message_id(&self.message, channel, cache);
355 } else {
356 let thread =
358 guild.threads.iter_mut().find(|thread| thread.id == self.message.channel_id);
359 if let Some(thread) = thread {
360 update_channel_last_message_id(&self.message, thread, cache);
361 }
362 }
363 }
364
365 let max = cache.settings().max_messages;
367
368 if max == 0 {
369 return None;
370 }
371
372 let mut messages = cache.messages.entry(self.message.channel_id).or_default();
373 let mut queue = cache.message_queue.entry(self.message.channel_id).or_default();
374
375 let mut removed_msg = None;
376
377 if messages.len() == max {
378 if let Some(id) = queue.pop_front() {
379 removed_msg = messages.remove(&id);
380 }
381 }
382
383 queue.push_back(self.message.id);
384 messages.insert(self.message.id, self.message.clone());
385
386 removed_msg
387 }
388}
389
390fn update_channel_last_message_id(message: &Message, channel: &mut GuildChannel, cache: &Cache) {
391 if let Some(last_message_id) = channel.last_message_id {
392 let most_recent_timestamp = cache.message(channel.id, last_message_id).map(|m| m.timestamp);
393 if let Some(most_recent_timestamp) = most_recent_timestamp {
394 if message.timestamp > most_recent_timestamp {
395 channel.last_message_id = Some(message.id);
396 }
397 } else {
398 channel.last_message_id = Some(message.id);
399 }
400 } else {
401 channel.last_message_id = Some(message.id);
402 }
403}
404
405impl CacheUpdate for MessageUpdateEvent {
406 type Output = Message;
407
408 fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
409 let mut messages = cache.messages.get_mut(&self.channel_id)?;
410 let message = messages.get_mut(&self.id)?;
411 let old_message = message.clone();
412
413 self.apply_to_message(message);
414
415 Some(old_message)
416 }
417}
418
419impl CacheUpdate for PresenceUpdateEvent {
420 type Output = ();
421
422 fn update(&mut self, cache: &Cache) -> Option<()> {
423 if let Some(user) = self.presence.user.to_user() {
424 cache.update_user_entry(&user);
425 }
426
427 if let Some(user) = cache.user(self.presence.user.id) {
428 self.presence.user.update_with_user(&user);
429 }
430
431 if let Some(guild_id) = self.presence.guild_id {
432 if let Some(mut guild) = cache.guilds.get_mut(&guild_id) {
433 if self.presence.status == OnlineStatus::Offline {
435 guild.presences.remove(&self.presence.user.id);
436 } else {
437 guild.presences.insert(self.presence.user.id, self.presence.clone());
438 }
439
440 if let Some(user) = self.presence.user.to_user() {
442 guild.members.entry(self.presence.user.id).or_insert_with(|| Member {
443 deaf: false,
444 guild_id,
445 joined_at: None,
446 mute: false,
447 nick: None,
448 user,
449 roles: vec![],
450 pending: false,
451 premium_since: None,
452 permissions: None,
453 avatar: None,
454 communication_disabled_until: None,
455 flags: GuildMemberFlags::default(),
456 unusual_dm_activity_until: None,
457 });
458 }
459 }
460 }
461
462 None
463 }
464}
465
466impl CacheUpdate for ReadyEvent {
467 type Output = ();
468
469 fn update(&mut self, cache: &Cache) -> Option<()> {
470 let ready = self.ready.clone();
471
472 for unavailable in ready.guilds {
473 cache.guilds.remove(&unavailable.id);
474 cache.unavailable_guilds.insert(unavailable.id, ());
475 }
476
477 let mut guilds_to_remove = vec![];
479 let ready_guilds_hashset =
480 self.ready.guilds.iter().map(|status| status.id).collect::<HashSet<_>>();
481 let shard_data = self.ready.shard.unwrap_or_else(|| ShardInfo::new(ShardId(1), 1));
482
483 for guild_entry in cache.guilds.iter() {
484 let guild = guild_entry.key();
485 if crate::utils::shard_id(*guild, shard_data.total) == shard_data.id.0
487 && !ready_guilds_hashset.contains(guild)
488 {
489 guilds_to_remove.push(*guild);
490 }
491 }
492 if !guilds_to_remove.is_empty() {
493 for guild in guilds_to_remove {
494 cache.guilds.remove(&guild);
495 }
496 }
497
498 {
499 let mut cached_shard_data = cache.shard_data.write();
500 cached_shard_data.total = shard_data.total;
501 cached_shard_data.connected.insert(shard_data.id);
502 }
503 *cache.user.write() = ready.user;
504
505 None
506 }
507}
508
509impl CacheUpdate for ThreadCreateEvent {
510 type Output = GuildChannel;
511
512 fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
513 let (guild_id, thread_id) = (self.thread.guild_id, self.thread.id);
514
515 cache.guilds.get_mut(&guild_id).and_then(|mut g| {
516 if let Some(i) = g.threads.iter().position(|e| e.id == thread_id) {
517 Some(std::mem::replace(&mut g.threads[i], self.thread.clone()))
518 } else {
519 g.threads.push(self.thread.clone());
520 None
521 }
522 })
523 }
524}
525
526impl CacheUpdate for ThreadUpdateEvent {
527 type Output = GuildChannel;
528
529 fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
530 let (guild_id, thread_id) = (self.thread.guild_id, self.thread.id);
531
532 cache.guilds.get_mut(&guild_id).and_then(|mut g| {
533 if let Some(i) = g.threads.iter().position(|e| e.id == thread_id) {
534 Some(std::mem::replace(&mut g.threads[i], self.thread.clone()))
535 } else {
536 g.threads.push(self.thread.clone());
537 None
538 }
539 })
540 }
541}
542
543impl CacheUpdate for ThreadDeleteEvent {
544 type Output = GuildChannel;
545
546 fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
547 let (guild_id, thread_id) = (self.thread.guild_id, self.thread.id);
548
549 cache.guilds.get_mut(&guild_id).and_then(|mut g| {
550 g.threads.iter().position(|e| e.id == thread_id).map(|i| g.threads.remove(i))
551 })
552 }
553}
554
555impl CacheUpdate for UserUpdateEvent {
556 type Output = CurrentUser;
557
558 fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
559 let mut user = cache.user.write();
560 Some(std::mem::replace(&mut user, self.current_user.clone()))
561 }
562}
563
564impl CacheUpdate for VoiceStateUpdateEvent {
565 type Output = VoiceState;
566
567 fn update(&mut self, cache: &Cache) -> Option<VoiceState> {
568 if let Some(guild_id) = self.voice_state.guild_id {
569 if let Some(mut guild) = cache.guilds.get_mut(&guild_id) {
570 if let Some(member) = &self.voice_state.member {
571 guild.members.insert(member.user.id, member.clone());
572 }
573
574 if self.voice_state.channel_id.is_some() {
575 guild.voice_states.insert(self.voice_state.user_id, self.voice_state.clone())
577 } else {
578 guild.voice_states.remove(&self.voice_state.user_id)
580 }
581 } else {
582 None
583 }
584 } else {
585 None
586 }
587 }
588}
589
590impl CacheUpdate for VoiceChannelStatusUpdateEvent {
591 type Output = String;
592
593 fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
594 let mut guild = cache.guilds.get_mut(&self.guild_id)?;
595 let channel = guild.channels.get_mut(&self.id)?;
596
597 let old = channel.status.clone();
598 channel.status.clone_from(&self.status);
599 old
600 }
601}