From 6ce1859edef5f235d0b1f85dd99703e8874175a6 Mon Sep 17 00:00:00 2001 From: boxdot Date: Tue, 2 May 2023 18:06:04 +0200 Subject: [PATCH 1/3] feat: add ephemeral status to sent messages on errors Messages that could not be sent are marked as such by adding a read field below showing the error message. The status is ephemeral and is not stored. Resending of message is not implemented. Also upgrade presage to incl. the fix which does not reuse websocket connection for sending. This should fix sending messages. --- Cargo.lock | 4 +- Cargo.toml | 4 +- src/app.rs | 132 ++++++++++++++++++++++++++++++----------- src/data.rs | 4 ++ src/event.rs | 9 +++ src/lib.rs | 1 + src/main.rs | 21 +++++-- src/signal/impl.rs | 82 ++++++++++++++----------- src/signal/manager.rs | 3 +- src/signal/test.rs | 9 ++- src/storage/json.rs | 3 + src/ui/draw.rs | 13 +++- xtask/src/changelog.rs | 4 +- 13 files changed, 202 insertions(+), 87 deletions(-) create mode 100644 src/event.rs diff --git a/Cargo.lock b/Cargo.lock index a26a800..0c47672 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2573,7 +2573,7 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "presage" version = "0.6.0-dev" -source = "git+https://github.com/whisperfish/presage?rev=0.5.1#c9198cb15a3a4cf0aea12a08272a230451ac12f8" +source = "git+https://github.com/whisperfish/presage?rev=7823d28#7823d28e89606cc44c9042df30c6203750e925ac" dependencies = [ "base64 0.12.3", "futures", @@ -2592,7 +2592,7 @@ dependencies = [ [[package]] name = "presage-store-sled" version = "0.6.0-dev" -source = "git+https://github.com/whisperfish/presage?rev=0.5.1#c9198cb15a3a4cf0aea12a08272a230451ac12f8" +source = "git+https://github.com/whisperfish/presage?rev=7823d28#7823d28e89606cc44c9042df30c6203750e925ac" dependencies = [ "async-trait", "base64 0.12.3", diff --git a/Cargo.toml b/Cargo.toml index fb68b4f..e51a3ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,8 +28,8 @@ debug = true dev = ["prost", "base64"] [dependencies] -presage = { git = "https://github.com/whisperfish/presage", rev = "0.5.1" } -presage-store-sled = { git = "https://github.com/whisperfish/presage", rev = "0.5.1" } +presage = { git = "https://github.com/whisperfish/presage", rev = "7823d28" } +presage-store-sled = { git = "https://github.com/whisperfish/presage", rev = "7823d28" } anyhow = "1.0.66" async-trait = "0.1.58" diff --git a/src/app.rs b/src/app.rs index 16509fb..8d5de50 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,6 +1,7 @@ use crate::channels::SelectChannel; use crate::config::Config; use crate::data::{BodyRange, Channel, ChannelId, Message, TypingAction, TypingSet}; +use crate::event::Event; use crate::input::Input; use crate::receipt::{Receipt, ReceiptEvent, ReceiptHandler}; use crate::signal::{ @@ -28,6 +29,7 @@ use presage::prelude::{ AttachmentSpec, Content, ServiceAddress, }; use regex_automata::Regex; +use tokio::sync::mpsc; use tracing::{error, info, warn}; use uuid::Uuid; @@ -59,6 +61,7 @@ pub struct App { pub is_multiline_input: bool, pub(crate) select_channel: SelectChannel, clipboard: Option, + event_tx: mpsc::UnboundedSender, } impl App { @@ -66,7 +69,7 @@ impl App { config: Config, signal_manager: Box, storage: Box, - ) -> anyhow::Result { + ) -> anyhow::Result<(Self, mpsc::UnboundedReceiver)> { let user_id = signal_manager.user_id(); // build index of channels and messages for using them as lists content @@ -96,7 +99,9 @@ impl App { .map_err(|error| warn!(%error, "clipboard disabled")) .ok(); - Ok(Self { + let (event_tx, event_rx) = mpsc::unbounded_channel(); + + let app = Self { config, signal_manager, user_id, @@ -112,7 +117,9 @@ impl App { is_multiline_input: false, select_channel: Default::default(), clipboard, - }) + event_tx, + }; + Ok((app, event_rx)) } pub fn get_input(&mut self) -> &mut Input { @@ -183,7 +190,7 @@ impl App { } } - pub fn on_key(&mut self, key: KeyEvent) -> anyhow::Result<()> { + pub async fn on_key(&mut self, key: KeyEvent) -> anyhow::Result<()> { match key.code { KeyCode::Char('\r') => self.get_input().put_char('\n'), KeyCode::Enter => { @@ -194,7 +201,7 @@ impl App { self.get_input().new_line(); } else if !self.input.data.is_empty() { if let Some(idx) = self.channels.state.selected() { - self.send_input(idx)?; + self.send_input(idx); } } else { // input is empty @@ -349,7 +356,7 @@ impl App { self.get_input().take() } - fn send_input(&mut self, channel_idx: usize) -> anyhow::Result<()> { + fn send_input(&mut self, channel_idx: usize) { let input = self.take_input(); let (input, attachments) = self.extract_attachments(&input); let channel_id = self.channels.items[channel_idx]; @@ -358,10 +365,21 @@ impl App { .channel(channel_id) .expect("non-existent channel"); let quote = self.selected_message(); - let sent_message = + let (sent_message, response) = self.signal_manager .send_text(&channel, input, quote.as_deref(), attachments); + let message_id = MessageId::new(channel_id, sent_message.arrived_at); + let tx = self.event_tx.clone(); + tokio::spawn(async move { + if let Ok(result) = response.await { + tx.send(Event::SentTextResult { message_id, result }) + .expect("event sender gone"); + } else { + error!(?message_id, "response for sending message was lost"); + } + }); + let sent_message = self.storage.store_message(channel_id, sent_message); self.messages .get_mut(&channel_id) @@ -375,7 +393,6 @@ impl App { self.reset_message_selection(); } self.bubble_up_channel(channel_idx); - Ok(()) } pub fn select_previous_channel(&mut self) { @@ -1322,6 +1339,23 @@ impl App { } } } + + pub fn handle_event(&mut self, event: Event) -> anyhow::Result<()> { + match event { + Event::SentTextResult { message_id, result } => { + if let Err(error) = result { + let mut message = self + .storage + .message(message_id) + .context("no message")? + .into_owned(); + message.send_failed = Some(error.to_string()); + self.storage.store_message(message_id.channel_id, message); + } + } + } + Ok(()) + } } /// Returns an emoji string if `s` is an emoji or if `s` is a GitHub emoji shortcode. @@ -1372,7 +1406,11 @@ mod tests { use std::cell::RefCell; use std::rc::Rc; - fn test_app() -> (App, Rc>>) { + fn test_app() -> ( + App, + mpsc::UnboundedReceiver, + Rc>>, + ) { let signal_manager = SignalManagerMock::new(); let sent_messages = signal_manager.sent_messages.clone(); @@ -1402,6 +1440,7 @@ mod tests { reactions: Default::default(), receipt: Default::default(), body_ranges: Default::default(), + send_failed: Default::default(), }, ); @@ -1409,7 +1448,7 @@ mod tests { name: "Tyler Durden".to_string(), phone_number: "+0000000000".to_string(), }; - let mut app = App::try_new( + let (mut app, events) = App::try_new( Config::with_user(user), Box::new(signal_manager), Box::new(storage), @@ -1417,64 +1456,85 @@ mod tests { .unwrap(); app.channels.state.select(Some(0)); - (app, sent_messages) + (app, events, sent_messages) } - #[test] - fn test_send_input() { - let (mut app, sent_messages) = test_app(); + #[tokio::test] + async fn test_send_input() { + let (mut app, mut events, sent_messages) = test_app(); let input = "Hello, World!"; for c in input.chars() { app.get_input().put_char(c); } - app.send_input(0).unwrap(); + app.send_input(0); - let sent = sent_messages.borrow(); - assert_eq!(sent.len(), 1); - assert_eq!(sent[0].message.as_ref().unwrap(), input); + assert_eq!(sent_messages.borrow().len(), 1); + let msg = sent_messages.borrow()[0].clone(); + assert_eq!(msg.message.as_ref().unwrap(), input); let channel_id = app.channels.items[0]; let channel = app.storage.channel(channel_id).unwrap(); assert_eq!(channel.unread_messages, 0); assert_eq!(app.get_input().data, ""); + + match events.recv().await.unwrap() { + Event::SentTextResult { message_id, result } => { + assert_eq!(message_id.arrived_at, msg.arrived_at); + assert!(result.is_ok()); + } + } } - #[test] - fn test_send_input_with_emoji() { - let (mut app, sent_messages) = test_app(); + #[tokio::test] + async fn test_send_input_with_emoji() { + let (mut app, mut events, sent_messages) = test_app(); let input = "👻"; for c in input.chars() { app.get_input().put_char(c); } - app.send_input(0).unwrap(); + app.send_input(0); - let sent = sent_messages.borrow(); - assert_eq!(sent.len(), 1); - assert_eq!(sent[0].message.as_ref().unwrap(), input); + assert_eq!(sent_messages.borrow().len(), 1); + let msg = sent_messages.borrow()[0].clone(); + assert_eq!(msg.message.as_ref().unwrap(), input); assert_eq!(app.get_input().data, ""); + + match events.recv().await.unwrap() { + Event::SentTextResult { message_id, result } => { + assert_eq!(message_id.arrived_at, msg.arrived_at); + assert!(result.is_ok()); + } + } } - #[test] - fn test_send_input_with_emoji_codepoint() { - let (mut app, sent_messages) = test_app(); + #[tokio::test] + async fn test_send_input_with_emoji_codepoint() { + let (mut app, mut events, sent_messages) = test_app(); let input = ":thumbsup:"; for c in input.chars() { app.get_input().put_char(c); } - app.send_input(0).unwrap(); + app.send_input(0); - let sent = sent_messages.borrow(); - assert_eq!(sent.len(), 1); - assert_eq!(sent[0].message.as_ref().unwrap(), "👍"); + assert_eq!(sent_messages.borrow().len(), 1); + let msg = sent_messages.borrow()[0].clone(); + assert_eq!(msg.message.as_ref().unwrap(), "👍"); + + match events.recv().await.unwrap() { + Event::SentTextResult { message_id, result } => { + assert_eq!(message_id.arrived_at, msg.arrived_at); + assert!(result.is_ok()); + } + } } #[test] fn test_add_reaction_with_emoji() { - let (mut app, _sent_messages) = test_app(); + let (mut app, _events, _sent_messages) = test_app(); let channel_id = app.channels.items[0]; app.messages @@ -1498,7 +1558,7 @@ mod tests { #[test] fn test_add_reaction_with_emoji_codepoint() { - let (mut app, _sent_messages) = test_app(); + let (mut app, _events, _sent_messages) = test_app(); let channel_id = app.channels.items[0]; app.messages @@ -1524,7 +1584,7 @@ mod tests { #[test] fn test_remove_reaction() { - let (mut app, _sent_messages) = test_app(); + let (mut app, _events, _sent_messages) = test_app(); let channel_id = app.channels.items[0]; app.messages @@ -1553,7 +1613,7 @@ mod tests { #[test] fn test_add_invalid_reaction() { - let (mut app, _sent_messages) = test_app(); + let (mut app, _events, _sent_messages) = test_app(); let channel_id = app.channels.items[0]; app.messages .get_mut(&channel_id) diff --git a/src/data.rs b/src/data.rs index 6dd397f..00c6271 100644 --- a/src/data.rs +++ b/src/data.rs @@ -130,6 +130,8 @@ pub struct Message { pub receipt: Receipt, #[serde(default)] pub(crate) body_ranges: Vec, + #[serde(skip)] + pub(crate) send_failed: Option, } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] @@ -236,6 +238,7 @@ impl Message { reactions: Default::default(), receipt: Receipt::Sent, body_ranges: body_ranges.into_iter().collect(), + send_failed: Default::default(), } } @@ -253,6 +256,7 @@ impl Message { .into_iter() .filter_map(BodyRange::from_proto) .collect(), + send_failed: Default::default(), }) } diff --git a/src/event.rs b/src/event.rs new file mode 100644 index 0000000..ea339df --- /dev/null +++ b/src/event.rs @@ -0,0 +1,9 @@ +use crate::storage::MessageId; + +#[derive(Debug)] +pub enum Event { + SentTextResult { + message_id: MessageId, + result: anyhow::Result<()>, + }, +} diff --git a/src/lib.rs b/src/lib.rs index d85af2b..0cedc43 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ pub mod cursor; pub mod data; #[cfg(feature = "dev")] pub mod dev; +pub mod event; pub mod input; pub mod receipt; pub mod shortcuts; diff --git a/src/main.rs b/src/main.rs index c4d6599..1269218 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,7 @@ use crossterm::{ }; use gurk::{config, signal, ui}; use presage::prelude::Content; +use tokio::select; use tokio_stream::StreamExt; use tracing::{error, info, metadata::LevelFilter}; use tui::{backend::CrosstermBackend, Terminal}; @@ -91,13 +92,15 @@ pub enum Event { Quit(Option), ContactSynced(DateTime), Tick, + AppEvent(gurk::event::Event), } async fn run_single_threaded(relink: bool) -> anyhow::Result<()> { let (mut signal_manager, config) = signal::ensure_linked_device(relink).await?; let storage = JsonStorage::new(&config.data_path, config::fallback_data_path().as_deref())?; - let mut app = App::try_new(config, signal_manager.clone_boxed(), Box::new(storage))?; + let (mut app, mut app_events) = + App::try_new(config, signal_manager.clone_boxed(), Box::new(storage))?; // sync task can be only spawned after we start to listen to message, because it relies on // message sender to be running @@ -180,7 +183,7 @@ async fn run_single_threaded(relink: bool) -> anyhow::Result<()> { .await .expect("logic error: events channel closed") } - info!("messages channel disconnected. trying to reconnect.") + error!("messages channel disconnected. trying to reconnect.") } }); @@ -228,7 +231,12 @@ async fn run_single_threaded(relink: bool) -> anyhow::Result<()> { last_render_at = Instant::now(); } - match rx.recv().await { + let event = select! { + v = rx.recv() => v, + v = app_events.recv() => v.map(Event::AppEvent), + }; + + match event { Some(Event::Tick) => { app.step_receipts(); } @@ -357,7 +365,7 @@ async fn run_single_threaded(relink: bool) -> anyhow::Result<()> { KeyCode::Char('k') if event.modifiers.contains(KeyModifiers::CONTROL) => { app.get_input().on_delete_suffix(); } - _ => app.on_key(event)?, + _ => app.on_key(event).await?, }, Some(Event::Message(content)) => { if let Err(e) = app.on_message(content).await { @@ -379,6 +387,11 @@ async fn run_single_threaded(relink: bool) -> anyhow::Result<()> { app.storage.store_metadata(metadata); info!(%at, "synced contacts"); } + Some(Event::AppEvent(event)) => { + if let Err(error) = app.handle_event(event) { + error!(%error, "failed to handle app event"); + } + } None => { break; } diff --git a/src/signal/impl.rs b/src/signal/impl.rs index 81b095b..55c1fb2 100644 --- a/src/signal/impl.rs +++ b/src/signal/impl.rs @@ -15,6 +15,7 @@ use presage::prelude::{ }; use presage::Registered; use presage_store_sled::SledStore; +use tokio::sync::oneshot; use tokio_stream::Stream; use tracing::{error, warn}; use uuid::Uuid; @@ -110,7 +111,7 @@ impl SignalManager for PresageManager { }) } - fn send_receipt(&self, _sender_uuid: Uuid, timestamps: Vec, receipt: Receipt) { + fn send_receipt(&self, sender_uuid: Uuid, timestamps: Vec, receipt: Receipt) { let now_timestamp = utc_now_timestamp_msec(); let data_message = ReceiptMessage { r#type: Some(receipt.to_i32()), @@ -120,11 +121,8 @@ impl SignalManager for PresageManager { let mut manager = self.manager.clone(); tokio::task::spawn_local(async move { let body = ContentBody::ReceiptMessage(data_message); - if let Err(e) = manager - .send_message(_sender_uuid, body, now_timestamp) - .await - { - error!("Failed to send message to {}: {}", _sender_uuid, e); + if let Err(error) = manager.send_message(sender_uuid, body, now_timestamp).await { + error!(%error, %sender_uuid, "failed to send receipt"); } }); } @@ -135,7 +133,7 @@ impl SignalManager for PresageManager { text: String, quote_message: Option<&Message>, attachments: Vec<(AttachmentSpec, Vec)>, - ) -> Message { + ) -> (Message, oneshot::Receiver>) { let mut message: String = self.emoji_replacer.replace_all(&text).into_owned(); let has_attachments = !attachments.is_empty(); @@ -157,17 +155,25 @@ impl SignalManager for PresageManager { ..Default::default() }; + let (response_tx, response) = oneshot::channel(); match channel.id { ChannelId::User(uuid) => { let mut manager = self.manager.clone(); tokio::task::spawn_local(async move { - upload_attachments(&manager, attachments, &mut data_message).await; - + if let Err(error) = + upload_attachments(&manager, attachments, &mut data_message).await + { + error!(%error, "failed to upload attachments"); + let _ = response_tx.send(Err(error)); + return; + } let body = ContentBody::DataMessage(data_message); - if let Err(e) = manager.send_message(uuid, body, timestamp).await { - // TODO: Proper error handling - error!("Failed to send message to {}: {}", uuid, e); + if let Err(error) = manager.send_message(uuid, body, timestamp).await { + error!(dest =% uuid, %error, "failed to send message"); + let _ = response_tx.send(Err(error.into())); + return; } + let _ = response_tx.send(Ok(())); }); } ChannelId::Group(_) => { @@ -182,15 +188,22 @@ impl SignalManager for PresageManager { }); tokio::task::spawn_local(async move { - upload_attachments(&manager, attachments, &mut data_message).await; - - if let Err(e) = manager + if let Err(error) = + upload_attachments(&manager, attachments, &mut data_message).await + { + error!(%error, "failed to upload attachments"); + let _ = response_tx.send(Err(error)); + return; + } + if let Err(error) = manager .send_message_to_group(&master_key_bytes, data_message, timestamp) .await { - // TODO: Proper error handling - error!("Failed to send group message: {}", e); + error!(%error, "failed to send group message"); + let _ = response_tx.send(Err(error.into())); + return; } + let _ = response_tx.send(Ok(())); }); } else { error!("cannot send to broken channel without group data"); @@ -203,7 +216,7 @@ impl SignalManager for PresageManager { message = "".to_string(); } - Message { + let message = Message { from_id: self.user_id(), message: Some(message), arrived_at: timestamp, @@ -212,7 +225,9 @@ impl SignalManager for PresageManager { reactions: Default::default(), receipt: Receipt::Sent, body_ranges: Default::default(), - } + send_failed: Default::default(), + }; + (message, response) } fn send_reaction(&self, channel: &Channel, message: &Message, emoji: String, remove: bool) { @@ -302,21 +317,16 @@ async fn upload_attachments( manager: &presage::Manager, attachments: Vec<(AttachmentSpec, Vec)>, data_message: &mut DataMessage, -) { - match manager.upload_attachments(attachments).await { - Ok(attachment_pointers) => { - data_message.attachments = attachment_pointers - .into_iter() - .filter_map(|res| { - if let Err(e) = res.as_ref() { - error!("failed to upload attachment: {}", e); - } - res.ok() - }) - .collect(); - } - Err(e) => { - error!("failed to upload attachments: {}", e); - } - } +) -> anyhow::Result<()> { + let attachment_pointers = manager.upload_attachments(attachments).await?; + data_message.attachments = attachment_pointers + .into_iter() + .filter_map(|res| { + if let Err(e) = res.as_ref() { + error!("failed to upload attachment: {}", e); + } + res.ok() + }) + .collect(); + Ok(()) } diff --git a/src/signal/manager.rs b/src/signal/manager.rs index 41c6183..07d45f7 100644 --- a/src/signal/manager.rs +++ b/src/signal/manager.rs @@ -7,6 +7,7 @@ use async_trait::async_trait; use presage::prelude::proto::AttachmentPointer; use presage::prelude::{AttachmentSpec, Contact, Content}; use serde::{Deserialize, Serialize}; +use tokio::sync::oneshot; use tokio_stream::Stream; use uuid::Uuid; @@ -40,7 +41,7 @@ pub trait SignalManager { text: String, quote_message: Option<&Message>, attachments: Vec<(AttachmentSpec, Vec)>, - ) -> Message; + ) -> (Message, oneshot::Receiver>); fn send_reaction(&self, channel: &Channel, message: &Message, emoji: String, remove: bool); diff --git a/src/signal/test.rs b/src/signal/test.rs index d125580..6bb7f0e 100644 --- a/src/signal/test.rs +++ b/src/signal/test.rs @@ -7,6 +7,7 @@ use presage::libsignal_service::prelude::AttachmentIdentifier; use presage::prelude::proto::data_message::Quote; use presage::prelude::proto::AttachmentPointer; use presage::prelude::{AttachmentSpec, Contact, Content}; +use tokio::sync::oneshot; use tokio_stream::Stream; use uuid::Uuid; @@ -84,7 +85,7 @@ impl SignalManager for SignalManagerMock { text: String, quote_message: Option<&Message>, _attachments: Vec<(AttachmentSpec, Vec)>, - ) -> Message { + ) -> (Message, oneshot::Receiver>) { let message: String = self.emoji_replacer.replace_all(&text).into_owned(); let timestamp = utc_now_timestamp_msec(); let quote = quote_message.map(|message| Quote { @@ -101,12 +102,14 @@ impl SignalManager for SignalManagerMock { quote: quote_message, attachments: Default::default(), reactions: Default::default(), - // TODO make sure the message sending procedure did not fail receipt: Receipt::Sent, body_ranges: Default::default(), + send_failed: Default::default(), }; self.sent_messages.borrow_mut().push(message.clone()); - message + let (tx, rx) = oneshot::channel(); + let _ = tx.send(Ok(())); + (message, rx) } fn send_reaction(&self, _channel: &Channel, _message: &Message, _emoji: String, _remove: bool) { diff --git a/src/storage/json.rs b/src/storage/json.rs index f8ea91b..3d6b073 100644 --- a/src/storage/json.rs +++ b/src/storage/json.rs @@ -334,6 +334,7 @@ mod tests { reactions: Default::default(), receipt: Default::default(), body_ranges: Default::default(), + send_failed: Default::default(), }], unread_messages: 1, typing: Some(TypingSet::SingleTyping(false)), @@ -351,6 +352,7 @@ mod tests { reactions: Default::default(), receipt: Default::default(), body_ranges: Default::default(), + send_failed: Default::default(), }], unread_messages: 2, typing: Some(TypingSet::GroupTyping(Default::default())), @@ -499,6 +501,7 @@ mod tests { reactions: Default::default(), receipt: Default::default(), body_ranges: Default::default(), + send_failed: Default::default(), }, ); diff --git a/src/ui/draw.rs b/src/ui/draw.rs index 76730e0..ad3dd29 100644 --- a/src/ui/draw.rs +++ b/src/ui/draw.rs @@ -530,12 +530,22 @@ fn display_message( Span::from(line.strip_prefix(prefix).unwrap().to_string()), ] } else { - vec![Span::from(line.to_string())] + vec![Span::from(line.into_owned())] }; Spans::from(res) }), ); + if let Some(reason) = msg.send_failed.as_deref() { + let error = format!("[Could no send: {reason}]"); + let error_style = Style::default().fg(Color::Red); + spans.extend( + textwrap::wrap(&error, &wrap_opts) + .into_iter() + .map(|line| Span::styled(line.into_owned(), error_style).into()), + ); + } + if spans.len() > height { // span is too big to be shown fully spans.resize(height - 1, Spans::from("")); @@ -762,6 +772,7 @@ mod tests { reactions: Default::default(), receipt: Receipt::Sent, body_ranges: Default::default(), + send_failed: Default::default(), } } diff --git a/xtask/src/changelog.rs b/xtask/src/changelog.rs index dd4d6f6..e3d6bec 100644 --- a/xtask/src/changelog.rs +++ b/xtask/src/changelog.rs @@ -26,7 +26,7 @@ fn get_version() -> Result { .map_err(|_| anyhow!("missing GITHUB_REF; not running in GitHub actions?"))?; github_ref .strip_prefix("refs/tags/v") - .map(|s| Version::parse(s)) + .map(Version::parse) .transpose()? .ok_or_else(|| { anyhow!( @@ -37,7 +37,7 @@ fn get_version() -> Result { } fn extract_section(changelog: &str, version: Version) -> Result<&str> { - let parser = Parser::new(&changelog); + let parser = Parser::new(changelog); let h2 = parser.into_offset_iter().filter_map(|(event, range)| { if let Event::Start(Tag::Heading(HeadingLevel::H2, _, _)) = event { Some(range) From d851e33a1754564c5236d38bb3b026ee4e332679 Mon Sep 17 00:00:00 2001 From: boxdot Date: Tue, 2 May 2023 18:26:09 +0200 Subject: [PATCH 2/3] Update enumflags2 --- Cargo.lock | 83 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c47672..cd78dbb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -214,7 +214,7 @@ checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -231,7 +231,7 @@ checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -542,7 +542,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -859,7 +859,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn", + "syn 1.0.103", ] [[package]] @@ -876,7 +876,7 @@ checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -887,7 +887,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -898,7 +898,7 @@ checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -970,7 +970,7 @@ checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -1005,9 +1005,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "enumflags2" -version = "0.7.5" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb" +checksum = "c041f5090df68b32bcd905365fd51769c8b9d553fe87fde0b683534f10c01bd2" dependencies = [ "enumflags2_derive", "serde", @@ -1015,13 +1015,13 @@ dependencies = [ [[package]] name = "enumflags2_derive" -version = "0.7.4" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" +checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] @@ -1225,7 +1225,7 @@ checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -2171,7 +2171,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -2418,7 +2418,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -2629,7 +2629,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.103", "version_check", ] @@ -2652,9 +2652,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] @@ -2731,7 +2731,7 @@ dependencies = [ "itertools 0.10.5", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -2744,7 +2744,7 @@ dependencies = [ "itertools 0.10.5", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -2835,14 +2835,14 @@ checksum = "b22a693222d716a9587786f37ac3f6b4faedb5b80c23914e7303ff5a1d8016e9" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -3174,7 +3174,7 @@ checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -3196,7 +3196,7 @@ checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -3400,7 +3400,7 @@ dependencies = [ "heck 0.3.3", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -3420,6 +3420,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "synstructure" version = "0.12.6" @@ -3428,7 +3439,7 @@ checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", "unicode-xid", ] @@ -3514,7 +3525,7 @@ checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -3625,7 +3636,7 @@ checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -3710,7 +3721,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -3992,7 +4003,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.103", "wasm-bindgen-shared", ] @@ -4014,7 +4025,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4492,7 +4503,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn", + "syn 1.0.103", ] [[package]] @@ -4523,7 +4534,7 @@ checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", "synstructure", ] @@ -4567,5 +4578,5 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] From 39cd3796bd30c3b9ed8e12a807574a163a33abf5 Mon Sep 17 00:00:00 2001 From: boxdot Date: Mon, 8 May 2023 10:45:39 +0200 Subject: [PATCH 3/3] Update to presage 0.5.2 to include group sending fixes --- Cargo.lock | 12 ++++++------ Cargo.toml | 4 ++-- src/signal/impl.rs | 2 +- src/signal/mod.rs | 2 +- src/util.rs | 3 ++- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd78dbb..48ace9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -458,9 +458,9 @@ checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" [[package]] name = "chrono" -version = "0.4.22" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" dependencies = [ "iana-time-zone", "num-integer", @@ -1787,7 +1787,7 @@ dependencies = [ [[package]] name = "libsignal-service" version = "0.1.0" -source = "git+https://github.com/whisperfish/libsignal-service-rs?rev=f11b2d1#f11b2d1683925ff52b2cfcd86a350405379b0336" +source = "git+https://github.com/whisperfish/libsignal-service-rs?rev=c2f70ef#c2f70efd88bbebc9b646690a8449c451af619f2c" dependencies = [ "aes", "aes-gcm", @@ -1820,7 +1820,7 @@ dependencies = [ [[package]] name = "libsignal-service-hyper" version = "0.1.0" -source = "git+https://github.com/whisperfish/libsignal-service-rs?rev=f11b2d1#f11b2d1683925ff52b2cfcd86a350405379b0336" +source = "git+https://github.com/whisperfish/libsignal-service-rs?rev=c2f70ef#c2f70efd88bbebc9b646690a8449c451af619f2c" dependencies = [ "async-trait", "async-tungstenite", @@ -2573,7 +2573,7 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "presage" version = "0.6.0-dev" -source = "git+https://github.com/whisperfish/presage?rev=7823d28#7823d28e89606cc44c9042df30c6203750e925ac" +source = "git+https://github.com/whisperfish/presage?rev=0.5.2#673d30686c8da8df6f45d2e9cf9d2d5eec2651c9" dependencies = [ "base64 0.12.3", "futures", @@ -2592,7 +2592,7 @@ dependencies = [ [[package]] name = "presage-store-sled" version = "0.6.0-dev" -source = "git+https://github.com/whisperfish/presage?rev=7823d28#7823d28e89606cc44c9042df30c6203750e925ac" +source = "git+https://github.com/whisperfish/presage?rev=0.5.2#673d30686c8da8df6f45d2e9cf9d2d5eec2651c9" dependencies = [ "async-trait", "base64 0.12.3", diff --git a/Cargo.toml b/Cargo.toml index e51a3ad..57094cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,8 +28,8 @@ debug = true dev = ["prost", "base64"] [dependencies] -presage = { git = "https://github.com/whisperfish/presage", rev = "7823d28" } -presage-store-sled = { git = "https://github.com/whisperfish/presage", rev = "7823d28" } +presage = { git = "https://github.com/whisperfish/presage", rev = "0.5.2" } +presage-store-sled = { git = "https://github.com/whisperfish/presage", rev = "0.5.2" } anyhow = "1.0.66" async-trait = "0.1.58" diff --git a/src/signal/impl.rs b/src/signal/impl.rs index 55c1fb2..f40a625 100644 --- a/src/signal/impl.rs +++ b/src/signal/impl.rs @@ -47,7 +47,7 @@ impl SignalManager for PresageManager { } fn user_id(&self) -> Uuid { - self.manager.uuid() + self.manager.state().service_ids.aci } async fn resolve_group( diff --git a/src/signal/mod.rs b/src/signal/mod.rs index 8fb4e2f..4490ec1 100644 --- a/src/signal/mod.rs +++ b/src/signal/mod.rs @@ -40,7 +40,7 @@ pub async fn ensure_linked_device( if !relink { if let Some(config) = config.clone() { - if let Ok(manager) = presage::Manager::load_registered(store.clone()) { + if let Ok(manager) = presage::Manager::load_registered(store.clone()).await { // done loading manager from store return Ok((Box::new(PresageManager::new(manager)), config)); } diff --git a/src/util.rs b/src/util.rs index 98339e4..ae6233b 100644 --- a/src/util.rs +++ b/src/util.rs @@ -94,7 +94,8 @@ impl StatefulList { } pub fn utc_timestamp_msec_to_local(timestamp: u64) -> DateTime { - let dt = NaiveDateTime::from_timestamp(timestamp as i64 / 1000, (timestamp % 1000) as u32); + let dt = NaiveDateTime::from_timestamp_opt(timestamp as i64 / 1000, (timestamp % 1000) as u32) + .expect("invalid datetime"); Utc.from_utc_datetime(&dt).with_timezone(&Local) }