6 import util.coroutines as coroutines
11 _moduleLogger = logging.getLogger("gvoice.conversations")
14 class Conversations(object):
16 def __init__(self, backend):
17 self._backend = backend
18 self._conversations = {}
20 self.updateSignalHandler = coroutines.CoTee()
22 def update(self, force=False):
23 if not force and self._conversations:
26 oldConversationIds = set(self._conversations.iterkeys())
28 updateConversationIds = set()
29 messages = self._backend.get_messages()
30 sortedMessages = backend.sort_messages(messages)
31 for messageData in sortedMessages:
32 key = messageData["contactId"], messageData["number"]
34 conversation = self._conversations[key]
35 isNewConversation = False
37 conversation = Conversation(self._backend, messageData)
38 self._conversations[key] = conversation
39 isNewConversation = True
42 # @todo see if this has issues with a user marking a item as unread/unarchive?
43 isConversationUpdated = True
45 isConversationUpdated = conversation.merge_conversation(messageData)
47 if isConversationUpdated:
48 updateConversationIds.add(key)
50 if updateConversationIds:
51 message = (self, updateConversationIds, )
52 self.updateSignalHandler.stage.send(message)
54 def get_conversations(self):
55 return self._conversations.iterkeys()
57 def get_conversation(self, key):
58 return self._conversations[key]
60 def clear_conversation(self, key):
62 del self._conversations[key]
64 _moduleLogger.info("Conversation never existed for %r" % (key,))
67 self._conversations.clear()
70 class Conversation(object):
72 def __init__(self, backend, data):
73 self._backend = backend
74 self._data = dict((key, value) for (key, value) in data.iteritems())
76 # confirm we have a list
77 self._data["messageParts"] = list(
78 self._append_time(message, self._data["time"])
79 for message in self._data["messageParts"]
82 def __getitem__(self, key):
83 return self._data[key]
85 def merge_conversation(self, moreData):
87 @returns True if there was content to merge (new messages arrived
88 rather than being a duplicate)
90 @warning This assumes merges are done in chronological order
92 for constantField in ("contactId", "number"):
93 assert self._data[constantField] == moreData[constantField], "Constant field changed, soemthing is seriously messed up: %r v %r" % (self._data, moreData)
95 if moreData["time"] < self._data["time"]:
96 # If its older, assuming it has nothing new to report
99 for preferredMoreField in ("id", "name", "time", "relTime", "prettyNumber", "location"):
100 preferredFieldValue = moreData[preferredMoreField]
101 if preferredFieldValue:
102 self._data[preferredMoreField] = preferredFieldValue
104 messageAppended = False
106 # @todo Handle No Transcription voicemails
107 messageParts = self._data["messageParts"]
108 for message in moreData["messageParts"]:
109 messageWithTimestamp = self._append_time(message, moreData["time"])
110 if messageWithTimestamp not in messageParts:
111 messageParts.append(messageWithTimestamp)
112 messageAppended = True
115 return messageAppended
118 def _append_time(message, exactWhen):
119 whoFrom, message, when = message
120 return exactWhen, whoFrom, message, when