sdk_base: message events in message queue have content redacted
The MessageQueue holds MessageEventStub<AnyMessageEventContent> so when a redaction event is encountered the redacted event's content can be replaced. The Unsigned field redacted_because is also populated with the redaction event itself with the addition of a room_id Stub -> full event.master
parent
dcc3d6e755
commit
e7c70854ab
|
@ -7,28 +7,42 @@ use std::cmp::Ordering;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::vec::IntoIter;
|
use std::vec::IntoIter;
|
||||||
|
|
||||||
use crate::events::AnyMessageEventStub;
|
use crate::events::{AnyMessageEventContent, AnyMessageEventStub, MessageEventStub};
|
||||||
|
|
||||||
use serde::{de, ser, Serialize};
|
use serde::{de, ser, Serialize};
|
||||||
|
|
||||||
const MESSAGE_QUEUE_CAP: usize = 35;
|
const MESSAGE_QUEUE_CAP: usize = 35;
|
||||||
|
|
||||||
|
pub type SyncMessageEvent = MessageEventStub<AnyMessageEventContent>;
|
||||||
|
|
||||||
/// A queue that holds the 35 most recent messages received from the server.
|
/// A queue that holds the 35 most recent messages received from the server.
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct MessageQueue {
|
pub struct MessageQueue {
|
||||||
msgs: Vec<MessageWrapper>,
|
pub(crate) msgs: Vec<MessageWrapper>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper for `ruma_events::AnyMessageEventStub` that allows implementation of
|
/// A wrapper for `ruma_events::SyncMessageEvent` that allows implementation of
|
||||||
/// Eq, Ord and the Partial versions of the traits.
|
/// Eq, Ord and the Partial versions of the traits.
|
||||||
///
|
///
|
||||||
/// `MessageWrapper` also implements Deref and DerefMut so accessing the events contents
|
/// `MessageWrapper` also implements Deref and DerefMut so accessing the events contents
|
||||||
/// are simplified.
|
/// are simplified.
|
||||||
#[derive(Clone, Debug, Serialize)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
pub struct MessageWrapper(pub AnyMessageEventStub);
|
pub struct MessageWrapper(pub SyncMessageEvent);
|
||||||
|
|
||||||
|
impl MessageWrapper {
|
||||||
|
pub fn clone_into_any_content(event: &AnyMessageEventStub) -> SyncMessageEvent {
|
||||||
|
MessageEventStub {
|
||||||
|
content: event.content().clone(),
|
||||||
|
sender: event.sender().clone(),
|
||||||
|
origin_server_ts: event.origin_server_ts().clone(),
|
||||||
|
event_id: event.event_id().clone(),
|
||||||
|
unsigned: event.unsigned().clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Deref for MessageWrapper {
|
impl Deref for MessageWrapper {
|
||||||
type Target = AnyMessageEventStub;
|
type Target = SyncMessageEvent;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.0
|
||||||
|
@ -43,7 +57,7 @@ impl DerefMut for MessageWrapper {
|
||||||
|
|
||||||
impl PartialEq for MessageWrapper {
|
impl PartialEq for MessageWrapper {
|
||||||
fn eq(&self, other: &MessageWrapper) -> bool {
|
fn eq(&self, other: &MessageWrapper) -> bool {
|
||||||
self.0.event_id() == other.0.event_id()
|
self.0.event_id == other.0.event_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +65,7 @@ impl Eq for MessageWrapper {}
|
||||||
|
|
||||||
impl PartialOrd for MessageWrapper {
|
impl PartialOrd for MessageWrapper {
|
||||||
fn partial_cmp(&self, other: &MessageWrapper) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &MessageWrapper) -> Option<Ordering> {
|
||||||
Some(self.0.origin_server_ts().cmp(&other.0.origin_server_ts()))
|
Some(self.0.origin_server_ts.cmp(&other.0.origin_server_ts))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +82,7 @@ impl PartialEq for MessageQueue {
|
||||||
.msgs
|
.msgs
|
||||||
.iter()
|
.iter()
|
||||||
.zip(other.msgs.iter())
|
.zip(other.msgs.iter())
|
||||||
.all(|(msg_a, msg_b)| msg_a.event_id() == msg_b.event_id())
|
.all(|(msg_a, msg_b)| msg_a.event_id == msg_b.event_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,10 +97,10 @@ impl MessageQueue {
|
||||||
/// Inserts a `MessageEvent` into `MessageQueue`, sorted by by `origin_server_ts`.
|
/// Inserts a `MessageEvent` into `MessageQueue`, sorted by by `origin_server_ts`.
|
||||||
///
|
///
|
||||||
/// Removes the oldest element in the queue if there are more than 10 elements.
|
/// Removes the oldest element in the queue if there are more than 10 elements.
|
||||||
pub fn push(&mut self, msg: AnyMessageEventStub) -> bool {
|
pub fn push(&mut self, msg: SyncMessageEvent) -> bool {
|
||||||
// only push new messages into the queue
|
// only push new messages into the queue
|
||||||
if let Some(latest) = self.msgs.last() {
|
if let Some(latest) = self.msgs.last() {
|
||||||
if msg.origin_server_ts() < latest.origin_server_ts() && self.msgs.len() >= 10 {
|
if msg.origin_server_ts < latest.origin_server_ts && self.msgs.len() >= 10 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +145,7 @@ pub(crate) mod ser_deser {
|
||||||
where
|
where
|
||||||
D: de::Deserializer<'de>,
|
D: de::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let messages: Vec<AnyMessageEventStub> = de::Deserialize::deserialize(deserializer)?;
|
let messages: Vec<SyncMessageEvent> = de::Deserialize::deserialize(deserializer)?;
|
||||||
|
|
||||||
let mut msgs = vec![];
|
let mut msgs = vec![];
|
||||||
for msg in messages {
|
for msg in messages {
|
||||||
|
@ -172,7 +186,7 @@ mod test {
|
||||||
let mut room = Room::new(&id, &user);
|
let mut room = Room::new(&id, &user);
|
||||||
|
|
||||||
let json: &serde_json::Value = &test_json::MESSAGE_TEXT;
|
let json: &serde_json::Value = &test_json::MESSAGE_TEXT;
|
||||||
let msg = serde_json::from_value::<AnyMessageEventStub>(json.clone()).unwrap();
|
let msg = serde_json::from_value::<SyncMessageEvent>(json.clone()).unwrap();
|
||||||
|
|
||||||
let mut msgs = MessageQueue::new();
|
let mut msgs = MessageQueue::new();
|
||||||
msgs.push(msg.clone());
|
msgs.push(msg.clone());
|
||||||
|
@ -218,7 +232,7 @@ mod test {
|
||||||
let mut room = Room::new(&id, &user);
|
let mut room = Room::new(&id, &user);
|
||||||
|
|
||||||
let json: &serde_json::Value = &test_json::MESSAGE_TEXT;
|
let json: &serde_json::Value = &test_json::MESSAGE_TEXT;
|
||||||
let msg = serde_json::from_value::<AnyMessageEventStub>(json.clone()).unwrap();
|
let msg = serde_json::from_value::<SyncMessageEvent>(json.clone()).unwrap();
|
||||||
|
|
||||||
let mut msgs = MessageQueue::new();
|
let mut msgs = MessageQueue::new();
|
||||||
msgs.push(msg.clone());
|
msgs.push(msg.clone());
|
||||||
|
|
|
@ -34,18 +34,34 @@ use crate::events::room::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::events::{
|
use crate::events::{
|
||||||
Algorithm, AnyRoomEventStub, AnyStateEventStub, AnyStrippedStateEventStub, EventType,
|
Algorithm, AnyMessageEventContent, AnyRoomEventStub, AnyStateEventStub,
|
||||||
StateEventStub, StrippedStateEventStub,
|
AnyStrippedStateEventStub, EventJson, EventType, StateEventStub, StrippedStateEventStub,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "messages")]
|
#[cfg(feature = "messages")]
|
||||||
use crate::events::{room::redaction::RedactionEventStub, AnyMessageEventStub};
|
use crate::events::{
|
||||||
|
room::redaction::{RedactionEvent, RedactionEventStub},
|
||||||
|
AnyMessageEventStub,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::identifiers::{RoomAliasId, RoomId, UserId};
|
use crate::identifiers::{RoomAliasId, RoomId, UserId};
|
||||||
|
|
||||||
use crate::js_int::{Int, UInt};
|
use crate::js_int::{Int, UInt};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[cfg(feature = "messages")]
|
||||||
|
fn full_event_from_stub(event: RedactionEventStub, room_id: RoomId) -> RedactionEvent {
|
||||||
|
RedactionEvent {
|
||||||
|
content: event.content,
|
||||||
|
redacts: event.redacts,
|
||||||
|
event_id: event.event_id,
|
||||||
|
unsigned: event.unsigned,
|
||||||
|
sender: event.sender,
|
||||||
|
origin_server_ts: event.origin_server_ts,
|
||||||
|
room_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
||||||
/// `RoomName` allows the calculation of a text room name.
|
/// `RoomName` allows the calculation of a text room name.
|
||||||
pub struct RoomName {
|
pub struct RoomName {
|
||||||
|
@ -618,7 +634,8 @@ impl Room {
|
||||||
#[cfg(feature = "messages")]
|
#[cfg(feature = "messages")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "messages")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "messages")))]
|
||||||
pub fn handle_message(&mut self, event: &AnyMessageEventStub) -> bool {
|
pub fn handle_message(&mut self, event: &AnyMessageEventStub) -> bool {
|
||||||
self.messages.push(event.clone())
|
let message = MessageWrapper::clone_into_any_content(event);
|
||||||
|
self.messages.push(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle a room.redaction event and update the `MessageQueue` if necessary.
|
/// Handle a room.redaction event and update the `MessageQueue` if necessary.
|
||||||
|
@ -630,9 +647,12 @@ impl Room {
|
||||||
if let Some(msg) = self
|
if let Some(msg) = self
|
||||||
.messages
|
.messages
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|msg| &event.redacts == msg.event_id())
|
.find(|msg| event.redacts == msg.event_id)
|
||||||
{
|
{
|
||||||
*msg = MessageWrapper(AnyMessageEventStub::RoomRedaction(event.clone()));
|
msg.content = AnyMessageEventContent::RoomRedaction(event.content.clone());
|
||||||
|
|
||||||
|
let redaction = full_event_from_stub(event.clone(), self.room_id.clone());
|
||||||
|
msg.unsigned.redacted_because = Some(EventJson::from(redaction));
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -1152,6 +1172,51 @@ mod test {
|
||||||
assert_eq!(vec!["example2"], room_names);
|
assert_eq!(vec!["example2"], room_names);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "messages")]
|
||||||
|
#[async_test]
|
||||||
|
async fn message_queue_redaction_event() {
|
||||||
|
let room_id = get_room_id();
|
||||||
|
|
||||||
|
let mut response = sync_response(SyncResponseFile::DefaultWithSummary);
|
||||||
|
|
||||||
|
let session = Session {
|
||||||
|
access_token: "1234".to_owned(),
|
||||||
|
user_id: UserId::try_from("@example:localhost").unwrap(),
|
||||||
|
device_id: "DEVICEID".to_owned(),
|
||||||
|
};
|
||||||
|
let client = BaseClient::new().unwrap();
|
||||||
|
client.restore_login(session).await.unwrap();
|
||||||
|
client.receive_sync_response(&mut response).await.unwrap();
|
||||||
|
|
||||||
|
let json = serde_json::json!({
|
||||||
|
"content": {
|
||||||
|
"reason": "😀"
|
||||||
|
},
|
||||||
|
"event_id": "$151957878228ssqrJ:localhost",
|
||||||
|
"origin_server_ts": 151957878,
|
||||||
|
"sender": "@example:localhost",
|
||||||
|
"type": "m.room.redaction",
|
||||||
|
"redacts": "$152037280074GZeOm:localhost"
|
||||||
|
});
|
||||||
|
let mut event: EventJson<AnyRoomEventStub> = serde_json::from_value(json).unwrap();
|
||||||
|
client
|
||||||
|
.receive_joined_timeline_event(&room_id, &mut event)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
for room in client.joined_rooms().read().await.values() {
|
||||||
|
let queue = &room.read().await.messages;
|
||||||
|
println!("{:?}", queue);
|
||||||
|
if let crate::events::AnyMessageEventContent::RoomRedaction(content) =
|
||||||
|
&queue.msgs[0].content
|
||||||
|
{
|
||||||
|
assert_eq!(content.reason, Some("😀".to_string()));
|
||||||
|
} else {
|
||||||
|
panic!("message event in message queue should be redacted")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_test]
|
#[async_test]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
async fn encryption_info_test() {
|
async fn encryption_info_test() {
|
||||||
|
|
|
@ -9,7 +9,8 @@ pub mod sync;
|
||||||
|
|
||||||
pub use events::{
|
pub use events::{
|
||||||
ALIAS, ALIASES, EVENT_ID, KEYS_QUERY, KEYS_UPLOAD, LOGIN, LOGIN_RESPONSE_ERR, LOGOUT, MEMBER,
|
ALIAS, ALIASES, EVENT_ID, KEYS_QUERY, KEYS_UPLOAD, LOGIN, LOGIN_RESPONSE_ERR, LOGOUT, MEMBER,
|
||||||
MESSAGE_EDIT, MESSAGE_TEXT, NAME, POWER_LEVELS, PRESENCE, PUBLIC_ROOMS, REACTION,
|
MESSAGE_EDIT, MESSAGE_TEXT, NAME, POWER_LEVELS, PRESENCE, PUBLIC_ROOMS, REACTION, REDACTED,
|
||||||
REGISTRATION_RESPONSE_ERR, ROOM_ID, ROOM_MESSAGES, TYPING,
|
REDACTED_INVALID, REDACTED_STATE, REDACTION, REGISTRATION_RESPONSE_ERR, ROOM_ID, ROOM_MESSAGES,
|
||||||
|
TYPING,
|
||||||
};
|
};
|
||||||
pub use sync::{DEFAULT_SYNC_SUMMARY, INVITE_SYNC, LEAVE_SYNC, LEAVE_SYNC_EVENT, MORE_SYNC, SYNC};
|
pub use sync::{DEFAULT_SYNC_SUMMARY, INVITE_SYNC, LEAVE_SYNC, LEAVE_SYNC_EVENT, MORE_SYNC, SYNC};
|
||||||
|
|
Loading…
Reference in New Issue