diff --git a/src/blob.rs b/src/blob.rs index dcc157ada..886f295ae 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -1330,6 +1330,42 @@ mod tests { Ok(img) } + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_send_big_gif_as_image() -> Result<()> { + let bytes = include_bytes!("../test-data/image/screenshot.gif"); + let (width, height) = (1920u32, 1080u32); + let alice = TestContext::new_alice().await; + let bob = TestContext::new_bob().await; + alice + .set_config( + Config::MediaQuality, + Some(&(MediaQuality::Worse as i32).to_string()), + ) + .await?; + let file = alice.get_blobdir().join("file").with_extension("gif"); + fs::write(&file, &bytes) + .await + .context("failed to write file")?; + let mut msg = Message::new(Viewtype::Image); + msg.set_file(file.to_str().unwrap(), None); + let chat = alice.create_chat(&bob).await; + let sent = alice.send_msg(chat.id, &mut msg).await; + let bob_msg = bob.recv_msg(&sent).await; + // DC must detect the image as GIF and send it w/o reencoding. + assert_eq!(bob_msg.get_viewtype(), Viewtype::Gif); + assert_eq!(bob_msg.get_width() as u32, width); + assert_eq!(bob_msg.get_height() as u32, height); + let file_saved = bob + .get_blobdir() + .join("saved-".to_string() + &bob_msg.get_filename().unwrap()); + bob_msg.save_file(&bob, &file_saved).await?; + let blob = BlobObject::new_from_path(&bob, &file_saved).await?; + let (file_size, _) = blob.metadata()?; + assert_eq!(file_size, bytes.len() as u64); + check_image_size(file_saved, width, height); + Ok(()) + } + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_increation_in_blobdir() -> Result<()> { let t = TestContext::new_alice().await; diff --git a/src/chat.rs b/src/chat.rs index 3af6f94c0..f7ef21be6 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -2505,6 +2505,30 @@ async fn prepare_msg_blob(context: &Context, msg: &mut Message) -> Result<()> { .await? .with_context(|| format!("attachment missing for message of type #{}", msg.viewtype))?; + if msg.viewtype == Viewtype::File || msg.viewtype == Viewtype::Image { + // Correct the type, take care not to correct already very special + // formats as GIF or VOICE. + // + // Typical conversions: + // - from FILE to AUDIO/VIDEO/IMAGE + // - from FILE/IMAGE to GIF */ + if let Some((better_type, _)) = message::guess_msgtype_from_suffix(&blob.to_abs_path()) + { + if better_type != Viewtype::Webxdc + || context + .ensure_sendable_webxdc_file(&blob.to_abs_path()) + .await + .is_ok() + { + msg.viewtype = better_type; + } + } + } else if msg.viewtype == Viewtype::Webxdc { + context + .ensure_sendable_webxdc_file(&blob.to_abs_path()) + .await?; + } + let mut maybe_sticker = msg.viewtype == Viewtype::Sticker; if msg.viewtype == Viewtype::Image || maybe_sticker && !msg.param.exists(Param::ForceSticker) @@ -2526,34 +2550,6 @@ async fn prepare_msg_blob(context: &Context, msg: &mut Message) -> Result<()> { .set(Param::Filename, stem.to_string() + "." + blob_ext); } - if msg.viewtype == Viewtype::File || msg.viewtype == Viewtype::Image { - // Correct the type, take care not to correct already very special - // formats as GIF or VOICE. - // - // Typical conversions: - // - from FILE to AUDIO/VIDEO/IMAGE - // - from FILE/IMAGE to GIF */ - if let Some((better_type, better_mime)) = - message::guess_msgtype_from_suffix(&blob.to_abs_path()) - { - if better_type != Viewtype::Webxdc - || context - .ensure_sendable_webxdc_file(&blob.to_abs_path()) - .await - .is_ok() - { - msg.viewtype = better_type; - if !msg.param.exists(Param::MimeType) { - msg.param.set(Param::MimeType, better_mime); - } - } - } - } else if msg.viewtype == Viewtype::Webxdc { - context - .ensure_sendable_webxdc_file(&blob.to_abs_path()) - .await?; - } - if !msg.param.exists(Param::MimeType) { if let Some((_, mime)) = message::guess_msgtype_from_suffix(&blob.to_abs_path()) { msg.param.set(Param::MimeType, mime); diff --git a/test-data/image/screenshot.gif b/test-data/image/screenshot.gif new file mode 100644 index 000000000..57221835a Binary files /dev/null and b/test-data/image/screenshot.gif differ