1# $Id$ 2# 3# Presence and instant messaging 4# 5# Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> 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# 21import sys 22import pjsua as pj 23 24LOG_LEVEL = 3 25pending_pres = None 26pending_uri = None 27 28def log_cb(level, str, len): 29 print str, 30 31class MyAccountCallback(pj.AccountCallback): 32 def __init__(self, account=None): 33 pj.AccountCallback.__init__(self, account) 34 35 def on_incoming_subscribe(self, buddy, from_uri, contact_uri, pres): 36 global pending_pres, pending_uri 37 # Allow buddy to subscribe to our presence 38 if buddy: 39 return (200, None) 40 print 'Incoming SUBSCRIBE request from', from_uri 41 print 'Press "A" to accept and add, "R" to reject the request' 42 pending_pres = pres 43 pending_uri = from_uri 44 return (202, None) 45 46 47class MyBuddyCallback(pj.BuddyCallback): 48 def __init__(self, buddy=None): 49 pj.BuddyCallback.__init__(self, buddy) 50 51 def on_state(self): 52 print "Buddy", self.buddy.info().uri, "is", 53 print self.buddy.info().online_text 54 55 def on_pager(self, mime_type, body): 56 print "Instant message from", self.buddy.info().uri, 57 print "(", mime_type, "):" 58 print body 59 60 def on_pager_status(self, body, im_id, code, reason): 61 if code >= 300: 62 print "Message delivery failed for message", 63 print body, "to", self.buddy.info().uri, ":", reason 64 65 def on_typing(self, is_typing): 66 if is_typing: 67 print self.buddy.info().uri, "is typing" 68 else: 69 print self.buddy.info().uri, "stops typing" 70 71 72lib = pj.Lib() 73 74try: 75 # Init library with default config and some customized 76 # logging config. 77 lib.init(log_cfg = pj.LogConfig(level=LOG_LEVEL, callback=log_cb)) 78 79 # Create UDP transport which listens to any available port 80 transport = lib.create_transport(pj.TransportType.UDP, 81 pj.TransportConfig(0)) 82 print "\nListening on", transport.info().host, 83 print "port", transport.info().port, "\n" 84 85 # Start the library 86 lib.start() 87 88 # Create local account 89 acc = lib.create_account_for_transport(transport, cb=MyAccountCallback()) 90 acc.set_basic_status(True) 91 92 my_sip_uri = "sip:" + transport.info().host + \ 93 ":" + str(transport.info().port) 94 95 buddy = None 96 97 # Menu loop 98 while True: 99 print "My SIP URI is", my_sip_uri 100 print "Menu: a=add buddy, d=delete buddy, t=toggle", \ 101 " online status, i=send IM, q=quit" 102 103 input = sys.stdin.readline().rstrip("\r\n") 104 if input == "a": 105 # Add buddy 106 print "Enter buddy URI: ", 107 input = sys.stdin.readline().rstrip("\r\n") 108 if input == "": 109 continue 110 111 buddy = acc.add_buddy(input, cb=MyBuddyCallback()) 112 buddy.subscribe() 113 114 elif input == "t": 115 acc.set_basic_status(not acc.info().online_status) 116 117 elif input == "i": 118 if not buddy: 119 print "Add buddy first" 120 continue 121 122 buddy.send_typing_ind(True) 123 124 print "Type the message: ", 125 input = sys.stdin.readline().rstrip("\r\n") 126 if input == "": 127 buddy.send_typing_ind(False) 128 continue 129 130 buddy.send_pager(input) 131 132 elif input == "d": 133 if buddy: 134 buddy.delete() 135 buddy = None 136 else: 137 print 'No buddy was added' 138 139 elif input == "A": 140 if pending_pres: 141 acc.pres_notify(pending_pres, pj.SubscriptionState.ACTIVE) 142 buddy = acc.add_buddy(pending_uri, cb=MyBuddyCallback()) 143 buddy.subscribe() 144 pending_pres = None 145 pending_uri = None 146 else: 147 print "No pending request" 148 149 elif input == "R": 150 if pending_pres: 151 acc.pres_notify(pending_pres, pj.SubscriptionState.TERMINATED, 152 "rejected") 153 pending_pres = None 154 pending_uri = None 155 else: 156 print "No pending request" 157 158 elif input == "q": 159 break 160 161 # Shutdown the library 162 acc.delete() 163 acc = None 164 if pending_pres: 165 acc.pres_notify(pending_pres, pj.SubscriptionState.TERMINATED, 166 "rejected") 167 transport = None 168 lib.destroy() 169 lib = None 170 171except pj.Error, e: 172 print "Exception: " + str(e) 173 lib.destroy() 174 lib = None 175 176