diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 4d91df384..3a1efbc5b 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -1737,9 +1737,13 @@ pub unsafe extern "C" fn dc_block_contact( let ctx = &*context; block_on(async move { if block == 0 { - Contact::unblock(&ctx, contact_id).await; + Contact::unblock(&ctx, contact_id) + .await + .ok_or_log_msg(&ctx, "Can't unblock contact"); } else { - Contact::block(&ctx, contact_id).await; + Contact::block(&ctx, contact_id) + .await + .ok_or_log_msg(&ctx, "Can't block contact"); } }); } diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index fdaeb88a1..30723e5e6 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -1137,12 +1137,12 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu "block" => { ensure!(!arg1.is_empty(), "Argument missing."); let contact_id = arg1.parse()?; - Contact::block(&context, contact_id).await; + Contact::block(&context, contact_id).await?; } "unblock" => { ensure!(!arg1.is_empty(), "Argument missing."); let contact_id = arg1.parse()?; - Contact::unblock(&context, contact_id).await; + Contact::unblock(&context, contact_id).await?; } "listblocked" => { let contacts = Contact::get_all_blocked(&context).await?; diff --git a/src/contact.rs b/src/contact.rs index b058f26f3..ba4791e2a 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -236,13 +236,13 @@ impl Contact { } /// Block the given contact. - pub async fn block(context: &Context, id: u32) { - set_block_contact(context, id, true).await; + pub async fn block(context: &Context, id: u32) -> Result<()> { + set_block_contact(context, id, true).await } /// Unblock the given contact. - pub async fn unblock(context: &Context, id: u32) { - set_block_contact(context, id, false).await; + pub async fn unblock(context: &Context, id: u32) -> Result<()> { + set_block_contact(context, id, false).await } /// Add a single contact as a result of an _explicit_ user action. @@ -270,7 +270,7 @@ impl Contact { } } if blocked { - Contact::unblock(context, contact_id).await; + Contact::unblock(context, contact_id).await?; } Ok(contact_id) @@ -1162,56 +1162,58 @@ fn sanitize_name_and_addr(name: &str, addr: &str) -> (String, String) { } } -async fn set_block_contact(context: &Context, contact_id: u32, new_blocking: bool) { - if contact_id <= DC_CONTACT_ID_LAST_SPECIAL { - return; - } +async fn set_block_contact(context: &Context, contact_id: u32, new_blocking: bool) -> Result<()> { + ensure!( + contact_id > DC_CONTACT_ID_LAST_SPECIAL, + "Can't block special contact {}", + contact_id + ); - if let Ok(contact) = Contact::load_from_db(context, contact_id).await { - if contact.blocked != new_blocking - && context - .sql - .execute( - "UPDATE contacts SET blocked=? WHERE id=?;", - paramsv![new_blocking as i32, contact_id as i32], - ) - .await - .is_ok() - { - // also (un)block all chats with _only_ this contact - we do not delete them to allow a - // non-destructive blocking->unblocking. - // (Maybe, beside normal chats (type=100) we should also block group chats with only this user. - // However, I'm not sure about this point; it may be confusing if the user wants to add other people; - // this would result in recreating the same group...) - if context - .sql - .execute( - r#" + let contact = Contact::load_from_db(context, contact_id).await?; + + if contact.blocked != new_blocking { + context + .sql + .execute( + "UPDATE contacts SET blocked=? WHERE id=?;", + paramsv![new_blocking as i32, contact_id as i32], + ) + .await?; + + // also (un)block all chats with _only_ this contact - we do not delete them to allow a + // non-destructive blocking->unblocking. + // (Maybe, beside normal chats (type=100) we should also block group chats with only this user. + // However, I'm not sure about this point; it may be confusing if the user wants to add other people; + // this would result in recreating the same group...) + if context + .sql + .execute( + r#" UPDATE chats SET blocked=? WHERE type=? AND id IN ( SELECT chat_id FROM chats_contacts WHERE contact_id=? ); "#, - paramsv![new_blocking, Chattype::Single, contact_id], - ) - .await - .is_ok() - { - Contact::mark_noticed(context, contact_id).await; - context.emit_event(EventType::ContactsChanged(Some(contact_id))); - } + paramsv![new_blocking, Chattype::Single, contact_id], + ) + .await + .is_ok() + { + Contact::mark_noticed(context, contact_id).await; + context.emit_event(EventType::ContactsChanged(Some(contact_id))); + } - // also unblock mailinglist - // if the contact is a mailinglist address explicitly created to allow unblocking - if !new_blocking && contact.origin == Origin::MailinglistAddress { - if let Ok((chat_id, _, _)) = chat::get_chat_id_by_grpid(context, contact.addr).await - { - chat_id.set_blocked(context, Blocked::Not).await; - } + // also unblock mailinglist + // if the contact is a mailinglist address explicitly created to allow unblocking + if !new_blocking && contact.origin == Origin::MailinglistAddress { + if let Ok((chat_id, _, _)) = chat::get_chat_id_by_grpid(context, contact.addr).await { + chat_id.set_blocked(context, Blocked::Not).await; } } } + + Ok(()) } /// Set profile image for a contact. diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 4248f3755..1a2c147f7 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -3018,7 +3018,9 @@ mod tests { assert_eq!(msgs.len(), 0); // Unblock contact and check if the next message arrives in real chat - Contact::unblock(&t, *blocked.first().unwrap()).await; + Contact::unblock(&t, *blocked.first().unwrap()) + .await + .unwrap(); let blocked = Contact::get_all_blocked(&t).await.unwrap(); assert_eq!(blocked.len(), 0); diff --git a/src/message.rs b/src/message.rs index dace3be95..47c1172b9 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1196,7 +1196,11 @@ pub async fn decide_on_contact_request( Err(e) => warn!(context, "decide_on_contact_request error: {}", e), }, - (Block, false) => Contact::block(context, msg.from_id).await, + (Block, false) => { + if let Err(e) = Contact::block(context, msg.from_id).await { + warn!(context, "Can't block contact: {}", e); + } + } (Block, true) => { if !msg.chat_id.set_blocked(context, Blocked::Manually).await { warn!(context, "Block mailing list failed.")