1
0
Fork 0
mirror of https://github.com/deltachat/deltachat-core.git synced 2025-10-04 02:09:17 +02:00

introduce message.get_state() API which provides is_in_delivered()|is_out_delivered|... methods.

This commit is contained in:
holger krekel 2018-09-14 21:43:52 +02:00
parent 959ac73122
commit da2bcd0c5a
4 changed files with 96 additions and 16 deletions

View file

@ -2,7 +2,7 @@ from deltachat import capi
from deltachat.capi import ffi
from deltachat.account import Account # noqa
__version__ = "0.5.dev0"
__version__ = "0.5.dev1"
_DC_CALLBACK_MAP = {}

View file

@ -12,7 +12,7 @@ deltah = joinpath(dirname(dirname(dirname(here))), "src", "deltachat.h")
def read_event_defines():
rex = re.compile(r'#define\s+(?:DC_EVENT_|DC_CONTACT_ID_|DC_GCL|DC_CHAT)\S+\s+([x\d]+).*')
rex = re.compile(r'#define\s+(?:DC_EVENT_|DC_STATE_|DC_CONTACT_ID_|DC_GCL|DC_CHAT)\S+\s+([x\d]+).*')
return filter(rex.match, open(deltah))

View file

@ -1,4 +1,4 @@
""" Chatting related objects: Contact, Chat, Message. """
""" chatting related objects: Contact, Chat, Message. """
from . import capi
from .cutil import convert_to_bytes_utf8, ffi_unicode, iter_array_and_unref
@ -114,10 +114,22 @@ class Message(object):
def dc_msg_t(self):
return capi.lib.dc_get_msg(self.dc_context, self.id)
def _refresh(self):
if hasattr(self, "_property_cache"):
lib.dc_msg_unref(self.dc_msg_t)
self._property_cache.clear()
def __del__(self):
if lib is not None and hasattr(self, "_property_cache"):
lib.dc_msg_unref(self.dc_msg_t)
def get_state(self):
""" get the message in/out state.
:returns: :class:`MessageState`
"""
return MessageState(self)
@property_with_doc
def text(self):
"""unicode representation. """
@ -131,3 +143,63 @@ class Message(object):
"""
chat_id = capi.lib.dc_msg_get_chat_id(self.dc_msg_t)
return Chat(self.dc_context, chat_id)
@attr.s
class MessageState(object):
""" Current Message In/Out state, updated on each call of is_* methods.
"""
message = attr.ib(validator=v.instance_of(Message))
@property
def _msgstate(self):
self.message._refresh()
return lib.dc_msg_get_state(self.message.dc_msg_t)
def is_in_fresh(self):
""" return True if Message is incoming fresh message (un-noticed).
Fresh messages are not noticed nor seen and are typically
shown in notifications.
"""
return self._msgstate == lib.DC_STATE_IN_FRESH
def is_in_noticed(self):
"""Return True if Message is incoming and noticed.
Eg. chat opened but message not yet read - noticed messages
are not counted as unread but were not marked as read nor resulted in MDNs.
"""
return self._msgstate == lib.DC_STATE_IN_NOTICED
def is_in_seen(self):
"""Return True if Message is incoming, noticed and has been seen.
Eg. chat opened but message not yet read - noticed messages
are not counted as unread but were not marked as read nor resulted in MDNs.
"""
return self._msgstate == lib.DC_STATE_IN_SEEN
def is_out_pending(self):
"""Return True if Message is outgoing, but is pending (no single checkmark).
"""
return self._msgstate == lib.DC_STATE_OUT_PENDING
def is_out_failed(self):
"""Return True if Message is unrecoverably failed.
"""
return self._msgstate == lib.DC_STATE_OUT_FAILED
def is_out_delivered(self):
"""Return True if Message was successfully delivered to the server (one checkmark).
Note, that already delivered messages may get into the state is_out_failed().
"""
return self._msgstate == lib.DC_STATE_OUT_DELIVERED
def is_out_mdn_received(self):
"""Return True if message was marked as read by the recipient(s) (two checkmarks;
this requires goodwill on the receiver's side). If a sent message changes to this
state, you'll receive the event DC_EVENT_MSG_READ.
"""
return self._msgstate == lib.DC_STATE_OUT_MDN_RCVD

View file

@ -56,6 +56,15 @@ class TestOfflineAccount:
chat = ac1.create_chat_by_contact(contact1)
msg = chat.send_text_message("msg1")
assert msg
msg_state = msg.get_state()
assert not msg_state.is_in_fresh()
assert not msg_state.is_in_noticed()
assert not msg_state.is_in_seen()
# XXX the following line should work but doesn't:
# assert msg_state.is_out_pending()
assert not msg_state.is_out_failed()
assert not msg_state.is_out_delivered()
assert not msg_state.is_out_mdn_received()
class TestOnlineAccount:
@ -103,26 +112,27 @@ class TestOnlineAccount:
self.wait_successful_IMAP_SMTP_connection(ac2)
self.wait_configuration_progress(ac1, 1000)
self.wait_configuration_progress(ac2, 1000)
msg = chat.send_text_message("msg1")
msg_out = chat.send_text_message("message1")
ev = ac1._evlogger.get_matching("DC_EVENT_MSG_DELIVERED")
evt_name, data1, data2 = ev
assert data1 == chat.id
assert data2 == msg.id
assert data2 == msg_out.id
assert msg_out.get_state().is_out_delivered()
# wait for other account to receive
ev = ac2._evlogger.get_matching("DC_EVENT_MSGS_CHANGED")
assert ev[2] == msg.id
msg2 = ac2.get_message_by_id(msg.id)
assert msg2.text == "msg1"
assert ev[2] == msg_out.id
msg_in = ac2.get_message_by_id(msg_out.id)
assert msg_in.text == "message1"
# check the message arrived in contact-requets/deaddrop
chat2 = msg2.chat
assert msg2 in chat2.get_messages()
chat2 = msg_in.chat
assert msg_in in chat2.get_messages()
assert chat2.is_deaddrop()
assert chat2.count_fresh_messages() == 0
# create new chat with contact and verify it's proper
chat2b = ac2.create_chat_by_message(msg2)
chat2b = ac2.create_chat_by_message(msg_in)
assert not chat2b.is_deaddrop()
assert chat2b.count_fresh_messages() == 1
@ -131,8 +141,6 @@ class TestOnlineAccount:
assert chat2b.count_fresh_messages() == 0
# mark messages as seen and check ac1 sees the MDN
ac2.mark_seen_messages([msg2])
while 1:
ev = ac1._evlogger.get_matching("DC_EVENT_INFO")
if "Marking message" in ev[2]:
break
ac2.mark_seen_messages([msg_in])
ac1._evlogger.get_matching("DC_EVENT_MSGS_CHANGED")
assert msg_out.get_state().is_out_mdn_received()