From f130d537b773b6682b710f667f2f51445749ca50 Mon Sep 17 00:00:00 2001 From: Simon Laux Date: Sun, 23 Jul 2023 20:10:52 +0200 Subject: [PATCH] api(jsonrpc): add get_message_info_object --- deltachat-jsonrpc/src/api.rs | 12 +++- deltachat-jsonrpc/src/api/types/message.rs | 68 ++++++++++++++++++ src/message.rs | 83 +++++++++++++--------- 3 files changed, 130 insertions(+), 33 deletions(-) diff --git a/deltachat-jsonrpc/src/api.rs b/deltachat-jsonrpc/src/api.rs index 774e40826..d91ed8f68 100644 --- a/deltachat-jsonrpc/src/api.rs +++ b/deltachat-jsonrpc/src/api.rs @@ -47,7 +47,7 @@ use types::provider_info::ProviderInfo; use types::reactions::JSONRPCReactions; use types::webxdc::WebxdcMessageInfo; -use self::types::message::MessageLoadResult; +use self::types::message::{MessageInfo, MessageLoadResult}; use self::types::{ chat::{BasicChat, JSONRPCChatVisibility, MuteDuration}, location::JsonrpcLocation, @@ -1126,6 +1126,16 @@ impl CommandApi { MsgId::new(message_id).get_info(&ctx).await } + /// Returns additional information for single message. + async fn get_message_info_object( + &self, + account_id: u32, + message_id: u32, + ) -> Result { + let ctx = self.get_context(account_id).await?; + MessageInfo::from_msg_id(&ctx, MsgId::new(message_id)).await + } + /// Returns contacts that sent read receipts and the time of reading. async fn get_message_read_receipts( &self, diff --git a/deltachat-jsonrpc/src/api/types/message.rs b/deltachat-jsonrpc/src/api/types/message.rs index 4bd691e3a..414461e20 100644 --- a/deltachat-jsonrpc/src/api/types/message.rs +++ b/deltachat-jsonrpc/src/api/types/message.rs @@ -552,3 +552,71 @@ pub struct MessageReadReceipt { pub contact_id: u32, pub timestamp: i64, } + +#[derive(Serialize, TypeDef, schemars::JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct MessageInfo { + rawtext: String, + ephemeral_timer: EphemeralTimer, + /// When message is ephemeral this contains the timestamp of the message expiry + ephemeral_timestamp: Option, + error: Option, + rfc724_mid: String, + server_urls: Vec, + hop_info: Option, +} + +impl MessageInfo { + pub async fn from_msg_id(context: &Context, msg_id: MsgId) -> Result { + let message = Message::load_from_db(context, msg_id).await?; + let rawtext = msg_id.rawtext(context).await?; + let ephemeral_timer = message.get_ephemeral_timer().into(); + let ephemeral_timestamp = match message.get_ephemeral_timer() { + deltachat::ephemeral::Timer::Disabled => None, + deltachat::ephemeral::Timer::Enabled { .. } => Some(message.get_ephemeral_timestamp()), + }; + + let server_urls = + MsgId::get_info_server_urls(context, message.rfc724_mid().to_owned()).await?; + + let hop_info = msg_id.hop_info(context).await?; + + Ok(Self { + rawtext, + ephemeral_timer, + ephemeral_timestamp, + error: message.error(), + rfc724_mid: message.rfc724_mid().to_owned(), + server_urls, + hop_info, + }) + } +} + +#[derive( + Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize, TypeDef, schemars::JsonSchema, +)] +#[serde(rename_all = "camelCase", tag = "variant")] +pub enum EphemeralTimer { + /// Timer is disabled. + Disabled, + + /// Timer is enabled. + Enabled { + /// Timer duration in seconds. + /// + /// The value cannot be 0. + duration: u32, + }, +} + +impl From for EphemeralTimer { + fn from(value: deltachat::ephemeral::Timer) -> Self { + match value { + deltachat::ephemeral::Timer::Disabled => EphemeralTimer::Disabled, + deltachat::ephemeral::Timer::Enabled { duration } => { + EphemeralTimer::Enabled { duration } + } + } + } +} diff --git a/src/message.rs b/src/message.rs index 915c19af3..8e7e8e3db 100644 --- a/src/message.rs +++ b/src/message.rs @@ -150,21 +150,53 @@ WHERE id=?; self.0 } + /// Returns raw text of a message, used for message info + pub async fn rawtext(self, context: &Context) -> Result { + Ok(context + .sql + .query_get_value("SELECT txt_raw FROM msgs WHERE id=?", (self,)) + .await? + .unwrap_or_default()) + } + + /// Returns server foldernames and UIDs of a message, used for message info + pub async fn get_info_server_urls( + context: &Context, + rfc724_mid: String, + ) -> Result> { + context + .sql + .query_map( + "SELECT folder, uid FROM imap WHERE rfc724_mid=?", + (rfc724_mid,), + |row| { + let folder: String = row.get("folder")?; + let uid: u32 = row.get("uid")?; + Ok(format!("")) + }, + |rows| { + rows.collect::, _>>() + .map_err(Into::into) + }, + ) + .await + } + + /// Returns information about hops of a message, used for message info + pub async fn hop_info(self, context: &Context) -> Result> { + context + .sql + .query_get_value("SELECT hop_info FROM msgs WHERE id=?", (self,)) + .await + } + /// Returns detailed message information in a multi-line text form. pub async fn get_info(self, context: &Context) -> Result { let msg = Message::load_from_db(context, self).await?; - let rawtxt: Option = context - .sql - .query_get_value("SELECT txt_raw FROM msgs WHERE id=?", (self,)) - .await?; + let rawtxt: String = self.rawtext(context).await?; let mut ret = String::new(); - if rawtxt.is_none() { - ret += &format!("Cannot load message {self}."); - return Ok(ret); - } - let rawtxt = rawtxt.unwrap_or_default(); let rawtxt = truncate(rawtxt.trim(), DC_DESIRED_TEXT_LEN); let fts = timestamp_to_str(msg.get_timestamp()); @@ -282,32 +314,13 @@ WHERE id=?; if !msg.rfc724_mid.is_empty() { ret += &format!("\nMessage-ID: {}", msg.rfc724_mid); - let server_uids = context - .sql - .query_map( - "SELECT folder, uid FROM imap WHERE rfc724_mid=?", - (msg.rfc724_mid,), - |row| { - let folder: String = row.get("folder")?; - let uid: u32 = row.get("uid")?; - Ok((folder, uid)) - }, - |rows| { - rows.collect::, _>>() - .map_err(Into::into) - }, - ) - .await?; - - for (folder, uid) in server_uids { + let server_urls = Self::get_info_server_urls(context, msg.rfc724_mid).await?; + for server_url in server_urls { // Format as RFC 5092 relative IMAP URL. - ret += &format!("\n"); + ret += &format!("\n{server_url}"); } } - let hop_info: Option = context - .sql - .query_get_value("SELECT hop_info FROM msgs WHERE id=?;", (self,)) - .await?; + let hop_info = self.hop_info(context).await?; ret += "\n\n"; ret += &hop_info.unwrap_or_else(|| "No Hop Info".to_owned()); @@ -649,6 +662,12 @@ impl Message { self.id } + /// Returns the rfc724 message ID + /// May be empty + pub fn rfc724_mid(&self) -> &str { + &self.rfc724_mid + } + /// Returns the ID of the contact who wrote the message. pub fn get_from_id(&self) -> ContactId { self.from_id