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]
62 class Conversation(object):
64 def __init__(self, backend, data):
65 self._backend = backend
66 self._data = dict((key, value) for (key, value) in data.iteritems())
68 # confirm we have a list
69 self._data["messageParts"] = list(
70 self._append_time(message, self._data["time"])
71 for message in self._data["messageParts"]
74 def __getitem__(self, key):
75 return self._data[key]
77 def merge_conversation(self, moreData):
79 @returns True if there was content to merge (new messages arrived
80 rather than being a duplicate)
82 @warning This assumes merges are done in chronological order
84 for constantField in ("contactId", "number"):
85 assert self._data[constantField] == moreData[constantField], "Constant field changed, soemthing is seriously messed up: %r v %r" % (self._data, moreData)
87 if moreData["time"] < self._data["time"]:
88 # If its older, assuming it has nothing new to report
91 for preferredMoreField in ("id", "name", "time", "relTime", "prettyNumber", "location"):
92 preferredFieldValue = moreData[preferredMoreField]
93 if preferredFieldValue:
94 self._data[preferredMoreField] = preferredFieldValue
96 messageAppended = False
98 messageParts = self._data["messageParts"]
99 for message in moreData["messageParts"]:
100 messageWithTimestamp = self._append_time(message, moreData["time"])
101 if messageWithTimestamp not in messageParts:
102 messageParts.append(messageWithTimestamp)
103 messageAppended = True
106 return messageAppended
109 def _append_time(message, exactWhen):
110 whoFrom, message, when = message
111 return exactWhen, whoFrom, message, when