Skip to content

Commit cbe5c38

Browse files
committed
fix: Sync chat action even if sync message arrives before first one from contact (#6259)
A sync message for accepting or blocking a 1:1 chat may arrive before the first message from the contact, when it does not exist yet. This frequently happens in non-chatmail accounts that have moving to the DeltaChat folder disabled because Delta Chat unconditionally uploads sync messages to the DeltaChat folder. Let's create a hidden contact in this case and a 1:1 chat for it.
1 parent 755b245 commit cbe5c38

File tree

1 file changed

+71
-5
lines changed

1 file changed

+71
-5
lines changed

src/chat.rs

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4657,9 +4657,9 @@ impl Context {
46574657
Contact::create_ex(self, Nosync, to, addr).await?;
46584658
return Ok(());
46594659
}
4660-
let contact_id = Contact::lookup_id_by_addr_ex(self, addr, Origin::Unknown, None)
4661-
.await?
4662-
.with_context(|| format!("No contact for addr '{addr}'"))?;
4660+
let addr = ContactAddress::new(addr).context("Invalid address")?;
4661+
let (contact_id, _) =
4662+
Contact::add_or_lookup(self, "", &addr, Origin::Hidden).await?;
46634663
match action {
46644664
SyncAction::Block => {
46654665
return contact::set_blocked(self, Nosync, contact_id, true).await
@@ -4669,9 +4669,10 @@ impl Context {
46694669
}
46704670
_ => (),
46714671
}
4672-
ChatIdBlocked::lookup_by_contact(self, contact_id)
4672+
// Use `Request` so that even if the program crashes, the user doesn't have to look
4673+
// into the blocked contacts.
4674+
ChatIdBlocked::get_for_contact(self, contact_id, Blocked::Request)
46734675
.await?
4674-
.with_context(|| format!("No chat for addr '{addr}'"))?
46754676
.id
46764677
}
46774678
SyncId::Grpid(grpid) => {
@@ -7477,6 +7478,71 @@ mod tests {
74777478
Ok(())
74787479
}
74797480

7481+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
7482+
async fn test_sync_accept_before_first_msg() -> Result<()> {
7483+
let alice0 = &TestContext::new_alice().await;
7484+
let alice1 = &TestContext::new_alice().await;
7485+
for a in [alice0, alice1] {
7486+
a.set_config_bool(Config::SyncMsgs, true).await?;
7487+
}
7488+
let bob = TestContext::new_bob().await;
7489+
7490+
let ba_chat = bob.create_chat(alice0).await;
7491+
let sent_msg = bob.send_text(ba_chat.id, "hi").await;
7492+
let a0b_chat_id = alice0.recv_msg(&sent_msg).await.chat_id;
7493+
assert_eq!(alice0.get_chat(&bob).await.blocked, Blocked::Request);
7494+
a0b_chat_id.accept(alice0).await?;
7495+
let a0b_contact = alice0.add_or_lookup_contact(&bob).await;
7496+
assert_eq!(a0b_contact.origin, Origin::CreateChat);
7497+
assert_eq!(alice0.get_chat(&bob).await.blocked, Blocked::Not);
7498+
7499+
sync(alice0, alice1).await;
7500+
let a1b_contact = alice1.add_or_lookup_contact(&bob).await;
7501+
assert_eq!(a1b_contact.origin, Origin::CreateChat);
7502+
let a1b_chat = alice1.get_chat(&bob).await;
7503+
assert_eq!(a1b_chat.blocked, Blocked::Not);
7504+
let chats = Chatlist::try_load(alice1, 0, None, None).await?;
7505+
assert_eq!(chats.len(), 1);
7506+
7507+
let rcvd_msg = alice1.recv_msg(&sent_msg).await;
7508+
assert_eq!(rcvd_msg.chat_id, a1b_chat.id);
7509+
Ok(())
7510+
}
7511+
7512+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
7513+
async fn test_sync_block_before_first_msg() -> Result<()> {
7514+
let alice0 = &TestContext::new_alice().await;
7515+
let alice1 = &TestContext::new_alice().await;
7516+
for a in [alice0, alice1] {
7517+
a.set_config_bool(Config::SyncMsgs, true).await?;
7518+
}
7519+
let bob = TestContext::new_bob().await;
7520+
7521+
let ba_chat = bob.create_chat(alice0).await;
7522+
let sent_msg = bob.send_text(ba_chat.id, "hi").await;
7523+
let a0b_chat_id = alice0.recv_msg(&sent_msg).await.chat_id;
7524+
assert_eq!(alice0.get_chat(&bob).await.blocked, Blocked::Request);
7525+
a0b_chat_id.block(alice0).await?;
7526+
let a0b_contact = alice0.add_or_lookup_contact(&bob).await;
7527+
assert_eq!(a0b_contact.origin, Origin::IncomingUnknownFrom);
7528+
assert_eq!(alice0.get_chat(&bob).await.blocked, Blocked::Yes);
7529+
7530+
sync(alice0, alice1).await;
7531+
let a1b_contact = alice1.add_or_lookup_contact(&bob).await;
7532+
assert_eq!(a1b_contact.origin, Origin::Hidden);
7533+
assert!(ChatIdBlocked::lookup_by_contact(alice1, a1b_contact.id)
7534+
.await?
7535+
.is_none());
7536+
7537+
let rcvd_msg = alice1.recv_msg(&sent_msg).await;
7538+
let a1b_contact = alice1.add_or_lookup_contact(&bob).await;
7539+
assert_eq!(a1b_contact.origin, Origin::IncomingUnknownFrom);
7540+
let a1b_chat = alice1.get_chat(&bob).await;
7541+
assert_eq!(a1b_chat.blocked, Blocked::Yes);
7542+
assert_eq!(rcvd_msg.chat_id, a1b_chat.id);
7543+
Ok(())
7544+
}
7545+
74807546
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
74817547
async fn test_sync_adhoc_grp() -> Result<()> {
74827548
let alice0 = &TestContext::new_alice().await;

0 commit comments

Comments
 (0)