import dbus.glib import gobject import logging import sys from time import sleep from account import connection_from_file from telepathy.client.channel import Channel from telepathy.constants import ( CONNECTION_HANDLE_TYPE_CONTACT, CONNECTION_STATUS_CONNECTED, CHANNEL_TEXT_MESSAGE_TYPE_NORMAL) from telepathy.interfaces import CHANNEL_TYPE_TEXT, CONN_INTERFACE logging.basicConfig() class Message: def __init__(self, conn, *stuff): self.conn = conn self.contact = None self.message = None assert len(stuff) in (0, 2) if len(stuff) == 2: self.contact = stuff[0] self.message = stuff[1] conn[CONN_INTERFACE].connect_to_signal('StatusChanged', self.status_changed_cb) conn[CONN_INTERFACE].connect_to_signal('NewChannel', self.new_channel_cb) def run(self): print "main loop running" self.loop = gobject.MainLoop() self.loop.run() def quit(self): if self.loop: self.loop.quit() self.loop = None def status_changed_cb(self, state, reason): if state != CONNECTION_STATUS_CONNECTED: return print "connection became ready" if self.contact is not None: handle = conn[CONN_INTERFACE].RequestHandles( CONNECTION_HANDLE_TYPE_CONTACT, [self.contact])[0] print 'got handle %d for %s' % (handle, self.contact) conn[CONN_INTERFACE].RequestChannel( CHANNEL_TYPE_TEXT, CONNECTION_HANDLE_TYPE_CONTACT, handle, True, reply_handler=lambda *stuff: None, error_handler=self.request_channel_error_cb) def request_channel_error_cb(self, exception): print 'error:', exception self.quit() def new_channel_cb(self, object_path, channel_type, handle_type, handle, suppress_handler): if channel_type != CHANNEL_TYPE_TEXT: return print 'got text channel with handle (%d,%d)' % (handle_type, handle) channel = Channel(self.conn.service_name, object_path) channel[CHANNEL_TYPE_TEXT].connect_to_signal('Sent', self.sent_cb) channel[CHANNEL_TYPE_TEXT].connect_to_signal('Received', self.recvd_cb) channel[CHANNEL_TYPE_TEXT].connect_to_signal('SendError', self.send_error_cb) if self.message is not None: channel[CHANNEL_TYPE_TEXT].Send( CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, self.message) else: for message in channel[CHANNEL_TYPE_TEXT].ListPendingMessages(True): self.recvd_cb(*message) def recvd_cb(self, *args): print args id, timestamp, sender, type, flags, text = args print 'message #%d received from handle %d: """%s"""' \ % (id, sender, text) self.quit() def sent_cb(self, timestamp, type, text): print 'message sent: """%s"""' % text # if we Disconnect() immediately, the message might not actually # make it to the network before the socket is shut down (this can # be the case in Gabble) - as a workaround, delay before disconnecting gobject.timeout_add(5000, self.quit) def send_error_cb(self, error, timestamp, type, text): print 'error sending message: code %d' % error self.quit() if __name__ == '__main__': conn = connection_from_file(sys.argv[1]) msg = Message(conn, *sys.argv[2:]) print "connecting" conn[CONN_INTERFACE].Connect() try: msg.run() except KeyboardInterrupt: print "killed" conn[CONN_INTERFACE].Disconnect()