From 0751cc50b9b634ec2ffe88fb7e9e6dec39f7db3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kl=C3=A4hn?= <39526136+Septias@users.noreply.github.com> Date: Sat, 14 Oct 2023 10:34:46 +0200 Subject: [PATCH] api(json-rpc): force stickers to be sent as stickers (#4819) This approach uses a param field to enable forcing the sticker `viewtype`. The first commit has the memory-only flag implemented, but this flag is not persistent through the database conversion needed for draft/undraft. That's why `param` has to be used. follow up to #4814 fixes #4739 --------- Co-authored-by: Septias --- deltachat-jsonrpc/src/api/mod.rs | 3 ++ src/chat.rs | 50 +++++++++++++++++++++++++++++++- src/message.rs | 6 ++++ src/param.rs | 3 ++ 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/deltachat-jsonrpc/src/api/mod.rs b/deltachat-jsonrpc/src/api/mod.rs index 6b9e8d5ff7..e58adef60d 100644 --- a/deltachat-jsonrpc/src/api/mod.rs +++ b/deltachat-jsonrpc/src/api/mod.rs @@ -1756,6 +1756,9 @@ impl CommandApi { let mut msg = Message::new(Viewtype::Sticker); msg.set_file(&sticker_path, None); + // JSON-rpc does not need heuristics to turn [Viewtype::Sticker] into [Viewtype::Image] + msg.force_sticker(); + let message_id = deltachat::chat::send_msg(&ctx, ChatId::new(chat_id), &mut msg).await?; Ok(message_id.to_u32()) } diff --git a/src/chat.rs b/src/chat.rs index 7687e554ef..fe5cde4068 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -2208,9 +2208,12 @@ async fn prepare_msg_blob(context: &Context, msg: &mut Message) -> Result<()> { .with_context(|| format!("attachment missing for message of type #{}", msg.viewtype))?; let mut maybe_sticker = msg.viewtype == Viewtype::Sticker; - if msg.viewtype == Viewtype::Image || maybe_sticker { + if msg.viewtype == Viewtype::Image + || maybe_sticker && !msg.param.exists(Param::ForceSticker) + { blob.recode_to_image_size(context, &mut maybe_sticker) .await?; + if !maybe_sticker { msg.viewtype = Viewtype::Image; } @@ -5679,6 +5682,51 @@ mod tests { .await } + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_sticker_jpeg_force() { + let alice = TestContext::new_alice().await; + let bob = TestContext::new_bob().await; + let alice_chat = alice.create_chat(&bob).await; + + let file = alice.get_blobdir().join("sticker.jpg"); + tokio::fs::write( + &file, + include_bytes!("../test-data/image/avatar1000x1000.jpg"), + ) + .await + .unwrap(); + + // Images without force_sticker should be turned into [Viewtype::Image] + let mut msg = Message::new(Viewtype::Sticker); + msg.set_file(file.to_str().unwrap(), None); + let sent_msg = alice.send_msg(alice_chat.id, &mut msg).await; + let msg = bob.recv_msg(&sent_msg).await; + assert_eq!(msg.get_viewtype(), Viewtype::Image); + + // Images with `force_sticker = true` should keep [Viewtype::Sticker] + let mut msg = Message::new(Viewtype::Sticker); + msg.set_file(file.to_str().unwrap(), None); + msg.force_sticker(); + let sent_msg = alice.send_msg(alice_chat.id, &mut msg).await; + let msg = bob.recv_msg(&sent_msg).await; + assert_eq!(msg.get_viewtype(), Viewtype::Sticker); + + // Images with `force_sticker = true` should keep [Viewtype::Sticker] + // even on drafted messages + let mut msg = Message::new(Viewtype::Sticker); + msg.set_file(file.to_str().unwrap(), None); + msg.force_sticker(); + alice_chat + .id + .set_draft(&alice, Some(&mut msg)) + .await + .unwrap(); + let mut msg = alice_chat.id.get_draft(&alice).await.unwrap().unwrap(); + let sent_msg = alice.send_msg(alice_chat.id, &mut msg).await; + let msg = bob.recv_msg(&sent_msg).await; + assert_eq!(msg.get_viewtype(), Viewtype::Sticker); + } + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_sticker_gif() -> Result<()> { test_sticker( diff --git a/src/message.rs b/src/message.rs index 7e86f8c998..c3e21b8036 100644 --- a/src/message.rs +++ b/src/message.rs @@ -664,6 +664,12 @@ impl Message { self.viewtype } + /// Forces the message to **keep** [Viewtype::Sticker] + /// e.g the message will not be converted to a [Viewtype::Image]. + pub fn force_sticker(&mut self) { + self.param.set_int(Param::ForceSticker, 1); + } + /// Returns the state of the message. pub fn get_state(&self) -> MessageState { self.state diff --git a/src/param.rs b/src/param.rs index d0f3bb1aab..a9f5c1a425 100644 --- a/src/param.rs +++ b/src/param.rs @@ -187,6 +187,9 @@ pub enum Param { /// For Webxdc Message Instances: timestamp of summary update. WebxdcSummaryTimestamp = b'Q', + + /// For messages: Whether [crate::message::Viewtype::Sticker] should be forced. + ForceSticker = b'X', } /// An object for handling key=value parameter lists.