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()