From d7b4a5fc9e9c78429a1134e4ca227e586beee39f Mon Sep 17 00:00:00 2001 From: Floris Bruynooghe Date: Mon, 26 Apr 2021 22:41:13 +0200 Subject: [PATCH] Move module functions to type methods This moves the module-level lookup and creation functions to the types, which make the naming more consistent. Now the lookup_* get_* and create_* functions all behave similarly. Peraps even more important the API of the lookup now allows distinguishing failure from not found. This in turn is important to be able to remove reliance on a ChatId with a 0 or "unset" value. The locations where this ChatId(0) is still used is in database queries which should be solved in an independed commit. --- deltachat-ffi/src/lib.rs | 7 +- examples/repl/cmdline.rs | 2 +- examples/simple.rs | 4 +- src/chat.rs | 201 +++++++++++++++++-------------------- src/chatlist.rs | 23 ++--- src/context.rs | 5 +- src/dc_receive_imf.rs | 32 +++--- src/ephemeral.rs | 20 ++-- src/events.rs | 2 + src/imex.rs | 14 +-- src/job.rs | 29 +++--- src/message.rs | 9 +- src/mimefactory.rs | 6 +- src/securejoin.rs | 2 +- src/securejoin/bobstate.rs | 2 +- src/stock_str.rs | 5 +- src/test_utils.rs | 6 +- 17 files changed, 175 insertions(+), 194 deletions(-) diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 154b63607..075890758 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -639,7 +639,7 @@ pub unsafe extern "C" fn dc_create_chat_by_contact_id( let ctx = &*context; block_on(async move { - chat::create_by_contact_id(&ctx, contact_id) + ChatId::create_for_contact(&ctx, contact_id) .await .log_err(ctx, "Failed to create chat from contact_id") .map(|id| id.to_u32()) @@ -659,11 +659,12 @@ pub unsafe extern "C" fn dc_get_chat_id_by_contact_id( let ctx = &*context; block_on(async move { - chat::get_by_contact_id(&ctx, contact_id) + ChatId::lookup_by_contact(&ctx, contact_id) .await .log_err(ctx, "Failed to get chat for contact_id") + .unwrap_or_default() // unwraps the Result .map(|id| id.to_u32()) - .unwrap_or(0) + .unwrap_or(0) // unwraps the Option }) } diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index d5efb6d3d..51b8d669b 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -675,7 +675,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu "createchat" => { ensure!(!arg1.is_empty(), "Argument missing."); let contact_id: u32 = arg1.parse()?; - let chat_id = chat::create_by_contact_id(&context, contact_id).await?; + let chat_id = ChatId::create_for_contact(&context, contact_id).await?; println!("Single#{} created successfully.", chat_id,); } diff --git a/examples/simple.rs b/examples/simple.rs index 4f84db137..d257442fe 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -1,6 +1,6 @@ use tempfile::tempdir; -use deltachat::chat; +use deltachat::chat::{self, ChatId}; use deltachat::chatlist::*; use deltachat::config; use deltachat::contact::*; @@ -70,7 +70,7 @@ async fn main() { let contact_id = Contact::create(&ctx, "dignifiedquire", "dignifiedquire@gmail.com") .await .unwrap(); - let chat_id = chat::create_by_contact_id(&ctx, contact_id).await.unwrap(); + let chat_id = ChatId::create_for_contact(&ctx, contact_id).await.unwrap(); for i in 0..1 { log::info!("sending message {}", i); diff --git a/src/chat.rs b/src/chat.rs index 5e9bc6580..f6b2d33ed 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -155,15 +155,66 @@ impl ChatId { self == DC_CHAT_ID_ALLDONE_HINT } + /// Returns the [`ChatId`] for the 1:1 chat with `contact_id` if it exists. + /// + /// If it does not exist, `None` is returned. + pub async fn lookup_by_contact(context: &Context, contact_id: u32) -> Result> { + ChatIdBlocked::lookup_by_contact(context, contact_id) + .await + .map(|lookup| lookup.map(|chat| chat.id)) + } + /// Returns the [`ChatId`] for the 1:1 chat with `contact_id`. /// /// If the chat does not yet exist an unblocked chat ([`Blocked::Not`]) is created. + /// + /// This is an internal API, if **a user action** needs to get a chat + /// [`ChatId::create_for_contact`] should be used as this also scales up the + /// [`Contact`]'s origin. pub async fn get_for_contact(context: &Context, contact_id: u32) -> Result { ChatIdBlocked::get_for_contact(context, contact_id, Blocked::Not) .await .map(|chat| chat.id) } + /// Returns the unblocked 1:1 chat with `contact_id`. + /// + /// This should be used when **a user action** creates a chat 1:1, it ensures the chat + /// exists and is unblocked and scales the [`Contact`]'s origin. + /// + /// If a chat was in the deaddrop unblocking is how it becomes a normal chat and it will + /// look to the user like the chat was newly created. + pub async fn create_for_contact(context: &Context, contact_id: u32) -> Result { + let chat_id = match ChatIdBlocked::lookup_by_contact(context, contact_id).await? { + Some(chat) => { + if chat.blocked != Blocked::Not { + chat.id.unblock(context).await; + } + chat.id + } + None => { + if Contact::real_exists_by_id(context, contact_id).await + || contact_id == DC_CONTACT_ID_SELF + { + let chat_id = ChatId::get_for_contact(context, contact_id).await?; + Contact::scaleup_origin_by_id(context, contact_id, Origin::CreateChat).await; + chat_id + } else { + warn!( + context, + "Cannot create chat, contact {} does not exist.", contact_id, + ); + bail!("Can not create chat for non-existing contact"); + } + } + }; + context.emit_event(EventType::MsgsChanged { + chat_id: ChatId::new(0), + msg_id: MsgId::new(0), + }); + Ok(chat_id) + } + pub async fn set_selfavatar_timestamp(self, context: &Context, timestamp: i64) -> Result<()> { context .sql @@ -1312,50 +1363,9 @@ pub async fn create_by_msg_id(context: &Context, msg_id: MsgId) -> Result Result { - let chat_id = match lookup_by_contact_id(context, contact_id).await { - Ok((chat_id, chat_blocked)) => { - if chat_blocked != Blocked::Not { - // unblock chat (typically move it from the deaddrop to view) - chat_id.unblock(context).await; - } - chat_id - } - Err(err) => { - if !Contact::real_exists_by_id(context, contact_id).await - && contact_id != DC_CONTACT_ID_SELF - { - warn!( - context, - "Cannot create chat, contact {} does not exist.", contact_id, - ); - return Err(err); - } else { - let chat_id = ChatId::get_for_contact(context, contact_id).await?; - Contact::scaleup_origin_by_id(context, contact_id, Origin::CreateChat).await; - chat_id - } - } - }; - - context.emit_event(EventType::MsgsChanged { - chat_id: ChatId::new(0), - msg_id: MsgId::new(0), - }); - - Ok(chat_id) -} - pub(crate) async fn update_saved_messages_icon(context: &Context) -> Result<()> { // if there is no saved-messages chat, there is nothing to update. this is no error. - if let Ok((chat_id, _)) = lookup_by_contact_id(context, DC_CONTACT_ID_SELF).await { + if let Some(chat_id) = ChatId::lookup_by_contact(context, DC_CONTACT_ID_SELF).await? { let icon = include_bytes!("../assets/icon-saved-messages.png"); let blob = BlobObject::create(context, "icon-saved-messages.png".to_string(), icon).await?; let icon = blob.as_name().to_string(); @@ -1369,7 +1379,7 @@ pub(crate) async fn update_saved_messages_icon(context: &Context) -> Result<()> pub(crate) async fn update_device_icon(context: &Context) -> Result<()> { // if there is no device-chat, there is nothing to update. this is no error. - if let Ok((chat_id, _)) = lookup_by_contact_id(context, DC_CONTACT_ID_DEVICE).await { + if let Some(chat_id) = ChatId::lookup_by_contact(context, DC_CONTACT_ID_DEVICE).await? { let icon = include_bytes!("../assets/icon-device.png"); let blob = BlobObject::create(context, "icon-device.png".to_string(), icon).await?; let icon = blob.as_name().to_string(); @@ -1386,7 +1396,7 @@ pub(crate) async fn update_device_icon(context: &Context) -> Result<()> { } async fn update_special_chat_name(context: &Context, contact_id: u32, name: String) -> Result<()> { - if let Ok((chat_id, _)) = lookup_by_contact_id(context, contact_id).await { + if let Some(chat_id) = ChatId::lookup_by_contact(context, contact_id).await? { // the `!= name` condition avoids unneeded writes context .sql @@ -1432,7 +1442,7 @@ impl ChatIdBlocked { /// Searches the database for the 1:1 chat with this contact. /// /// If no chat is found `None` is returned. - async fn lookup_by_contact(context: &Context, contact_id: u32) -> Result, Error> { + pub async fn lookup_by_contact(context: &Context, contact_id: u32) -> Result> { ensure!(context.sql.is_open().await, "Database not available"); ensure!(contact_id > 0, "Invalid contact id requested"); @@ -1465,7 +1475,7 @@ impl ChatIdBlocked { context: &Context, contact_id: u32, create_blocked: Blocked, - ) -> Result { + ) -> Result { ensure!(context.sql.is_open().await, "Database not available"); ensure!(contact_id > 0, "Invalid contact id requested"); @@ -1533,41 +1543,6 @@ impl ChatIdBlocked { } } -pub(crate) async fn lookup_by_contact_id( - context: &Context, - contact_id: u32, -) -> Result<(ChatId, Blocked)> { - ensure!(context.sql.is_open().await, "Database not available"); - - let row = context - .sql - .query_row( - "SELECT c.id, c.blocked - FROM chats c - INNER JOIN chats_contacts j - ON c.id=j.chat_id - WHERE c.type=100 - AND c.id>9 - AND j.contact_id=?;", - paramsv![contact_id as i32], - |row| { - Ok(( - row.get::<_, ChatId>(0)?, - row.get::<_, Option<_>>(1)?.unwrap_or_default(), - )) - }, - ) - .await?; - Ok(row) -} - -pub async fn get_by_contact_id(context: &Context, contact_id: u32) -> Result { - let (chat_id, blocked) = lookup_by_contact_id(context, contact_id).await?; - ensure_eq!(blocked, Blocked::Not, "Requested contact is blocked"); - - Ok(chat_id) -} - pub async fn prepare_msg(context: &Context, chat_id: ChatId, msg: &mut Message) -> Result { ensure!( !chat_id.is_special(), @@ -3182,7 +3157,7 @@ mod tests { async fn test_add_remove_contact_for_single() { let ctx = TestContext::new_alice().await; let bob = Contact::create(&ctx, "", "bob@f.br").await.unwrap(); - let chat_id = create_by_contact_id(&ctx, bob).await.unwrap(); + let chat_id = ChatId::create_for_contact(&ctx, bob).await.unwrap(); let chat = Chat::load_from_db(&ctx, chat_id).await.unwrap(); assert_eq!(chat.typ, Chattype::Single); assert_eq!(get_chat_contacts(&ctx, chat.id).await.unwrap().len(), 1); @@ -3623,11 +3598,15 @@ mod tests { .unwrap(); assert_ne!(contact1, 0); - let chat_id = create_by_contact_id(&context.ctx, contact1).await.unwrap(); + let chat_id = ChatId::create_for_contact(&context.ctx, contact1) + .await + .unwrap(); assert!(!chat_id.is_special(), "chat_id too small {}", chat_id); let chat = Chat::load_from_db(&context.ctx, chat_id).await.unwrap(); - let chat2_id = create_by_contact_id(&context.ctx, contact1).await.unwrap(); + let chat2_id = ChatId::create_for_contact(&context.ctx, contact1) + .await + .unwrap(); assert_eq!(chat2_id, chat_id); let chat2 = Chat::load_from_db(&context.ctx, chat2_id).await.unwrap(); @@ -3823,13 +3802,16 @@ mod tests { // create contact, then unblocked chat let contact_id = Contact::create(&ctx, "", "bob@foo.de").await.unwrap(); assert_ne!(contact_id, 0); - let res = lookup_by_contact_id(&ctx, contact_id).await; - assert!(res.is_err()); + let found = ChatId::lookup_by_contact(&ctx, contact_id).await.unwrap(); + assert!(found.is_none()); - let chat_id = create_by_contact_id(&ctx, contact_id).await.unwrap(); - let (chat_id2, blocked) = lookup_by_contact_id(&ctx, contact_id).await.unwrap(); - assert_eq!(chat_id, chat_id2); - assert_eq!(blocked, Blocked::Not); + let chat_id = ChatId::create_for_contact(&ctx, contact_id).await.unwrap(); + let chat2 = ChatIdBlocked::lookup_by_contact(&ctx, contact_id) + .await + .unwrap() + .unwrap(); + assert_eq!(chat_id, chat2.id); + assert_eq!(chat2.blocked, Blocked::Not); // create contact, then blocked chat let contact_id = Contact::create(&ctx, "", "claire@foo.de").await.unwrap(); @@ -3837,33 +3819,38 @@ mod tests { .await .unwrap() .id; - let (chat_id2, blocked) = lookup_by_contact_id(&ctx, contact_id).await.unwrap(); - assert_eq!(chat_id, chat_id2); - assert_eq!(blocked, Blocked::Manually); + let chat2 = ChatIdBlocked::lookup_by_contact(&ctx, contact_id) + .await + .unwrap() + .unwrap(); + assert_eq!(chat_id, chat2.id); + assert_eq!(chat2.blocked, Blocked::Manually); - // test nonexistent contact, and also check if reasonable defaults are used - let res = lookup_by_contact_id(&ctx, 1234).await; - assert!(res.is_err()); + // test nonexistent contact + let found = ChatId::lookup_by_contact(&ctx, 1234).await.unwrap(); + assert!(found.is_none()); - let (chat_id, blocked) = lookup_by_contact_id(&ctx, 1234).await.unwrap_or_default(); - assert_eq!(chat_id, ChatId::new(0)); - assert_eq!(blocked, Blocked::Not); + let found = ChatIdBlocked::lookup_by_contact(&ctx, 1234).await.unwrap(); + assert!(found.is_none()); } #[async_std::test] async fn test_lookup_self_by_contact_id() { let ctx = TestContext::new_alice().await; - let res = lookup_by_contact_id(&ctx, DC_CONTACT_ID_SELF).await; - assert!(res.is_err()); - - ctx.update_device_chats().await.unwrap(); - let (chat_id, blocked) = lookup_by_contact_id(&ctx, DC_CONTACT_ID_SELF) + let chat = ChatId::lookup_by_contact(&ctx, DC_CONTACT_ID_SELF) .await .unwrap(); - assert!(!chat_id.is_special()); - assert!(chat_id.is_self_talk(&ctx).await.unwrap()); - assert_eq!(blocked, Blocked::Not); + assert!(chat.is_none()); + + ctx.update_device_chats().await.unwrap(); + let chat = ChatIdBlocked::lookup_by_contact(&ctx, DC_CONTACT_ID_SELF) + .await + .unwrap() + .unwrap(); + assert!(!chat.id.is_special()); + assert!(chat.id.is_self_talk(&ctx).await.unwrap()); + assert_eq!(chat.blocked, Blocked::Not); } #[async_std::test] diff --git a/src/chatlist.rs b/src/chatlist.rs index 325bba45a..827a06d61 100644 --- a/src/chatlist.rs +++ b/src/chatlist.rs @@ -2,7 +2,6 @@ use anyhow::{bail, ensure, Result}; -use crate::chat; use crate::chat::{update_special_chat_names, Chat, ChatId, ChatVisibility}; use crate::constants::{ Chattype, DC_CHAT_ID_ALLDONE_HINT, DC_CHAT_ID_ARCHIVED_LINK, DC_CHAT_ID_DEADDROP, @@ -110,15 +109,6 @@ impl Chatlist { let mut add_archived_link_item = false; - let skip_id = if flag_for_forwarding { - chat::lookup_by_contact_id(context, DC_CONTACT_ID_DEVICE) - .await - .unwrap_or_default() - .0 - } else { - ChatId::new(0) - }; - let process_row = |row: &rusqlite::Row| { let chat_id: ChatId = row.get(0)?; let msg_id: MsgId = row.get(1).unwrap_or_default(); @@ -130,6 +120,14 @@ impl Chatlist { .map_err(Into::into) }; + let skip_id = if flag_for_forwarding { + ChatId::lookup_by_contact(context, DC_CONTACT_ID_DEVICE) + .await? + .unwrap_or_default() + } else { + ChatId::new(0) + }; + // select with left join and minimum: // // - the inner select must use `hidden` and _not_ `m.hidden` @@ -232,10 +230,9 @@ impl Chatlist { } else { // show normal chatlist let sort_id_up = if flag_for_forwarding { - chat::lookup_by_contact_id(context, DC_CONTACT_ID_SELF) - .await + ChatId::lookup_by_contact(context, DC_CONTACT_ID_SELF) + .await? .unwrap_or_default() - .0 } else { ChatId::new(0) }; diff --git a/src/context.rs b/src/context.rs index bafb3e566..bcb490955 100644 --- a/src/context.rs +++ b/src/context.rs @@ -609,8 +609,7 @@ mod tests { use super::*; use crate::chat::{ - create_by_contact_id, get_chat_contacts, get_chat_msgs, send_msg, set_muted, Chat, - MuteDuration, + get_chat_contacts, get_chat_msgs, send_msg, set_muted, Chat, ChatId, MuteDuration, }; use crate::constants::{Viewtype, DC_CONTACT_ID_SELF}; use crate::dc_receive_imf::dc_receive_imf; @@ -893,7 +892,7 @@ mod tests { #[async_std::test] async fn test_search_msgs() -> Result<()> { let alice = TestContext::new_alice().await; - let self_talk = create_by_contact_id(&alice, DC_CONTACT_ID_SELF).await?; + let self_talk = ChatId::create_for_contact(&alice, DC_CONTACT_ID_SELF).await?; let chat = alice .create_chat_with_contact("Bob", "bob@example.org") .await; diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 26bde39ef..21fadeca7 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -474,10 +474,9 @@ async fn add_parts( } } - let (test_normal_chat_id, test_normal_chat_id_blocked) = - chat::lookup_by_contact_id(context, from_id) - .await - .unwrap_or_default(); + let test_normal_chat = ChatIdBlocked::lookup_by_contact(context, from_id) + .await + .unwrap_or_default(); // get the chat_id - a chat_id here is no indicator that the chat is displayed in the normal list, // it might also be blocked and displayed in the deaddrop as a result @@ -498,17 +497,18 @@ async fn add_parts( if chat_id.is_unset() { // try to create a group - let create_blocked = - if !test_normal_chat_id.is_unset() && test_normal_chat_id_blocked == Blocked::Not { - Blocked::Not - } else { - Blocked::Deaddrop - }; + let create_blocked = match test_normal_chat { + Some(ChatIdBlocked { + id: _, + blocked: Blocked::Not, + }) => Blocked::Not, + _ => Blocked::Deaddrop, + }; let (new_chat_id, new_chat_id_blocked) = create_or_lookup_group( context, &mut mime_parser, - if test_normal_chat_id.is_unset() { + if test_normal_chat.is_none() { allow_creation } else { true @@ -600,9 +600,9 @@ async fn add_parts( Blocked::Deaddrop }; - if !test_normal_chat_id.is_unset() { - *chat_id = test_normal_chat_id; - chat_id_blocked = test_normal_chat_id_blocked; + if let Some(chat) = test_normal_chat { + *chat_id = chat.id; + chat_id_blocked = chat.blocked; } else if allow_creation { if let Ok(chat) = ChatIdBlocked::get_for_contact(context, from_id, create_blocked) .await @@ -2358,7 +2358,7 @@ mod tests { let t = TestContext::new_alice().await; let bob_id = Contact::create(&t, "bob", "bob@example.com").await.unwrap(); - let one2one_id = chat::create_by_contact_id(&t, bob_id).await.unwrap(); + let one2one_id = ChatId::create_for_contact(&t, bob_id).await.unwrap(); one2one_id .set_visibility(&t, ChatVisibility::Archived) .await @@ -2527,7 +2527,7 @@ mod tests { let contact_id = Contact::create(&t, "foobar", "foobar@example.com") .await .unwrap(); - let chat_id = chat::create_by_contact_id(&t, contact_id).await.unwrap(); + let chat_id = ChatId::create_for_contact(&t, contact_id).await.unwrap(); dc_receive_imf( &t, b"From: =?UTF-8?B?0JjQvNGPLCDQpNCw0LzQuNC70LjRjw==?= \n\ diff --git a/src/ephemeral.rs b/src/ephemeral.rs index 3719a0cba..854b04697 100644 --- a/src/ephemeral.rs +++ b/src/ephemeral.rs @@ -65,19 +65,17 @@ use anyhow::{ensure, Context as _, Result}; use async_std::task; use serde::{Deserialize, Serialize}; +use crate::chat::{send_msg, ChatId}; use crate::constants::{ Viewtype, DC_CHAT_ID_LAST_SPECIAL, DC_CHAT_ID_TRASH, DC_CONTACT_ID_DEVICE, DC_CONTACT_ID_SELF, }; use crate::context::Context; use crate::dc_tools::time; use crate::events::EventType; +use crate::job; use crate::message::{Message, MessageState, MsgId}; use crate::mimeparser::SystemMessage; use crate::stock_str; -use crate::{ - chat::{lookup_by_contact_id, send_msg, ChatId}, - job, -}; #[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] pub enum Timer { @@ -329,14 +327,12 @@ WHERE > 0; if let Some(delete_device_after) = context.get_config_delete_device_after().await? { - let self_chat_id = lookup_by_contact_id(context, DC_CONTACT_ID_SELF) - .await - .unwrap_or_default() - .0; - let device_chat_id = lookup_by_contact_id(context, DC_CONTACT_ID_DEVICE) - .await - .unwrap_or_default() - .0; + let self_chat_id = ChatId::lookup_by_contact(context, DC_CONTACT_ID_SELF) + .await? + .unwrap_or_default(); + let device_chat_id = ChatId::lookup_by_contact(context, DC_CONTACT_ID_DEVICE) + .await? + .unwrap_or_default(); let threshold_timestamp = time() - delete_device_after; diff --git a/src/events.rs b/src/events.rs index d6abd8e3b..308182e4c 100644 --- a/src/events.rs +++ b/src/events.rs @@ -213,6 +213,8 @@ pub enum EventType { /// - Messages sent, received or removed /// - Chats created, deleted or archived /// - A draft has been set + /// + /// The `chat_id` and `msg_id` values will be 0 if more than one message is changed. #[strum(props(id = "2000"))] MsgsChanged { chat_id: ChatId, msg_id: MsgId }, diff --git a/src/imex.rs b/src/imex.rs index cdf156c6d..e2a9195ec 100644 --- a/src/imex.rs +++ b/src/imex.rs @@ -3,16 +3,18 @@ use std::any::Any; use std::ffi::OsStr; +use ::pgp::types::KeyTrait; use anyhow::{bail, ensure, format_err, Context as _, Result}; -use async_std::path::{Path, PathBuf}; use async_std::{ fs::{self, File}, + path::{Path, PathBuf}, prelude::*, }; +use async_tar::Archive; use rand::{thread_rng, Rng}; -use crate::chat; -use crate::chat::delete_and_reset_all_device_msgs; +use crate::blob::BlobObject; +use crate::chat::{self, delete_and_reset_all_device_msgs, ChatId}; use crate::config::Config; use crate::constants::{Viewtype, DC_CONTACT_ID_SELF}; use crate::context::Context; @@ -23,15 +25,13 @@ use crate::dc_tools::{ use crate::e2ee; use crate::events::EventType; use crate::key::{self, DcKey, DcSecretKey, SignedPublicKey, SignedSecretKey}; +use crate::log::LogExt; use crate::message::{Message, MsgId}; use crate::mimeparser::SystemMessage; use crate::param::Param; use crate::pgp; use crate::sql::{self, Sql}; use crate::stock_str; -use crate::{blob::BlobObject, log::LogExt}; -use ::pgp::types::KeyTrait; -use async_tar::Archive; // Name of the database file in the backup. const DBFILE_BACKUP_NAME: &str = "dc_database_backup.sqlite"; @@ -231,7 +231,7 @@ async fn do_initiate_key_transfer(context: &Context) -> Result { ) .await?; - let chat_id = chat::create_by_contact_id(context, DC_CONTACT_ID_SELF).await?; + let chat_id = ChatId::create_for_contact(context, DC_CONTACT_ID_SELF).await?; msg = Message::default(); msg.viewtype = Viewtype::File; msg.param.set(Param::File, setup_file_blob.as_name()); diff --git a/src/job.rs b/src/job.rs index ba2b8b374..7b95a747b 100644 --- a/src/job.rs +++ b/src/job.rs @@ -12,25 +12,24 @@ use deltachat_derive::{FromSql, ToSql}; use itertools::Itertools; use rand::{thread_rng, Rng}; +use crate::blob::BlobObject; +use crate::chat::{self, Chat, ChatId, ChatIdBlocked, ChatItem}; +use crate::config::Config; +use crate::constants::{Blocked, Chattype, DC_CHAT_ID_DEADDROP}; +use crate::contact::{normalize_name, Contact, Modifier, Origin}; +use crate::context::Context; use crate::dc_tools::{dc_delete_file, dc_read_file, time}; use crate::ephemeral::load_imap_deletion_msgid; use crate::events::EventType; use crate::imap::{Imap, ImapActionResult}; use crate::location; -use crate::message::MsgId; -use crate::message::{self, Message, MessageState}; +use crate::log::LogExt; +use crate::message::{self, Message, MessageState, MsgId}; use crate::mimefactory::MimeFactory; use crate::param::{Param, Params}; +use crate::scheduler::InterruptInfo; use crate::smtp::Smtp; -use crate::{blob::BlobObject, contact::normalize_name, contact::Modifier, contact::Origin}; -use crate::{ - chat::{self, Chat, ChatId, ChatItem}, - constants::DC_CHAT_ID_DEADDROP, -}; -use crate::{config::Config, constants::Blocked}; -use crate::{constants::Chattype, contact::Contact}; -use crate::{context::Context, log::LogExt}; -use crate::{scheduler::InterruptInfo, sql}; +use crate::sql; // results in ~3 weeks for the last backoff timespan const JOB_RETRIES: u32 = 17; @@ -729,10 +728,12 @@ impl Job { }; match chat.typ { Chattype::Group | Chattype::Mailinglist => { - if let Ok((_1to1_chat, Blocked::Not)) = - chat::lookup_by_contact_id(context, msg.from_id).await + if let Ok(Some(one_to_one_chat)) = + ChatIdBlocked::lookup_by_contact(context, msg.from_id).await { - chat.id.unblock(context).await; + if one_to_one_chat.blocked == Blocked::Not { + chat.id.unblock(context).await; + } } } Chattype::Single | Chattype::Undefined => {} diff --git a/src/message.rs b/src/message.rs index ed267cf89..d32abe6f3 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1941,10 +1941,9 @@ pub async fn estimate_deletion_cnt( from_server: bool, seconds: i64, ) -> Result { - let self_chat_id = chat::lookup_by_contact_id(context, DC_CONTACT_ID_SELF) - .await - .unwrap_or_default() - .0; + let self_chat_id = ChatId::lookup_by_contact(context, DC_CONTACT_ID_SELF) + .await? + .unwrap_or_default(); let threshold_timestamp = time() - seconds; let cnt = if from_server { @@ -2226,7 +2225,7 @@ mod tests { let contact_id = Contact::create(&t.ctx, "", "bob@example.net") .await .unwrap(); - chat::create_by_contact_id(&t.ctx, contact_id) + ChatId::create_for_contact(&t.ctx, contact_id) .await .unwrap(); } diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 33492cc94..a679faca6 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -1348,11 +1348,11 @@ mod tests { use async_std::prelude::*; use crate::chat::ChatId; + use crate::chatlist::Chatlist; use crate::contact::Origin; use crate::dc_receive_imf::dc_receive_imf; use crate::mimeparser::MimeMessage; - use crate::test_utils::TestContext; - use crate::{chatlist::Chatlist, test_utils::get_chat_msg}; + use crate::test_utils::{get_chat_msg, TestContext}; use async_std::fs::File; use pretty_assertions::assert_eq; @@ -1687,7 +1687,7 @@ mod tests { .unwrap() .0; - let chat_id = chat::create_by_contact_id(&t, contact_id).await.unwrap(); + let chat_id = ChatId::create_for_contact(&t, contact_id).await.unwrap(); let mut new_msg = Message::new(Viewtype::Text); new_msg.set_text(Some("Hi".to_string())); diff --git a/src/securejoin.rs b/src/securejoin.rs index dc3c0091e..b213c5bfe 100644 --- a/src/securejoin.rs +++ b/src/securejoin.rs @@ -304,7 +304,7 @@ async fn securejoin(context: &Context, qr: &str) -> Result { StartedProtocolVariant::SetupContact => { // for a one-to-one-chat, the chat is already known, return the chat-id, // the verification runs in background - let chat_id = chat::create_by_contact_id(context, invite.contact_id()) + let chat_id = ChatId::create_for_contact(context, invite.contact_id()) .await .map_err(JoinError::UnknownContact)?; Ok(chat_id) diff --git a/src/securejoin/bobstate.rs b/src/securejoin/bobstate.rs index 48bc6308f..e36159c0c 100644 --- a/src/securejoin/bobstate.rs +++ b/src/securejoin/bobstate.rs @@ -185,7 +185,7 @@ impl BobState { context: &Context, invite: QrInvite, ) -> Result<(Self, BobHandshakeStage), JoinError> { - let chat_id = chat::create_by_contact_id(context, invite.contact_id()) + let chat_id = ChatId::create_for_contact(context, invite.contact_id()) .await .map_err(JoinError::UnknownContact)?; if fingerprint_equals_sender(context, invite.fingerprint(), chat_id).await? { diff --git a/src/stock_str.rs b/src/stock_str.rs index a3182eef6..99eca8e1f 100644 --- a/src/stock_str.rs +++ b/src/stock_str.rs @@ -8,8 +8,7 @@ use strum::EnumProperty; use strum_macros::EnumProperty; use crate::blob::BlobObject; -use crate::chat; -use crate::chat::ProtectionStatus; +use crate::chat::{self, ChatId, ProtectionStatus}; use crate::config::Config; use crate::constants::{Viewtype, DC_CONTACT_ID_SELF}; use crate::contact::{Contact, Origin}; @@ -916,7 +915,7 @@ impl Context { self.sql .set_raw_config_bool("self-chat-added", true) .await?; - chat::create_by_contact_id(self, DC_CONTACT_ID_SELF).await?; + ChatId::create_for_contact(self, DC_CONTACT_ID_SELF).await?; } // add welcome-messages. by the label, this is done only once, diff --git a/src/test_utils.rs b/src/test_utils.rs index aef9be4da..f960b2d06 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -355,7 +355,7 @@ impl TestContext { .await .unwrap(); - let chat_id = chat::create_by_contact_id(self, contact_id).await.unwrap(); + let chat_id = ChatId::create_for_contact(self, contact_id).await.unwrap(); Chat::load_from_db(self, chat_id).await.unwrap() } @@ -367,13 +367,13 @@ impl TestContext { let contact = Contact::create(self, name, addr) .await .expect("failed to create contact"); - let chat_id = chat::create_by_contact_id(self, contact).await.unwrap(); + let chat_id = ChatId::create_for_contact(self, contact).await.unwrap(); Chat::load_from_db(self, chat_id).await.unwrap() } /// Retrieves the "self" chat. pub async fn get_self_chat(&self) -> Chat { - let chat_id = chat::create_by_contact_id(self, DC_CONTACT_ID_SELF) + let chat_id = ChatId::create_for_contact(self, DC_CONTACT_ID_SELF) .await .unwrap(); Chat::load_from_db(self, chat_id).await.unwrap()