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()
23 def update(self, force=False):
24 if not force and self._conversations:
27 oldConversationIds = set(self._conversations.iterkeys())
29 updateConversationIds = set()
30 messages = self._backend.get_messages()
31 sortedMessages = backend.sort_messages(messages)
32 for messageData in sortedMessages:
33 key = messageData["contactId"], messageData["number"]
35 conversation = self._conversations[key]
36 isNewConversation = False
38 conversation = Conversation(self._backend, messageData)
39 self._conversations[key] = conversation
40 isNewConversation = True
43 # @todo see if this has issues with a user marking a item as unread/unarchive?
44 isConversationUpdated = True
46 isConversationUpdated = conversation.merge_conversation(messageData)
48 if isConversationUpdated:
49 updateConversationIds.add(key)
51 if updateConversationIds:
52 message = (self, updateConversationIds, )
53 self.updateSignalHandler.stage.send(message)
55 def get_conversations(self):
56 return self._conversations.iterkeys()
58 def get_conversation(self, key):
59 return self._conversations[key]
61 def clear_conversation(self, key):
63 del self._conversations[key]
65 _moduleLogger.info("Conversation never existed for %r" % (key,))
68 self._conversations.clear()
71 class Conversation(object):
73 def __init__(self, backend, data):
74 self._backend = backend
75 self._data = dict((key, value) for (key, value) in data.iteritems())
77 # confirm we have a list
78 self._data["messageParts"] = list(
79 self._append_time(message, self._data["time"])
80 for message in self._data["messageParts"]
83 def __getitem__(self, key):
84 return self._data[key]
86 def merge_conversation(self, moreData):
88 @returns True if there was content to merge (new messages arrived
89 rather than being a duplicate)
91 @warning This assumes merges are done in chronological order
93 for constantField in ("contactId", "number"):
94 assert self._data[constantField] == moreData[constantField], "Constant field changed, soemthing is seriously messed up: %r v %r" % (self._data, moreData)
96 if moreData["time"] < self._data["time"]:
97 # If its older, assuming it has nothing new to report
100 for preferredMoreField in ("id", "name", "time", "relTime", "prettyNumber", "location"):
101 preferredFieldValue = moreData[preferredMoreField]
102 if preferredFieldValue:
103 self._data[preferredMoreField] = preferredFieldValue
105 messageAppended = False
107 # @todo Handle No Transcription voicemails
108 messageParts = self._data["messageParts"]
109 for message in moreData["messageParts"]:
110 messageWithTimestamp = self._append_time(message, moreData["time"])
111 if messageWithTimestamp not in messageParts:
112 messageParts.append(messageWithTimestamp)
113 messageAppended = True
116 return messageAppended
119 def _append_time(message, exactWhen):
120 whoFrom, message, when = message
121 return exactWhen, whoFrom, message, when