refine member-added and member-removed plugin hooks to signal the sender (who added/removed a contact )

add ac_chat_modified hook event
add account.get_contact_by_addr (thanks @r10s)
This commit is contained in:
holger krekel
2020-04-17 21:32:27 +02:00
parent a87a2d0b71
commit 9eda710538
7 changed files with 133 additions and 76 deletions

View File

@@ -245,6 +245,14 @@ class Account(object):
assert contact_id > const.DC_CHAT_ID_LAST_SPECIAL
return bool(lib.dc_delete_contact(self._dc_context, contact_id))
def get_contact_by_addr(self, email):
""" get a contact for the email address or None if it's blocked or doesn't exist. """
_, addr = parseaddr(email)
addr = as_dc_charpointer(addr)
contact_id = lib.dc_lookup_contact_id_by_addr(self._dc_context, addr)
if contact_id:
return self.get_contact_by_id(contact_id)
def get_contacts(self, query=None, with_self=False, only_verified=False):
""" get a (filtered) list of contacts.
@@ -617,25 +625,46 @@ class Account(object):
return "ac_configure_completed", dict(success=success)
elif name == "DC_EVENT_INCOMING_MSG":
msg = self.get_message_by_id(ffi_event.data2)
return "ac_incoming_message", dict(message=msg)
return self._map_incoming(msg)
elif name == "DC_EVENT_MSGS_CHANGED":
if ffi_event.data2 != 0:
msg = self.get_message_by_id(ffi_event.data2)
if msg.is_outgoing():
evname, kwargs = self._map_incoming(msg)
if evname.startswith("ac_member"):
return evname, kwargs
if msg.is_in_fresh():
return "ac_incoming_message", dict(message=msg)
return self._map_incoming(msg)
elif name == "DC_EVENT_MSG_DELIVERED":
msg = self.get_message_by_id(ffi_event.data2)
return "ac_message_delivered", dict(message=msg)
elif name == "DC_EVENT_MEMBER_ADDED":
elif name == "DC_EVENT_CHAT_MODIFIED":
chat = self.get_chat_by_id(ffi_event.data1)
contact = self.get_contact_by_id(ffi_event.data2)
return "ac_member_added", dict(chat=chat, contact=contact)
elif name == "DC_EVENT_MEMBER_REMOVED":
chat = self.get_chat_by_id(ffi_event.data1)
contact = self.get_contact_by_id(ffi_event.data2)
return "ac_member_removed", dict(chat=chat, contact=contact)
return "ac_chat_modified", dict(chat=chat)
return None, {}
def _map_incoming(self, msg):
if msg.is_system_message():
res = parse_system_add_remove(msg.text)
if res:
contact = msg.account.get_contact_by_addr(res[1])
if contact:
d = dict(chat=msg.chat, contact=contact, sender=msg.get_sender_contact())
return "ac_member_" + res[0], d
return "ac_incoming_message", dict(message=msg)
def parse_system_add_remove(text):
# Member Me (x@y) removed by a@b.
# Member x@y removed by a@b
text = text.lower()
parts = text.split()
if parts[0] == "member":
if parts[2] in ("removed", "added"):
return parts[2], parts[1]
if parts[3] in ("removed", "added"):
return parts[3], parts[2].strip("()")
def _destroy_dc_context(dc_context, dc_context_unref=lib.dc_context_unref):
# destructor for dc_context

View File

@@ -53,11 +53,15 @@ class PerAccount:
""" Called when an outgoing message has been delivered to SMTP. """
@account_hookspec
def ac_member_added(self, chat, contact):
""" Called for each contact added to a chat. """
def ac_chat_modified(self, chat):
""" Chat was created or modified regarding membership, avatar, title. """
@account_hookspec
def ac_member_removed(self, chat, contact):
def ac_member_added(self, chat, contact, sender):
""" Called for each contact added to an accepted chat. """
@account_hookspec
def ac_member_removed(self, chat, contact, sender):
""" Called for each contact removed from a chat. """

View File

@@ -91,6 +91,10 @@ class Message(object):
"""mime type of the file (if it exists)"""
return from_dc_charpointer(lib.dc_msg_get_filemime(self._dc_msg))
def is_system_message(self):
""" return True if this message is a system/info message. """
return lib.dc_msg_is_info(self._dc_msg)
def is_setup_message(self):
""" return True if this message is a setup message. """
return lib.dc_msg_is_setupmessage(self._dc_msg)
@@ -224,6 +228,13 @@ class Message(object):
"""
return self._msgstate == const.DC_STATE_IN_SEEN
def is_outgoing(self):
"""Return True if Message is outgoing. """
return self._msgstate in (
const.DC_STATE_OUT_PREPARING, const.DC_STATE_OUT_PENDING,
const.DC_STATE_OUT_FAILED, const.DC_STATE_OUT_MDN_RCVD,
const.DC_STATE_OUT_DELIVERED)
def is_out_preparing(self):
"""Return True if Message is outgoing, but its file is being prepared.
"""