Skip to content

Commit

Permalink
Add support for editing messages (#196)
Browse files Browse the repository at this point in the history
  • Loading branch information
gferon authored Oct 9, 2023
1 parent e3a6084 commit 6125534
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 57 deletions.
20 changes: 19 additions & 1 deletion presage-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ use presage::libsignal_service::content::Reaction;
use presage::libsignal_service::proto::data_message::Quote;
use presage::libsignal_service::proto::sync_message::Sent;
use presage::libsignal_service::{groups_v2::Group, prelude::ProfileKey};
use presage::prelude::proto::EditMessage;
use presage::prelude::SyncMessage;
use presage::ContentTimestamp;
use presage::{
prelude::{
content::{Content, ContentBody, DataMessage, GroupContextV2},
Expand Down Expand Up @@ -366,6 +368,10 @@ fn print_message<C: Store>(
ContentBody::DataMessage(data_message) => {
format_data_message(&thread, data_message).map(|body| Msg::Received(&thread, body))
}
ContentBody::EditMessage(EditMessage {
data_message: Some(data_message),
..
}) => format_data_message(&thread, data_message).map(|body| Msg::Received(&thread, body)),
ContentBody::SynchronizeMessage(SyncMessage {
sent:
Some(Sent {
Expand All @@ -374,14 +380,26 @@ fn print_message<C: Store>(
}),
..
}) => format_data_message(&thread, data_message).map(|body| Msg::Sent(&thread, body)),
ContentBody::SynchronizeMessage(SyncMessage {
sent:
Some(Sent {
edit_message:
Some(EditMessage {
data_message: Some(data_message),
..
}),
..
}),
..
}) => format_data_message(&thread, data_message).map(|body| Msg::Sent(&thread, body)),
ContentBody::CallMessage(_) => Some(Msg::Received(&thread, "is calling!".into())),
ContentBody::TypingMessage(_) => Some(Msg::Received(&thread, "is typing...".into())),
c => {
log::warn!("unsupported message {c:?}");
None
}
} {
let ts = content.metadata.timestamp;
let ts = content.timestamp();
let (prefix, body) = match msg {
Msg::Received(Thread::Contact(sender), body) => {
let contact = format_contact(sender);
Expand Down
38 changes: 20 additions & 18 deletions presage-store-sled/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,24 @@ use std::{

use async_trait::async_trait;
use log::{debug, error, trace, warn};
use presage::libsignal_service::{
self,
groups_v2::Group,
models::Contact,
prelude::{Content, ProfileKey, Uuid},
protocol::{
Direction, GenericSignedPreKey, IdentityKey, IdentityKeyPair, IdentityKeyStore,
KyberPreKeyId, KyberPreKeyRecord, KyberPreKeyStore, PreKeyId, PreKeyRecord, PreKeyStore,
ProtocolAddress, ProtocolStore, SenderKeyRecord, SenderKeyStore, SessionRecord,
SessionStore, SignalProtocolError, SignedPreKeyId, SignedPreKeyRecord, SignedPreKeyStore,
use presage::{
libsignal_service::{
self,
groups_v2::Group,
models::Contact,
prelude::{Content, ProfileKey, Uuid},
protocol::{
Direction, GenericSignedPreKey, IdentityKey, IdentityKeyPair, IdentityKeyStore,
KyberPreKeyId, KyberPreKeyRecord, KyberPreKeyStore, PreKeyId, PreKeyRecord,
PreKeyStore, ProtocolAddress, ProtocolStore, SenderKeyRecord, SenderKeyStore,
SessionRecord, SessionStore, SignalProtocolError, SignedPreKeyId, SignedPreKeyRecord,
SignedPreKeyStore,
},
push_service::DEFAULT_DEVICE_ID,
session_store::SessionStoreExt,
Profile, ServiceAddress,
},
push_service::DEFAULT_DEVICE_ID,
session_store::SessionStoreExt,
Profile, ServiceAddress,
ContentTimestamp,
};
use prost::Message;
use protobuf::ContentProto;
Expand Down Expand Up @@ -545,13 +549,11 @@ impl Store for SledStore {
}

fn save_message(&mut self, thread: &Thread, message: Content) -> Result<(), SledStoreError> {
log::trace!(
"storing a message with thread: {thread}, timestamp: {}",
message.metadata.timestamp,
);
let ts = message.timestamp();
log::trace!("storing a message with thread: {thread}, timestamp: {ts}",);

let tree = self.messages_thread_tree_name(thread);
let key = message.metadata.timestamp.to_be_bytes();
let key = ts.to_be_bytes();

let proto: ContentProto = message.into();
let value = proto.encode_to_vec();
Expand Down
4 changes: 2 additions & 2 deletions presage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ authors = ["Gabriel Féron <g@leirbag.net>"]
edition = "2021"

[dependencies]
libsignal-service = { git = "https://github.com/whisperfish/libsignal-service-rs", rev = "8305357" }
libsignal-service-hyper = { git = "https://github.com/whisperfish/libsignal-service-rs", rev = "8305357" }
libsignal-service = { git = "https://github.com/whisperfish/libsignal-service-rs", rev = "454d234" }
libsignal-service-hyper = { git = "https://github.com/whisperfish/libsignal-service-rs", rev = "454d234" }

base64 = "0.12"
futures = "0.3"
Expand Down
2 changes: 1 addition & 1 deletion presage/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod store;

pub use errors::Error;
pub use manager::{Confirmation, Linking, Manager, Registered, Registration, RegistrationOptions};
pub use store::{Store, StoreError, Thread};
pub use store::{ContentTimestamp, Store, StoreError, Thread};

#[deprecated(note = "Please help use improve the prelude module instead")]
pub use libsignal_service;
Expand Down
102 changes: 75 additions & 27 deletions presage/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use rand::{
use serde::{Deserialize, Serialize};
use url::Url;

use libsignal_service::proto::EditMessage;
use libsignal_service::push_service::{RegistrationMethod, VerificationTransport};
use libsignal_service::{
attachment_cipher::decrypt_in_place,
Expand Down Expand Up @@ -1043,8 +1044,7 @@ impl<C: Store> Manager<C, Registered> {
body: content_body,
};

let thread = Thread::Contact(recipient.uuid);
save_message_with_thread(&mut self.config_store, content, thread)?;
save_message(&mut self.config_store, content)?;

Ok(())
}
Expand Down Expand Up @@ -1346,11 +1346,10 @@ async fn upsert_group<C: Store>(
Ok(config_store.group(master_key_bytes.try_into()?)?)
}

fn save_message_with_thread<C: Store>(
config_store: &mut C,
message: Content,
thread: Thread,
) -> Result<(), Error<C::Error>> {
fn save_message<C: Store>(config_store: &mut C, message: Content) -> Result<(), Error<C::Error>> {
// derive the thread from the message type
let thread = Thread::try_from(&message)?;

// update recipient profile keys
if let ContentBody::DataMessage(DataMessage {
profile_key: Some(profile_key_bytes),
Expand All @@ -1366,15 +1365,17 @@ fn save_message_with_thread<C: Store>(
}

// only save DataMessage and SynchronizeMessage (sent)
match &message.body {
ContentBody::NullMessage(_) => config_store.save_message(&thread, message)?,
ContentBody::DataMessage(d)
let message = match message.body {
ContentBody::NullMessage(_) => Some(message),
ContentBody::DataMessage(ref data_message)
| ContentBody::SynchronizeMessage(SyncMessage {
sent: Some(sync_message::Sent {
message: Some(d), ..
}),
sent:
Some(sync_message::Sent {
message: Some(ref data_message),
..
}),
..
}) => match d {
}) => match data_message {
DataMessage {
delete:
Some(Delete {
Expand All @@ -1388,32 +1389,79 @@ fn save_message_with_thread<C: Store>(
existing_msg.body = NullMessage::default().into();
config_store.save_message(&thread, existing_msg)?;
debug!("message in thread {thread} @ {ts} deleted");
None
} else {
warn!("could not find message to delete in thread {thread} @ {ts}");
None
}
}
_ => config_store.save_message(&thread, message)?,
_ => Some(message),
},
ContentBody::EditMessage(EditMessage {
target_sent_timestamp: Some(ts),
data_message: Some(data_message),
})
| ContentBody::SynchronizeMessage(SyncMessage {
sent:
Some(sync_message::Sent {
edit_message:
Some(EditMessage {
target_sent_timestamp: Some(ts),
data_message: Some(data_message),
}),
..
}),
..
}) => {
if let Some(mut existing_msg) = config_store.message(&thread, ts)? {
existing_msg.metadata = message.metadata;
existing_msg.body = ContentBody::DataMessage(data_message);
// TODO: find a way to mark the message as edited (so that it's visible in a client)
trace!("message in thread {thread} @ {ts} edited");
Some(existing_msg)
} else {
warn!("could not find edited message {thread} @ {ts}");
None
}
}
ContentBody::CallMessage(_)
| ContentBody::SynchronizeMessage(SyncMessage {
call_event: Some(_),
..
}) => config_store.save_message(&thread, message)?,
ContentBody::SynchronizeMessage(_) => {
debug!("skipping saving sync message without interesting fields")
}) => Some(message),
ContentBody::SynchronizeMessage(s) => {
debug!("skipping saving sync message without interesting fields: {s:?}");
None
}
ContentBody::ReceiptMessage(_) => debug!("skipping saving receipt message"),
ContentBody::TypingMessage(_) => debug!("skipping saving typing message"),
ContentBody::StoryMessage(_) => debug!("skipping story message"),
ContentBody::PniSignatureMessage(_) => todo!(),
ContentBody::ReceiptMessage(_) => {
debug!("skipping saving receipt message");
None
}
ContentBody::TypingMessage(_) => {
debug!("skipping saving typing message");
None
}
ContentBody::StoryMessage(_) => {
debug!("skipping story message");
None
}
ContentBody::PniSignatureMessage(_) => {
debug!("skipping PNI signature message");
None
}
ContentBody::EditMessage(_) => {
debug!("invalid edited");
None
}
};

if let Some(message) = message {
config_store.save_message(&thread, message)?;
}

Ok(())
}

fn save_message<C: Store>(config_store: &mut C, message: Content) -> Result<(), Error<C::Error>> {
let thread = Thread::try_from(&message)?;
save_message_with_thread(config_store, message, thread)
}

#[cfg(test)]
mod tests {
use libsignal_service::prelude::ProfileKey;
Expand Down
Loading

0 comments on commit 6125534

Please sign in to comment.