diff options
-rw-r--r-- | sunshine/channel/text.py | 17 | ||||
-rw-r--r-- | sunshine/connection.py | 31 | ||||
-rwxr-xr-x | sunshine/lqsoft/pygadu/models.py | 8 | ||||
-rwxr-xr-x | sunshine/lqsoft/pygadu/network_v8.py | 18 | ||||
-rwxr-xr-x | sunshine/lqsoft/pygadu/twisted_protocol.py | 8 |
5 files changed, 73 insertions, 9 deletions
diff --git a/sunshine/channel/text.py b/sunshine/channel/text.py index d37b6d0..fe63763 100644 --- a/sunshine/channel/text.py +++ b/sunshine/channel/text.py @@ -32,7 +32,8 @@ __all__ = ['SunshineTextChannel'] logger = logging.getLogger('Sunshine.TextChannel') -class SunshineTextChannel(telepathy.server.ChannelTypeText): +class SunshineTextChannel(telepathy.server.ChannelTypeText, + telepathy.server.ChannelInterfaceChatState): def __init__(self, conn, manager, conversation, props, object_path=None): _, surpress_handler, handle = manager._get_type_requested_handle(props) @@ -42,6 +43,7 @@ class SunshineTextChannel(telepathy.server.ChannelTypeText): self.handle = handle telepathy.server.ChannelTypeText.__init__(self, conn, manager, props, object_path=None) + telepathy.server.ChannelInterfaceChatState.__init__(self) def Send(self, message_type, text): if message_type == telepathy.CHANNEL_TEXT_MESSAGE_TYPE_NORMAL: @@ -49,7 +51,8 @@ class SunshineTextChannel(telepathy.server.ChannelTypeText): msg = text.decode('UTF-8').encode('windows-1250', 'replace') #gg_text = escape(text.decode('UTF-8')).encode('UTF-8').replace('<', '<').replace('>', '>') gg_text = text.decode('UTF-8', 'xmlcharrefreplace').replace('<', '<').replace('>', '>') - self.conn.gadu_client.sendTo(int(self.handle.name), str(gg_text), str(msg)) + self._conn_ref().profile.sendTo(int(self.handle.name), str(gg_text), str(msg)) + self._conn_ref().profile.sendTypingNotify(int(self.handle.name), 0) else: raise telepathy.NotImplemented("Unhandled message type") self.Sent(int(time.time()), message_type, text) @@ -79,6 +82,16 @@ class SunshineTextChannel(telepathy.server.ChannelTypeText): def ListPendingMessages(self, clear): return telepathy.server.ChannelTypeText.ListPendingMessages(self, clear) + def SetChatState(self, state): + # Not useful if we dont have a conversation. + if state == telepathy.CHANNEL_CHAT_STATE_COMPOSING: + t = 1 + else: + t = 0 + + handle = SunshineHandleFactory(self._conn_ref(), 'self') + self._conn_ref().profile.sendTypingNotify(int(self.handle.name), t) + self.ChatStateChanged(handle, state) class SunshineRoomTextChannel(telepathy.server.ChannelTypeText, telepathy.server.ChannelInterfaceGroup): diff --git a/sunshine/connection.py b/sunshine/connection.py index 53454de..52aadbe 100644 --- a/sunshine/connection.py +++ b/sunshine/connection.py @@ -185,7 +185,7 @@ class GaduClientFactory(protocol.ClientFactory): self.config.exportLoop = None if reactor.running: reactor.stop() - sys.exit(0) + os._exit(1) def clientConnectionFailed(self, connector, reason): logger.info('Connection failed. Reason: %s' % (reason)) @@ -198,7 +198,7 @@ class GaduClientFactory(protocol.ClientFactory): self.config.exportLoop = None if reactor.running: reactor.stop() - sys.exit(0) + os._exit(1) class SunshineConnection(telepathy.server.Connection, telepathy.server.ConnectionInterfaceRequests, @@ -253,6 +253,7 @@ class SunshineConnection(telepathy.server.Connection, self.profile.onLoginFailure = self.on_loginFailed self.profile.onContactStatusChange = self.on_updateContact self.profile.onMessageReceived = self.on_messageReceived + self.profile.onTypingNotification = self.onTypingNotification self.profile.onXmlAction = self.onXmlAction self.profile.onXmlEvent = self.onXmlEvent self.profile.onUserData = self.onUserData @@ -644,11 +645,12 @@ class SunshineConnection(telepathy.server.Connection, if msg.content.html_message: #we need to strip all html tags - text = stripHTML(msg.content.html_message).replace('<', '<').replace('>', '>') + text = unescape(stripHTML(msg.content.html_message)) else: - text = (msg.content.plain_message).decode('windows-1250') + text = unescape((msg.content.plain_message).decode('windows-1250')) + - message = "%s" % unicode(str(text).replace('\x00', '').replace('\r', '').decode('UTF-8')) + message = "%s" % unicode(str(text).replace('\x00', '').replace('\r', '')) #print 'message: ', message channel.Received(self._recv_id, timestamp, ahandle, type, 0, message) self._recv_id += 1 @@ -688,6 +690,25 @@ class SunshineConnection(telepathy.server.Connection, #print 'message: ', message channel.Received(self._recv_id, timestamp, handle, type, 0, message) self._recv_id += 1 + + def onTypingNotification(self, data): + logger.info("TypingNotification uin=%d, type=%d" % (data.uin, data.type)) + + handle_id = self.get_handle_id_by_name(telepathy.constants.HANDLE_TYPE_CONTACT, + str(data.uin)) + if handle_id != 0: + handle = self.handle(telepathy.constants.HANDLE_TYPE_CONTACT, handle_id) + + props = self._generate_props(telepathy.CHANNEL_TYPE_TEXT, + handle, False) + channel = self._channel_manager.channel_for_props(props, + signal=True, conversation=None) + + if type == 0: + channel.ChatStateChanged(handle, telepathy.CHANNEL_CHAT_STATE_PAUSED) + elif type >= 1: + channel.ChatStateChanged(handle, telepathy.CHANNEL_CHAT_STATE_COMPOSING) + reactor.callLater(3, channel.ChatStateChanged, handle, telepathy.CHANNEL_CHAT_STATE_PAUSED) def onXmlAction(self, xml): logger.info("XmlAction: %s" % xml.data) diff --git a/sunshine/lqsoft/pygadu/models.py b/sunshine/lqsoft/pygadu/models.py index 311dbc9..ced5dbe 100755 --- a/sunshine/lqsoft/pygadu/models.py +++ b/sunshine/lqsoft/pygadu/models.py @@ -121,6 +121,11 @@ class GaduProfile(object): raise RuntimeError("You need to be connected, to send messages.") self.__connection.sendConfMessage(uin, html_message + '\0', plain_message + '\0', recipients) + def sendTypingNotify(self, uin, type): + if not self.connected: + raise RuntimeError("You need to be connected, to send notifies.") + self.__connection.sendTypingNotify(uin, type) + def importContacts(self, callback): """Issue an import request. This is non-blocking and returns no data.""" if not self.connected: @@ -191,6 +196,9 @@ class GaduProfile(object): def onStatusNoticiesRecv(self): """Called when a contact list notify was sent""" pass + + def onTypingNotification(self, data): + pass def onXmlAction(self, data): """Called when a XML action packet was sent""" diff --git a/sunshine/lqsoft/pygadu/network_v8.py b/sunshine/lqsoft/pygadu/network_v8.py index 60d9f17..591239c 100755 --- a/sunshine/lqsoft/pygadu/network_v8.py +++ b/sunshine/lqsoft/pygadu/network_v8.py @@ -105,7 +105,7 @@ class LoginPacket(GaduPacket): login_hash = StringField(3, length=64) status = UIntField(4, default=0x02) flags = UIntField(5, default=0x03) - features = UIntField(6, default=0x637) + features = UIntField(6, default=0x2637) local_ip = IntField(7) local_port = ShortField(8) external_ip = IntField(9) @@ -233,4 +233,18 @@ class RecvMsgAck(GaduPacket): class UserDataPacket(GaduPacket): type = IntField(0) num = IntField(1) - users = ArrayField(2, length='num', subfield=StructField(0, struct=StructUserDataUser))
\ No newline at end of file + users = ArrayField(2, length='num', subfield=StructField(0, struct=StructUserDataUser)) + +# +# GG_TYPING_NOTIFY packets +# +@inpacket(0x59) +@outpacket(0x59) +class TypingNotifyPacket(GaduPacket): + TYPE = Enum({ + 'START': 0x01, + 'PAUSE': 0x05, + 'STOP': 0x00 + }) + type = ShortField(0) + uin = IntField(1) diff --git a/sunshine/lqsoft/pygadu/twisted_protocol.py b/sunshine/lqsoft/pygadu/twisted_protocol.py index f5d5481..ff99bba 100755 --- a/sunshine/lqsoft/pygadu/twisted_protocol.py +++ b/sunshine/lqsoft/pygadu/twisted_protocol.py @@ -153,6 +153,10 @@ class GaduClient(Protocol): def _handleMessageAckPacket(self, msg): print "MSG_Status=%x, recipient=%d, seq=%d" % (msg.msg_status, msg.recipient, msg.seq) + def _handleTypingNotifyPacket(self, data): + #print "MSG Typing Notify uin=%d, type=%d" % (data.uin, data.type) + self.user_profile.onTypingNotification(data) + def _handleDisconnectPacket(self, msg): print 'Server sent - disconnect packet' Protocol.connectionLost(self, None) @@ -216,6 +220,10 @@ class GaduClient(Protocol): self._sendPacket( klass( recipient=rcpt, seq=int(time.time()), content=payload) ) + def sendTypingNotify(self, uin, type): + klass = Resolver.by_name('TypingNotifyPacket') + self._sendPacket(klass(uin=uin, type=type)) + def sendConfMessage(self, rcpt, html_text, plain_message, contacts): klass = Resolver.by_name('MessageOutPacket') |