mirror of
https://github.com/chatmail/core.git
synced 2026-04-28 19:06:35 +03:00
fix member_added/member_removed event with tests and and provide a group-tracking example
This commit is contained in:
55
src/chat.rs
55
src/chat.rs
@@ -1830,36 +1830,61 @@ pub fn create_group_chat(
|
||||
Ok(chat_id)
|
||||
}
|
||||
|
||||
/// add a contact to the chats_contact table
|
||||
/// on success emit MemberAdded event and return true
|
||||
pub(crate) fn add_to_chat_contacts_table(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
contact_id: u32,
|
||||
) -> bool {
|
||||
// add a contact to a chat; the function does not check the type or if any of the record exist or are already
|
||||
// added to the chat!
|
||||
sql::execute(
|
||||
match sql::execute(
|
||||
context,
|
||||
&context.sql,
|
||||
"INSERT INTO chats_contacts (chat_id, contact_id) VALUES(?, ?)",
|
||||
params![chat_id, contact_id as i32],
|
||||
)
|
||||
.is_ok()
|
||||
) {
|
||||
Ok(()) => {
|
||||
context.call_cb(Event::MemberAdded {
|
||||
chat_id,
|
||||
contact_id,
|
||||
});
|
||||
|
||||
true
|
||||
}
|
||||
Err(err) => {
|
||||
error!(
|
||||
context,
|
||||
"could not add {} to chat {} table: {}", contact_id, chat_id, err
|
||||
);
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// remove a contact from the chats_contact table
|
||||
/// on success emit MemberRemoved event and return true
|
||||
pub(crate) fn remove_from_chat_contacts_table(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
contact_id: u32,
|
||||
) -> bool {
|
||||
// remove a contact from the chats_contact table unconditionally
|
||||
// the function does not check the type or if the record exist
|
||||
sql::execute(
|
||||
match sql::execute(
|
||||
context,
|
||||
&context.sql,
|
||||
"DELETE FROM chats_contacts WHERE chat_id=? AND contact_id=?",
|
||||
params![chat_id, contact_id as i32],
|
||||
)
|
||||
.is_ok()
|
||||
) {
|
||||
Ok(()) => {
|
||||
context.call_cb(Event::MemberRemoved {
|
||||
chat_id,
|
||||
contact_id,
|
||||
});
|
||||
|
||||
true
|
||||
}
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a contact to the chat.
|
||||
@@ -1955,12 +1980,6 @@ pub(crate) fn add_contact_to_chat_ex(
|
||||
msg.param.set_int(Param::Arg2, from_handshake.into());
|
||||
|
||||
msg.id = send_msg(context, chat_id, &mut msg)?;
|
||||
// send_msg sends MsgsChanged event
|
||||
// so we only send an explicit MemberAdded one
|
||||
context.call_cb(Event::MemberAdded {
|
||||
chat_id,
|
||||
contact_id: contact.id,
|
||||
});
|
||||
} else {
|
||||
// send an event for unpromoted groups
|
||||
// XXX probably not neccessary because ChatModified should suffice
|
||||
@@ -2173,10 +2192,6 @@ pub fn remove_contact_from_chat(
|
||||
msg.param.set_cmd(SystemMessage::MemberRemovedFromGroup);
|
||||
msg.param.set(Param::Arg, contact.get_addr());
|
||||
msg.id = send_msg(context, chat_id, &mut msg)?;
|
||||
context.call_cb(Event::MemberRemoved {
|
||||
chat_id,
|
||||
contact_id: contact.id,
|
||||
});
|
||||
context.call_cb(Event::MsgsChanged {
|
||||
chat_id,
|
||||
msg_id: msg.id,
|
||||
|
||||
@@ -24,9 +24,6 @@ use crate::peerstate::*;
|
||||
use crate::sql;
|
||||
use crate::stock::StockMessage;
|
||||
|
||||
/// Contacts with at least this origin value are shown in the contact list.
|
||||
const DC_ORIGIN_MIN_CONTACT_LIST: i32 = 0x100;
|
||||
|
||||
/// An object representing a single contact in memory.
|
||||
///
|
||||
/// The contact object is not updated.
|
||||
@@ -94,6 +91,7 @@ pub enum Origin {
|
||||
UnhandledQrScan = 0x80,
|
||||
|
||||
/// Reply-To: of incoming message of known sender
|
||||
/// Contacts with at least this origin value are shown in the contact list.
|
||||
IncomingReplyTo = 0x100,
|
||||
|
||||
/// Cc: of incoming message of known sender
|
||||
@@ -274,7 +272,7 @@ impl Contact {
|
||||
///
|
||||
/// To validate an e-mail address independently of the contact database
|
||||
/// use `dc_may_be_valid_addr()`.
|
||||
pub fn lookup_id_by_addr(context: &Context, addr: impl AsRef<str>) -> u32 {
|
||||
pub fn lookup_id_by_addr(context: &Context, addr: impl AsRef<str>, min_origin: Origin) -> u32 {
|
||||
if addr.as_ref().is_empty() {
|
||||
return 0;
|
||||
}
|
||||
@@ -287,14 +285,13 @@ impl Contact {
|
||||
if addr_cmp(addr_normalized, addr_self) {
|
||||
return DC_CONTACT_ID_SELF;
|
||||
}
|
||||
|
||||
context.sql.query_get_value(
|
||||
context,
|
||||
"SELECT id FROM contacts WHERE addr=?1 COLLATE NOCASE AND id>?2 AND origin>=?3 AND blocked=0;",
|
||||
params![
|
||||
addr_normalized,
|
||||
DC_CONTACT_ID_LAST_SPECIAL as i32,
|
||||
DC_ORIGIN_MIN_CONTACT_LIST,
|
||||
min_origin as u32,
|
||||
],
|
||||
).unwrap_or_default()
|
||||
}
|
||||
|
||||
@@ -800,7 +800,6 @@ fn create_or_lookup_group(
|
||||
let mut chat_id_blocked = Blocked::Not;
|
||||
let mut recreate_member_list = false;
|
||||
let mut send_EVENT_CHAT_MODIFIED = false;
|
||||
let mut X_MrRemoveFromGrp = None;
|
||||
let mut X_MrAddToGrp = None;
|
||||
let mut X_MrGrpNameChanged = false;
|
||||
let mut better_msg: String = From::from("");
|
||||
@@ -848,22 +847,25 @@ fn create_or_lookup_group(
|
||||
// but we might not know about this group
|
||||
|
||||
let grpname = mime_parser.get(HeaderDef::ChatGroupName).cloned();
|
||||
let mut removed_id = 0;
|
||||
|
||||
if let Some(optional_field) = mime_parser.get(HeaderDef::ChatGroupMemberRemoved).cloned() {
|
||||
X_MrRemoveFromGrp = Some(optional_field);
|
||||
mime_parser.is_system_message = SystemMessage::MemberRemovedFromGroup;
|
||||
let left_group = Contact::lookup_id_by_addr(context, X_MrRemoveFromGrp.as_ref().unwrap())
|
||||
== from_id as u32;
|
||||
better_msg = context.stock_system_msg(
|
||||
if left_group {
|
||||
StockMessage::MsgGroupLeft
|
||||
} else {
|
||||
StockMessage::MsgDelMember
|
||||
},
|
||||
X_MrRemoveFromGrp.as_ref().unwrap(),
|
||||
"",
|
||||
from_id as u32,
|
||||
)
|
||||
if let Some(removed_addr) = mime_parser.get(HeaderDef::ChatGroupMemberRemoved).cloned() {
|
||||
removed_id = Contact::lookup_id_by_addr(context, &removed_addr, Origin::Unknown);
|
||||
if removed_id == 0 {
|
||||
warn!(context, "removed {:?} has no contact_id", removed_addr);
|
||||
} else {
|
||||
mime_parser.is_system_message = SystemMessage::MemberRemovedFromGroup;
|
||||
better_msg = context.stock_system_msg(
|
||||
if removed_id == from_id as u32 {
|
||||
StockMessage::MsgGroupLeft
|
||||
} else {
|
||||
StockMessage::MsgDelMember
|
||||
},
|
||||
&removed_addr,
|
||||
"",
|
||||
from_id as u32,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let field = mime_parser.get(HeaderDef::ChatGroupMemberAdded).cloned();
|
||||
if let Some(optional_field) = field {
|
||||
@@ -949,7 +951,7 @@ fn create_or_lookup_group(
|
||||
&& !grpid.is_empty()
|
||||
&& grpname.is_some()
|
||||
// otherwise, a pending "quit" message may pop up
|
||||
&& X_MrRemoveFromGrp.is_none()
|
||||
&& removed_id == 0
|
||||
// re-create explicitly left groups only if ourself is re-added
|
||||
&& (!group_explicitly_left
|
||||
|| X_MrAddToGrp.is_some() && addr_cmp(&self_addr, X_MrAddToGrp.as_ref().unwrap()))
|
||||
@@ -1083,12 +1085,8 @@ fn create_or_lookup_group(
|
||||
}
|
||||
}
|
||||
send_EVENT_CHAT_MODIFIED = true;
|
||||
} else if let Some(removed_addr) = X_MrRemoveFromGrp {
|
||||
let contact_id = Contact::lookup_id_by_addr(context, removed_addr);
|
||||
if contact_id != 0 {
|
||||
info!(context, "remove {:?} from chat id={}", contact_id, chat_id);
|
||||
chat::remove_from_chat_contacts_table(context, chat_id, contact_id);
|
||||
}
|
||||
} else if removed_id > 0 {
|
||||
chat::remove_from_chat_contacts_table(context, chat_id, removed_id);
|
||||
send_EVENT_CHAT_MODIFIED = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -314,7 +314,7 @@ impl Context {
|
||||
from_id: u32,
|
||||
) -> String {
|
||||
let insert1 = if id == StockMessage::MsgAddMember || id == StockMessage::MsgDelMember {
|
||||
let contact_id = Contact::lookup_id_by_addr(self, param1.as_ref());
|
||||
let contact_id = Contact::lookup_id_by_addr(self, param1.as_ref(), Origin::Unknown);
|
||||
if contact_id != 0 {
|
||||
Contact::get_by_id(self, contact_id)
|
||||
.map(|contact| contact.get_name_n_addr())
|
||||
|
||||
Reference in New Issue
Block a user