Reducing debug output
[theonering] / src / channel / text.py
1 import time
2 import datetime
3 import logging
4
5 import telepathy
6
7 import util.go_utils as gobject_utils
8 import util.coroutines as coroutines
9 import gtk_toolbox
10
11
12 _moduleLogger = logging.getLogger("channel.text")
13
14
15 class TextChannel(telepathy.server.ChannelTypeText):
16         """
17         Look into implementing ChannelInterfaceMessages for rich text formatting
18         """
19
20         def __init__(self, connection, manager, props, contactHandle):
21                 self._manager = manager
22                 self._props = props
23
24                 try:
25                         # HACK Older python-telepathy way
26                         telepathy.server.ChannelTypeText.__init__(self, connection, contactHandle)
27                 except TypeError:
28                         # HACK Newer python-telepathy way
29                         telepathy.server.ChannelTypeText.__init__(self, connection, manager, props)
30                 self._nextRecievedId = 0
31                 self._lastMessageTimestamp = datetime.datetime(1, 1, 1)
32
33                 self._otherHandle = contactHandle
34
35                 self._callback = coroutines.func_sink(
36                         coroutines.expand_positional(
37                                 self._on_conversations_updated
38                         )
39                 )
40                 self._conn.session.voicemails.updateSignalHandler.register_sink(
41                         self._callback
42                 )
43                 self._conn.session.texts.updateSignalHandler.register_sink(
44                         self._callback
45                 )
46
47                 # The only reason there should be anything in the conversation is if
48                 # its new, so report it all
49                 try:
50                         mergedConversations = self._conn.session.voicemails.get_conversation(self._contactKey)
51                 except KeyError:
52                         _moduleLogger.debug("Nothing in the conversation yet for %r" % (self._contactKey, ))
53                 else:
54                         self._report_conversation(mergedConversations)
55                 try:
56                         mergedConversations = self._conn.session.texts.get_conversation(self._contactKey)
57                 except KeyError:
58                         _moduleLogger.debug("Nothing in the conversation yet for %r" % (self._contactKey, ))
59                 else:
60                         self._report_conversation(mergedConversations)
61
62         @gtk_toolbox.log_exception(_moduleLogger)
63         def Send(self, messageType, text):
64                 if messageType != telepathy.CHANNEL_TEXT_MESSAGE_TYPE_NORMAL:
65                         raise telepathy.errors.NotImplemented("Unhandled message type: %r" % messageType)
66
67                 self._conn.session.backend.send_sms(self._otherHandle.phoneNumber, text)
68                 self._conn.session.textsStateMachine.reset_timers()
69
70                 self.Sent(int(time.time()), messageType, text)
71
72         @gtk_toolbox.log_exception(_moduleLogger)
73         def Close(self):
74                 self.close()
75
76         def close(self):
77                 self._conn.session.voicemails.updateSignalHandler.unregister_sink(
78                         self._callback
79                 )
80                 self._conn.session.texts.updateSignalHandler.unregister_sink(
81                         self._callback
82                 )
83                 self._callback = None
84
85                 telepathy.server.ChannelTypeText.Close(self)
86                 if self._manager.channel_exists(self._props):
87                         # HACK Older python-telepathy requires doing this manually
88                         self._manager.remove_channel(self)
89                 self.remove_from_connection()
90
91         @property
92         def _contactKey(self):
93                 contactKey = self._otherHandle.contactID, self._otherHandle.phoneNumber
94                 return contactKey
95
96         @gobject_utils.async
97         @gtk_toolbox.log_exception(_moduleLogger)
98         def _on_conversations_updated(self, conv, conversationIds):
99                 if self._contactKey not in conversationIds:
100                         return
101                 _moduleLogger.debug("Incoming messages from %r for existing conversation" % (self._contactKey, ))
102                 mergedConversations = conv.get_conversation(self._contactKey)
103                 self._report_conversation(mergedConversations)
104
105         def _report_conversation(self, mergedConversations):
106                 newConversations = mergedConversations.conversations
107                 newConversations = self._filter_out_reported(newConversations)
108                 newConversations = self._filter_out_read(newConversations)
109                 newConversations = list(newConversations)
110                 if not newConversations:
111                         _moduleLogger.debug(
112                                 "New messages for %r have already been read externally" % (self._contactKey, )
113                         )
114                         return
115                 self._lastMessageTimestamp = newConversations[-1].time
116
117                 messages = [
118                         newMessage
119                         for newConversation in newConversations
120                         for newMessage in newConversation.messages
121                         if newMessage.whoFrom != "Me:"
122                 ]
123                 if not newConversations:
124                         _moduleLogger.debug(
125                                 "All incoming messages were really outbound messages for %r" % (self._contactKey, )
126                         )
127                         return
128
129                 for newMessage in messages:
130                         formattedMessage = self._format_message(newMessage)
131                         self._report_new_message(formattedMessage)
132
133         def _filter_out_reported(self, conversations):
134                 return (
135                         conversation
136                         for conversation in conversations
137                         if self._lastMessageTimestamp < conversation.time
138                 )
139
140         def _filter_out_read(self, conversations):
141                 return (
142                         conversation
143                         for conversation in conversations
144                         if not conversation.isRead and not conversation.isArchived
145                 )
146
147         def _format_message(self, message):
148                 return " ".join(part.text.strip() for part in message.body)
149
150         def _report_new_message(self, message):
151                 currentReceivedId = self._nextRecievedId
152                 timestamp = int(time.time())
153                 type = telepathy.CHANNEL_TEXT_MESSAGE_TYPE_NORMAL
154
155                 _moduleLogger.info("Received message from User %r" % self._otherHandle)
156                 self.Received(currentReceivedId, timestamp, self._otherHandle, type, 0, message)
157
158                 self._nextRecievedId += 1