Skip to content

Commit

Permalink
refactor(model, cache): a full message object for MessageUpdate eve…
Browse files Browse the repository at this point in the history
…nt (#2387)

`MessageUpdate` event now contains a full `Message` object.

Refs:
- discord/discord-api-docs#7017

---------

Co-authored-by: Erk <[email protected]>
Co-authored-by: ITOH <[email protected]>
  • Loading branch information
3 people authored Nov 25, 2024
1 parent c93fb5a commit f7a6c3e
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 116 deletions.
7 changes: 0 additions & 7 deletions examples/cache-optimization/models/message.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use twilight_cache_inmemory::CacheableMessage;
use twilight_model::{
channel::{message::Reaction, Message},
gateway::payload::incoming::MessageUpdate,
id::{marker::MessageMarker, Id},
};

Expand Down Expand Up @@ -50,10 +49,4 @@ impl CacheableMessage for MinimalCachedMessage {
fn retain_reactions(&mut self, _f: impl FnMut(&Reaction) -> bool) {
// No-op
}

fn update_with_message_update(&mut self, message_update: &MessageUpdate) {
if let Some(content) = &message_update.content {
self.content.clone_from(content);
}
}
}
38 changes: 35 additions & 3 deletions twilight-cache-inmemory/src/event/message.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{config::ResourceType, CacheableMessage, CacheableModels, InMemoryCache, UpdateCache};
use crate::{config::ResourceType, CacheableModels, InMemoryCache, UpdateCache};
use std::borrow::Cow;
use twilight_model::gateway::payload::incoming::{
MessageCreate, MessageDelete, MessageDeleteBulk, MessageUpdate,
Expand Down Expand Up @@ -80,13 +80,45 @@ impl<CacheModels: CacheableModels> UpdateCache<CacheModels> for MessageDeleteBul

impl<CacheModels: CacheableModels> UpdateCache<CacheModels> for MessageUpdate {
fn update(&self, cache: &InMemoryCache<CacheModels>) {
if cache.wants(ResourceType::USER) {
cache.cache_user(Cow::Borrowed(&self.author), self.guild_id);
}

if let (Some(member), Some(guild_id), true) = (
&self.member,
self.guild_id,
cache.wants(ResourceType::MEMBER),
) {
cache.cache_borrowed_partial_member(guild_id, member, self.author.id);
}

if !cache.wants(ResourceType::MESSAGE) {
return;
}

if let Some(mut message) = cache.messages.get_mut(&self.id) {
message.update_with_message_update(self);
// In special cases, this message was popped out due to the limitation
// of the message cache capacity, or its Event::MessageCreate was missed.
// If that is the case, we do not only add it to the message cache but
// also add its ID to the channel messages cache.
if cache
.messages
.insert(self.id, CacheModels::Message::from(self.0.clone()))
.is_some()
{
return;
}

let mut channel_messages = cache.channel_messages.entry(self.0.channel_id).or_default();

// If this channel cache is full, we pop an message ID out of
// the channel cache and also remove it from the message cache.
if channel_messages.len() >= cache.config.message_cache_size() {
if let Some(popped_id) = channel_messages.pop_back() {
cache.messages.remove(&popped_id);
}
}

channel_messages.push_front(self.0.id);
}
}

Expand Down
43 changes: 0 additions & 43 deletions twilight-cache-inmemory/src/model/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use twilight_model::{
},
Attachment, ChannelMention,
},
gateway::payload::incoming::MessageUpdate,
guild::PartialMember,
id::{
marker::{
Expand Down Expand Up @@ -427,48 +426,6 @@ impl PartialEq<Message> for CachedMessage {
}

impl CacheableMessage for CachedMessage {
fn update_with_message_update(&mut self, message_update: &MessageUpdate) {
if let Some(attachments) = &message_update.attachments {
self.attachments.clone_from(attachments);
}

if let Some(content) = &message_update.content {
self.content.clone_from(content);
}

if let Some(edited_timestamp) = message_update.edited_timestamp {
self.edited_timestamp.replace(edited_timestamp);
}

if let Some(embeds) = &message_update.embeds {
self.embeds.clone_from(embeds);
}

if let Some(mention_everyone) = message_update.mention_everyone {
self.mention_everyone = mention_everyone;
}

if let Some(mention_roles) = &message_update.mention_roles {
self.mention_roles.clone_from(mention_roles);
}

if let Some(mentions) = &message_update.mentions {
self.mentions = mentions.iter().map(|x| x.id).collect::<Vec<_>>();
}

if let Some(pinned) = message_update.pinned {
self.pinned = pinned;
}

if let Some(timestamp) = message_update.timestamp {
self.timestamp = timestamp;
}

if let Some(tts) = message_update.tts {
self.tts = tts;
}
}

fn reactions(&self) -> &[Reaction] {
&self.reactions
}
Expand Down
5 changes: 1 addition & 4 deletions twilight-cache-inmemory/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use twilight_model::{
Channel, ChannelType, Message, StageInstance,
},
gateway::{
payload::incoming::{GuildUpdate, MemberUpdate, MessageUpdate},
payload::incoming::{GuildUpdate, MemberUpdate},
presence::Presence,
},
guild::{
Expand Down Expand Up @@ -235,9 +235,6 @@ pub trait CacheableVoiceState:
pub trait CacheableMessage:
From<Message> + PartialEq<Message> + PartialEq<Self> + Clone + Debug
{
/// Update the cached data with a [`MessageUpdate`] event.
fn update_with_message_update(&mut self, message_update: &MessageUpdate);

/// Reactions added to this message.
fn reactions(&self) -> &[Reaction];

Expand Down
2 changes: 1 addition & 1 deletion twilight-model/src/gateway/event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ impl Event {
Event::MessageCreate(e) => e.0.guild_id,
Event::MessageDelete(e) => e.guild_id,
Event::MessageDeleteBulk(e) => e.guild_id,
Event::MessageUpdate(e) => e.guild_id,
Event::MessageUpdate(e) => e.0.guild_id,
Event::MessagePollVoteAdd(e) => e.guild_id,
Event::MessagePollVoteRemove(e) => e.guild_id,
Event::PresenceUpdate(e) => Some(e.0.guild_id),
Expand Down
75 changes: 17 additions & 58 deletions twilight-model/src/gateway/payload/incoming/message_update.rs
Original file line number Diff line number Diff line change
@@ -1,62 +1,21 @@
use crate::{
channel::{
message::{Embed, Mention, MessageType},
Attachment,
},
id::{
marker::{ChannelMarker, GuildMarker, MessageMarker, RoleMarker},
Id,
},
user::User,
util::Timestamp,
};
use crate::channel::Message;
use serde::{Deserialize, Serialize};
use std::ops::{Deref, DerefMut};

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct MessageUpdate {
/// List of attachments.
///
/// Refer to the documentation for [`Message::attachments`] for caveats with
/// receiving the attachments of messages.
///
/// [`Message::attachments`]: crate::channel::Message::attachments
#[serde(skip_serializing_if = "Option::is_none")]
pub attachments: Option<Vec<Attachment>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub author: Option<User>,
pub channel_id: Id<ChannelMarker>,
/// Content of the message.
///
/// Refer to the documentation for [`Message::content`] for caveats with
/// receiving the content of messages.
///
/// [`Message::content`]: crate::channel::Message::content
pub content: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub edited_timestamp: Option<Timestamp>,
/// List of embeds.
///
/// Refer to the documentation for [`Message::embeds`] for caveats with
/// receiving the embeds of messages.
///
/// [`Message::embeds`]: crate::channel::Message::embeds
#[serde(skip_serializing_if = "Option::is_none")]
pub embeds: Option<Vec<Embed>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub guild_id: Option<Id<GuildMarker>>,
pub id: Id<MessageMarker>,
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
pub kind: Option<MessageType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mention_everyone: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mention_roles: Option<Vec<Id<RoleMarker>>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mentions: Option<Vec<Mention>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pinned: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp: Option<Timestamp>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tts: Option<bool>,
#[serde(transparent)]
pub struct MessageUpdate(pub Message);

impl Deref for MessageUpdate {
type Target = Message;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl DerefMut for MessageUpdate {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

0 comments on commit f7a6c3e

Please sign in to comment.