~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjsip-apps/src/confbot/confbot.py

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2015-01-07 14:51:16 UTC
  • mfrom: (4.3.5 sid)
  • Revision ID: package-import@ubuntu.com-20150107145116-yxnafinf4lrdvrmx
Tags: 1.4.1-0.1ubuntu1
* Merge with Debian, remaining changes:
 - Drop soprano, nepomuk build-dep
* Drop ubuntu patches, now upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# $Id: confbot.py 2912 2009-08-24 11:56:13Z bennylp $
2
 
#
3
 
# SIP Conference Bot
4
 
#
5
 
# Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
6
 
#
7
 
# This program is free software; you can redistribute it and/or modify
8
 
# it under the terms of the GNU General Public License as published by
9
 
# the Free Software Foundation; either version 2 of the License, or
10
 
# (at your option) any later version.
11
 
#
12
 
# This program is distributed in the hope that it will be useful,
13
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
# GNU General Public License for more details.
16
 
#
17
 
# You should have received a copy of the GNU General Public License
18
 
# along with this program; if not, write to the Free Software
19
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
20
 
#
21
 
import pjsua as pj
22
 
import string
23
 
import sys
24
 
 
25
 
CFG_FILE = "config"
26
 
 
27
 
INFO = 1
28
 
TRACE = 2
29
 
        
30
 
# Call callback. This would just forward the event to the Member class
31
 
class CallCb(pj.CallCallback):
32
 
        def __init__(self, member, call=None):
33
 
                pj.CallCallback.__init__(self, call)
34
 
                self.member = member
35
 
        
36
 
        def on_state(self):
37
 
                self.member.on_call_state(self.call)
38
 
        
39
 
        def on_media_state(self):
40
 
                self.member.on_call_media_state(self.call)
41
 
 
42
 
        def on_dtmf_digit(self, digits):
43
 
                self.member.on_call_dtmf_digit(self.call, digits)
44
 
 
45
 
        def on_transfer_request(self, dst, code):
46
 
                return self.member.on_call_transfer_request(self.call, dst, code)
47
 
        
48
 
        def on_transfer_status(self, code, reason, final, cont):
49
 
                return self.member.on_call_transfer_status(self.call, code, reason, final, cont)
50
 
 
51
 
        def on_replace_request(self, code, reason):
52
 
                return self.member.on_call_replace_request(self.call, code, reason)
53
 
                
54
 
        def on_replaced(self, new_call):
55
 
                self.member.on_call_replaced(self.call, new_call)
56
 
 
57
 
        def on_typing(self, is_typing):
58
 
                self.member.on_typing(is_typing, call=self.call)
59
 
 
60
 
        def on_pager(self, mime_type, body):
61
 
                self.member.on_pager(mime_type, body, call=self.call)
62
 
        
63
 
        def on_pager_status(self, body, im_id, code, reason):
64
 
                self.member.on_pager_status(body, im_id, code, reason, call=self.call)
65
 
 
66
 
# Buddy callback. This would just forward the event to Member class
67
 
class BuddyCb(pj.BuddyCallback):
68
 
        def __init__(self, member, buddy=None):
69
 
                pj.BuddyCallback.__init__(self, buddy)
70
 
                self.member = member
71
 
        
72
 
        def on_pager(self, mime_type, body):
73
 
                self.member.on_pager(mime_type, body, buddy=self.buddy)
74
 
 
75
 
        def on_pager_status(self, body, im_id, code, reason):
76
 
                self.member.on_pager_status(body, im_id, code, reason, buddy=self.buddy)
77
 
 
78
 
        def on_state(self):
79
 
                self.member.on_pres_state(self.buddy)
80
 
 
81
 
        def on_typing(self, is_typing):
82
 
                self.member.on_typing(is_typing, buddy=self.buddy)
83
 
 
84
 
 
85
 
 
86
 
 
87
 
##############################################################################
88
 
#
89
 
#
90
 
# This class represents individual room member (either/both chat and voice conf)
91
 
#
92
 
#
93
 
class Member:
94
 
        def __init__(self, bot, uri):
95
 
                self.uri = uri
96
 
                self.bot = bot
97
 
                self.call = None
98
 
                self.buddy = None
99
 
                self.bi = pj.BuddyInfo()
100
 
                self.in_chat = False
101
 
                self.in_voice = False
102
 
                self.im_error = False
103
 
                self.html = False
104
 
        
105
 
        def __str__(self):
106
 
                str = string.ljust(self.uri, 30) + " -- " 
107
 
                if self.buddy:
108
 
                        bi = self.buddy.info()
109
 
                        str = str + bi.online_text
110
 
                else:
111
 
                        str = str + "Offline"
112
 
                str = str + " ["
113
 
                if (self.in_voice):
114
 
                        str = str + " voice"
115
 
                if (self.in_chat):
116
 
                        str = str + " chat"
117
 
                        if (self.html):
118
 
                                str = str + " html"
119
 
                        else:
120
 
                                str = str + " plain"
121
 
 
122
 
                if (self.im_error):
123
 
                        str = str + " im_error"
124
 
                str = str + "]"
125
 
                return str
126
 
                
127
 
        def join_call(self, call):
128
 
                if self.call:
129
 
                        self.call.hangup(603, "You have been disconnected for making another call")
130
 
                self.call = call
131
 
                call.set_callback(CallCb(self, call))
132
 
                msg = "%(uri)s is attempting to join the voice conference" % \
133
 
                          {'uri': self.uri}
134
 
                self.bot.DEBUG(msg + "\n", INFO)
135
 
                self.bot.broadcast_pager(None, msg)
136
 
        
137
 
        def join_chat(self):
138
 
                if not self.buddy:
139
 
                        self.bot.DEBUG(self.uri + " joining chatroom...\n", INFO)
140
 
                        self.buddy = self.bot.acc.add_buddy(self.uri)
141
 
                        self.buddy.set_callback(BuddyCb(self, self.buddy))
142
 
                        self.buddy.subscribe()
143
 
                else:
144
 
                        self.bot.DEBUG(self.uri + " already in chatroom, resubscribing..\n", INFO)
145
 
                        self.buddy.subscribe()
146
 
 
147
 
        def send_pager(self, body, mime="text/plain"):
148
 
                self.bot.DEBUG("send_pager() to " + self.uri)
149
 
                if self.in_chat and not self.im_error and self.buddy:
150
 
                        if self.html:
151
 
                                #This will make us receive html!
152
 
                                #mime = "text/html"
153
 
                                body = body.replace("<", "&lt;")
154
 
                                body = body.replace(">", "&gt;")
155
 
                                body = body.replace('"', "&quot;")
156
 
                                body = body.replace("\n", "<BR>\n")
157
 
                        self.buddy.send_pager(body, content_type=mime)
158
 
                        self.bot.DEBUG("..sent\n")
159
 
                else:
160
 
                        self.bot.DEBUG("..not sent!\n")
161
 
                
162
 
        def on_call_state(self, call):
163
 
                ci = call.info()
164
 
                if ci.state==pj.CallState.DISCONNECTED:
165
 
                        if self.in_voice:
166
 
                                msg = "%(uri)s has left the voice conference (%(1)d/%(2)s)" % \
167
 
                                          {'uri': self.uri, '1': ci.last_code, '2': ci.last_reason}
168
 
                                self.bot.DEBUG(msg + "\n", INFO)
169
 
                                self.bot.broadcast_pager(None, msg)
170
 
                        self.in_voice = False
171
 
                        self.call = None
172
 
                        self.bot.on_member_left(self)
173
 
                elif ci.state==pj.CallState.CONFIRMED:
174
 
                        msg = "%(uri)s has joined the voice conference" % \
175
 
                                  {'uri': self.uri}
176
 
                        self.bot.DEBUG(msg + "\n", INFO)
177
 
                        self.bot.broadcast_pager(None, msg)
178
 
        
179
 
        def on_call_media_state(self, call):
180
 
                self.bot.DEBUG("Member.on_call_media_state\n")
181
 
                ci = call.info()
182
 
                if ci.conf_slot!=-1:
183
 
                        if not self.in_voice:
184
 
                                msg = self.uri + " call media is active"
185
 
                                self.bot.broadcast_pager(None, msg)
186
 
                        self.in_voice = True
187
 
                        self.bot.add_to_voice_conf(self)
188
 
                else:
189
 
                        if self.in_voice:
190
 
                                msg = self.uri + " call media is inactive"
191
 
                                self.bot.broadcast_pager(None, msg)
192
 
                        self.in_voice = False
193
 
 
194
 
        def on_call_dtmf_digit(self, call, digits):
195
 
                msg = "%(uri)s sent DTMF digits %(dig)s" % \
196
 
                          {'uri': self.uri, 'dig': digits}
197
 
                self.bot.broadcast_pager(None, msg)
198
 
 
199
 
        def on_call_transfer_request(self, call, dst, code):
200
 
                msg = "%(uri)s is transfering the call to %(dst)s" % \
201
 
                          {'uri': self.uri, 'dst': dst}
202
 
                self.bot.broadcast_pager(None, msg)
203
 
                return 202
204
 
        
205
 
        def on_call_transfer_status(self, call, code, reason, final, cont):
206
 
                msg = "%(uri)s call transfer status is %(code)d/%(res)s" % \
207
 
                          {'uri': self.uri, 'code': code, 'res': reason}
208
 
                self.bot.broadcast_pager(None, msg)
209
 
                return True
210
 
 
211
 
        def on_call_replace_request(self, call, code, reason):
212
 
                msg = "%(uri)s is requesting call replace" % \
213
 
                          {'uri': self.uri}
214
 
                self.bot.broadcast_pager(None, msg)
215
 
                return (code, reason)
216
 
                
217
 
        def on_call_replaced(self, call, new_call):
218
 
                msg = "%(uri)s call is replaced" % \
219
 
                          {'uri': self.uri}
220
 
                self.bot.broadcast_pager(None, msg)
221
 
 
222
 
        def on_pres_state(self, buddy):
223
 
                old_bi = self.bi
224
 
                self.bi = buddy.info()
225
 
                msg = "%(uri)s status is %(st)s" % \
226
 
                  {'uri': self.uri, 'st': self.bi.online_text}
227
 
                self.bot.DEBUG(msg + "\n", INFO)
228
 
                self.bot.broadcast_pager(self, msg)
229
 
 
230
 
                if self.bi.sub_state==pj.SubscriptionState.ACTIVE:
231
 
                        if not self.in_chat:
232
 
                                self.in_chat = True
233
 
                                buddy.send_pager("Welcome to chatroom")
234
 
                                self.bot.broadcast_pager(self, self.uri + " has joined the chat room")
235
 
                        else:
236
 
                                self.in_chat = True
237
 
                elif self.bi.sub_state==pj.SubscriptionState.NULL or \
238
 
                         self.bi.sub_state==pj.SubscriptionState.TERMINATED or \
239
 
                         self.bi.sub_state==pj.SubscriptionState.UNKNOWN:
240
 
                        self.buddy.delete()
241
 
                        self.buddy = None
242
 
                        if self.in_chat:
243
 
                                self.in_chat = False
244
 
                                self.bot.broadcast_pager(self, self.uri + " has left the chat room")
245
 
                        else:
246
 
                                self.in_chat = False
247
 
                        self.bot.on_member_left(self)
248
 
                
249
 
        def on_typing(self, is_typing, call=None, buddy=None):
250
 
                if is_typing:
251
 
                        msg = self.uri + " is typing..."
252
 
                else:
253
 
                        msg = self.uri + " has stopped typing"
254
 
                self.bot.broadcast_pager(self, msg)
255
 
 
256
 
        def on_pager(self, mime_type, body, call=None, buddy=None):
257
 
                if not self.bot.handle_cmd(self, None, body):
258
 
                        msg = self.uri + ": " + body
259
 
                        self.bot.broadcast_pager(self, msg, mime_type)
260
 
        
261
 
        def on_pager_status(self, body, im_id, code, reason, call=None, buddy=None):
262
 
                self.im_error = (code/100 != 2)
263
 
 
264
 
 
265
 
 
266
 
##############################################################################
267
 
#
268
 
#
269
 
# The Bot instance (singleton)
270
 
#
271
 
#
272
 
class Bot(pj.AccountCallback):
273
 
        def __init__(self):
274
 
                pj.AccountCallback.__init__(self, None)
275
 
                self.lib = pj.Lib()
276
 
                self.acc = None
277
 
                self.calls = []
278
 
                self.members = {}
279
 
                self.cfg = None
280
 
 
281
 
        def DEBUG(self, msg, level=TRACE):
282
 
                print msg,
283
 
                
284
 
        def helpstring(self):
285
 
                return """
286
 
--h[elp]            Display this help screen
287
 
--j[oin]            Join the chat room
288
 
--html on|off       Set to receive HTML or plain text
289
 
 
290
 
Participant commands:
291
 
--s[how]            Show confbot settings
292
 
--leave             Leave the chatroom
293
 
--l[ist]            List all members
294
 
 
295
 
Admin commands:
296
 
--a[dmin] <CMD> Where <CMD> are:
297
 
    list            List the admins
298
 
    add <URI>       Add URI as admin
299
 
    del <URI>       Remove URI as admin
300
 
    rr              Reregister account to server
301
 
    call <URI>      Make call to the URI and add to voice conf
302
 
    dc <URI>        Disconnect call to URI
303
 
    hold <URI>      Hold call with that URI
304
 
    update <URI>    Send UPDATE to call with that URI
305
 
    reinvite <URI>  Send re-INVITE to call with that URI
306
 
"""
307
 
 
308
 
        def listmembers(self):
309
 
                msg = ""
310
 
                for uri, m in self.members.iteritems():
311
 
                        msg = msg + str(m) + "\n"
312
 
                return msg
313
 
        
314
 
        def showsettings(self):
315
 
                ai = self.acc.info()
316
 
                msg = """
317
 
ConfBot status and settings:
318
 
  URI:        %(uri)s
319
 
  Status:     %(pres)s
320
 
  Reg Status: %(reg_st)d
321
 
  Reg Reason: %(reg_res)s
322
 
""" % {'uri': ai.uri, 'pres': ai.online_text, \
323
 
           'reg_st': ai.reg_status, 'reg_res': ai.reg_reason}
324
 
                return msg
325
 
  
326
 
        def main(self, cfg_file):
327
 
                try:
328
 
                        cfg = self.cfg = __import__(cfg_file)
329
 
                        
330
 
                        self.lib.init(ua_cfg=cfg.ua_cfg, log_cfg=cfg.log_cfg, media_cfg=cfg.media_cfg)
331
 
                        self.lib.set_null_snd_dev()
332
 
                        
333
 
                        transport = None
334
 
                        if cfg.udp_cfg:
335
 
                                transport = self.lib.create_transport(pj.TransportType.UDP, cfg.udp_cfg)
336
 
                        if cfg.tcp_cfg:
337
 
                                t = self.lib.create_transport(pj.TransportType.TCP, cfg.tcp_cfg)
338
 
                                if not transport:
339
 
                                        transport = t
340
 
                                
341
 
                        self.lib.start()
342
 
                        
343
 
                        if cfg.acc_cfg:
344
 
                                self.DEBUG("Creating account %(uri)s..\n" % {'uri': cfg.acc_cfg.id}, INFO)
345
 
                                self.acc = self.lib.create_account(cfg.acc_cfg, cb=self)
346
 
                        else:
347
 
                                self.DEBUG("Creating account for %(t)s..\n" % \
348
 
                                                        {'t': transport.info().description}, INFO)
349
 
                                self.acc = self.lib.create_account_for_transport(transport, cb=self)
350
 
                        
351
 
                        self.acc.set_basic_status(True)
352
 
                        
353
 
                        # Wait for ENTER before quitting
354
 
                        print "Press q to quit or --help/--h for help"
355
 
                        while True:
356
 
                                input = sys.stdin.readline().strip(" \t\r\n")
357
 
                                if not self.handle_cmd(None, None, input):
358
 
                                        if input=="q":
359
 
                                                break
360
 
                        
361
 
                        self.lib.destroy()
362
 
                        self.lib = None
363
 
 
364
 
                except pj.Error, e:
365
 
                        print "Exception: " + str(e)
366
 
                        if self.lib:
367
 
                                self.lib.destroy()
368
 
                                self.lib = None
369
 
        
370
 
        def broadcast_pager(self, exclude_member, body, mime_type="text/plain"):
371
 
                self.DEBUG("Broadcast: " + body + "\n")
372
 
                for uri, m in self.members.iteritems():
373
 
                        if m != exclude_member:
374
 
                                m.send_pager(body, mime_type)
375
 
 
376
 
        def add_to_voice_conf(self, member):
377
 
                if not member.call:
378
 
                        return
379
 
                src_ci = member.call.info()
380
 
                self.DEBUG("bot.add_to_voice_conf\n")
381
 
                for uri, m in self.members.iteritems():
382
 
                        if m==member:
383
 
                                continue
384
 
                        if not m.call:
385
 
                                continue
386
 
                        dst_ci = m.call.info()
387
 
                        if dst_ci.media_state==pj.MediaState.ACTIVE and dst_ci.conf_slot!=-1:
388
 
                                self.lib.conf_connect(src_ci.conf_slot, dst_ci.conf_slot)
389
 
                                self.lib.conf_connect(dst_ci.conf_slot, src_ci.conf_slot)
390
 
        
391
 
        def on_member_left(self, member):
392
 
                if not member.call and not member.buddy:
393
 
                        del self.members[member.uri]
394
 
                        del member
395
 
                        
396
 
        def handle_admin_cmd(self, member, body):
397
 
                if member and self.cfg.admins and not member.uri in self.cfg.admins:
398
 
                        member.send_pager("You are not admin")
399
 
                        return
400
 
                args = body.split()
401
 
                msg = ""
402
 
 
403
 
                if len(args)==1:
404
 
                        args.append(" ")
405
 
 
406
 
                if args[1]=="list":
407
 
                        if not self.cfg.admins:
408
 
                                msg = "Everyone is admin!"
409
 
                        else:
410
 
                                msg = str(self.cfg.admins)
411
 
                elif args[1]=="add":
412
 
                        if len(args)!=3:
413
 
                                msg = "Usage: add <URI>"
414
 
                        else:
415
 
                                self.cfg.admins.append(args[2])
416
 
                                msg = args[2] + " added as admin"
417
 
                elif args[1]=="del":
418
 
                        if len(args)!=3:
419
 
                                msg = "Usage: del <URI>"
420
 
                        elif args[2] not in self.cfg.admins:
421
 
                                msg = args[2] + " is not admin"
422
 
                        else:
423
 
                                self.cfg.admins.remove(args[2])
424
 
                                msg = args[2] + " has been removed from admins"
425
 
                elif args[1]=="rr":
426
 
                        msg = "Reregistering.."
427
 
                        self.acc.set_registration(True)
428
 
                elif args[1]=="call":
429
 
                        if len(args)!=3:
430
 
                                msg = "Usage: call <URI>"
431
 
                        else:
432
 
                                uri = args[2]
433
 
                                try:
434
 
                                        call = self.acc.make_call(uri)
435
 
                                except pj.Error, e:
436
 
                                        msg = "Error: " + str(e)
437
 
                                        call = None
438
 
 
439
 
                                if call:
440
 
                                        if not uri in self.members:
441
 
                                                m = Member(self, uri)
442
 
                                                self.members[m.uri] = m
443
 
                                        else:
444
 
                                                m = self.members[uri]
445
 
                                        msg = "Adding " + m.uri + " to voice conference.."
446
 
                                        m.join_call(call)
447
 
                elif args[1]=="dc" or args[1]=="hold" or args[1]=="update" or args[1]=="reinvite":
448
 
                        if len(args)!=3:
449
 
                                msg = "Usage: " + args[1] + " <URI>"
450
 
                        else:
451
 
                                uri = args[2]
452
 
                                if not uri in self.members:
453
 
                                        msg = "Member not found/URI doesn't match (note: case matters!)"
454
 
                                else:
455
 
                                        m = self.members[uri]
456
 
                                        if m.call:
457
 
                                                if args[1]=="dc":
458
 
                                                        msg = "Disconnecting.."
459
 
                                                        m.call.hangup(603, "You're disconnected by admin")
460
 
                                                elif args[1]=="hold":
461
 
                                                        msg = "Holding the call"
462
 
                                                        m.call.hold()
463
 
                                                elif args[1]=="update":
464
 
                                                        msg = "Sending UPDATE"
465
 
                                                        m.call.update()
466
 
                                                elif args[1]=="reinvite":
467
 
                                                        msg = "Sending re-INVITE"
468
 
                                                        m.call.reinvite()
469
 
                                        else:
470
 
                                                msg = "He is not in call"
471
 
                else:
472
 
                        msg = "Unknown admin command " + body
473
 
 
474
 
                #print "msg is '%(msg)s'" % {'msg': msg}
475
 
 
476
 
                if True:
477
 
                        if member:
478
 
                                member.send_pager(msg)
479
 
                        else:
480
 
                                print msg
481
 
 
482
 
        def handle_cmd(self, member, from_uri, body):
483
 
                body = body.strip(" \t\r\n")
484
 
                msg = ""
485
 
                handled = True
486
 
                if body=="--l" or body=="--list":
487
 
                        msg = self.listmembers()
488
 
                        if msg=="":
489
 
                                msg = "Nobody is here"
490
 
                elif body[0:3]=="--s":
491
 
                        msg = self.showsettings()
492
 
                elif body[0:6]=="--html" and member:
493
 
                        if body[8:11]=="off":
494
 
                                member.html = False
495
 
                        else:
496
 
                                member.html = True
497
 
                elif body=="--h" or body=="--help":
498
 
                        msg = self.helpstring()
499
 
                elif body=="--leave":
500
 
                        if not member or not member.buddy:
501
 
                                msg = "You are not in chatroom"
502
 
                        else:
503
 
                                member.buddy.unsubscribe()
504
 
                elif body[0:3]=="--j":
505
 
                        if not from_uri in self.members:
506
 
                                m = Member(self, from_uri)
507
 
                                self.members[m.uri] = m
508
 
                                self.DEBUG("Adding " + m.uri + " to chatroom\n")
509
 
                                m.join_chat()
510
 
                        else:
511
 
                                m = self.members[from_uri]
512
 
                                self.DEBUG("Adding " + m.uri + " to chatroom\n")
513
 
                                m.join_chat()
514
 
                elif body[0:3]=="--a":
515
 
                        self.handle_admin_cmd(member, body)
516
 
                        handled = True
517
 
                else:
518
 
                        handled = False
519
 
 
520
 
                if msg:
521
 
                        if member:
522
 
                                member.send_pager(msg)
523
 
                        elif from_uri:
524
 
                                self.acc.send_pager(from_uri, msg);
525
 
                        else:
526
 
                                print msg
527
 
                return handled
528
 
        
529
 
        def on_incoming_call(self, call):
530
 
                self.DEBUG("on_incoming_call from %(uri)s\n" % {'uri': call.info().remote_uri}, INFO)
531
 
                ci = call.info()
532
 
                if not ci.remote_uri in self.members:
533
 
                        m = Member(self, ci.remote_uri)
534
 
                        self.members[m.uri] = m
535
 
                        m.join_call(call)
536
 
                else:
537
 
                        m = self.members[ci.remote_uri]
538
 
                        m.join_call(call)
539
 
                call.answer(200)
540
 
        
541
 
        def on_incoming_subscribe(self, buddy, from_uri, contact_uri, pres_obj):
542
 
                self.DEBUG("on_incoming_subscribe from %(uri)s\n" % from_uri, INFO)
543
 
                return (200, 'OK')
544
 
 
545
 
        def on_reg_state(self):
546
 
                ai = self.acc.info()
547
 
                self.DEBUG("Registration state: %(code)d/%(reason)s\n" % \
548
 
                                        {'code': ai.reg_status, 'reason': ai.reg_reason}, INFO)
549
 
                if ai.reg_status/100==2 and ai.reg_expires > 0:
550
 
                        self.acc.set_basic_status(True)
551
 
 
552
 
        def on_pager(self, from_uri, contact, mime_type, body):
553
 
                body = body.strip(" \t\r\n")
554
 
                if not self.handle_cmd(None, from_uri, body):
555
 
                        self.acc.send_pager(from_uri, "You have not joined the chat room. Type '--join' to join or '--help' for the help")
556
 
 
557
 
        def on_pager_status(self, to_uri, body, im_id, code, reason):
558
 
                pass
559
 
 
560
 
        def on_typing(self, from_uri, contact, is_typing):
561
 
                pass
562
 
 
563
 
 
564
 
 
565
 
 
566
 
##############################################################################
567
 
#
568
 
#
569
 
# main()
570
 
#
571
 
#
572
 
if __name__ == "__main__":
573
 
        bot = Bot()
574
 
        bot.main(CFG_FILE)
575