mirror of
https://github.com/chatmail/core.git
synced 2026-04-28 19:06:35 +03:00
Introduce a ContactId newtype
This makes the contact ID its own newtype instead of being a plain u32. The change purposefully does not yet try and reap any benefits from this yet, instead aiming for a boring change that's easy to review. Only exception is the ToSql/FromSql as not doing that yet would also have created churn in the database code and it is easier to go straight for the right solution here.
This commit is contained in:
@@ -31,7 +31,7 @@ use rand::Rng;
|
||||
|
||||
use deltachat::chat::{ChatId, ChatVisibility, MuteDuration, ProtectionStatus};
|
||||
use deltachat::constants::DC_MSG_ID_LAST_SPECIAL;
|
||||
use deltachat::contact::{Contact, Origin};
|
||||
use deltachat::contact::{Contact, ContactId, Origin};
|
||||
use deltachat::context::Context;
|
||||
use deltachat::ephemeral::Timer as EphemeralTimer;
|
||||
use deltachat::key::DcKey;
|
||||
@@ -493,14 +493,16 @@ pub unsafe extern "C" fn dc_event_get_data1_int(event: *mut dc_event_t) -> libc:
|
||||
| EventType::ChatEphemeralTimerModified { chat_id, .. } => chat_id.to_u32() as libc::c_int,
|
||||
EventType::ContactsChanged(id) | EventType::LocationChanged(id) => {
|
||||
let id = id.unwrap_or_default();
|
||||
id as libc::c_int
|
||||
id.to_u32() as libc::c_int
|
||||
}
|
||||
EventType::ConfigureProgress { progress, .. } | EventType::ImexProgress(progress) => {
|
||||
*progress as libc::c_int
|
||||
}
|
||||
EventType::ImexFileWritten(_) => 0,
|
||||
EventType::SecurejoinInviterProgress { contact_id, .. }
|
||||
| EventType::SecurejoinJoinerProgress { contact_id, .. } => *contact_id as libc::c_int,
|
||||
| EventType::SecurejoinJoinerProgress { contact_id, .. } => {
|
||||
contact_id.to_u32() as libc::c_int
|
||||
}
|
||||
EventType::WebxdcStatusUpdate(msg_id) => msg_id.to_u32() as libc::c_int,
|
||||
}
|
||||
}
|
||||
@@ -715,7 +717,11 @@ pub unsafe extern "C" fn dc_get_chatlist(
|
||||
let ctx = &*context;
|
||||
let qs = to_opt_string_lossy(query_str);
|
||||
|
||||
let qi = if query_id == 0 { None } else { Some(query_id) };
|
||||
let qi = if query_id == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(ContactId::new(query_id))
|
||||
};
|
||||
|
||||
block_on(async move {
|
||||
match chatlist::Chatlist::try_load(ctx, flags as usize, qs.as_deref(), qi)
|
||||
@@ -743,7 +749,7 @@ pub unsafe extern "C" fn dc_create_chat_by_contact_id(
|
||||
let ctx = &*context;
|
||||
|
||||
block_on(async move {
|
||||
ChatId::create_for_contact(ctx, contact_id)
|
||||
ChatId::create_for_contact(ctx, ContactId::new(contact_id))
|
||||
.await
|
||||
.log_err(ctx, "Failed to create chat from contact_id")
|
||||
.map(|id| id.to_u32())
|
||||
@@ -763,7 +769,7 @@ pub unsafe extern "C" fn dc_get_chat_id_by_contact_id(
|
||||
let ctx = &*context;
|
||||
|
||||
block_on(async move {
|
||||
ChatId::lookup_by_contact(ctx, contact_id)
|
||||
ChatId::lookup_by_contact(ctx, ContactId::new(contact_id))
|
||||
.await
|
||||
.log_err(ctx, "Failed to get chat for contact_id")
|
||||
.unwrap_or_default() // unwraps the Result
|
||||
@@ -1340,7 +1346,10 @@ pub unsafe extern "C" fn dc_get_chat_contacts(
|
||||
let arr = dc_array_t::from(
|
||||
chat::get_chat_contacts(ctx, ChatId::new(chat_id))
|
||||
.await
|
||||
.unwrap_or_log_default(ctx, "Failed get_chat_contacts"),
|
||||
.unwrap_or_log_default(ctx, "Failed get_chat_contacts")
|
||||
.iter()
|
||||
.map(|id| id.to_u32())
|
||||
.collect::<Vec<u32>>(),
|
||||
);
|
||||
Box::into_raw(Box::new(arr))
|
||||
})
|
||||
@@ -1450,7 +1459,7 @@ pub unsafe extern "C" fn dc_is_contact_in_chat(
|
||||
block_on(chat::is_contact_in_chat(
|
||||
ctx,
|
||||
ChatId::new(chat_id),
|
||||
contact_id,
|
||||
ContactId::new(contact_id),
|
||||
))
|
||||
.log_err(ctx, "is_contact_in_chat failed")
|
||||
.unwrap_or_default() as libc::c_int
|
||||
@@ -1471,7 +1480,7 @@ pub unsafe extern "C" fn dc_add_contact_to_chat(
|
||||
block_on(chat::add_contact_to_chat(
|
||||
ctx,
|
||||
ChatId::new(chat_id),
|
||||
contact_id,
|
||||
ContactId::new(contact_id),
|
||||
))
|
||||
.log_err(ctx, "Failed to add contact")
|
||||
.is_ok() as libc::c_int
|
||||
@@ -1492,7 +1501,7 @@ pub unsafe extern "C" fn dc_remove_contact_from_chat(
|
||||
block_on(chat::remove_contact_from_chat(
|
||||
ctx,
|
||||
ChatId::new(chat_id),
|
||||
contact_id,
|
||||
ContactId::new(contact_id),
|
||||
))
|
||||
.log_err(ctx, "Failed to remove contact")
|
||||
.is_ok() as libc::c_int
|
||||
@@ -1827,7 +1836,8 @@ pub unsafe extern "C" fn dc_lookup_contact_id_by_addr(
|
||||
Contact::lookup_id_by_addr(ctx, &to_string_lossy(addr), Origin::IncomingReplyTo)
|
||||
.await
|
||||
.unwrap_or_log_default(ctx, "failed to lookup id")
|
||||
.unwrap_or(0)
|
||||
.map(|id| id.to_u32())
|
||||
.unwrap_or_default()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1847,6 +1857,7 @@ pub unsafe extern "C" fn dc_create_contact(
|
||||
block_on(async move {
|
||||
Contact::create(ctx, &name, &to_string_lossy(addr))
|
||||
.await
|
||||
.map(|id| id.to_u32())
|
||||
.unwrap_or(0)
|
||||
})
|
||||
}
|
||||
@@ -1885,7 +1896,9 @@ pub unsafe extern "C" fn dc_get_contacts(
|
||||
|
||||
block_on(async move {
|
||||
match Contact::get_all(ctx, flags, query).await {
|
||||
Ok(contacts) => Box::into_raw(Box::new(dc_array_t::from(contacts))),
|
||||
Ok(contacts) => Box::into_raw(Box::new(dc_array_t::from(
|
||||
contacts.iter().map(|id| id.to_u32()).collect::<Vec<u32>>(),
|
||||
))),
|
||||
Err(_) => ptr::null_mut(),
|
||||
}
|
||||
})
|
||||
@@ -1922,7 +1935,10 @@ pub unsafe extern "C" fn dc_get_blocked_contacts(
|
||||
Contact::get_all_blocked(ctx)
|
||||
.await
|
||||
.log_err(ctx, "Can't get blocked contacts")
|
||||
.unwrap_or_default(),
|
||||
.unwrap_or_default()
|
||||
.iter()
|
||||
.map(|id| id.to_u32())
|
||||
.collect::<Vec<u32>>(),
|
||||
)))
|
||||
})
|
||||
}
|
||||
@@ -1933,18 +1949,18 @@ pub unsafe extern "C" fn dc_block_contact(
|
||||
contact_id: u32,
|
||||
block: libc::c_int,
|
||||
) {
|
||||
if context.is_null() || contact_id <= constants::DC_CONTACT_ID_LAST_SPECIAL as u32 {
|
||||
if context.is_null() || contact_id <= constants::DC_CONTACT_ID_LAST_SPECIAL.to_u32() {
|
||||
eprintln!("ignoring careless call to dc_block_contact()");
|
||||
return;
|
||||
}
|
||||
let ctx = &*context;
|
||||
block_on(async move {
|
||||
if block == 0 {
|
||||
Contact::unblock(ctx, contact_id)
|
||||
Contact::unblock(ctx, ContactId::new(contact_id))
|
||||
.await
|
||||
.ok_or_log_msg(ctx, "Can't unblock contact");
|
||||
} else {
|
||||
Contact::block(ctx, contact_id)
|
||||
Contact::block(ctx, ContactId::new(contact_id))
|
||||
.await
|
||||
.ok_or_log_msg(ctx, "Can't block contact");
|
||||
}
|
||||
@@ -1963,7 +1979,7 @@ pub unsafe extern "C" fn dc_get_contact_encrinfo(
|
||||
let ctx = &*context;
|
||||
|
||||
block_on(async move {
|
||||
Contact::get_encrinfo(ctx, contact_id)
|
||||
Contact::get_encrinfo(ctx, ContactId::new(contact_id))
|
||||
.await
|
||||
.map(|s| s.strdup())
|
||||
.unwrap_or_else(|e| {
|
||||
@@ -1978,14 +1994,14 @@ pub unsafe extern "C" fn dc_delete_contact(
|
||||
context: *mut dc_context_t,
|
||||
contact_id: u32,
|
||||
) -> libc::c_int {
|
||||
if context.is_null() || contact_id <= constants::DC_CONTACT_ID_LAST_SPECIAL as u32 {
|
||||
if context.is_null() || contact_id <= constants::DC_CONTACT_ID_LAST_SPECIAL.to_u32() {
|
||||
eprintln!("ignoring careless call to dc_delete_contact()");
|
||||
return 0;
|
||||
}
|
||||
let ctx = &*context;
|
||||
|
||||
block_on(async move {
|
||||
match Contact::delete(ctx, contact_id).await {
|
||||
match Contact::delete(ctx, ContactId::new(contact_id)).await {
|
||||
Ok(_) => 1,
|
||||
Err(_) => 0,
|
||||
}
|
||||
@@ -2004,7 +2020,7 @@ pub unsafe extern "C" fn dc_get_contact(
|
||||
let ctx = &*context;
|
||||
|
||||
block_on(async move {
|
||||
Contact::get_by_id(ctx, contact_id)
|
||||
Contact::get_by_id(ctx, ContactId::new(contact_id))
|
||||
.await
|
||||
.map(|contact| Box::into_raw(Box::new(ContactWrapper { context, contact })))
|
||||
.unwrap_or_else(|_| ptr::null_mut())
|
||||
@@ -2427,7 +2443,7 @@ pub unsafe extern "C" fn dc_array_get_contact_id(
|
||||
return 0;
|
||||
}
|
||||
|
||||
(*array).get_location(index).contact_id
|
||||
(*array).get_location(index).contact_id.to_u32()
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_msg_id(
|
||||
@@ -2943,7 +2959,7 @@ pub unsafe extern "C" fn dc_msg_get_from_id(msg: *mut dc_msg_t) -> u32 {
|
||||
return 0;
|
||||
}
|
||||
let ffi_msg = &*msg;
|
||||
ffi_msg.message.get_from_id()
|
||||
ffi_msg.message.get_from_id().to_u32()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -3654,7 +3670,7 @@ pub unsafe extern "C" fn dc_contact_get_id(contact: *mut dc_contact_t) -> u32 {
|
||||
return 0;
|
||||
}
|
||||
let ffi_contact = &*contact;
|
||||
ffi_contact.contact.get_id()
|
||||
ffi_contact.contact.get_id().to_u32()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
||||
@@ -111,19 +111,19 @@ impl Lot {
|
||||
match self {
|
||||
Self::Summary(_) => Default::default(),
|
||||
Self::Qr(qr) => match qr {
|
||||
Qr::AskVerifyContact { contact_id, .. } => *contact_id,
|
||||
Qr::AskVerifyContact { contact_id, .. } => contact_id.to_u32(),
|
||||
Qr::AskVerifyGroup { .. } => Default::default(),
|
||||
Qr::FprOk { contact_id } => *contact_id,
|
||||
Qr::FprMismatch { contact_id } => contact_id.unwrap_or_default(),
|
||||
Qr::FprOk { contact_id } => contact_id.to_u32(),
|
||||
Qr::FprMismatch { contact_id } => contact_id.unwrap_or_default().to_u32(),
|
||||
Qr::FprWithoutAddr { .. } => Default::default(),
|
||||
Qr::Account { .. } => Default::default(),
|
||||
Qr::WebrtcInstance { .. } => Default::default(),
|
||||
Qr::Addr { contact_id } => *contact_id,
|
||||
Qr::Addr { contact_id } => contact_id.to_u32(),
|
||||
Qr::Url { .. } => Default::default(),
|
||||
Qr::Text { .. } => Default::default(),
|
||||
Qr::WithdrawVerifyContact { contact_id, .. } => *contact_id,
|
||||
Qr::WithdrawVerifyContact { contact_id, .. } => contact_id.to_u32(),
|
||||
Qr::WithdrawVerifyGroup { .. } => Default::default(),
|
||||
Qr::ReviveVerifyContact { contact_id, .. } => *contact_id,
|
||||
Qr::ReviveVerifyContact { contact_id, .. } => contact_id.to_u32(),
|
||||
Qr::ReviveVerifyGroup { .. } => Default::default(),
|
||||
},
|
||||
Self::Error(_) => Default::default(),
|
||||
|
||||
@@ -209,7 +209,7 @@ async fn log_msg(context: &Context, prefix: impl AsRef<str>, msg: &Message) {
|
||||
contact_id,
|
||||
msgtext.unwrap_or_default(),
|
||||
if msg.has_html() { "[HAS-HTML]️" } else { "" },
|
||||
if msg.get_from_id() == 1 {
|
||||
if msg.get_from_id() == DC_CONTACT_ID_SELF {
|
||||
""
|
||||
} else if msg.get_state() == MessageState::InSeen {
|
||||
"[SEEN]"
|
||||
@@ -267,7 +267,7 @@ async fn log_msglist(context: &Context, msglist: &[MsgId]) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn log_contactlist(context: &Context, contacts: &[u32]) -> Result<()> {
|
||||
async fn log_contactlist(context: &Context, contacts: &[ContactId]) -> Result<()> {
|
||||
for contact_id in contacts {
|
||||
let mut line2 = "".to_string();
|
||||
let contact = Contact::get_by_id(context, *contact_id).await?;
|
||||
@@ -296,7 +296,7 @@ async fn log_contactlist(context: &Context, contacts: &[u32]) -> Result<()> {
|
||||
let peerstate = Peerstate::from_addr(context, addr)
|
||||
.await
|
||||
.expect("peerstate error");
|
||||
if peerstate.is_some() && *contact_id != 1 {
|
||||
if peerstate.is_some() && *contact_id != DC_CONTACT_ID_SELF {
|
||||
line2 = format!(
|
||||
", prefer-encrypt={}",
|
||||
peerstate.as_ref().unwrap().prefer_encrypt
|
||||
@@ -714,7 +714,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
|
||||
}
|
||||
"createchat" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <contact-id> missing.");
|
||||
let contact_id: u32 = arg1.parse()?;
|
||||
let contact_id = ContactId::new(arg1.parse()?);
|
||||
let chat_id = ChatId::create_for_contact(&context, contact_id).await?;
|
||||
|
||||
println!("Single#{} created successfully.", chat_id,);
|
||||
@@ -742,7 +742,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
|
||||
ensure!(sel_chat.is_some(), "No chat selected");
|
||||
ensure!(!arg1.is_empty(), "Argument <contact-id> missing.");
|
||||
|
||||
let contact_id_0: u32 = arg1.parse()?;
|
||||
let contact_id_0 = ContactId::new(arg1.parse()?);
|
||||
chat::add_contact_to_chat(&context, sel_chat.as_ref().unwrap().get_id(), contact_id_0)
|
||||
.await?;
|
||||
println!("Contact added to chat.");
|
||||
@@ -750,7 +750,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
|
||||
"removemember" => {
|
||||
ensure!(sel_chat.is_some(), "No chat selected.");
|
||||
ensure!(!arg1.is_empty(), "Argument <contact-id> missing.");
|
||||
let contact_id_1: u32 = arg1.parse()?;
|
||||
let contact_id_1 = ContactId::new(arg1.parse()?);
|
||||
chat::remove_contact_from_chat(
|
||||
&context,
|
||||
sel_chat.as_ref().unwrap().get_id(),
|
||||
@@ -1134,7 +1134,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
|
||||
"contactinfo" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <contact-id> missing.");
|
||||
|
||||
let contact_id: u32 = arg1.parse()?;
|
||||
let contact_id = ContactId::new(arg1.parse()?);
|
||||
let contact = Contact::get_by_id(&context, contact_id).await?;
|
||||
let name_n_addr = contact.get_name_n_addr();
|
||||
|
||||
@@ -1169,16 +1169,16 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
|
||||
}
|
||||
"delcontact" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <contact-id> missing.");
|
||||
Contact::delete(&context, arg1.parse()?).await?;
|
||||
Contact::delete(&context, ContactId::new(arg1.parse()?)).await?;
|
||||
}
|
||||
"block" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <contact-id> missing.");
|
||||
let contact_id = arg1.parse()?;
|
||||
let contact_id = ContactId::new(arg1.parse()?);
|
||||
Contact::block(&context, contact_id).await?;
|
||||
}
|
||||
"unblock" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <contact-id> missing.");
|
||||
let contact_id = arg1.parse()?;
|
||||
let contact_id = ContactId::new(arg1.parse()?);
|
||||
Contact::unblock(&context, contact_id).await?;
|
||||
}
|
||||
"listblocked" => {
|
||||
|
||||
108
src/chat.rs
108
src/chat.rs
@@ -20,7 +20,7 @@ use crate::constants::{
|
||||
DC_CONTACT_ID_LAST_SPECIAL, DC_CONTACT_ID_SELF, DC_GCM_ADDDAYMARKER, DC_GCM_INFO_ONLY,
|
||||
DC_RESEND_USER_AVATAR_DAYS,
|
||||
};
|
||||
use crate::contact::{addr_cmp, Contact, Origin, VerifiedStatus};
|
||||
use crate::contact::{addr_cmp, Contact, ContactId, Origin, VerifiedStatus};
|
||||
use crate::context::Context;
|
||||
use crate::dc_receive_imf::ReceivedMsg;
|
||||
use crate::dc_tools::{
|
||||
@@ -153,7 +153,10 @@ impl ChatId {
|
||||
/// 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<Option<Self>> {
|
||||
pub async fn lookup_by_contact(
|
||||
context: &Context,
|
||||
contact_id: ContactId,
|
||||
) -> Result<Option<Self>> {
|
||||
ChatIdBlocked::lookup_by_contact(context, contact_id)
|
||||
.await
|
||||
.map(|lookup| lookup.map(|chat| chat.id))
|
||||
@@ -166,7 +169,7 @@ impl ChatId {
|
||||
/// 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<Self> {
|
||||
pub async fn get_for_contact(context: &Context, contact_id: ContactId) -> Result<Self> {
|
||||
ChatIdBlocked::get_for_contact(context, contact_id, Blocked::Not)
|
||||
.await
|
||||
.map(|chat| chat.id)
|
||||
@@ -176,7 +179,7 @@ impl ChatId {
|
||||
///
|
||||
/// This should be used when **a user action** creates a chat 1:1, it ensures the chat
|
||||
/// exists, is unblocked and scales the [`Contact`]'s origin.
|
||||
pub async fn create_for_contact(context: &Context, contact_id: u32) -> Result<Self> {
|
||||
pub async fn create_for_contact(context: &Context, contact_id: ContactId) -> Result<Self> {
|
||||
ChatId::create_for_contact_with_blocked(context, contact_id, Blocked::Not).await
|
||||
}
|
||||
|
||||
@@ -185,7 +188,7 @@ impl ChatId {
|
||||
/// `create_blocked` won't block already unblocked chats again.
|
||||
pub(crate) async fn create_for_contact_with_blocked(
|
||||
context: &Context,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
create_blocked: Blocked,
|
||||
) -> Result<Self> {
|
||||
let chat_id = match ChatIdBlocked::lookup_by_contact(context, contact_id).await? {
|
||||
@@ -420,7 +423,7 @@ impl ChatId {
|
||||
context: &Context,
|
||||
protect: ProtectionStatus,
|
||||
promote: bool,
|
||||
from_id: u32,
|
||||
from_id: ContactId,
|
||||
) -> Result<()> {
|
||||
let msg_text = context.stock_protection_msg(protect, from_id).await;
|
||||
let cmd = match protect {
|
||||
@@ -1628,7 +1631,11 @@ pub(crate) async fn get_broadcast_icon(context: &Context) -> Result<String> {
|
||||
Ok(icon)
|
||||
}
|
||||
|
||||
async fn update_special_chat_name(context: &Context, contact_id: u32, name: String) -> Result<()> {
|
||||
async fn update_special_chat_name(
|
||||
context: &Context,
|
||||
contact_id: ContactId,
|
||||
name: String,
|
||||
) -> Result<()> {
|
||||
if let Some(chat_id) = ChatId::lookup_by_contact(context, contact_id).await? {
|
||||
// the `!= name` condition avoids unneeded writes
|
||||
context
|
||||
@@ -1675,9 +1682,15 @@ impl ChatIdBlocked {
|
||||
/// Searches the database for the 1:1 chat with this contact.
|
||||
///
|
||||
/// If no chat is found `None` is returned.
|
||||
pub async fn lookup_by_contact(context: &Context, contact_id: u32) -> Result<Option<Self>> {
|
||||
pub async fn lookup_by_contact(
|
||||
context: &Context,
|
||||
contact_id: ContactId,
|
||||
) -> Result<Option<Self>> {
|
||||
ensure!(context.sql.is_open().await, "Database not available");
|
||||
ensure!(contact_id > 0, "Invalid contact id requested");
|
||||
ensure!(
|
||||
contact_id > ContactId::new(0),
|
||||
"Invalid contact id requested"
|
||||
);
|
||||
|
||||
context
|
||||
.sql
|
||||
@@ -1706,11 +1719,14 @@ impl ChatIdBlocked {
|
||||
/// state.
|
||||
pub async fn get_for_contact(
|
||||
context: &Context,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
create_blocked: Blocked,
|
||||
) -> Result<Self> {
|
||||
ensure!(context.sql.is_open().await, "Database not available");
|
||||
ensure!(contact_id > 0, "Invalid contact id requested");
|
||||
ensure!(
|
||||
contact_id > ContactId::new(0),
|
||||
"Invalid contact id requested"
|
||||
);
|
||||
|
||||
if let Some(res) = Self::lookup_by_contact(context, contact_id).await? {
|
||||
// Already exists, no need to create.
|
||||
@@ -1914,7 +1930,7 @@ async fn prepare_msg_common(
|
||||
pub async fn is_contact_in_chat(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
) -> Result<bool> {
|
||||
// this function works for group and for normal chats, however, it is more useful
|
||||
// for group chats.
|
||||
@@ -1925,7 +1941,7 @@ pub async fn is_contact_in_chat(
|
||||
.sql
|
||||
.exists(
|
||||
"SELECT COUNT(*) FROM chats_contacts WHERE chat_id=? AND contact_id=?;",
|
||||
paramsv![chat_id, contact_id as i32],
|
||||
paramsv![chat_id, contact_id],
|
||||
)
|
||||
.await?;
|
||||
Ok(exists)
|
||||
@@ -2227,9 +2243,12 @@ pub async fn get_chat_msgs(
|
||||
|row: &rusqlite::Row| {
|
||||
// is_info logic taken from Message.is_info()
|
||||
let params = row.get::<_, String>("param")?;
|
||||
let (from_id, to_id) = (row.get::<_, u32>("from_id")?, row.get::<_, u32>("to_id")?);
|
||||
let is_info_msg: bool = from_id == DC_CONTACT_ID_INFO as u32
|
||||
|| to_id == DC_CONTACT_ID_INFO as u32
|
||||
let (from_id, to_id) = (
|
||||
row.get::<_, ContactId>("from_id")?,
|
||||
row.get::<_, ContactId>("to_id")?,
|
||||
);
|
||||
let is_info_msg: bool = from_id == DC_CONTACT_ID_INFO
|
||||
|| to_id == DC_CONTACT_ID_INFO
|
||||
|| match Params::from_str(¶ms) {
|
||||
Ok(p) => {
|
||||
let cmd = p.get_cmd();
|
||||
@@ -2530,7 +2549,7 @@ pub async fn get_next_media(
|
||||
}
|
||||
|
||||
/// Returns a vector of contact IDs for given chat ID.
|
||||
pub async fn get_chat_contacts(context: &Context, chat_id: ChatId) -> Result<Vec<u32>> {
|
||||
pub async fn get_chat_contacts(context: &Context, chat_id: ChatId) -> Result<Vec<ContactId>> {
|
||||
// Normal chats do not include SELF. Group chats do (as it may happen that one is deleted from a
|
||||
// groupchat but the chats stays visible, moreover, this makes displaying lists easier)
|
||||
|
||||
@@ -2544,7 +2563,7 @@ pub async fn get_chat_contacts(context: &Context, chat_id: ChatId) -> Result<Vec
|
||||
WHERE cc.chat_id=?
|
||||
ORDER BY c.id=1, LOWER(c.name||c.addr), c.id;",
|
||||
paramsv![chat_id],
|
||||
|row| row.get::<_, u32>(0),
|
||||
|row| row.get::<_, ContactId>(0),
|
||||
|ids| ids.collect::<Result<Vec<_>, _>>().map_err(Into::into),
|
||||
)
|
||||
.await?;
|
||||
@@ -2651,13 +2670,13 @@ pub async fn create_broadcast_list(context: &Context) -> Result<ChatId> {
|
||||
pub(crate) async fn add_to_chat_contacts_table(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
) -> Result<()> {
|
||||
context
|
||||
.sql
|
||||
.execute(
|
||||
"INSERT INTO chats_contacts (chat_id, contact_id) VALUES(?, ?)",
|
||||
paramsv![chat_id, contact_id as i32],
|
||||
paramsv![chat_id, contact_id],
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
@@ -2667,13 +2686,13 @@ pub(crate) async fn add_to_chat_contacts_table(
|
||||
pub(crate) async fn remove_from_chat_contacts_table(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
) -> Result<()> {
|
||||
context
|
||||
.sql
|
||||
.execute(
|
||||
"DELETE FROM chats_contacts WHERE chat_id=? AND contact_id=?",
|
||||
paramsv![chat_id, contact_id as i32],
|
||||
paramsv![chat_id, contact_id],
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
@@ -2683,7 +2702,7 @@ pub(crate) async fn remove_from_chat_contacts_table(
|
||||
pub async fn add_contact_to_chat(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
) -> Result<()> {
|
||||
add_contact_to_chat_ex(context, chat_id, contact_id, false).await?;
|
||||
Ok(())
|
||||
@@ -2692,7 +2711,7 @@ pub async fn add_contact_to_chat(
|
||||
pub(crate) async fn add_contact_to_chat_ex(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
from_handshake: bool,
|
||||
) -> Result<bool> {
|
||||
ensure!(!chat_id.is_special(), "can not add member to special chats");
|
||||
@@ -2769,9 +2788,8 @@ pub(crate) async fn add_contact_to_chat_ex(
|
||||
if chat.typ == Chattype::Group && chat.is_promoted() {
|
||||
msg.viewtype = Viewtype::Text;
|
||||
|
||||
msg.text = Some(
|
||||
stock_str::msg_add_member(context, contact.get_addr(), DC_CONTACT_ID_SELF as u32).await,
|
||||
);
|
||||
msg.text =
|
||||
Some(stock_str::msg_add_member(context, contact.get_addr(), DC_CONTACT_ID_SELF).await);
|
||||
msg.param.set_cmd(SystemMessage::MemberAddedToGroup);
|
||||
msg.param.set(Param::Arg, contact.get_addr());
|
||||
msg.param.set_int(Param::Arg2, from_handshake.into());
|
||||
@@ -2874,7 +2892,7 @@ pub async fn set_muted(context: &Context, chat_id: ChatId, duration: MuteDuratio
|
||||
pub async fn remove_contact_from_chat(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
) -> Result<()> {
|
||||
ensure!(
|
||||
!chat_id.is_special(),
|
||||
@@ -2903,15 +2921,14 @@ pub async fn remove_contact_from_chat(
|
||||
msg.viewtype = Viewtype::Text;
|
||||
if contact.id == DC_CONTACT_ID_SELF {
|
||||
set_group_explicitly_left(context, &chat.grpid).await?;
|
||||
msg.text = Some(
|
||||
stock_str::msg_group_left(context, DC_CONTACT_ID_SELF as u32).await,
|
||||
);
|
||||
msg.text =
|
||||
Some(stock_str::msg_group_left(context, DC_CONTACT_ID_SELF).await);
|
||||
} else {
|
||||
msg.text = Some(
|
||||
stock_str::msg_del_member(
|
||||
context,
|
||||
contact.get_addr(),
|
||||
DC_CONTACT_ID_SELF as u32,
|
||||
DC_CONTACT_ID_SELF,
|
||||
)
|
||||
.await,
|
||||
);
|
||||
@@ -3004,13 +3021,8 @@ pub async fn set_chat_name(context: &Context, chat_id: ChatId, new_name: &str) -
|
||||
if chat.is_promoted() && !chat.is_mailing_list() && chat.typ != Chattype::Broadcast {
|
||||
msg.viewtype = Viewtype::Text;
|
||||
msg.text = Some(
|
||||
stock_str::msg_grp_name(
|
||||
context,
|
||||
&chat.name,
|
||||
&new_name,
|
||||
DC_CONTACT_ID_SELF as u32,
|
||||
)
|
||||
.await,
|
||||
stock_str::msg_grp_name(context, &chat.name, &new_name, DC_CONTACT_ID_SELF)
|
||||
.await,
|
||||
);
|
||||
msg.param.set_cmd(SystemMessage::GroupNameChanged);
|
||||
if !chat.name.is_empty() {
|
||||
@@ -3063,7 +3075,7 @@ pub async fn set_chat_profile_image(
|
||||
if new_image.as_ref().is_empty() {
|
||||
chat.param.remove(Param::ProfileImage);
|
||||
msg.param.remove(Param::Arg);
|
||||
msg.text = Some(stock_str::msg_grp_img_deleted(context, DC_CONTACT_ID_SELF as u32).await);
|
||||
msg.text = Some(stock_str::msg_grp_img_deleted(context, DC_CONTACT_ID_SELF).await);
|
||||
} else {
|
||||
let mut image_blob = match BlobObject::from_path(context, Path::new(new_image.as_ref())) {
|
||||
Ok(blob) => Ok(blob),
|
||||
@@ -3077,7 +3089,7 @@ pub async fn set_chat_profile_image(
|
||||
image_blob.recode_to_avatar_size(context).await?;
|
||||
chat.param.set(Param::ProfileImage, image_blob.as_name());
|
||||
msg.param.set(Param::Arg, image_blob.as_name());
|
||||
msg.text = Some(stock_str::msg_grp_img_changed(context, DC_CONTACT_ID_SELF as u32).await);
|
||||
msg.text = Some(stock_str::msg_grp_img_changed(context, DC_CONTACT_ID_SELF).await);
|
||||
}
|
||||
chat.update_param(context).await?;
|
||||
if chat.is_promoted() && !chat.is_mailing_list() {
|
||||
@@ -3905,7 +3917,7 @@ mod tests {
|
||||
async fn test_self_talk() -> Result<()> {
|
||||
let t = TestContext::new_alice().await;
|
||||
let chat = &t.get_self_chat().await;
|
||||
assert_eq!(DC_CONTACT_ID_SELF, 1);
|
||||
assert_eq!(DC_CONTACT_ID_SELF, ContactId::new(1));
|
||||
assert!(!chat.id.is_special());
|
||||
assert!(chat.is_self_talk());
|
||||
assert!(chat.visibility == ChatVisibility::Normal);
|
||||
@@ -4322,7 +4334,7 @@ mod tests {
|
||||
let contact1 = Contact::create(&context.ctx, "bob", "bob@mail.de")
|
||||
.await
|
||||
.unwrap();
|
||||
assert_ne!(contact1, 0);
|
||||
assert_ne!(contact1, ContactId::new(0));
|
||||
|
||||
let chat_id = ChatId::create_for_contact(&context.ctx, contact1)
|
||||
.await
|
||||
@@ -4527,7 +4539,7 @@ mod tests {
|
||||
|
||||
// create contact, then unblocked chat
|
||||
let contact_id = Contact::create(&ctx, "", "bob@foo.de").await.unwrap();
|
||||
assert_ne!(contact_id, 0);
|
||||
assert_ne!(contact_id, ContactId::new(0));
|
||||
let found = ChatId::lookup_by_contact(&ctx, contact_id).await.unwrap();
|
||||
assert!(found.is_none());
|
||||
|
||||
@@ -4553,10 +4565,14 @@ mod tests {
|
||||
assert_eq!(chat2.blocked, Blocked::Yes);
|
||||
|
||||
// test nonexistent contact
|
||||
let found = ChatId::lookup_by_contact(&ctx, 1234).await.unwrap();
|
||||
let found = ChatId::lookup_by_contact(&ctx, ContactId::new(1234))
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(found.is_none());
|
||||
|
||||
let found = ChatIdBlocked::lookup_by_contact(&ctx, 1234).await.unwrap();
|
||||
let found = ChatIdBlocked::lookup_by_contact(&ctx, ContactId::new(1234))
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(found.is_none());
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::constants::{
|
||||
DC_CONTACT_ID_SELF, DC_CONTACT_ID_UNDEFINED, DC_GCL_ADD_ALLDONE_HINT, DC_GCL_ARCHIVED_ONLY,
|
||||
DC_GCL_FOR_FORWARDING, DC_GCL_NO_SPECIALS,
|
||||
};
|
||||
use crate::contact::Contact;
|
||||
use crate::contact::{Contact, ContactId};
|
||||
use crate::context::Context;
|
||||
use crate::ephemeral::delete_expired_messages;
|
||||
use crate::message::{Message, MessageState, MsgId};
|
||||
@@ -85,7 +85,7 @@ impl Chatlist {
|
||||
context: &Context,
|
||||
listflags: usize,
|
||||
query: Option<&str>,
|
||||
query_contact_id: Option<u32>,
|
||||
query_contact_id: Option<ContactId>,
|
||||
) -> Result<Self> {
|
||||
let flag_archived_only = 0 != listflags & DC_GCL_ARCHIVED_ONLY;
|
||||
let flag_for_forwarding = 0 != listflags & DC_GCL_FOR_FORWARDING;
|
||||
@@ -147,7 +147,7 @@ impl Chatlist {
|
||||
AND c.id IN(SELECT chat_id FROM chats_contacts WHERE contact_id=?2)
|
||||
GROUP BY c.id
|
||||
ORDER BY c.archived=?3 DESC, IFNULL(m.timestamp,c.created_timestamp) DESC, m.id DESC;",
|
||||
paramsv![MessageState::OutDraft, query_contact_id as i32, ChatVisibility::Pinned],
|
||||
paramsv![MessageState::OutDraft, query_contact_id, ChatVisibility::Pinned],
|
||||
process_row,
|
||||
process_rows,
|
||||
).await?
|
||||
|
||||
@@ -4,6 +4,7 @@ use once_cell::sync::Lazy;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::chat::ChatId;
|
||||
use crate::contact::ContactId;
|
||||
|
||||
pub static DC_VERSION_STR: Lazy<String> = Lazy::new(|| env!("CARGO_PKG_VERSION").to_string());
|
||||
|
||||
@@ -179,11 +180,11 @@ pub const DC_ELLIPSIS: &str = "[...]";
|
||||
/// `char`s), not Unicode Grapheme Clusters.
|
||||
pub const DC_DESIRED_TEXT_LEN: usize = 5000;
|
||||
|
||||
pub const DC_CONTACT_ID_UNDEFINED: u32 = 0;
|
||||
pub const DC_CONTACT_ID_SELF: u32 = 1;
|
||||
pub const DC_CONTACT_ID_INFO: u32 = 2;
|
||||
pub const DC_CONTACT_ID_DEVICE: u32 = 5;
|
||||
pub const DC_CONTACT_ID_LAST_SPECIAL: u32 = 9;
|
||||
pub const DC_CONTACT_ID_UNDEFINED: ContactId = ContactId::new(0);
|
||||
pub const DC_CONTACT_ID_SELF: ContactId = ContactId::new(1);
|
||||
pub const DC_CONTACT_ID_INFO: ContactId = ContactId::new(2);
|
||||
pub const DC_CONTACT_ID_DEVICE: ContactId = ContactId::new(5);
|
||||
pub const DC_CONTACT_ID_LAST_SPECIAL: ContactId = ContactId::new(9);
|
||||
|
||||
// decorative address that is used for DC_CONTACT_ID_DEVICE
|
||||
// when an api that returns an email is called.
|
||||
|
||||
160
src/contact.rs
160
src/contact.rs
@@ -1,12 +1,14 @@
|
||||
//! Contacts module
|
||||
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::fmt;
|
||||
|
||||
use anyhow::{bail, ensure, Context as _, Result};
|
||||
use async_std::path::PathBuf;
|
||||
use deltachat_derive::{FromSql, ToSql};
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::aheader::EncryptPreference;
|
||||
use crate::chat::ChatId;
|
||||
@@ -27,6 +29,67 @@ use crate::param::{Param, Params};
|
||||
use crate::peerstate::{Peerstate, PeerstateVerifiedStatus};
|
||||
use crate::{chat, stock_str};
|
||||
|
||||
/// Contact ID, including reserved IDs.
|
||||
///
|
||||
/// Some contact IDs are reserved to identify special contacts. This
|
||||
/// type can represent both the special as well as normal contacts.
|
||||
#[derive(
|
||||
Debug, Copy, Clone, Default, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct ContactId(u32);
|
||||
|
||||
impl ContactId {
|
||||
/// Creates a new [`ContactId`].
|
||||
pub const fn new(id: u32) -> ContactId {
|
||||
ContactId(id)
|
||||
}
|
||||
|
||||
/// Bad evil escape hatch, do not use.
|
||||
pub const fn to_u32(&self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ContactId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
// TODO: Something like this
|
||||
// if self == DC_CONTACT_ID_UNDEFINED {
|
||||
// write!(f, "Contact#Undefined")
|
||||
// } else if self == DC_CONTACT_ID_SELF {
|
||||
// write!(f, "Contact#Self")
|
||||
// } else if self == DC_CONTACT_ID_INFO {
|
||||
// write!(f, "Contact#Info")
|
||||
// } else if self == DC_CONTACT_ID_DEVICE {
|
||||
// write!(f, "Contact#Device")
|
||||
// } else if self <= DC_CONTACT_ID_LAST_SPECIAL {
|
||||
// write!(f, "Contact#Special{}", self.0)
|
||||
// } else {
|
||||
// write!(f, "Contact#{}", self.0)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
/// Allow converting [`ContactId`] to an SQLite type.
|
||||
impl rusqlite::types::ToSql for ContactId {
|
||||
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput> {
|
||||
let val = rusqlite::types::Value::Integer(i64::from(self.0));
|
||||
let out = rusqlite::types::ToSqlOutput::Owned(val);
|
||||
Ok(out)
|
||||
}
|
||||
}
|
||||
|
||||
/// Allow converting an SQLite integer directly into [`ContactId`].
|
||||
impl rusqlite::types::FromSql for ContactId {
|
||||
fn column_result(value: rusqlite::types::ValueRef) -> rusqlite::types::FromSqlResult<Self> {
|
||||
i64::column_result(value).and_then(|val| {
|
||||
val.try_into()
|
||||
.map(ContactId::new)
|
||||
.map_err(|_| rusqlite::types::FromSqlError::OutOfRange(val))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// An object representing a single contact in memory.
|
||||
///
|
||||
/// The contact object is not updated.
|
||||
@@ -48,7 +111,7 @@ pub struct Contact {
|
||||
/// `dc_set_config` using "addr".
|
||||
///
|
||||
/// Normal contact IDs are larger than these special ones (larger than DC_CONTACT_ID_LAST_SPECIAL).
|
||||
pub id: u32,
|
||||
pub id: ContactId,
|
||||
|
||||
/// Contact name. It is recommended to use `Contact::get_name`,
|
||||
/// `Contact::get_display_name` or `Contact::get_name_n_addr` to access this field.
|
||||
@@ -183,7 +246,7 @@ impl Default for VerifiedStatus {
|
||||
}
|
||||
|
||||
impl Contact {
|
||||
pub async fn load_from_db(context: &Context, contact_id: u32) -> Result<Self> {
|
||||
pub async fn load_from_db(context: &Context, contact_id: ContactId) -> Result<Self> {
|
||||
let mut contact = context
|
||||
.sql
|
||||
.query_row(
|
||||
@@ -191,7 +254,7 @@ impl Contact {
|
||||
c.authname, c.param, c.status
|
||||
FROM contacts c
|
||||
WHERE c.id=?;",
|
||||
paramsv![contact_id as i32],
|
||||
paramsv![contact_id],
|
||||
|row| {
|
||||
let name: String = row.get(0)?;
|
||||
let addr: String = row.get(1)?;
|
||||
@@ -245,18 +308,18 @@ impl Contact {
|
||||
}
|
||||
|
||||
/// Check if a contact is blocked.
|
||||
pub async fn is_blocked_load(context: &Context, id: u32) -> Result<bool> {
|
||||
pub async fn is_blocked_load(context: &Context, id: ContactId) -> Result<bool> {
|
||||
let blocked = Self::load_from_db(context, id).await?.blocked;
|
||||
Ok(blocked)
|
||||
}
|
||||
|
||||
/// Block the given contact.
|
||||
pub async fn block(context: &Context, id: u32) -> Result<()> {
|
||||
pub async fn block(context: &Context, id: ContactId) -> Result<()> {
|
||||
set_block_contact(context, id, true).await
|
||||
}
|
||||
|
||||
/// Unblock the given contact.
|
||||
pub async fn unblock(context: &Context, id: u32) -> Result<()> {
|
||||
pub async fn unblock(context: &Context, id: ContactId) -> Result<()> {
|
||||
set_block_contact(context, id, false).await
|
||||
}
|
||||
|
||||
@@ -269,7 +332,7 @@ impl Contact {
|
||||
/// a bunch of addresses.
|
||||
///
|
||||
/// May result in a `#DC_EVENT_CONTACTS_CHANGED` event.
|
||||
pub async fn create(context: &Context, name: &str, addr: &str) -> Result<u32> {
|
||||
pub async fn create(context: &Context, name: &str, addr: &str) -> Result<ContactId> {
|
||||
let name = improve_single_line_input(name);
|
||||
ensure!(!addr.is_empty(), "Cannot create contact with empty address");
|
||||
|
||||
@@ -292,12 +355,12 @@ impl Contact {
|
||||
}
|
||||
|
||||
/// Mark messages from a contact as noticed.
|
||||
pub async fn mark_noticed(context: &Context, id: u32) -> Result<()> {
|
||||
pub async fn mark_noticed(context: &Context, id: ContactId) -> Result<()> {
|
||||
context
|
||||
.sql
|
||||
.execute(
|
||||
"UPDATE msgs SET state=? WHERE from_id=? AND state=?;",
|
||||
paramsv![MessageState::InNoticed, id as i32, MessageState::InFresh],
|
||||
paramsv![MessageState::InNoticed, id, MessageState::InFresh],
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
@@ -313,7 +376,7 @@ impl Contact {
|
||||
context: &Context,
|
||||
addr: &str,
|
||||
min_origin: Origin,
|
||||
) -> Result<Option<u32>> {
|
||||
) -> Result<Option<ContactId>> {
|
||||
if addr.is_empty() {
|
||||
bail!("lookup_id_by_addr: empty address");
|
||||
}
|
||||
@@ -333,7 +396,7 @@ impl Contact {
|
||||
AND id>?2 AND origin>=?3 AND blocked=0;",
|
||||
paramsv![
|
||||
addr_normalized,
|
||||
DC_CONTACT_ID_LAST_SPECIAL as i32,
|
||||
DC_CONTACT_ID_LAST_SPECIAL,
|
||||
min_origin as u32,
|
||||
],
|
||||
)
|
||||
@@ -371,7 +434,7 @@ impl Contact {
|
||||
name: &str,
|
||||
addr: &str,
|
||||
mut origin: Origin,
|
||||
) -> Result<(u32, Modifier)> {
|
||||
) -> Result<(ContactId, Modifier)> {
|
||||
let mut sth_modified = Modifier::None;
|
||||
|
||||
ensure!(!addr.is_empty(), "Can not add_or_lookup empty address");
|
||||
@@ -500,7 +563,7 @@ impl Contact {
|
||||
paramsv![Chattype::Single, isize::try_from(row_id)?]
|
||||
).await?;
|
||||
if let Some(chat_id) = chat_id {
|
||||
let contact = Contact::get_by_id(context, row_id as u32).await?;
|
||||
let contact = Contact::get_by_id(context, ContactId::new(row_id)).await?;
|
||||
let chat_name = contact.get_display_name();
|
||||
match context
|
||||
.sql
|
||||
@@ -557,7 +620,7 @@ impl Contact {
|
||||
}
|
||||
}
|
||||
|
||||
Ok((row_id, sth_modified))
|
||||
Ok((ContactId::new(row_id), sth_modified))
|
||||
}
|
||||
|
||||
/// Add a number of contacts.
|
||||
@@ -617,7 +680,7 @@ impl Contact {
|
||||
context: &Context,
|
||||
listflags: u32,
|
||||
query: Option<impl AsRef<str>>,
|
||||
) -> Result<Vec<u32>> {
|
||||
) -> Result<Vec<ContactId>> {
|
||||
let self_addr = context
|
||||
.get_config(Config::ConfiguredAddr)
|
||||
.await?
|
||||
@@ -644,16 +707,16 @@ impl Contact {
|
||||
ORDER BY LOWER(iif(c.name='',c.authname,c.name)||c.addr),c.id;",
|
||||
paramsv![
|
||||
self_addr,
|
||||
DC_CONTACT_ID_LAST_SPECIAL as i32,
|
||||
DC_CONTACT_ID_LAST_SPECIAL,
|
||||
Origin::IncomingReplyTo,
|
||||
s3str_like_cmd,
|
||||
s3str_like_cmd,
|
||||
if flag_verified_only { 0i32 } else { 1i32 },
|
||||
],
|
||||
|row| row.get::<_, i32>(0),
|
||||
|row| row.get::<_, ContactId>(0),
|
||||
|ids| {
|
||||
for id in ids {
|
||||
ret.push(id? as u32);
|
||||
ret.push(id?);
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
@@ -690,13 +753,13 @@ impl Contact {
|
||||
ORDER BY LOWER(iif(name='',authname,name)||addr),id;",
|
||||
paramsv![
|
||||
self_addr,
|
||||
DC_CONTACT_ID_LAST_SPECIAL as i32,
|
||||
DC_CONTACT_ID_LAST_SPECIAL,
|
||||
Origin::IncomingReplyTo
|
||||
],
|
||||
|row| row.get::<_, i32>(0),
|
||||
|row| row.get::<_, ContactId>(0),
|
||||
|ids| {
|
||||
for id in ids {
|
||||
ret.push(id? as u32);
|
||||
ret.push(id?);
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
@@ -767,7 +830,7 @@ impl Contact {
|
||||
}
|
||||
|
||||
/// Get blocked contacts.
|
||||
pub async fn get_all_blocked(context: &Context) -> Result<Vec<u32>> {
|
||||
pub async fn get_all_blocked(context: &Context) -> Result<Vec<ContactId>> {
|
||||
Contact::update_blocked_mailinglist_contacts(context)
|
||||
.await
|
||||
.context("cannot update blocked mailinglist contacts")?;
|
||||
@@ -776,8 +839,8 @@ impl Contact {
|
||||
.sql
|
||||
.query_map(
|
||||
"SELECT id FROM contacts WHERE id>? AND blocked!=0 ORDER BY LOWER(iif(name='',authname,name)||addr),id;",
|
||||
paramsv![DC_CONTACT_ID_LAST_SPECIAL as i32],
|
||||
|row| row.get::<_, u32>(0),
|
||||
paramsv![DC_CONTACT_ID_LAST_SPECIAL],
|
||||
|row| row.get::<_, ContactId>(0),
|
||||
|ids| {
|
||||
ids.collect::<std::result::Result<Vec<_>, _>>()
|
||||
.map_err(Into::into)
|
||||
@@ -792,7 +855,7 @@ impl Contact {
|
||||
/// This function returns a string explaining the encryption state
|
||||
/// of the contact and if the connection is encrypted the
|
||||
/// fingerprints of the keys involved.
|
||||
pub async fn get_encrinfo(context: &Context, contact_id: u32) -> Result<String> {
|
||||
pub async fn get_encrinfo(context: &Context, contact_id: ContactId) -> Result<String> {
|
||||
ensure!(
|
||||
contact_id > DC_CONTACT_ID_LAST_SPECIAL,
|
||||
"Can not provide encryption info for special contact"
|
||||
@@ -861,7 +924,7 @@ impl Contact {
|
||||
/// possible as the contact is in use. In this case, the contact can be blocked.
|
||||
///
|
||||
/// May result in a `#DC_EVENT_CONTACTS_CHANGED` event.
|
||||
pub async fn delete(context: &Context, contact_id: u32) -> Result<()> {
|
||||
pub async fn delete(context: &Context, contact_id: ContactId) -> Result<()> {
|
||||
ensure!(
|
||||
contact_id > DC_CONTACT_ID_LAST_SPECIAL,
|
||||
"Can not delete special contact"
|
||||
@@ -871,17 +934,14 @@ impl Contact {
|
||||
.sql
|
||||
.count(
|
||||
"SELECT COUNT(*) FROM chats_contacts WHERE contact_id=?;",
|
||||
paramsv![contact_id as i32],
|
||||
paramsv![contact_id],
|
||||
)
|
||||
.await?;
|
||||
|
||||
if count_chats == 0 {
|
||||
match context
|
||||
.sql
|
||||
.execute(
|
||||
"DELETE FROM contacts WHERE id=?;",
|
||||
paramsv![contact_id as i32],
|
||||
)
|
||||
.execute("DELETE FROM contacts WHERE id=?;", paramsv![contact_id])
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
@@ -907,7 +967,7 @@ impl Contact {
|
||||
/// For contact DC_CONTACT_ID_SELF (1), the function returns sth.
|
||||
/// like "Me" in the selected language and the email address
|
||||
/// defined by dc_set_config().
|
||||
pub async fn get_by_id(context: &Context, contact_id: u32) -> Result<Contact> {
|
||||
pub async fn get_by_id(context: &Context, contact_id: ContactId) -> Result<Contact> {
|
||||
let contact = Contact::load_from_db(context, contact_id).await?;
|
||||
|
||||
Ok(contact)
|
||||
@@ -919,7 +979,7 @@ impl Contact {
|
||||
.sql
|
||||
.execute(
|
||||
"UPDATE contacts SET param=? WHERE id=?",
|
||||
paramsv![self.param.to_string(), self.id as i32],
|
||||
paramsv![self.param.to_string(), self.id],
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
@@ -931,14 +991,14 @@ impl Contact {
|
||||
.sql
|
||||
.execute(
|
||||
"UPDATE contacts SET status=? WHERE id=?",
|
||||
paramsv![self.status, self.id as i32],
|
||||
paramsv![self.status, self.id],
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get the ID of the contact.
|
||||
pub fn get_id(&self) -> u32 {
|
||||
pub fn get_id(&self) -> ContactId {
|
||||
self.id
|
||||
}
|
||||
|
||||
@@ -1065,7 +1125,7 @@ impl Contact {
|
||||
pub async fn addr_equals_contact(
|
||||
context: &Context,
|
||||
addr: &str,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
) -> Result<bool> {
|
||||
if addr.is_empty() {
|
||||
return Ok(false);
|
||||
@@ -1091,13 +1151,13 @@ impl Contact {
|
||||
.sql
|
||||
.count(
|
||||
"SELECT COUNT(*) FROM contacts WHERE id>?;",
|
||||
paramsv![DC_CONTACT_ID_LAST_SPECIAL as i32],
|
||||
paramsv![DC_CONTACT_ID_LAST_SPECIAL],
|
||||
)
|
||||
.await?;
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
pub async fn real_exists_by_id(context: &Context, contact_id: u32) -> Result<bool> {
|
||||
pub async fn real_exists_by_id(context: &Context, contact_id: ContactId) -> Result<bool> {
|
||||
if contact_id <= DC_CONTACT_ID_LAST_SPECIAL {
|
||||
return Ok(false);
|
||||
}
|
||||
@@ -1106,7 +1166,7 @@ impl Contact {
|
||||
.sql
|
||||
.exists(
|
||||
"SELECT COUNT(*) FROM contacts WHERE id=?;",
|
||||
paramsv![contact_id as i32],
|
||||
paramsv![contact_id],
|
||||
)
|
||||
.await?;
|
||||
Ok(exists)
|
||||
@@ -1114,14 +1174,14 @@ impl Contact {
|
||||
|
||||
pub async fn scaleup_origin_by_id(
|
||||
context: &Context,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
origin: Origin,
|
||||
) -> Result<()> {
|
||||
context
|
||||
.sql
|
||||
.execute(
|
||||
"UPDATE contacts SET origin=? WHERE id=? AND origin<?;",
|
||||
paramsv![origin, contact_id as i32, origin],
|
||||
paramsv![origin, contact_id, origin],
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
@@ -1165,7 +1225,11 @@ fn sanitize_name_and_addr(name: &str, addr: &str) -> (String, String) {
|
||||
}
|
||||
}
|
||||
|
||||
async fn set_block_contact(context: &Context, contact_id: u32, new_blocking: bool) -> Result<()> {
|
||||
async fn set_block_contact(
|
||||
context: &Context,
|
||||
contact_id: ContactId,
|
||||
new_blocking: bool,
|
||||
) -> Result<()> {
|
||||
ensure!(
|
||||
contact_id > DC_CONTACT_ID_LAST_SPECIAL,
|
||||
"Can't block special contact {}",
|
||||
@@ -1179,7 +1243,7 @@ async fn set_block_contact(context: &Context, contact_id: u32, new_blocking: boo
|
||||
.sql
|
||||
.execute(
|
||||
"UPDATE contacts SET blocked=? WHERE id=?;",
|
||||
paramsv![i32::from(new_blocking), contact_id as i32],
|
||||
paramsv![i32::from(new_blocking), contact_id],
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -1230,7 +1294,7 @@ WHERE type=? AND id IN (
|
||||
/// this typically happens if we see message with our own profile image, sent from another device.
|
||||
pub(crate) async fn set_profile_image(
|
||||
context: &Context,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
profile_image: &AvatarAction,
|
||||
was_encrypted: bool,
|
||||
) -> Result<()> {
|
||||
@@ -1277,7 +1341,7 @@ pub(crate) async fn set_profile_image(
|
||||
/// between Delta Chat devices.
|
||||
pub(crate) async fn set_status(
|
||||
context: &Context,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
status: String,
|
||||
encrypted: bool,
|
||||
has_chat_version: bool,
|
||||
@@ -1303,7 +1367,7 @@ pub(crate) async fn set_status(
|
||||
/// Updates last seen timestamp of the contact if it is earlier than the given `timestamp`.
|
||||
pub(crate) async fn update_last_seen(
|
||||
context: &Context,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
timestamp: i64,
|
||||
) -> Result<()> {
|
||||
ensure!(
|
||||
@@ -1474,7 +1538,7 @@ mod tests {
|
||||
Origin::IncomingReplyTo,
|
||||
)
|
||||
.await?;
|
||||
assert_ne!(id, 0);
|
||||
assert_ne!(id, ContactId::new(0));
|
||||
|
||||
let contact = Contact::load_from_db(&context.ctx, id).await.unwrap();
|
||||
assert_eq!(contact.get_name(), "");
|
||||
@@ -1629,7 +1693,7 @@ mod tests {
|
||||
|
||||
// check SELF
|
||||
let contact = Contact::load_from_db(&t, DC_CONTACT_ID_SELF).await.unwrap();
|
||||
assert_eq!(DC_CONTACT_ID_SELF, 1);
|
||||
assert_eq!(DC_CONTACT_ID_SELF, ContactId::new(1));
|
||||
assert_eq!(contact.get_name(), stock_str::self_msg(&t).await);
|
||||
assert_eq!(contact.get_addr(), ""); // we're not configured
|
||||
assert!(!contact.is_blocked());
|
||||
|
||||
@@ -18,7 +18,7 @@ use crate::constants::{
|
||||
DC_CONTACT_ID_SELF,
|
||||
};
|
||||
use crate::contact::{
|
||||
addr_cmp, may_be_valid_addr, normalize_name, Contact, Origin, VerifiedStatus,
|
||||
addr_cmp, may_be_valid_addr, normalize_name, Contact, ContactId, Origin, VerifiedStatus,
|
||||
};
|
||||
use crate::context::Context;
|
||||
use crate::dc_tools::{dc_create_id, dc_extract_grpid_from_rfc724_mid, dc_smeared_time};
|
||||
@@ -199,7 +199,7 @@ pub(crate) async fn dc_receive_imf_inner(
|
||||
.map_or(rcvd_timestamp, |value| min(value, rcvd_timestamp));
|
||||
|
||||
if mime_parser.is_system_message == SystemMessage::LocationStreamingEnabled {
|
||||
let better_msg = stock_str::msg_location_enabled_by(context, from_id as u32).await;
|
||||
let better_msg = stock_str::msg_location_enabled_by(context, from_id).await;
|
||||
set_better_msg(&mut mime_parser, &better_msg);
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ pub(crate) async fn dc_receive_imf_inner(
|
||||
}
|
||||
|
||||
if let Some(avatar_action) = &mime_parser.user_avatar {
|
||||
if from_id != 0
|
||||
if from_id != ContactId::new(0)
|
||||
&& context
|
||||
.update_contacts_timestamp(from_id, Param::AvatarTimestamp, sent_timestamp)
|
||||
.await?
|
||||
@@ -311,7 +311,7 @@ pub(crate) async fn dc_receive_imf_inner(
|
||||
// Ignore MDNs though, as they never contain the signature even if user has set it.
|
||||
if mime_parser.mdn_reports.is_empty()
|
||||
&& is_partial_download.is_none()
|
||||
&& from_id != 0
|
||||
&& from_id != ContactId::new(0)
|
||||
&& context
|
||||
.update_contacts_timestamp(from_id, Param::StatusTimestamp, sent_timestamp)
|
||||
.await?
|
||||
@@ -387,7 +387,7 @@ pub async fn from_field_to_contact_id(
|
||||
context: &Context,
|
||||
from_address_list: &[SingleInfo],
|
||||
prevent_rename: bool,
|
||||
) -> Result<(u32, bool, Origin)> {
|
||||
) -> Result<(ContactId, bool, Origin)> {
|
||||
let from_ids = dc_add_or_lookup_contacts_by_address_list(
|
||||
context,
|
||||
from_address_list,
|
||||
@@ -420,7 +420,7 @@ pub async fn from_field_to_contact_id(
|
||||
"mail has an empty From header: {:?}", from_address_list
|
||||
);
|
||||
|
||||
Ok((0, false, Origin::Unknown))
|
||||
Ok((ContactId::new(0), false, Origin::Unknown))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,11 +431,11 @@ async fn add_parts(
|
||||
imf_raw: &[u8],
|
||||
incoming: bool,
|
||||
server_folder: &str,
|
||||
to_ids: &[u32],
|
||||
to_ids: &[ContactId],
|
||||
rfc724_mid: &str,
|
||||
sent_timestamp: i64,
|
||||
rcvd_timestamp: i64,
|
||||
from_id: u32,
|
||||
from_id: ContactId,
|
||||
seen: bool,
|
||||
is_partial_download: Option<u32>,
|
||||
needs_delete_job: &mut bool,
|
||||
@@ -488,7 +488,7 @@ async fn add_parts(
|
||||
// - outgoing messages introduce a chat with the first to: address if they are sent by a messenger
|
||||
// - incoming messages introduce a chat only for known contacts if they are sent by a messenger
|
||||
// (of course, the user can add other chats manually later)
|
||||
let to_id: u32;
|
||||
let to_id: ContactId;
|
||||
|
||||
let state: MessageState;
|
||||
if incoming {
|
||||
@@ -524,7 +524,7 @@ async fn add_parts(
|
||||
securejoin_seen = false;
|
||||
}
|
||||
|
||||
let test_normal_chat = if from_id == 0 {
|
||||
let test_normal_chat = if from_id == ContactId::new(0) {
|
||||
Default::default()
|
||||
} else {
|
||||
ChatIdBlocked::lookup_by_contact(context, from_id).await?
|
||||
@@ -583,7 +583,7 @@ async fn add_parts(
|
||||
// In lookup_chat_by_reply() and create_or_lookup_group(), it can happen that the message is put into a chat
|
||||
// but the From-address is not a member of this chat.
|
||||
if let Some(chat_id) = chat_id {
|
||||
if !chat::is_contact_in_chat(context, chat_id, from_id as u32).await? {
|
||||
if !chat::is_contact_in_chat(context, chat_id, from_id).await? {
|
||||
let chat = Chat::load_from_db(context, chat_id).await?;
|
||||
if chat.is_protected() {
|
||||
let s = stock_str::unknown_sender_for_chat(context).await;
|
||||
@@ -1031,9 +1031,7 @@ async fn add_parts(
|
||||
}
|
||||
set_better_msg(
|
||||
mime_parser,
|
||||
context
|
||||
.stock_protection_msg(new_status, from_id as u32)
|
||||
.await,
|
||||
context.stock_protection_msg(new_status, from_id).await,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1156,8 +1154,8 @@ INSERT INTO msgs
|
||||
stmt.execute(paramsv![
|
||||
rfc724_mid,
|
||||
chat_id,
|
||||
if trash { 0 } else { i64::from(from_id) },
|
||||
if trash { 0 } else { i64::from(to_id) },
|
||||
if trash { ContactId::new(0) } else { from_id },
|
||||
if trash { ContactId::new(0) } else { to_id },
|
||||
sort_timestamp,
|
||||
sent_timestamp,
|
||||
rcvd_timestamp,
|
||||
@@ -1256,7 +1254,7 @@ async fn save_locations(
|
||||
context: &Context,
|
||||
mime_parser: &MimeMessage,
|
||||
chat_id: ChatId,
|
||||
from_id: u32,
|
||||
from_id: ContactId,
|
||||
msg_id: MsgId,
|
||||
) -> Result<()> {
|
||||
if chat_id.is_special() {
|
||||
@@ -1335,8 +1333,8 @@ async fn lookup_chat_by_reply(
|
||||
context: &Context,
|
||||
mime_parser: &mut MimeMessage,
|
||||
parent: &Option<Message>,
|
||||
from_id: u32,
|
||||
to_ids: &[u32],
|
||||
from_id: ContactId,
|
||||
to_ids: &[ContactId],
|
||||
) -> Result<Option<(ChatId, Blocked)>> {
|
||||
// Try to assign message to the same chat as the parent message.
|
||||
|
||||
@@ -1376,10 +1374,10 @@ async fn lookup_chat_by_reply(
|
||||
/// If it returns false, it shall be assigned to the parent chat.
|
||||
async fn is_probably_private_reply(
|
||||
context: &Context,
|
||||
to_ids: &[u32],
|
||||
to_ids: &[ContactId],
|
||||
mime_parser: &MimeMessage,
|
||||
parent_chat_id: ChatId,
|
||||
from_id: u32,
|
||||
from_id: ContactId,
|
||||
) -> Result<bool> {
|
||||
// Usually we don't want to show private replies in the parent chat, but in the
|
||||
// 1:1 chat with the sender.
|
||||
@@ -1416,18 +1414,18 @@ async fn create_or_lookup_group(
|
||||
mime_parser: &mut MimeMessage,
|
||||
allow_creation: bool,
|
||||
create_blocked: Blocked,
|
||||
from_id: u32,
|
||||
to_ids: &[u32],
|
||||
from_id: ContactId,
|
||||
to_ids: &[ContactId],
|
||||
) -> Result<Option<(ChatId, Blocked)>> {
|
||||
let grpid = if let Some(grpid) = try_getting_grpid(mime_parser) {
|
||||
grpid
|
||||
} else if allow_creation {
|
||||
let mut member_ids: Vec<u32> = to_ids.to_vec();
|
||||
if !member_ids.contains(&(from_id as u32)) {
|
||||
member_ids.push(from_id as u32);
|
||||
let mut member_ids: Vec<ContactId> = to_ids.to_vec();
|
||||
if !member_ids.contains(&(from_id)) {
|
||||
member_ids.push(from_id);
|
||||
}
|
||||
if !member_ids.contains(&(DC_CONTACT_ID_SELF as u32)) {
|
||||
member_ids.push(DC_CONTACT_ID_SELF as u32);
|
||||
if !member_ids.contains(&(DC_CONTACT_ID_SELF)) {
|
||||
member_ids.push(DC_CONTACT_ID_SELF);
|
||||
}
|
||||
|
||||
let res = create_adhoc_group(context, mime_parser, create_blocked, &member_ids)
|
||||
@@ -1561,8 +1559,8 @@ async fn apply_group_changes(
|
||||
mime_parser: &mut MimeMessage,
|
||||
sent_timestamp: i64,
|
||||
chat_id: ChatId,
|
||||
from_id: u32,
|
||||
to_ids: &[u32],
|
||||
from_id: ContactId,
|
||||
to_ids: &[ContactId],
|
||||
) -> Result<()> {
|
||||
let mut chat = Chat::load_from_db(context, chat_id).await?;
|
||||
if chat.typ != Chattype::Group {
|
||||
@@ -1626,8 +1624,7 @@ async fn apply_group_changes(
|
||||
send_event_chat_modified = true;
|
||||
}
|
||||
|
||||
let better_msg =
|
||||
stock_str::msg_grp_name(context, old_name, grpname, from_id as u32).await;
|
||||
let better_msg = stock_str::msg_grp_name(context, old_name, grpname, from_id).await;
|
||||
set_better_msg(mime_parser, &better_msg);
|
||||
mime_parser.is_system_message = SystemMessage::GroupNameChanged;
|
||||
}
|
||||
@@ -1953,7 +1950,7 @@ async fn create_adhoc_group(
|
||||
context: &Context,
|
||||
mime_parser: &MimeMessage,
|
||||
create_blocked: Blocked,
|
||||
member_ids: &[u32],
|
||||
member_ids: &[ContactId],
|
||||
) -> Result<Option<ChatId>> {
|
||||
if mime_parser.is_mailinglist_message() {
|
||||
info!(
|
||||
@@ -2023,7 +2020,7 @@ async fn create_adhoc_group(
|
||||
/// This ensures that different Delta Chat clients generate the same group ID unless some of them
|
||||
/// are hidden in BCC. This group ID is sent by DC in the messages sent to this chat,
|
||||
/// so having the same ID prevents group split.
|
||||
async fn create_adhoc_grp_id(context: &Context, member_ids: &[u32]) -> Result<String> {
|
||||
async fn create_adhoc_grp_id(context: &Context, member_ids: &[ContactId]) -> Result<String> {
|
||||
let member_ids_str = member_ids
|
||||
.iter()
|
||||
.map(|x| x.to_string())
|
||||
@@ -2070,8 +2067,8 @@ fn hex_hash(s: &str) -> String {
|
||||
async fn check_verified_properties(
|
||||
context: &Context,
|
||||
mimeparser: &MimeMessage,
|
||||
from_id: u32,
|
||||
to_ids: &[u32],
|
||||
from_id: ContactId,
|
||||
to_ids: &[ContactId],
|
||||
) -> Result<()> {
|
||||
let contact = Contact::load_from_db(context, from_id).await?;
|
||||
|
||||
@@ -2118,7 +2115,7 @@ async fn check_verified_properties(
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|id| *id != DC_CONTACT_ID_SELF)
|
||||
.collect::<Vec<u32>>();
|
||||
.collect::<Vec<ContactId>>();
|
||||
|
||||
if to_ids.is_empty() {
|
||||
return Ok(());
|
||||
@@ -2301,7 +2298,7 @@ async fn dc_add_or_lookup_contacts_by_address_list(
|
||||
address_list: &[SingleInfo],
|
||||
origin: Origin,
|
||||
prevent_rename: bool,
|
||||
) -> Result<Vec<u32>> {
|
||||
) -> Result<Vec<ContactId>> {
|
||||
let mut contact_ids = BTreeSet::new();
|
||||
for info in address_list.iter() {
|
||||
let addr = &info.addr;
|
||||
@@ -2317,7 +2314,7 @@ async fn dc_add_or_lookup_contacts_by_address_list(
|
||||
.insert(add_or_lookup_contact_by_addr(context, display_name, addr, origin).await?);
|
||||
}
|
||||
|
||||
Ok(contact_ids.into_iter().collect::<Vec<u32>>())
|
||||
Ok(contact_ids.into_iter().collect::<Vec<ContactId>>())
|
||||
}
|
||||
|
||||
/// Add contacts to database on receiving messages.
|
||||
@@ -2326,7 +2323,7 @@ async fn add_or_lookup_contact_by_addr(
|
||||
display_name: Option<&str>,
|
||||
addr: &str,
|
||||
origin: Origin,
|
||||
) -> Result<u32> {
|
||||
) -> Result<ContactId> {
|
||||
if context.is_self_addr(addr).await? {
|
||||
return Ok(DC_CONTACT_ID_SELF);
|
||||
}
|
||||
@@ -2334,8 +2331,6 @@ async fn add_or_lookup_contact_by_addr(
|
||||
|
||||
let (row_id, _modified) =
|
||||
Contact::add_or_lookup(context, &display_name_normalized, addr, origin).await?;
|
||||
ensure!(row_id > 0, "could not add contact: {:?}", addr);
|
||||
|
||||
Ok(row_id)
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ 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::contact::ContactId;
|
||||
use crate::context::Context;
|
||||
use crate::dc_tools::time;
|
||||
use crate::download::MIN_DELETE_SERVER_AFTER;
|
||||
@@ -212,7 +213,7 @@ impl ChatId {
|
||||
pub(crate) async fn stock_ephemeral_timer_changed(
|
||||
context: &Context,
|
||||
timer: Timer,
|
||||
from_id: u32,
|
||||
from_id: ContactId,
|
||||
) -> String {
|
||||
match timer {
|
||||
Timer::Disabled => stock_str::msg_ephemeral_timer_disabled(context, from_id).await,
|
||||
@@ -823,8 +824,8 @@ mod tests {
|
||||
|
||||
// Check that if there is a message left, the text and metadata are gone
|
||||
if let Ok(msg) = Message::load_from_db(t, msg_id).await {
|
||||
assert_eq!(msg.from_id, 0);
|
||||
assert_eq!(msg.to_id, 0);
|
||||
assert_eq!(msg.from_id, ContactId::new(0));
|
||||
assert_eq!(msg.to_id, ContactId::new(0));
|
||||
assert!(msg.text.is_none_or_empty(), "{:?}", msg.text);
|
||||
let rawtxt: Option<String> = t
|
||||
.sql
|
||||
|
||||
@@ -7,6 +7,7 @@ use async_std::path::PathBuf;
|
||||
use strum::EnumProperty;
|
||||
|
||||
use crate::chat::ChatId;
|
||||
use crate::contact::ContactId;
|
||||
use crate::ephemeral::Timer as EphemeralTimer;
|
||||
use crate::message::MsgId;
|
||||
|
||||
@@ -252,7 +253,7 @@ pub enum EventType {
|
||||
///
|
||||
/// @param data1 (int) If set, this is the contact_id of an added contact that should be selected.
|
||||
#[strum(props(id = "2030"))]
|
||||
ContactsChanged(Option<u32>),
|
||||
ContactsChanged(Option<ContactId>),
|
||||
|
||||
/// Location of one or more contact has changed.
|
||||
///
|
||||
@@ -260,7 +261,7 @@ pub enum EventType {
|
||||
/// If the locations of several contacts have been changed,
|
||||
/// eg. after calling dc_delete_all_locations(), this parameter is set to `None`.
|
||||
#[strum(props(id = "2035"))]
|
||||
LocationChanged(Option<u32>),
|
||||
LocationChanged(Option<ContactId>),
|
||||
|
||||
/// Inform about the configuration progress started by configure().
|
||||
#[strum(props(id = "2041"))]
|
||||
@@ -304,7 +305,10 @@ pub enum EventType {
|
||||
/// 800=vg-member-added-received received, shown as "bob@addr securely joined GROUP", only sent for the verified-group-protocol.
|
||||
/// 1000=Protocol finished for this contact.
|
||||
#[strum(props(id = "2060"))]
|
||||
SecurejoinInviterProgress { contact_id: u32, progress: usize },
|
||||
SecurejoinInviterProgress {
|
||||
contact_id: ContactId,
|
||||
progress: usize,
|
||||
},
|
||||
|
||||
/// Progress information of a secure-join handshake from the view of the joiner
|
||||
/// (Bob, the person who scans the QR code).
|
||||
@@ -315,7 +319,10 @@ pub enum EventType {
|
||||
/// 400=vg-/vc-request-with-auth sent, typically shown as "alice@addr verified, introducing myself."
|
||||
/// (Bob has verified alice and waits until Alice does the same for him)
|
||||
#[strum(props(id = "2061"))]
|
||||
SecurejoinJoinerProgress { contact_id: u32, progress: usize },
|
||||
SecurejoinJoinerProgress {
|
||||
contact_id: ContactId,
|
||||
progress: usize,
|
||||
},
|
||||
|
||||
/// The connectivity to the server changed.
|
||||
/// This means that you should refresh the connectivity view
|
||||
|
||||
12
src/job.rs
12
src/job.rs
@@ -9,7 +9,7 @@ use deltachat_derive::{FromSql, ToSql};
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::contact::{normalize_name, Contact, Modifier, Origin};
|
||||
use crate::contact::{normalize_name, Contact, ContactId, Modifier, Origin};
|
||||
use crate::context::Context;
|
||||
use crate::dc_tools::time;
|
||||
use crate::events::EventType;
|
||||
@@ -224,7 +224,7 @@ impl Job {
|
||||
async fn get_additional_mdn_jobs(
|
||||
&self,
|
||||
context: &Context,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
) -> Result<(Vec<u32>, Vec<String>)> {
|
||||
// Extract message IDs from job parameters
|
||||
let res: Vec<(u32, MsgId)> = context
|
||||
@@ -271,7 +271,7 @@ impl Job {
|
||||
return Status::Finished(Err(format_err!("MDNs are disabled")));
|
||||
}
|
||||
|
||||
let contact_id = self.foreign_id;
|
||||
let contact_id = ContactId::new(self.foreign_id);
|
||||
let contact = job_try!(Contact::load_from_db(context, contact_id).await);
|
||||
if contact.is_blocked() {
|
||||
return Status::Finished(Err(format_err!("Contact is blocked")));
|
||||
@@ -685,7 +685,11 @@ async fn send_mdn(context: &Context, msg: &Message) -> Result<()> {
|
||||
let mut param = Params::new();
|
||||
param.set(Param::MsgId, msg.id.to_u32().to_string());
|
||||
|
||||
add(context, Job::new(Action::SendMdn, msg.from_id, param, 0)).await?;
|
||||
add(
|
||||
context,
|
||||
Job::new(Action::SendMdn, msg.from_id.to_u32(), param, 0),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use quick_xml::events::{BytesEnd, BytesStart, BytesText};
|
||||
use crate::chat::{self, ChatId};
|
||||
use crate::config::Config;
|
||||
use crate::constants::{Viewtype, DC_CONTACT_ID_SELF};
|
||||
use crate::contact::ContactId;
|
||||
use crate::context::Context;
|
||||
use crate::dc_tools::time;
|
||||
use crate::events::EventType;
|
||||
@@ -25,7 +26,7 @@ pub struct Location {
|
||||
pub longitude: f64,
|
||||
pub accuracy: f64,
|
||||
pub timestamp: i64,
|
||||
pub contact_id: u32,
|
||||
pub contact_id: ContactId,
|
||||
pub msg_id: u32,
|
||||
pub chat_id: ChatId,
|
||||
pub marker: Option<String>,
|
||||
@@ -558,7 +559,7 @@ pub async fn set_msg_location_id(context: &Context, msg_id: MsgId, location_id:
|
||||
pub(crate) async fn save(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
locations: &[Location],
|
||||
independent: bool,
|
||||
) -> Result<Option<u32>> {
|
||||
@@ -585,12 +586,12 @@ pub(crate) async fn save(
|
||||
conn.prepare_cached("SELECT id FROM locations WHERE timestamp=? AND from_id=?")?;
|
||||
let mut stmt_insert = conn.prepare_cached(stmt_insert)?;
|
||||
|
||||
let exists = stmt_test.exists(paramsv![timestamp, contact_id as i32])?;
|
||||
let exists = stmt_test.exists(paramsv![timestamp, contact_id])?;
|
||||
|
||||
if independent || !exists {
|
||||
stmt_insert.execute(paramsv![
|
||||
timestamp,
|
||||
contact_id as i32,
|
||||
contact_id,
|
||||
chat_id,
|
||||
latitude,
|
||||
longitude,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//! # Messages and their identifiers.
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::convert::TryInto;
|
||||
|
||||
use anyhow::{ensure, format_err, Context as _, Result};
|
||||
use async_std::path::{Path, PathBuf};
|
||||
@@ -14,7 +13,7 @@ use crate::constants::{
|
||||
Blocked, Chattype, VideochatType, Viewtype, DC_CHAT_ID_TRASH, DC_CONTACT_ID_INFO,
|
||||
DC_CONTACT_ID_SELF, DC_DESIRED_TEXT_LEN, DC_MSG_ID_LAST_SPECIAL,
|
||||
};
|
||||
use crate::contact::{Contact, Origin};
|
||||
use crate::contact::{Contact, ContactId, Origin};
|
||||
use crate::context::Context;
|
||||
use crate::dc_tools::{
|
||||
dc_create_smeared_timestamp, dc_get_filebytes, dc_get_filemeta, dc_gm2local_offset,
|
||||
@@ -240,8 +239,8 @@ impl Default for MessengerMessage {
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct Message {
|
||||
pub(crate) id: MsgId,
|
||||
pub(crate) from_id: u32,
|
||||
pub(crate) to_id: u32,
|
||||
pub(crate) from_id: ContactId,
|
||||
pub(crate) to_id: ContactId,
|
||||
pub(crate) chat_id: ChatId,
|
||||
pub(crate) viewtype: Viewtype,
|
||||
pub(crate) state: MessageState,
|
||||
@@ -456,7 +455,7 @@ impl Message {
|
||||
self.id
|
||||
}
|
||||
|
||||
pub fn get_from_id(&self) -> u32 {
|
||||
pub fn get_from_id(&self) -> ContactId {
|
||||
self.from_id
|
||||
}
|
||||
|
||||
@@ -1049,7 +1048,7 @@ pub async fn get_msg_info(context: &Context, msg_id: MsgId) -> Result<String> {
|
||||
"SELECT contact_id, timestamp_sent FROM msgs_mdns WHERE msg_id=?;",
|
||||
paramsv![msg_id],
|
||||
|row| {
|
||||
let contact_id: i32 = row.get(0)?;
|
||||
let contact_id: ContactId = row.get(0)?;
|
||||
let ts: i64 = row.get(1)?;
|
||||
Ok((contact_id, ts))
|
||||
},
|
||||
@@ -1061,7 +1060,7 @@ pub async fn get_msg_info(context: &Context, msg_id: MsgId) -> Result<String> {
|
||||
let fts = dc_timestamp_to_str(ts);
|
||||
ret += &format!("Read: {}", fts);
|
||||
|
||||
let name = Contact::load_from_db(context, contact_id.try_into()?)
|
||||
let name = Contact::load_from_db(context, contact_id)
|
||||
.await
|
||||
.map(|contact| contact.get_name_n_addr())
|
||||
.unwrap_or_default();
|
||||
@@ -1426,7 +1425,7 @@ pub async fn set_msg_failed(context: &Context, msg_id: MsgId, error: Option<impl
|
||||
/// returns Some if an event should be send
|
||||
pub async fn handle_mdn(
|
||||
context: &Context,
|
||||
from_id: u32,
|
||||
from_id: ContactId,
|
||||
rfc724_mid: &str,
|
||||
timestamp_sent: i64,
|
||||
) -> Result<Option<(ChatId, MsgId)>> {
|
||||
@@ -1479,7 +1478,7 @@ pub async fn handle_mdn(
|
||||
.sql
|
||||
.exists(
|
||||
"SELECT COUNT(*) FROM msgs_mdns WHERE msg_id=? AND contact_id=?;",
|
||||
paramsv![msg_id, from_id as i32,],
|
||||
paramsv![msg_id, from_id],
|
||||
)
|
||||
.await?
|
||||
{
|
||||
@@ -1487,7 +1486,7 @@ pub async fn handle_mdn(
|
||||
.sql
|
||||
.execute(
|
||||
"INSERT INTO msgs_mdns (msg_id, contact_id, timestamp_sent) VALUES (?, ?, ?);",
|
||||
paramsv![msg_id, from_id as i32, timestamp_sent],
|
||||
paramsv![msg_id, from_id, timestamp_sent],
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ use once_cell::sync::Lazy;
|
||||
use crate::aheader::Aheader;
|
||||
use crate::blob::BlobObject;
|
||||
use crate::constants::{Viewtype, DC_DESIRED_TEXT_LEN, DC_ELLIPSIS};
|
||||
use crate::contact::addr_normalize;
|
||||
use crate::contact::{addr_normalize, ContactId};
|
||||
use crate::context::Context;
|
||||
use crate::dc_tools::{dc_get_filemeta, dc_truncate, parse_receive_headers};
|
||||
use crate::dehtml::dehtml;
|
||||
@@ -1369,7 +1369,7 @@ impl MimeMessage {
|
||||
pub async fn handle_reports(
|
||||
&self,
|
||||
context: &Context,
|
||||
from_id: u32,
|
||||
from_id: ContactId,
|
||||
sent_timestamp: i64,
|
||||
parts: &[Part],
|
||||
) {
|
||||
|
||||
26
src/qr.rs
26
src/qr.rs
@@ -9,7 +9,7 @@ use std::collections::BTreeMap;
|
||||
use crate::chat::{self, get_chat_id_by_grpid, ChatIdBlocked};
|
||||
use crate::config::Config;
|
||||
use crate::constants::Blocked;
|
||||
use crate::contact::{addr_normalize, may_be_valid_addr, Contact, Origin};
|
||||
use crate::contact::{addr_normalize, may_be_valid_addr, Contact, ContactId, Origin};
|
||||
use crate::context::Context;
|
||||
use crate::dc_tools::time;
|
||||
use crate::key::Fingerprint;
|
||||
@@ -30,7 +30,7 @@ const HTTPS_SCHEME: &str = "https://";
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Qr {
|
||||
AskVerifyContact {
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
fingerprint: Fingerprint,
|
||||
invitenumber: String,
|
||||
authcode: String,
|
||||
@@ -38,16 +38,16 @@ pub enum Qr {
|
||||
AskVerifyGroup {
|
||||
grpname: String,
|
||||
grpid: String,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
fingerprint: Fingerprint,
|
||||
invitenumber: String,
|
||||
authcode: String,
|
||||
},
|
||||
FprOk {
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
},
|
||||
FprMismatch {
|
||||
contact_id: Option<u32>,
|
||||
contact_id: Option<ContactId>,
|
||||
},
|
||||
FprWithoutAddr {
|
||||
fingerprint: String,
|
||||
@@ -60,7 +60,7 @@ pub enum Qr {
|
||||
instance_pattern: String,
|
||||
},
|
||||
Addr {
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
},
|
||||
Url {
|
||||
url: String,
|
||||
@@ -69,7 +69,7 @@ pub enum Qr {
|
||||
text: String,
|
||||
},
|
||||
WithdrawVerifyContact {
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
fingerprint: Fingerprint,
|
||||
invitenumber: String,
|
||||
authcode: String,
|
||||
@@ -77,13 +77,13 @@ pub enum Qr {
|
||||
WithdrawVerifyGroup {
|
||||
grpname: String,
|
||||
grpid: String,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
fingerprint: Fingerprint,
|
||||
invitenumber: String,
|
||||
authcode: String,
|
||||
},
|
||||
ReviveVerifyContact {
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
fingerprint: Fingerprint,
|
||||
invitenumber: String,
|
||||
authcode: String,
|
||||
@@ -91,7 +91,7 @@ pub enum Qr {
|
||||
ReviveVerifyGroup {
|
||||
grpname: String,
|
||||
grpid: String,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
fingerprint: Fingerprint,
|
||||
invitenumber: String,
|
||||
authcode: String,
|
||||
@@ -711,7 +711,7 @@ mod tests {
|
||||
..
|
||||
} = qr
|
||||
{
|
||||
assert_ne!(contact_id, 0);
|
||||
assert_ne!(contact_id, ContactId::new(0));
|
||||
assert_eq!(grpname, "test ? test !");
|
||||
} else {
|
||||
bail!("Wrong QR code type");
|
||||
@@ -729,7 +729,7 @@ mod tests {
|
||||
..
|
||||
} = qr
|
||||
{
|
||||
assert_ne!(contact_id, 0);
|
||||
assert_ne!(contact_id, ContactId::new(0));
|
||||
assert_eq!(grpname, "test ? test !");
|
||||
|
||||
let contact = Contact::get_by_id(&ctx.ctx, contact_id).await?;
|
||||
@@ -751,7 +751,7 @@ mod tests {
|
||||
).await?;
|
||||
|
||||
if let Qr::AskVerifyContact { contact_id, .. } = qr {
|
||||
assert_ne!(contact_id, 0);
|
||||
assert_ne!(contact_id, ContactId::new(0));
|
||||
} else {
|
||||
bail!("Wrong QR code type");
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::aheader::EncryptPreference;
|
||||
use crate::chat::{self, Chat, ChatId, ChatIdBlocked};
|
||||
use crate::config::Config;
|
||||
use crate::constants::{Blocked, Viewtype, DC_CONTACT_ID_LAST_SPECIAL};
|
||||
use crate::contact::{Contact, Origin, VerifiedStatus};
|
||||
use crate::contact::{Contact, ContactId, Origin, VerifiedStatus};
|
||||
use crate::context::Context;
|
||||
use crate::dc_tools::time;
|
||||
use crate::e2ee::ensure_secret_key_exists;
|
||||
@@ -205,7 +205,7 @@ pub struct SendMsgError(#[from] anyhow::Error);
|
||||
/// Bob's handshake messages are sent in `BobState::send_handshake_message()`.
|
||||
async fn send_alice_handshake_msg(
|
||||
context: &Context,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
step: &str,
|
||||
fingerprint: Option<Fingerprint>,
|
||||
) -> Result<(), SendMsgError> {
|
||||
@@ -233,7 +233,7 @@ async fn send_alice_handshake_msg(
|
||||
}
|
||||
|
||||
/// Get an unblocked chat that can be used for info messages.
|
||||
async fn info_chat_id(context: &Context, contact_id: u32) -> Result<ChatId> {
|
||||
async fn info_chat_id(context: &Context, contact_id: ContactId) -> Result<ChatId> {
|
||||
let chat_id_blocked = ChatIdBlocked::get_for_contact(context, contact_id, Blocked::Not).await?;
|
||||
Ok(chat_id_blocked.id)
|
||||
}
|
||||
@@ -241,7 +241,7 @@ async fn info_chat_id(context: &Context, contact_id: u32) -> Result<ChatId> {
|
||||
async fn fingerprint_equals_sender(
|
||||
context: &Context,
|
||||
fingerprint: &Fingerprint,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
) -> Result<bool, Error> {
|
||||
let contact = Contact::load_from_db(context, contact_id).await?;
|
||||
let peerstate = match Peerstate::from_addr(context, contact.get_addr()).await {
|
||||
@@ -308,7 +308,7 @@ pub(crate) enum HandshakeMessage {
|
||||
pub(crate) async fn handle_securejoin_handshake(
|
||||
context: &Context,
|
||||
mime_message: &MimeMessage,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
) -> Result<HandshakeMessage> {
|
||||
if contact_id <= DC_CONTACT_ID_LAST_SPECIAL {
|
||||
return Err(Error::msg("Can not be called with special contact ID"));
|
||||
@@ -571,7 +571,7 @@ pub(crate) async fn handle_securejoin_handshake(
|
||||
pub(crate) async fn observe_securejoin_on_other_device(
|
||||
context: &Context,
|
||||
mime_message: &MimeMessage,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
) -> Result<HandshakeMessage> {
|
||||
if contact_id <= DC_CONTACT_ID_LAST_SPECIAL {
|
||||
return Err(Error::msg("Can not be called with special contact ID"));
|
||||
@@ -636,7 +636,7 @@ pub(crate) async fn observe_securejoin_on_other_device(
|
||||
|
||||
async fn secure_connection_established(
|
||||
context: &Context,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
chat_id: ChatId,
|
||||
) -> Result<(), Error> {
|
||||
let contact = Contact::get_by_id(context, contact_id).await?;
|
||||
@@ -648,7 +648,7 @@ async fn secure_connection_established(
|
||||
|
||||
async fn could_not_establish_secure_connection(
|
||||
context: &Context,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
chat_id: ChatId,
|
||||
details: &str,
|
||||
) -> Result<(), Error> {
|
||||
|
||||
@@ -8,6 +8,7 @@ use std::convert::TryFrom;
|
||||
|
||||
use anyhow::{bail, Error, Result};
|
||||
|
||||
use crate::contact::ContactId;
|
||||
use crate::key::Fingerprint;
|
||||
use crate::qr::Qr;
|
||||
|
||||
@@ -17,13 +18,13 @@ use crate::qr::Qr;
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub enum QrInvite {
|
||||
Contact {
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
fingerprint: Fingerprint,
|
||||
invitenumber: String,
|
||||
authcode: String,
|
||||
},
|
||||
Group {
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
fingerprint: Fingerprint,
|
||||
name: String,
|
||||
grpid: String,
|
||||
@@ -37,7 +38,7 @@ impl QrInvite {
|
||||
///
|
||||
/// The actual QR-code contains a URL-encoded email address, but upon scanning this is
|
||||
/// translated to a contact ID.
|
||||
pub fn contact_id(&self) -> u32 {
|
||||
pub fn contact_id(&self) -> ContactId {
|
||||
match self {
|
||||
Self::Contact { contact_id, .. } | Self::Group { contact_id, .. } => *contact_id,
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::blob::BlobObject;
|
||||
use crate::chat::{self, Chat, ChatId, ProtectionStatus};
|
||||
use crate::config::Config;
|
||||
use crate::constants::{Viewtype, DC_CONTACT_ID_SELF};
|
||||
use crate::contact::{Contact, Origin};
|
||||
use crate::contact::{Contact, ContactId, Origin};
|
||||
use crate::context::Context;
|
||||
use crate::dc_tools::dc_timestamp_to_str;
|
||||
use crate::message::Message;
|
||||
@@ -389,7 +389,7 @@ trait StockStringMods: AsRef<str> + Sized {
|
||||
fn action_by_contact<'a>(
|
||||
self,
|
||||
context: &'a Context,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
) -> Pin<Box<dyn Future<Output = String> + Send + 'a>>
|
||||
where
|
||||
Self: Send + 'a,
|
||||
@@ -457,7 +457,7 @@ pub(crate) async fn msg_grp_name(
|
||||
context: &Context,
|
||||
from_group: impl AsRef<str>,
|
||||
to_group: impl AsRef<str>,
|
||||
by_contact: u32,
|
||||
by_contact: ContactId,
|
||||
) -> String {
|
||||
translated(context, StockMessage::MsgGrpName)
|
||||
.await
|
||||
@@ -468,7 +468,7 @@ pub(crate) async fn msg_grp_name(
|
||||
}
|
||||
|
||||
/// Stock string: `Group image changed.`.
|
||||
pub(crate) async fn msg_grp_img_changed(context: &Context, by_contact: u32) -> String {
|
||||
pub(crate) async fn msg_grp_img_changed(context: &Context, by_contact: ContactId) -> String {
|
||||
translated(context, StockMessage::MsgGrpImgChanged)
|
||||
.await
|
||||
.action_by_contact(context, by_contact)
|
||||
@@ -482,7 +482,7 @@ pub(crate) async fn msg_grp_img_changed(context: &Context, by_contact: u32) -> S
|
||||
pub(crate) async fn msg_add_member(
|
||||
context: &Context,
|
||||
added_member_addr: impl AsRef<str>,
|
||||
by_contact: u32,
|
||||
by_contact: ContactId,
|
||||
) -> String {
|
||||
let addr = added_member_addr.as_ref();
|
||||
let who = match Contact::lookup_id_by_addr(context, addr, Origin::Unknown).await {
|
||||
@@ -506,7 +506,7 @@ pub(crate) async fn msg_add_member(
|
||||
pub(crate) async fn msg_del_member(
|
||||
context: &Context,
|
||||
removed_member_addr: impl AsRef<str>,
|
||||
by_contact: u32,
|
||||
by_contact: ContactId,
|
||||
) -> String {
|
||||
let addr = removed_member_addr.as_ref();
|
||||
let who = match Contact::lookup_id_by_addr(context, addr, Origin::Unknown).await {
|
||||
@@ -524,7 +524,7 @@ pub(crate) async fn msg_del_member(
|
||||
}
|
||||
|
||||
/// Stock string: `Group left.`.
|
||||
pub(crate) async fn msg_group_left(context: &Context, by_contact: u32) -> String {
|
||||
pub(crate) async fn msg_group_left(context: &Context, by_contact: ContactId) -> String {
|
||||
translated(context, StockMessage::MsgGroupLeft)
|
||||
.await
|
||||
.action_by_contact(context, by_contact)
|
||||
@@ -574,7 +574,7 @@ pub(crate) async fn read_rcpt_mail_body(context: &Context, message: impl AsRef<s
|
||||
}
|
||||
|
||||
/// Stock string: `Group image deleted.`.
|
||||
pub(crate) async fn msg_grp_img_deleted(context: &Context, by_contact: u32) -> String {
|
||||
pub(crate) async fn msg_grp_img_deleted(context: &Context, by_contact: ContactId) -> String {
|
||||
translated(context, StockMessage::MsgGrpImgDeleted)
|
||||
.await
|
||||
.action_by_contact(context, by_contact)
|
||||
@@ -587,7 +587,10 @@ pub(crate) async fn e2e_preferred(context: &Context) -> String {
|
||||
}
|
||||
|
||||
/// Stock string: `%1$s invited you to join this group. Waiting for the device of %2$s to reply…`.
|
||||
pub(crate) async fn secure_join_started(context: &Context, inviter_contact_id: u32) -> String {
|
||||
pub(crate) async fn secure_join_started(
|
||||
context: &Context,
|
||||
inviter_contact_id: ContactId,
|
||||
) -> String {
|
||||
if let Ok(contact) = Contact::get_by_id(context, inviter_contact_id).await {
|
||||
translated(context, StockMessage::SecureJoinStarted)
|
||||
.await
|
||||
@@ -602,7 +605,7 @@ pub(crate) async fn secure_join_started(context: &Context, inviter_contact_id: u
|
||||
}
|
||||
|
||||
/// Stock string: `%1$s replied, waiting for being added to the group…`.
|
||||
pub(crate) async fn secure_join_replies(context: &Context, contact_id: u32) -> String {
|
||||
pub(crate) async fn secure_join_replies(context: &Context, contact_id: ContactId) -> String {
|
||||
if let Ok(contact) = Contact::get_by_id(context, contact_id).await {
|
||||
translated(context, StockMessage::SecureJoinReplies)
|
||||
.await
|
||||
@@ -718,7 +721,7 @@ pub(crate) async fn msg_location_enabled(context: &Context) -> String {
|
||||
}
|
||||
|
||||
/// Stock string: `Location streaming enabled by ...`.
|
||||
pub(crate) async fn msg_location_enabled_by(context: &Context, contact: u32) -> String {
|
||||
pub(crate) async fn msg_location_enabled_by(context: &Context, contact: ContactId) -> String {
|
||||
translated(context, StockMessage::MsgLocationEnabled)
|
||||
.await
|
||||
.action_by_contact(context, contact)
|
||||
@@ -784,7 +787,10 @@ pub(crate) async fn failed_sending_to(context: &Context, name: impl AsRef<str>)
|
||||
}
|
||||
|
||||
/// Stock string: `Message deletion timer is disabled.`.
|
||||
pub(crate) async fn msg_ephemeral_timer_disabled(context: &Context, by_contact: u32) -> String {
|
||||
pub(crate) async fn msg_ephemeral_timer_disabled(
|
||||
context: &Context,
|
||||
by_contact: ContactId,
|
||||
) -> String {
|
||||
translated(context, StockMessage::MsgEphemeralTimerDisabled)
|
||||
.await
|
||||
.action_by_contact(context, by_contact)
|
||||
@@ -795,7 +801,7 @@ pub(crate) async fn msg_ephemeral_timer_disabled(context: &Context, by_contact:
|
||||
pub(crate) async fn msg_ephemeral_timer_enabled(
|
||||
context: &Context,
|
||||
timer: impl AsRef<str>,
|
||||
by_contact: u32,
|
||||
by_contact: ContactId,
|
||||
) -> String {
|
||||
translated(context, StockMessage::MsgEphemeralTimerEnabled)
|
||||
.await
|
||||
@@ -805,7 +811,7 @@ pub(crate) async fn msg_ephemeral_timer_enabled(
|
||||
}
|
||||
|
||||
/// Stock string: `Message deletion timer is set to 1 minute.`.
|
||||
pub(crate) async fn msg_ephemeral_timer_minute(context: &Context, by_contact: u32) -> String {
|
||||
pub(crate) async fn msg_ephemeral_timer_minute(context: &Context, by_contact: ContactId) -> String {
|
||||
translated(context, StockMessage::MsgEphemeralTimerMinute)
|
||||
.await
|
||||
.action_by_contact(context, by_contact)
|
||||
@@ -813,7 +819,7 @@ pub(crate) async fn msg_ephemeral_timer_minute(context: &Context, by_contact: u3
|
||||
}
|
||||
|
||||
/// Stock string: `Message deletion timer is set to 1 hour.`.
|
||||
pub(crate) async fn msg_ephemeral_timer_hour(context: &Context, by_contact: u32) -> String {
|
||||
pub(crate) async fn msg_ephemeral_timer_hour(context: &Context, by_contact: ContactId) -> String {
|
||||
translated(context, StockMessage::MsgEphemeralTimerHour)
|
||||
.await
|
||||
.action_by_contact(context, by_contact)
|
||||
@@ -821,7 +827,7 @@ pub(crate) async fn msg_ephemeral_timer_hour(context: &Context, by_contact: u32)
|
||||
}
|
||||
|
||||
/// Stock string: `Message deletion timer is set to 1 day.`.
|
||||
pub(crate) async fn msg_ephemeral_timer_day(context: &Context, by_contact: u32) -> String {
|
||||
pub(crate) async fn msg_ephemeral_timer_day(context: &Context, by_contact: ContactId) -> String {
|
||||
translated(context, StockMessage::MsgEphemeralTimerDay)
|
||||
.await
|
||||
.action_by_contact(context, by_contact)
|
||||
@@ -829,7 +835,7 @@ pub(crate) async fn msg_ephemeral_timer_day(context: &Context, by_contact: u32)
|
||||
}
|
||||
|
||||
/// Stock string: `Message deletion timer is set to 1 week.`.
|
||||
pub(crate) async fn msg_ephemeral_timer_week(context: &Context, by_contact: u32) -> String {
|
||||
pub(crate) async fn msg_ephemeral_timer_week(context: &Context, by_contact: ContactId) -> String {
|
||||
translated(context, StockMessage::MsgEphemeralTimerWeek)
|
||||
.await
|
||||
.action_by_contact(context, by_contact)
|
||||
@@ -874,7 +880,7 @@ pub(crate) async fn error_no_network(context: &Context) -> String {
|
||||
}
|
||||
|
||||
/// Stock string: `Chat protection enabled.`.
|
||||
pub(crate) async fn protection_enabled(context: &Context, by_contact: u32) -> String {
|
||||
pub(crate) async fn protection_enabled(context: &Context, by_contact: ContactId) -> String {
|
||||
translated(context, StockMessage::ProtectionEnabled)
|
||||
.await
|
||||
.action_by_contact(context, by_contact)
|
||||
@@ -882,7 +888,7 @@ pub(crate) async fn protection_enabled(context: &Context, by_contact: u32) -> St
|
||||
}
|
||||
|
||||
/// Stock string: `Chat protection disabled.`.
|
||||
pub(crate) async fn protection_disabled(context: &Context, by_contact: u32) -> String {
|
||||
pub(crate) async fn protection_disabled(context: &Context, by_contact: ContactId) -> String {
|
||||
translated(context, StockMessage::ProtectionDisabled)
|
||||
.await
|
||||
.action_by_contact(context, by_contact)
|
||||
@@ -908,7 +914,7 @@ pub(crate) async fn delete_server_turned_off(context: &Context) -> String {
|
||||
pub(crate) async fn msg_ephemeral_timer_minutes(
|
||||
context: &Context,
|
||||
minutes: impl AsRef<str>,
|
||||
by_contact: u32,
|
||||
by_contact: ContactId,
|
||||
) -> String {
|
||||
translated(context, StockMessage::MsgEphemeralTimerMinutes)
|
||||
.await
|
||||
@@ -921,7 +927,7 @@ pub(crate) async fn msg_ephemeral_timer_minutes(
|
||||
pub(crate) async fn msg_ephemeral_timer_hours(
|
||||
context: &Context,
|
||||
hours: impl AsRef<str>,
|
||||
by_contact: u32,
|
||||
by_contact: ContactId,
|
||||
) -> String {
|
||||
translated(context, StockMessage::MsgEphemeralTimerHours)
|
||||
.await
|
||||
@@ -934,7 +940,7 @@ pub(crate) async fn msg_ephemeral_timer_hours(
|
||||
pub(crate) async fn msg_ephemeral_timer_days(
|
||||
context: &Context,
|
||||
days: impl AsRef<str>,
|
||||
by_contact: u32,
|
||||
by_contact: ContactId,
|
||||
) -> String {
|
||||
translated(context, StockMessage::MsgEphemeralTimerDays)
|
||||
.await
|
||||
@@ -947,7 +953,7 @@ pub(crate) async fn msg_ephemeral_timer_days(
|
||||
pub(crate) async fn msg_ephemeral_timer_weeks(
|
||||
context: &Context,
|
||||
weeks: impl AsRef<str>,
|
||||
by_contact: u32,
|
||||
by_contact: ContactId,
|
||||
) -> String {
|
||||
translated(context, StockMessage::MsgEphemeralTimerWeeks)
|
||||
.await
|
||||
@@ -1104,7 +1110,7 @@ impl Context {
|
||||
pub(crate) async fn stock_protection_msg(
|
||||
&self,
|
||||
protect: ProtectionStatus,
|
||||
from_id: u32,
|
||||
from_id: ContactId,
|
||||
) -> String {
|
||||
match protect {
|
||||
ProtectionStatus::Unprotected => protection_enabled(self, from_id).await,
|
||||
|
||||
@@ -851,7 +851,7 @@ async fn log_msg(context: &Context, prefix: impl AsRef<str>, msg: &Message) {
|
||||
&contact_name,
|
||||
contact_id,
|
||||
msgtext.unwrap_or_default(),
|
||||
if msg.get_from_id() == 1u32 {
|
||||
if msg.get_from_id() == DC_CONTACT_ID_SELF {
|
||||
""
|
||||
} else if msg.get_state() == MessageState::InSeen {
|
||||
"[SEEN]"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! # Functions to update timestamps.
|
||||
|
||||
use crate::chat::{Chat, ChatId};
|
||||
use crate::contact::Contact;
|
||||
use crate::contact::{Contact, ContactId};
|
||||
use crate::context::Context;
|
||||
use crate::param::{Param, Params};
|
||||
use anyhow::Result;
|
||||
@@ -12,7 +12,7 @@ impl Context {
|
||||
/// (if we have a ContactId type at some point, the function should go there)
|
||||
pub(crate) async fn update_contacts_timestamp(
|
||||
&self,
|
||||
contact_id: u32,
|
||||
contact_id: ContactId,
|
||||
scope: Param,
|
||||
new_timestamp: i64,
|
||||
) -> Result<bool> {
|
||||
|
||||
Reference in New Issue
Block a user