python_iface_messaging/example.py

Source File

#!/usr/bin/env python

import sys

import gobject
import dbus.mainloop.glib
dbus.mainloop.glib.DBusGMainLoop(set_as_default = True)

import telepathy
import telepathy.client
from telepathy.interfaces import CONNECTION_MANAGER, \
                                 CONNECTION, \
                                 CONNECTION_INTERFACE_REQUESTS, \
                                 CHANNEL, \
                                 CHANNEL_TYPE_TEXT, \
                                 CHANNEL_INTERFACE_MESSAGES, \
                                 CHANNEL_INTERFACE_GROUP
from telepathy.constants import CONNECTION_STATUS_CONNECTED, \
                                CONNECTION_STATUS_DISCONNECTED, \
                                HANDLE_TYPE_CONTACT

DBUS_PROPERTIES = 'org.freedesktop.DBus.Properties'

# Begin Example 6-2
class TextChannel (telepathy.client.Channel):
    def __init__ (self, parent, channel_path):
        self.parent = parent
        conn = parent.conn

        super (TextChannel, self).__init__ (conn.service_name, channel_path)
        # End Example 6-2
        channel = self

        channel[DBUS_PROPERTIES].Get(CHANNEL, 'Interfaces',
                                     reply_handler = self.interfaces_cb,
                                     error_handler = self.parent.error_cb)
    # Begin Example 8-3
    def interfaces_cb (self, interfaces):
        channel = self

        print "Channel Interfaces:"
        for interface in interfaces:
            print " - %s" % interface

        if CHANNEL_INTERFACE_MESSAGES in interfaces:
            channel[CHANNEL_INTERFACE_MESSAGES].connect_to_signal(
                'MessageReceived', self.message_received_cb)
            channel[CHANNEL_INTERFACE_MESSAGES].connect_to_signal(
                'PendingMessagesRemoved', self.pending_messages_removed_cb)

            # find out if we have any pending messages
            channel[DBUS_PROPERTIES].Get(CHANNEL_INTERFACE_MESSAGES,
                'PendingMessages',
                reply_handler = self.get_pending_messages,
                error_handler = self.parent.error_cb)

    def get_pending_messages (self, messages):
        for message in messages:
            self.message_received_cb (message)

    def message_received_cb (self, message):
        channel = self

        # we need to acknowledge the message
        msg_id = message[0]['pending-message-id']
        channel[CHANNEL_TYPE_TEXT].AcknowledgePendingMessages([msg_id],
            reply_handler = self.parent.generic_reply,
            error_handler = self.parent.error_cb)
        # End Example 8-3

        print '-' * 78
        print 'Received Message:'
        for d in message:
            print '{'
            for k, v in d.iteritems():
                print '  %s: %s' % (k, v)
            print '}'
        print '-' * 78

        # let's echo the content back
        new_message = [
            {}, # let the CM fill in the headers
            {
                'content': '%s?' % message[1]['content'], # FIXME may be wrong part
                'content-type': 'text/plain',
            },
        ]
        channel[CHANNEL_INTERFACE_MESSAGES].SendMessage(new_message, 0,
            reply_handler = self.send_message_cb,
            error_handler = self.parent.error_cb)

    def pending_messages_removed_cb (self, message_ids):
        print "Acked messages %s" % message_ids

    def send_message_cb (self, token):
        print "Sending message with token %s" % token

class Example (object):
    def __init__ (self, account, password):
        """e.g. account  = 'bob@example.com/test'
                password = 'bigbob'
        """

        reg = telepathy.client.ManagerRegistry()
        reg.LoadManagers()

        # get the gabble Connection Manager
        self.cm = cm = reg.GetManager('gabble')

        # get the parameters required to make a Jabber connection
        cm[CONNECTION_MANAGER].RequestConnection('jabber',
            {
                'account':  account,
                'password': password,
            },
            reply_handler = self.request_connection_cb,
            error_handler = self.error_cb)

        self.loop = gobject.MainLoop()
        try:
            self.loop.run()
        except KeyboardInterrupt:
            print "Terminating connection..."
            self.disconnect()
            # reengage the mainloop so that we can disconnect cleanly
            self.loop.run()

    def generic_reply (self, *args): pass

    def error_cb (self, error):
        print "Error:", error
        self.disconnect()

    def disconnect (self):
        self.conn[CONNECTION].Disconnect(reply_handler = self.generic_reply,
                                         error_handler = self.error_cb)

    def request_connection_cb (self, bus_name, object_path):
        print bus_name, object_path
        self.conn = conn = telepathy.client.Connection(bus_name, object_path)

        conn[CONNECTION].connect_to_signal('StatusChanged',
            self.status_changed_cb)

        print "Establishing connection..."
        conn[CONNECTION].Connect(reply_handler = self.generic_reply,
                                 error_handler = self.error_cb)

    def status_changed_cb (self, status, reason):
        conn = self.conn

        if status == CONNECTION_STATUS_DISCONNECTED:
            print "Disconnected!"
            self.loop.quit()

        if status != CONNECTION_STATUS_CONNECTED: return

        print 'Carrier Detected' # remember dialup modems?
        print 'Ctrl-C to disconnect'

        # get a list of interfaces on this connection
        conn[CONNECTION].GetInterfaces(reply_handler = self.get_interfaces_cb,
                                       error_handler = self.error_cb)

    # Begin Example 8-2
    def get_interfaces_cb (self, interfaces):
        conn = self.conn

        print "Connection Interfaces:"
        for interface in interfaces:
            print " - %s" % interface

        if CONNECTION_INTERFACE_REQUESTS in interfaces:
            conn[CONNECTION_INTERFACE_REQUESTS].connect_to_signal('NewChannels',
                self.new_channels_cb)

    def new_channels_cb (self, channels):
        for channel, props in channels:
            if props[CHANNEL + '.ChannelType'] == CHANNEL_TYPE_TEXT:
                print 'New chat from %s' % props[CHANNEL + '.TargetID']
                # let's hook up to this channel
                TextChannel(self, channel)
    # End Example 8-2

if __name__ == '__main__':
    import getpass
    password = getpass.getpass()
    Example(sys.argv[1], password)