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 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
|
"""
__version__ = "$Revision: 1.9 $"
__date__ = "$Date: 2004/04/14 02:38:48 $"
"""
import wx
import os, sys
import jabber
DEBUG_LEVEL = 1
class JabberConnection:
def __init__(self, parent, account):
self.keepRunning = 1
self._parent = parent
self.con = None
self.server = account['server']
self.username = account['username']
self.password = account['password']
self.resource = account['resource']
self.createNewConnection()
def createNewConnection(self):
# should make debug level settable in configuration
con = jabber.Client(host=self.server, debug=DEBUG_LEVEL, log=sys.stderr)
self.con = con
con.setMessageHandler(self.messageCB)
con.setPresenceHandler(self.presenceCB)
con.setIqHandler(self.iqCB)
con.setDisconnectHandler(self.disconnectedCB)
try:
con.connect()
except IOError, e:
print "Couldn't connect: %s" % e
##sys.exit(0)
return
else:
print "Connected"
if con.auth(self.username, self.password, self.resource):
print "Logged in as %s to server %s" % (self.username, self.server)
else:
print "eek -> ", con.lastErr, con.lastErrCode
print "Requesting Roster Info"
con.requestRoster()
con.sendInitPresence()
JID = self.username + '@' + self.server + '/' + self.resource
print "JID", JID
self.JID = JID
self.shortJID = str(self.JID.split('/')[0])
self.updateRoster()
self.updateRosterDisplay()
# track which groupchat rooms we've joined
# for special presence handling
self.groupchatJIDS = {}
def updateRoster(self):
_roster = self.con.getRoster()
print "\n"
self.roster = {}
for jid in _roster.getJIDs():
# 2002-11-30
# don't show gateways in the roster
# what is the proper handling of gateways?!
if '@' not in str(jid):
continue
print "%s :: %s (%s/%s)" % \
(jid, _roster.getOnline(jid), _roster.getStatus(jid), _roster.getShow(jid))
self.roster[str(jid)] = [_roster.getOnline(jid), _roster.getStatus(jid), _roster.getShow(jid)]
print "\n"
def updateRosterDisplay(self):
roster = self.roster
items = {}
for key in roster:
jid = str(key)
status = roster[key][0].lower()
show = roster[key][1]
if show is None:
show = ""
else:
# I noticed that some clients might let in a CR/LF on the end
# so might as well get rid of leading and trailing whitespace
show = show.strip()
items[jid] = (status, show)
self._parent.rosterQueue.put((None, items))
wx.WakeUpIdle()
"""
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python22\lib\threading.py", line 408, in __bootstrap
self.run()
File "C:\Python22\lib\threading.py", line 396, in run
apply(self.__target, self.__args, self.__kwargs)
File "C:\python\jabberChat\connection.py", line 92, in spinMyWheels
self.con.process(1)
File "C:\python\xmlstream.py", line 450, in process
if not len(self.read()): # length of 0 means disconnect
File "C:\python\xmlstream.py", line 379, in read
data_in = data_in + \
File "<string>", line 1, in recv
error: (10054, 'Connection reset by peer')
"""
def spinMyWheels(self):
while self.keepRunning and self.con is not None:
#print "spinning..."
try:
self.con.process(1)
except:
# sometimes I get the connection error above
# so this is an attempt to workaround losing
# the connection by creating a new one
self.createNewConnection()
print "***** CONNECTION PROBLEM *****"
def sendMessage(self, to, txt, messageType='chat'):
print "\n"
msg = jabber.Message(to, txt.strip())
msg.setType(messageType)
print "<%s> %s" % (self.JID, msg.getBody())
self.con.send(msg)
print "\n"
def sendChatMessage(self, to, txt):
self.sendMessage(to, txt, 'chat')
def sendGroupChatMessage(self, to, txt):
self.sendMessage(to, txt, 'groupchat')
def joinGroupChat(self, to, nickname=None):
if to not in self.groupchatJIDS:
self.groupchatJIDS[to] = {}
if nickname is None:
nickname = self.username
print "****** JOINING ROOM ******", to, "as", nickname
self.sendPresence(to=to + '/' + nickname)
# we could get an error joining, but I'm not sure
# where to process that yet
def messageCB(self, con, msg):
"""Called when a message is recieved"""
if msg.getBody(): ## Dont show blank messages ##
print '<' + str(msg.getFrom()) + '>' + ' ' + msg.getBody()
txt = msg.getBody()
self._parent.msgQueue.put((msg.getFrom(), txt))
wx.WakeUpIdle()
def presenceCB(self, con, prs):
"""Called when a presence is recieved"""
who = str(prs.getFrom())
type = prs.getType()
if type is None:
type = 'available'
txt = None
# subscription request:
# - accept their subscription
# - send request for subscription to their presence
if type == 'subscribe':
print "subscribe request from %s" % (who)
con.send(jabber.Presence(to=who, type='subscribed'))
con.send(jabber.Presence(to=who, type='subscribe'))
txt = "subscribe request from %s" % (who)
# unsubscription request:
# - accept their unsubscription
# - send request for unsubscription to their presence
elif type == 'unsubscribe':
print "unsubscribe request from %s" % (who)
con.send(jabber.Presence(to=who, type='unsubscribed'))
con.send(jabber.Presence(to=who, type='unsubscribe'))
txt = "unsubscribe request from %s" % (who)
elif type == 'subscribed':
print "we are now subscribed to %s" % (who)
txt = "we are now subscribed to %s" % (who)
elif type == 'unsubscribed':
print "we are now unsubscribed to %s" % (who)
txt = "we are now unsubscribed to %s" % (who)
elif type == 'available':
print "%s is available (%s / %s)" % (who, prs.getShow(), prs.getStatus())
txt = "%s is available (%s / %s)" % (who, prs.getShow(), prs.getStatus())
# who is of the form 'username@domain/resource'
jid = str(who.split('/')[0])
# KEA 2002-11-30
# should presences for the same jid such as altis@jabber.org/Exodus
# and altis@jabber.org/default be treated separately?
# for now, skip duplicate jids for both
# available and unavailable
#
# I'm not showing gateways either
# and still need to figure out the proper handling
# of them
if '@' in jid and jid != self.shortJID:
if jid in self.groupchatJIDS:
nickname = str(who.split('/')[1])
print "*******GROUPCHAT", jid, who, prs.getStatus(), prs.getShow()
self.groupchatJIDS[jid][nickname] = (prs.getStatus(), prs.getShow())
self._parent.rosterQueue.put((jid, self.groupchatJIDS[jid]))
wx.WakeUpIdle()
else:
self.roster[jid] = ['online', prs.getStatus(), prs.getShow()]
self.updateRosterDisplay()
elif type == 'unavailable':
print "%s is unavailable (%s / %s)" % (who, prs.getShow(), prs.getStatus())
txt = "%s is unavailable (%s / %s)" % (who, prs.getShow(), prs.getStatus())
# who is of the form 'username@domain/resource'
jid = str(who.split('/')[0])
if '@' in jid and jid != self.shortJID:
if jid in self.groupchatJIDS:
nickname = str(who.split('/')[1])
print "*******GROUPCHAT", jid, who, prs.getStatus(), prs.getShow()
try:
del self.groupchatJIDS[jid][nickname]
self._parent.rosterQueue.put((jid, self.groupchatJIDS[jid]))
wx.WakeUpIdle()
except:
pass
else:
self.roster[jid] = ['offline', prs.getStatus(), prs.getShow()]
self.updateRosterDisplay()
if txt is not None:
# need to decide whether we want a separate queue for
# status messages, for now just let the messages be
# printed to the console
#self._parent.msgQueue.put(txt)
#wx.WakeUpIdle()
pass
def iqCB(self, con,iq):
"""Called when an iq is recieved, we just let the library handle it at the moment"""
pass
# see p. 145 of the Programming Jabber
# and
# http://www.jabber.org/protocol/coredata.html#presence
def sendPresence(self, status="Available", to=None):
#presence = jabber.Presence(type='available')
presence = jabber.Presence(to)
presence.setStatus(status)
if status == "Available":
# apparently "normal" is the default
#presence.setShow("normal")
pass
elif status == "Do Not Disturb":
presence.setShow("dnd")
else:
presence.setShow("away")
self.con.send(presence)
def disconnectedCB(self, con):
print "Ouch, network error"
#sys.exit(1)
def disconnect(self):
self.con.disconnect()
print "Bye!"
|