summaryrefslogtreecommitdiff
path: root/docs/examples/python_iface_messaging/example.py
blob: 5563964d10d8b92bc93ccc8d9aa957c28762b0c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#!/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 ex.channel.requesting.python.class
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 ex.channel.requesting.python.class
        channel = self

        channel[DBUS_PROPERTIES].Get(CHANNEL, 'Interfaces',
                                     reply_handler = self.interfaces_cb,
                                     error_handler = self.parent.error_cb)
    # begin ex.channel.text.messages.receiving.main
    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 ex.channel.text.messages.receiving.main

        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 ex.channel.text.messages.receiving.newchannels
    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 ex.channel.text.messages.receiving.newchannels

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