mirror of
https://github.com/deltachat/deltachat-core.git
synced 2025-10-04 10:19:16 +02:00
introduce message.get_state() API which provides is_in_delivered()|is_out_delivered|... methods.
This commit is contained in:
parent
959ac73122
commit
da2bcd0c5a
4 changed files with 96 additions and 16 deletions
|
@ -2,7 +2,7 @@ from deltachat import capi
|
||||||
from deltachat.capi import ffi
|
from deltachat.capi import ffi
|
||||||
from deltachat.account import Account # noqa
|
from deltachat.account import Account # noqa
|
||||||
|
|
||||||
__version__ = "0.5.dev0"
|
__version__ = "0.5.dev1"
|
||||||
|
|
||||||
|
|
||||||
_DC_CALLBACK_MAP = {}
|
_DC_CALLBACK_MAP = {}
|
||||||
|
|
|
@ -12,7 +12,7 @@ deltah = joinpath(dirname(dirname(dirname(here))), "src", "deltachat.h")
|
||||||
|
|
||||||
|
|
||||||
def read_event_defines():
|
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))
|
return filter(rex.match, open(deltah))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
""" Chatting related objects: Contact, Chat, Message. """
|
""" chatting related objects: Contact, Chat, Message. """
|
||||||
|
|
||||||
from . import capi
|
from . import capi
|
||||||
from .cutil import convert_to_bytes_utf8, ffi_unicode, iter_array_and_unref
|
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):
|
def dc_msg_t(self):
|
||||||
return capi.lib.dc_get_msg(self.dc_context, self.id)
|
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):
|
def __del__(self):
|
||||||
if lib is not None and hasattr(self, "_property_cache"):
|
if lib is not None and hasattr(self, "_property_cache"):
|
||||||
lib.dc_msg_unref(self.dc_msg_t)
|
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
|
@property_with_doc
|
||||||
def text(self):
|
def text(self):
|
||||||
"""unicode representation. """
|
"""unicode representation. """
|
||||||
|
@ -131,3 +143,63 @@ class Message(object):
|
||||||
"""
|
"""
|
||||||
chat_id = capi.lib.dc_msg_get_chat_id(self.dc_msg_t)
|
chat_id = capi.lib.dc_msg_get_chat_id(self.dc_msg_t)
|
||||||
return Chat(self.dc_context, chat_id)
|
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
|
||||||
|
|
|
@ -56,6 +56,15 @@ class TestOfflineAccount:
|
||||||
chat = ac1.create_chat_by_contact(contact1)
|
chat = ac1.create_chat_by_contact(contact1)
|
||||||
msg = chat.send_text_message("msg1")
|
msg = chat.send_text_message("msg1")
|
||||||
assert msg
|
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:
|
class TestOnlineAccount:
|
||||||
|
@ -103,26 +112,27 @@ class TestOnlineAccount:
|
||||||
self.wait_successful_IMAP_SMTP_connection(ac2)
|
self.wait_successful_IMAP_SMTP_connection(ac2)
|
||||||
self.wait_configuration_progress(ac1, 1000)
|
self.wait_configuration_progress(ac1, 1000)
|
||||||
self.wait_configuration_progress(ac2, 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")
|
ev = ac1._evlogger.get_matching("DC_EVENT_MSG_DELIVERED")
|
||||||
evt_name, data1, data2 = ev
|
evt_name, data1, data2 = ev
|
||||||
assert data1 == chat.id
|
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
|
# wait for other account to receive
|
||||||
ev = ac2._evlogger.get_matching("DC_EVENT_MSGS_CHANGED")
|
ev = ac2._evlogger.get_matching("DC_EVENT_MSGS_CHANGED")
|
||||||
assert ev[2] == msg.id
|
assert ev[2] == msg_out.id
|
||||||
msg2 = ac2.get_message_by_id(msg.id)
|
msg_in = ac2.get_message_by_id(msg_out.id)
|
||||||
assert msg2.text == "msg1"
|
assert msg_in.text == "message1"
|
||||||
|
|
||||||
# check the message arrived in contact-requets/deaddrop
|
# check the message arrived in contact-requets/deaddrop
|
||||||
chat2 = msg2.chat
|
chat2 = msg_in.chat
|
||||||
assert msg2 in chat2.get_messages()
|
assert msg_in in chat2.get_messages()
|
||||||
assert chat2.is_deaddrop()
|
assert chat2.is_deaddrop()
|
||||||
assert chat2.count_fresh_messages() == 0
|
assert chat2.count_fresh_messages() == 0
|
||||||
|
|
||||||
# create new chat with contact and verify it's proper
|
# 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 not chat2b.is_deaddrop()
|
||||||
assert chat2b.count_fresh_messages() == 1
|
assert chat2b.count_fresh_messages() == 1
|
||||||
|
|
||||||
|
@ -131,8 +141,6 @@ class TestOnlineAccount:
|
||||||
assert chat2b.count_fresh_messages() == 0
|
assert chat2b.count_fresh_messages() == 0
|
||||||
|
|
||||||
# mark messages as seen and check ac1 sees the MDN
|
# mark messages as seen and check ac1 sees the MDN
|
||||||
ac2.mark_seen_messages([msg2])
|
ac2.mark_seen_messages([msg_in])
|
||||||
while 1:
|
ac1._evlogger.get_matching("DC_EVENT_MSGS_CHANGED")
|
||||||
ev = ac1._evlogger.get_matching("DC_EVENT_INFO")
|
assert msg_out.get_state().is_out_mdn_received()
|
||||||
if "Marking message" in ev[2]:
|
|
||||||
break
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue