summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrzysztof Klinikowski <kkszysiu@gmail.com>2010-04-24 16:13:31 +0200
committerKrzysztof Klinikowski <kkszysiu@gmail.com>2010-04-24 16:13:31 +0200
commit0e261b0d5afb831f6ce4b45176749b07da2fe94d (patch)
treee931a3717d30573146098b6e6b21136d4e38fe03
parent2032cf05a66260d0b423134eaf38397e105d44b2 (diff)
Typing notifications, called "pisak" in GG implemented.
-rw-r--r--sunshine/channel/text.py17
-rw-r--r--sunshine/connection.py31
-rwxr-xr-xsunshine/lqsoft/pygadu/models.py8
-rwxr-xr-xsunshine/lqsoft/pygadu/network_v8.py18
-rwxr-xr-xsunshine/lqsoft/pygadu/twisted_protocol.py8
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('<', '&lt;').replace('>', '&gt;')
gg_text = text.decode('UTF-8', 'xmlcharrefreplace').replace('<', '&lt;').replace('>', '&gt;')
- 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('&lt;', '<').replace('&gt;', '>')
+ 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')