-# Copyright 2004 James Bunton <james@delx.cjb.net>
+# Copyright 2004-2005 James Bunton <james@delx.cjb.net>
# Licensed for distribution under the GPL version 2, check COPYING for details
from twisted.internet import reactor
from twisted.internet.protocol import ClientFactory
+from twisted.python import log
+from debug import LogEvent, INFO, WARN, ERROR
from tlib import msn
+import math
+import base64
+import binascii
+import math
import config
import utils
-import debug
-
+import lang
+MAXMESSAGESIZE = 1400
class MSNConnection:
self.inited = False
self.tries = 0
self.initMe()
- debug.log("MSNConnection: \"%s\" created" % (self.username))
+ LogEvent(INFO, self.session.jabberID)
def initMe(self):
- if(self.inited):
+ if self.inited:
MSNConnection.removeMe(self)
self.switchboardSessions = {}
self.notificationFactory.initialListVersion = self.initialListVersion
self.notificationProtocol = None
- self.savedStatus = None
+ self.savedEvents = SavedEvents()
self.inited = True
- debug.log("MSNConnection: \"%s\" initialised" % (self.username))
+ LogEvent(INFO, self.session.jabberID)
def removeMe(self):
- debug.log("MSNConnection: \"%s\" destroyed" % (self.username))
- if(self.notificationProtocol):
+ LogEvent(INFO, self.session.jabberID)
+ if self.notificationProtocol:
self.notificationProtocol.removeMe()
- if(self.notificationFactory):
+ if self.notificationFactory:
self.notificationFactory.msncon = None
self.notificationFactory = None
self.notificationProtocol = None
- for userHandle in utils.copyDict(self.switchboardSessions):
+ self.savedEvents = SavedEvents()
+ for userHandle in self.switchboardSessions.copy():
self.switchboardSessions[userHandle].removeMe()
self.switchboardSessions = {}
def resourceOffline(self, offlineResource):
for contact in self.switchboardSessions.keys():
- if(self.switchboardSessions[contact].resource == offlineResource):
+ if self.switchboardSessions[contact].resource == offlineResource:
self.switchboardSessions[contact].resource = self.highestResource()
def getContacts(self):
- if(self.notificationFactory):
+ if self.notificationFactory:
return self.notificationFactory.contacts
else:
return None
def sendMessage(self, remoteUser, resource, text, noerror):
- debug.log("MSNConnection: \"%s\" sendMessage(\"%s\", \"%s\")" % (self.username, remoteUser, text))
- if(self.notificationProtocol):
- if(not self.switchboardSessions.has_key(remoteUser)):
+ LogEvent(INFO, self.session.jabberID)
+ if self.notificationProtocol:
+ if not self.switchboardSessions.has_key(remoteUser):
self.switchboardSessions[remoteUser] = SwitchboardSession(self, remoteUser, resource)
self.switchboardSessions[remoteUser].resource = resource
self.switchboardSessions[remoteUser].sendMessage(text.replace("\n", "\r\n"), noerror)
- elif(not noerror):
+ elif not noerror:
self.failedMessage(remoteUser, text)
+ def requestAvatar(self, userHandle):
+ LogEvent(INFO, self.session.jabberID)
+ resource = self.session.highestResource()
+ if config.getAllAvatars:
+ if not self.switchboardSessions.has_key(userHandle):
+ self.switchboardSessions[userHandle] = SwitchboardSession(self, userHandle, resource)
+ else:
+ self.switchboardSessions[userHandle].requestAvatar()
+ else:
+ if self.switchboardSessions.has_key(userHandle): # Only request avatars for open switchboards
+ self.switchboardSessions[userHandle].requestAvatar()
+
def sendTypingToContact(self, remoteUser):
- if(self.switchboardSessions.has_key(remoteUser)):
+ if self.switchboardSessions.has_key(remoteUser):
self.switchboardSessions[remoteUser].sendTypingNofication()
def notificationProtocolReady(self, notificationProtocol):
self.loggedIn()
self.tries = 0
- def sendSavedStatus(self):
- # Hack for initial status
- if(self.savedStatus):
- statusCode, screenName = self.savedStatus
- self.savedStatus = None
- self.changeStatus(statusCode, screenName)
+ def sendSavedEvents(self):
+ # Hack for events sent before we're logged in
+ self.savedEvents.send(self)
+ self.savedEvents = None
- def changeStatus(self, statusCode, screenName):
- if(self.notificationProtocol):
+ def changeAvatar(self, imageData):
+ if self.notificationProtocol:
+ self.notificationProtocol.changeAvatar(imageData, push=True)
+ else:
+ self.savedEvents.avatarImageData = imageData
+
+ def changeStatus(self, statusCode, screenName, personal):
+ if self.notificationProtocol:
def cb1(arg):
self.ourStatusChanged(arg[0])
def cb2(arg):
self.ourNickChanged(arg[0])
- debug.log("MSNConnection: \"%s\" - changing status and screenName (\"%s\", \"%s\")" % (self.username, statusCode, screenName))
- if(statusCode):
+ def cb3(arg):
+ self.ourPersonalChanged(personal)
+ LogEvent(INFO, self.session.jabberID)
+ if statusCode:
statusCode = str(statusCode.encode("utf-8"))
self.notificationProtocol.changeStatus(statusCode).addCallback(cb1)
- if(screenName):
+ if screenName:
screenName = str(screenName.encode("utf-8"))
self.notificationProtocol.changeScreenName(screenName).addCallback(cb2)
+ if personal:
+ personal = str(personal.encode("utf-8"))
+ else:
+ personal = ""
+ self.notificationProtocol.changePersonalMessage(personal).addCallback(cb3)
else:
- self.savedStatus = (statusCode, screenName)
+ self.savedEvents.statusCode = statusCode
+ self.savedEvents.screenName = screenName
+ self.savedEvents.personal = personal
def connectionLostBase(self, reason):
# Attempts to reconnect
- if(self.tries < 5 and self.session):
+ if self.tries < 5 and self.session:
reactor.callLater(2 ** self.tries, self.initMe)
self.tries += 1
else:
self.connectionLost(self)
def addContact(self, listType, userHandle):
- return self.notificationProtocol.addContact(listType, str(userHandle))
+ if self.notificationProtocol:
+ return self.notificationProtocol.addContact(listType, str(userHandle))
+ else:
+ self.savedEvents.addContacts.append((listType, str(userHandle)))
def remContact(self, listType, userHandle, groupID=0):
- return self.notificationProtocol.remContact(listType, str(userHandle))
+ if self.notificationProtocol:
+ return self.notificationProtocol.remContact(listType, str(userHandle))
+ else:
+ self.savedEvents.remContacts.append((listType, str(userHandle)))
def gotMessage(self, remoteUser, resource, text):
pass
+ def avatarHashChanged(self, userHandle, hash):
+ pass
+
+ def gotAvatarImage(self, to, image):
+ pass
+
+ def gotSendRequest(self, fileReceive):
+ pass
+
def listSynchronized(self):
pass
def ourStatusChanged(self, statusCode):
pass
- def userMapping(self, passport, jid):
+ def ourNickChanged(self, nick):
pass
- def gotContactTyping(self, remoteUser, resource):
+ def ourPersonalChanged(self, personal):
pass
- def ourNickChanged(self, arg):
+ def userMapping(self, passport, jid):
+ pass
+
+ def gotContactTyping(self, remoteUser, resource):
pass
def serverGoingDown(self):
+class SavedEvents:
+ def __init__(self):
+ self.nickname = ""
+ self.statusCode = ""
+ self.personal = ""
+ self.avatarImageData = ""
+ self.addContacts = []
+ self.remContacts = []
+
+ def send(self, msncon):
+ if self.avatarImageData:
+ msncon.notificationProtocol.changeAvatar(self.avatarImageData, push=False)
+ if self.nickname or self.statusCode or self.personal:
+ msncon.changeStatus(self.statusCode, self.nickname, self.personal)
+ for listType, userHandle in self.addContacts:
+ msncon.addContact(listType, userHandle)
+ for listType, userHandle in self.remContacts:
+ msncon.remContact(listType, userHandle)
+
+
def switchToGroupchat(switchboardSession, user1, user2):
gcsbs = GroupchatSwitchboardSession()
gcsbs.userJoined(user2)
groupchat.sendUserInvite(msn2jid(switchboardSession.remoteUser))
switchboardSession.removeMe(False)
- debug.log("GroupchatSwitchboardSession: \"%s\" \"%s\" created by conversion" % (gcsbs.groupchat.roomJID(), gcsbs))
+ LogEvent(INFO, gcsbs.msncon.session.jabberID)
return gcsbs
-class GroupchatSwitchboardSession:
+class SwitchboardSessionBase:
+ def sendMessage(self, message, noerror):
+ if self.ready:
+ def failedMessage(ignored):
+ if isinstance(self, GroupchatSwitchboardSession):
+ tempmsncon.failedMessage(self.groupchat.roomJID(), message)
+ else:
+ tempmsncon.failedMessage(self.remoteUser, message)
+
+ tempmsncon = self.msncon # In case MSN tells us the message failed after removeMe()
+
+ LogEvent(INFO, self.ident)
+ message = str(message.encode("utf-8"))
+
+ if len(message) < MAXMESSAGESIZE:
+ msnmessage = msn.MSNMessage(message=message)
+ msnmessage.setHeader("Content-Type", "text/plain; charset=UTF-8")
+ msnmessage.ack = msn.MSNMessage.MESSAGE_NACK
+
+ d = self.switchboard.sendMessage(msnmessage)
+ if not noerror:
+ d.addCallback(failedMessage)
+ else:
+ chunks = int(math.ceil(len(message) / float(MAXMESSAGESIZE)))
+ chunk = 0
+ guid = utils.random_guid()
+ while chunk < chunks:
+ offset = chunk * MAXMESSAGESIZE
+ text = message[offset : offset + MAXMESSAGESIZE]
+
+ msnmessage = msn.MSNMessage(message=text)
+ msnmessage.setHeader("Message-ID", guid)
+ if chunk == 0:
+ msnmessage.setHeader("Content-Type", "text/plain; charset=UTF-8")
+ msnmessage.setHeader("Chunks", str(chunks))
+ else:
+ msnmessage.setHeader("Chunk", str(chunk))
+ msnmessage.ack = msn.MSNMessage.MESSAGE_NACK
+
+ d = self.switchboard.sendMessage(msnmessage)
+ if not noerror:
+ d.addCallback(failedMessage)
+ chunk += 1
+
+ self.resetTimer()
+ else:
+ self.messageBuffer.append((message, noerror))
+
+ def gotAvatarImage(self, to, image):
+ self.msncon.gotAvatarImage(to, image)
+
+ def gotSendRequest(self, fileReceive):
+ self.msncon.gotSendRequest(fileReceive)
+
+ def switchboardReady(self, switchboard):
+ LogEvent(INFO, self.ident)
+ self.ready = True
+ self.switchboard = switchboard
+ self.flushBuffer()
+
+ def resetTimer(self):
+ pass
+
+
+class GroupchatSwitchboardSession(SwitchboardSessionBase):
def __init__(self, groupchat=None, makeSwitchboard=False):
self.removed = False
self.msncon = None
- self.groupchat = None
- if(groupchat):
+ if groupchat:
+ self.ident = groupchat.roomJID()
self.groupchat = groupchat
self.msncon = self.groupchat.session.legacycon
+ else:
+ self.ident = str(self)
+ self.groupchat = None
self.switchboard = None
self.ready = False
self.messageBuffer = []
self.invitedUsers = []
self.oneUserHasJoined = False
- if(makeSwitchboard and groupchat):
- debug.log("GroupchatSwitchboardSession: \"%s\" \"%s\" requesting a switchboard session" % (self.groupchat.roomJID(), self))
+ if makeSwitchboard and groupchat:
+ LogEvent(INFO, self.ident, "Requesting switchboard.")
d = self.msncon.notificationProtocol.requestSwitchboardServer()
d.addCallback(self.sbRequestAccepted)
d.addErrback(self.removeMe)
- if(self.msncon):
- debug.log("GroupchatSwitchboardSession: \"%s\" \"%s\" created" % (self.msncon.username, self))
+ if self.msncon:
+ LogEvent(INFO, self.ident, "Created groupchat for " + self.msncon.username)
def removeMe(self):
- if(self.removed):
- debug.log("GroupchatSwitchboardSession: removeMe called more than once! Traceback!")
+ if self.removed:
+ log.err("removeMe called more than once!")
return
self.removed = True
- debug.log("GroupchatSwitchboardSession: \"%s\" \"%s\" destroyed" % (self.groupchat.roomJID(), self))
+ LogEvent(INFO, self.ident)
self.msncon = None
- if(self.switchboard):
+ if self.switchboard:
self.switchboard.removeMe()
self.switchboard = None
self.groupchat = None
def sbRequestAccepted(self, (host, port, key)):
# Connect to the switchboard server
- debug.log("GroupchatSwitchboardSession: \"%s\" \"%s\" sbRequestAccepted()" % (self.msncon.username, self))
+ LogEvent(INFO, self.ident)
reactor.connectTCP(host, port, SwitchboardFactory(self, key))
def sendMessage(self, message, noerror):
- if(self.ready and self.oneUserHasJoined):
- def failedMessage(ignored=None):
- tempmsncon.failedMessage(self.groupchat.roomJID(), message)
- message = str(message.encode("utf-8"))
- msnmessage = msn.MSNMessage(message=message)
- msnmessage.setHeader("Content-Type", "text/plain; charset=UTF-8")
- msnmessage.ack = msn.MSNMessage.MESSAGE_NACK
- tempmsncon = self.msncon # In case MSN tells us the message failed after removeMe()
- d = self.switchboard.sendMessage(msnmessage)
- if(not noerror):
- d.addCallback(failedMessage)
+ if self.oneUserHasJoined:
+ SwitchboardSessionBase.sendMessage(self, message, noerror)
else:
- self.messageBuffer.append(message)
+ self.messageBuffer.append((message, noerror))
def inviteUser(self, userHandle):
userHandle = str(userHandle)
- if(self.ready):
- debug.log("GroupchatSwitchboardSession: \"%s\" \"%s\" inviting %s" % (self.msncon.username, self, userHandle))
+ if self.ready:
+ LogEvent(INFO, self.ident)
self.switchboard.inviteUser(userHandle)
else:
self.invitedUsers.append(userHandle)
self.groupchat.messageReceived(message.userHandle, message.getMessage())
def flushBuffer(self):
- for m in utils.copyList(self.messageBuffer):
- self.messageBuffer.remove(m)
- self.sendMessage(m, True)
+ for m, noerror in self.messageBuffer[:]:
+ self.messageBuffer.remove((m, noerror))
+ self.sendMessage(m, noerror)
- for i in utils.copyList(self.invitedUsers):
+ for i in self.invitedUsers[:]:
self.invitedUsers.remove(i)
self.inviteUser(i)
def userJoined(self, userHandle):
- debug.log("GroupchatSwitchboardSession: \"%s\" \"%s\" userJoined(\"%s\")" % (self.msncon.username, self, userHandle))
+ LogEvent(INFO, self.ident)
self.oneUserHasJoined = True
self.flushBuffer()
self.groupchat.contactJoined(userHandle)
def userLeft(self, userHandle):
- debug.log("GroupchatSwitchboardSession: \"%s\" \"%s\" userLeft(\"%s\")" % (self.msncon.username, self, userHandle))
+ LogEvent(INFO, self.ident)
self.groupchat.contactLeft(userHandle)
-class SwitchboardSession:
+class SwitchboardSession(SwitchboardSessionBase):
def __init__(self, msncon, remoteUser, resource, reply=False, host=None, port=None, key=None, sessionID=None):
self.removed = False
+ self.ident = (msncon.session.jabberID, remoteUser)
self.msncon = msncon
self.remoteUser = str(remoteUser)
self.resource = str(resource)
self.messageBuffer = [] # Any messages sent before the switchboard is ready are buffered
self.ready = False # Is True when we are connected to the switchboard, and the remote user has accepted our invite
- if(not reply):
+ if not reply:
# Request a switchboard
d = self.msncon.notificationProtocol.requestSwitchboardServer()
d.addCallback(self.sbRequestAccepted)
else:
reactor.connectTCP(host, port, SwitchboardFactory(self, key, sessionID, reply))
- debug.log("SwitchboardSession: \"%s\" \"%s\" \"%s\" created" % (self.msncon.username, self.remoteUser, self.resource))
+ LogEvent(INFO, self.ident)
def removeMe(self, sbflag=True):
- if(self.removed):
- debug.log("SwitchboardSession: removeMe called more than once! Traceback!")
+ if self.removed:
+ log.err("removeMe called more than once!")
return
self.removed = True
- debug.log("SwitchboardSession: \"%s\" \"%s\" \"%s\" destroyed" % (self.msncon.username, self.remoteUser, self.resource))
+ LogEvent(INFO, self.ident)
for message, noerror in self.messageBuffer:
- if(not noerror):
+ if not noerror:
self.msncon.failedMessage(self.remoteUser, message)
self.messageBuffer = []
del self.msncon.switchboardSessions[self.remoteUser]
self.msncon = None
- if(sbflag and self.switchboard):
+ if sbflag and self.switchboard:
self.switchboard.removeMe()
self.switchboard = None
self.ready = False
- if(self.killTimer and not self.killTimer.called):
+ if self.killTimer and not self.killTimer.called:
self.killTimer.cancel()
self.killTimer = None
# Connect to the switchboard server
reactor.connectTCP(host, port, SwitchboardFactory(self, key))
- def sendMessage(self, message, noerror):
- if(self.ready):
- debug.log("SwitchboardSession: \"%s\" \"%s\" sending message \"%s\"" % (self.msncon.username, self.remoteUser, message))
- message = str(message.encode("utf-8"))
- msnmessage = msn.MSNMessage(message=message)
- msnmessage.setHeader("Content-Type", "text/plain; charset=UTF-8")
- msnmessage.ack = msn.MSNMessage.MESSAGE_NACK
- def failedMessage(ignored):
- tempmsncon.failedMessage(self.remoteUser, message)
- d = self.switchboard.sendMessage(msnmessage)
- tempmsncon = self.msncon # In case MSN tells us the message failed after removeMe()
- if(not noerror):
- d.addCallback(failedMessage)
- self.resetTimer()
- else:
- self.messageBuffer.append((message, noerror))
-
def sendTypingNofication(self):
- if(self.ready):
+ if self.ready:
self.switchboard.sendTypingNotification()
def contactTyping(self):
self.msncon.gotContactTyping(self.remoteUser, self.resource)
def flushBuffer(self):
- for m, noerror in utils.copyList(self.messageBuffer):
+ for m, noerror in self.messageBuffer[:]:
self.messageBuffer.remove((m, noerror))
self.sendMessage(m, noerror)
self.msncon.gotMessage(self.remoteUser, self.resource, message.getMessage())
self.resetTimer()
+ CAPS = msn.MSNContact.MSNC1 | msn.MSNContact.MSNC2 | msn.MSNContact.MSNC3 | msn.MSNContact.MSNC4
+ def requestAvatar(self):
+ if not self.switchboard: return
+ msnContacts = self.msncon.getContacts()
+ if not msnContacts: return
+ msnContact = msnContacts.getContact(self.remoteUser)
+ if not (msnContact and msnContact.caps & self.CAPS and msnContact.msnobj): return
+ if msnContact.msnobjGot: return
+ msnContact.msnobjGot = True # This is deliberately set before we get the avatar. So that we don't try to reget failed avatars over & over
+ self.switchboard.sendAvatarRequest(self.remoteUser, msnContact.msnobj)
+
def userJoined(self, userHandle):
- if(userHandle != self.remoteUser):
+ if userHandle != self.remoteUser:
# Another user has joined, so we now have three participants (these two and ourself)
switchToGroupchat(self, self.remoteUser, userHandle)
+ else:
+ self.requestAvatar()
def userLeft(self, userHandle):
- if(userHandle == self.remoteUser):
+ if userHandle == self.remoteUser:
self.removeMe()
-
-
-
class DispatchFactory(ClientFactory):
def __init__(self, msncon):
self.msncon = msncon
p = Dispatch(self.msncon)
del self.msncon # No longer needed
return p
-
+
+ def clientConnectionFailed(self, connector, reason):
+ self.msncon.connectionLostBase(reason)
+
class Dispatch(msn.DispatchClient):
def __init__(self, msncon):
def gotNotificationReferral(self, host, port):
self.transport.loseConnection()
- if(self.msncon and self.msncon.session and self.msncon.session.alive):
+ if self.msncon and self.msncon.session and self.msncon.session.alive:
reactor.connectTCP(host, port, self.msncon.notificationFactory)
def __init__(self):
self.removed = False
- msn.NotificationClient.__init__(self, proxy=config.proxyServer, proxyport=config.proxyPort)
+ msn.NotificationClient.__init__(self)
def removeMe(self):
- if(self.removed):
- debug.log("Notification: removeMe called more than once! Traceback!")
+ if self.removed:
+ log.err("removeMe called more than once!")
return
self.removed = True
self.logOut()
self.transport.loseConnection()
- if(self.factory.msncon):
+ if self.factory.msncon:
self.factory.msncon.notificationProtocol = None
self.factory.msncon = None
self.factory = None
utils.mutilateMe(self)
def badConditions(self):
- if(not (self.factory and self.factory.msncon and self.factory.msncon.session and self.factory.msncon.session.alive)):
- if(not self.removed):
+ if not (self.factory and self.factory.msncon and self.factory.msncon.session and self.factory.msncon.session.alive):
+ if not self.removed:
self.removeMe()
return True
return False
def loginFailure(self, message):
- if(self.badConditions()): return
+ if self.badConditions(): return
self.factory.msncon.loginFailure(message)
- def loggedIn(self, userHandle, screenName, verified):
- if(self.badConditions()): return
+ def loggedIn(self, userHandle, verified):
+ if self.badConditions(): return
self.factory.msncon.notificationProtocolReady(self)
- if(not verified):
+ if not verified:
self.factory.msncon.accountNotVerified()
- msn.NotificationClient.loggedIn(self, userHandle, screenName, verified)
+ msn.NotificationClient.loggedIn(self, userHandle, verified)
- debug.log("NotificationClient: \"%s\" authenticated with MSN servers" % (self.factory.msncon.username))
-
- def gotMessage(self, msnmessage):
- if(self.badConditions()): return
- debug.log("NotificationClient: \"%s\" gotMessage()" % (self.factory.msncon.username))
-
- cTypes = [s.lstrip() for s in msnmessage.getHeader("Content-Type").split(';')]
- def getFields():
- fields = msnmessage.getMessage().strip().split('\n')
- values = {}
- for i in fields:
- a = i.split(':')
- if(len(a) != 2): continue
- f, v = a
- f = f.strip()
- v = v.strip()
- values[f] = v
- return values
-
- if("text/x-msmsgsinitialemailnotification" in cTypes and config.mailNotifications):
- values = getFields()
- try:
- inboxunread = int(values["Inbox-Unread"])
- foldersunread = int(values["Folders-Unread"])
- except KeyError:
- return
- if(foldersunread + inboxunread == 0): return # For some reason MSN sends notifications about empty inboxes sometimes?
- debug.log("NotificationClient: \"%s\" Initial hotmail notification" % (self.factory.msncon.username))
- self.factory.msncon.initialEmailNotification(inboxunread, foldersunread)
-
- elif("text/x-msmsgsemailnotification" in cTypes and config.mailNotifications):
- values = getFields()
- try:
- mailfrom = values["From"]
- fromaddr = values["From-Addr"]
- subject = values["Subject"]
- junkbeginning = "=?\"us-ascii\"?Q?"
- junkend = "?="
- subject = subject.replace(junkbeginning, "").replace(junkend, "").replace("_", " ")
- except KeyError:
- # If any of the fields weren't found then it's not a big problem. We just ignore the message
- return
- debug.log("NotificationClient: \"%s\" Live hotmail notification" % (self.factory.msncon.username))
- self.factory.msncon.realtimeEmailNotification(mailfrom, fromaddr, subject)
-
- elif("NOTIFICATION" == msnmessage.userHandle):
- notification = utils.parseText(msnmessage.message)
- siteurl = notification.getAttribute("siteurl")
- notid = notification.getAttribute("id")
-
- msg = None
- for e in notification.elements():
- if(e.name == "MSG"):
- msg = e
- break
- else: return
-
- msgid = msg.getAttribute("id")
-
- action = None
- subscr = None
- bodytext = None
- for e in msg.elements():
- if(e.name == "ACTION"):
- action = e.getAttribute("url")
- if(e.name == "SUBSCR"):
- subscr = e.getAttribute("url")
- if(e.name == "BODY"):
- for e2 in e.elements():
- if(e2.name == "TEXT"):
- bodytext = e2.__str__()
- if(not (action and subscr and bodytext)): return
-
-
- actionurl = "%s¬ification_id=%s&message_id=%s&agent=messenger" % (action, notid, msgid)
- subscrurl = "%s¬ification_id=%s&message_id=%s&agent=messenger" % (subscr, notid, msgid)
-
- self.factory.msncon.msnAlert(bodytext, actionurl, subscrurl)
-
+ LogEvent(INFO, self.factory.msncon.session.jabberID)
+ def msnAlertReceived(self, body, action, subscr):
+ if self.badConditions(): return
+ self.factory.msncon.msnAlert(body, action, subscr)
+
+ def initialEmailNotification(self, inboxunread, foldersunread):
+ if self.badConditions() or not config.mailNotifications: return
+ self.factory.msncon.initialEmailNotification(inboxunread, foldersunread)
+
+ def realtimeEmailNotification(self, mailfrom, fromaddr, subject):
+ if self.badConditions() or not config.mailNotifications: return
+ self.factory.msncon.realtimeEmailNotification(mailfrom, fromaddr, subject)
def connectionLost(self, reason):
- if(self.badConditions()): return
+ if self.badConditions(): return
def wait():
- debug.log("NotificationClient: \"%s\" lost connection with MSN servers" % (self.factory.userHandle))
+ LogEvent(INFO, self.factory.msncon.session.jabberID)
msn.NotificationClient.connectionLost(self, reason)
self.factory.msncon.connectionLostBase(reason)
# Make sure this event is handled after any others
reactor.callLater(0, wait)
def listSynchronized(self, *args):
- if(self.badConditions()): return
- debug.log("NotificationClient: \"%s\" MSN contact lists synchronised" % (self.factory.userHandle))
+ if self.badConditions(): return
+ LogEvent(INFO, self.factory.msncon.session.jabberID)
self.factory.msncon.listSynchronized()
- if(self.badConditions()): return # Just in case the session is deregistered
- self.factory.msncon.sendSavedStatus()
+ if self.badConditions(): return # Just in case the session is deregistered
+ self.factory.msncon.sendSavedEvents()
+ self.setPrivacyMode(False)
def gotSwitchboardInvitation(self, sessionID, host, port, key, remoteUser, screenName):
- if(self.badConditions()): return
- debug.log("NotificationClient: \"%s\" gotSwitchboardInvitation(\"%s\")" % (self.factory.userHandle, remoteUser))
+ if self.badConditions(): return
+ LogEvent(INFO, self.factory.msncon.session.jabberID)
sbs = SwitchboardSession(self.factory.msncon, remoteUser, self.factory.msncon.session.highestResource(), True, host, port, key, sessionID)
- if(self.factory.msncon.switchboardSessions.has_key(remoteUser)):
+ if self.factory.msncon.switchboardSessions.has_key(remoteUser):
self.factory.msncon.switchboardSessions[remoteUser].removeMe()
self.factory.msncon.switchboardSessions[remoteUser] = sbs
+ def avatarHashChanged(self, userHandle, hash):
+ if self.badConditions(): return
+ LogEvent(INFO, self.factory.msncon.session.jabberID)
+ hash = base64.decodestring(hash)
+ hash = binascii.hexlify(hash)
+ self.factory.msncon.avatarHashChanged(userHandle, hash)
+
def contactStatusChanged(self, statusCode, userHandle, screenName):
- if(self.badConditions()): return
- debug.log("NotificationClient: \"%s\" contactStatusChanged(\"%s\", \"%s\")" % (self.factory.userHandle, statusCode, userHandle))
- msn.NotificationClient.contactStatusChanged(self, statusCode, userHandle, screenName)
+ if self.badConditions(): return
+ LogEvent(INFO, self.factory.msncon.session.jabberID)
self.factory.msncon.contactStatusChanged(userHandle)
- def gotContactStatus(self, statusCode, userHandle, screenName):
- if(self.badConditions()): return
- msn.NotificationClient.gotContactStatus(self, statusCode, userHandle, screenName)
- debug.log("NotificationClient: \"%s\" gotContactStatus(\"%s\", \"%s\")" % (self.factory.userHandle, statusCode, userHandle))
-
+ def contactPersonalChanged(self, userHandle, personal):
+ if self.badConditions(): return
+ msn.NotificationClient.contactPersonalChanged(self, userHandle, personal)
self.factory.msncon.contactStatusChanged(userHandle)
def contactOffline(self, userHandle):
- if(self.badConditions()): return
- debug.log("NotificationClient: \"%s\" contactOffline(\"%s\")" % (self.factory.userHandle, userHandle))
+ if self.badConditions(): return
+ LogEvent(INFO, self.factory.msncon.session.jabberID)
msn.NotificationClient.contactOffline(self, userHandle)
self.factory.msncon.contactStatusChanged(userHandle)
- def userAddedMe(self, userHandle, screenName, listVersion):
- if(self.badConditions()): return
- debug.log("NotificationClient: \"%s\" userAddedMe(\"%s\", \"%s\")" % (self.factory.userHandle, userHandle, listVersion))
- msn.NotificationClient.userAddedMe(self, userHandle, screenName, listVersion)
+ def userAddedMe(self, userGuid, userHandle, screenName):
+ if self.badConditions(): return
+ LogEvent(INFO, self.factory.msncon.session.jabberID)
+ msn.NotificationClient.userAddedMe(self, userGuid, userHandle, screenName)
self.factory.msncon.userAddedMe(userHandle)
- def userRemovedMe(self, userHandle, listVersion):
- if(self.badConditions()): return
- debug.log("NotificationClient: \"%s\" userRemovedMe(\"%s\", \"%s\")" % (self.factory.userHandle, userHandle, listVersion))
- msn.NotificationClient.userRemovedMe(self, userHandle, listVersion)
+ def userRemovedMe(self, userGuid, userHandle):
+ if self.badConditions(): return
+ LogEvent(INFO, self.factory.msncon.session.jabberID)
+ msn.NotificationClient.userRemovedMe(self, userGuid, userHandle)
self.factory.msncon.userRemovedMe(userHandle)
def multipleLogin(self):
- if(self.badConditions()): return
- debug.log("NotificationClient: \"%s\" multiple logins" % (self.factory.msncon.username))
+ if self.badConditions(): return
+ LogEvent(INFO, self.factory.msncon.session.jabberID)
self.factory.msncon.multipleLogin()
def buildProtocol(self, addr):
p = Switchboard(self.switchboardSession)
- if(p.badConditions()): return p
+ if p.badConditions(): return p
p.key = self.key
p.sessionID = self.sessionID
p.reply = self.reply
def __init__(self, switchboardSession):
self.removed = False
- msn.SwitchboardClient.__init__(self)
self.switchboardSession = switchboardSession
self.chattingUsers = []
self.callid = None
- if(self.badConditions()): return
- debug.log("SwitchboardClient: \"%s\" \"%s\" - created" % (self.switchboardSession.msncon.username, self.switchboardSession))
+ msn.SwitchboardClient.__init__(self)
+ if self.badConditions(): return
+ self.msnobj = self.switchboardSession.msncon.notificationProtocol.msnobj
+ LogEvent(INFO, self.switchboardSession.ident)
def removeMe(self):
- if(self.removed):
- debug.log("Switchboard: removeMe called more than once! Traceback!")
+ if self.removed:
+ log.err("removeMe called more than once!")
return
self.removed = True
self.transport.loseConnection()
- debug.log("SwitchboardClient: \"%s\" - destroyed" % (self.switchboardSession))
+ LogEvent(INFO, self.switchboardSession.ident)
self.switchboardSession = None
self.factory.switchboardSession = None
self.factory = None
- if(self.callid and not self.callid.called):
+ if self.callid and not self.callid.called:
self.callid.cancel() # Cancel the invite fail message
self.callid = None
utils.mutilateMe(self)
def badConditions(self):
- if(not (self.switchboardSession and self.switchboardSession.msncon and self.switchboardSession.msncon.session and self.switchboardSession.msncon.session.alive)):
- if(self.switchboardSession):
- if(not self.switchboardSession.removed):
+ if not (self.switchboardSession and self.switchboardSession.msncon and self.switchboardSession.msncon.session and self.switchboardSession.msncon.session.alive):
+ if self.switchboardSession:
+ if not self.switchboardSession.removed:
self.switchboardSession.removeMe()
- elif(not self.removed):
+ elif not self.removed:
self.removeMe()
return True
return False
def loggedIn(self):
- if(self.badConditions()): return
- if((not self.reply) and self.switchboardSession.__class__ == SwitchboardSession):
+ if self.badConditions(): return
+ if (not self.reply) and isinstance(self.switchboardSession, SwitchboardSession):
def failCB(arg=None):
- debug.log(templogmessage)
+ LogEvent(INFO, ident, "User has not joined after 30 seconds.")
self.switchboardSession.removeMe()
d = self.inviteUser(self.switchboardSession.remoteUser)
d.addErrback(failCB)
- templogmessage = "SwitchboardClient: \"%s\" \"%s\" - user has NOT joined after 30 seconds" % (self.switchboardSession.msncon.username, self.switchboardSession.remoteUser)
+ ident = self.switchboardSession.ident
# If the user doesn't join then we want to tear down the SwitchboardSession
self.callid = reactor.callLater(30.0, failCB)
else:
self.readySwitchboardSession()
- def readySwitchboardSession(self, ignored=None):
- if(self.badConditions()): return
- debug.log("SwitchboardClient: \"%s\" \"%s\" - ready for use" % (self.switchboardSession.msncon.username, self.switchboardSession))
- self.switchboardSession.ready = True
- self.switchboardSession.switchboard = self
- self.switchboardSession.flushBuffer()
+ def readySwitchboardSession(self):
+ self.switchboardSession.switchboardReady(self)
for user in self.chattingUsers:
self.switchboardSession.userJoined(user)
- if(self.callid and not self.callid.called):
+ if self.callid and not self.callid.called:
self.callid.cancel() # Cancel the invite fail message (only applies if we needed to invite the user)
self.callid = None
self.chattingUsers.append(user)
def userJoined(self, userHandle, screenName):
- if(self.badConditions()): return
- if((not self.reply) and self.switchboardSession.__class__ == SwitchboardSession):
+ if self.badConditions(): return
+ # FIXME - check this is correct
+ if (not self.reply) and isinstance(self.switchboardSession, SwitchboardSession):
self.readySwitchboardSession()
- debug.log("SwitchboardClient: \"%s\" \"%s\" - userJoined(\"%s\")" % (self.switchboardSession.msncon.username, self.switchboardSession, userHandle))
+ LogEvent(INFO, self.switchboardSession.ident)
self.switchboardSession.userJoined(userHandle)
- self.sendClientCaps()
def userLeft(self, userHandle):
- if(self.badConditions()): return
- debug.log("SwitchboardClient: \"%s\" \"%s\" - userLeft(\"%s\")" % (self.switchboardSession.msncon.username, self.switchboardSession, userHandle))
+ if self.badConditions(): return
+ LogEvent(INFO, self.switchboardSession.ident)
def wait():
+ if self.badConditions(): return
self.switchboardSession.userLeft(userHandle)
# Make sure this event is handled after any others (eg, gotMessage)
reactor.callLater(0, wait)
def gotMessage(self, message):
- if(self.badConditions()):
- debug.log("SwitchboardClient: gotMessage called too late! Traceback!")
+ if self.badConditions():
+ LogEvent(WARN, self.switchboardSession.ident, "gotMessage() called too late. Dropped a message!")
return
- debug.log("SwitchboardClient: \"%s\" \"%s\" gotMessage(\"%s\")" % (self.switchboardSession.msncon.username, message.userHandle, message.getMessage()))
+
+ LogEvent(INFO, self.switchboardSession.ident)
cTypes = [s.lstrip() for s in message.getHeader("Content-Type").split(';')]
- if("text/plain" in cTypes):
- if(len(cTypes) > 1 and cTypes[1].find("UTF-8") >= 0):
- message.message = message.message.decode("utf-8")
- self.switchboardSession.gotMessage(message)
+ if "text/plain" in cTypes:
+ try:
+ if len(cTypes) > 1 and cTypes[1].find("UTF-8") >= 0:
+ message.message = message.message.decode("utf-8")
+ self.switchboardSession.gotMessage(message)
+ except:
+ self.switchboardSession.gotMessage(lang.get(self.switchboardSession.msncon.session.lang).msnDroppedMessage) # FIXME, this is a little deep
+ raise
return
- if("text/x-clientcaps" in cTypes):
- if(message.hasHeader("JabberID")):
+ if "text/x-clientcaps" in cTypes:
+ if message.hasHeader("JabberID"):
jid = message.getHeader("JabberID")
self.switchboardSession.msncon.userMapping(message.userHandle, jid)
return
- debug.log("Discarding unknown message type: %s" % (message.getMessage()))
+ LogEvent(INFO, self.switchboardSession.ident, "Discarding unknown message type.")
def userTyping(self, message):
- if(self.badConditions()): return
- if(self.switchboardSession.__class__ == SwitchboardSession): # Ignore typing in groupchats
- if(message.userHandle == self.switchboardSession.remoteUser):
+ if self.badConditions(): return
+ if isinstance(self.switchboardSession, SwitchboardSession): # Ignore typing in groupchats
+ if message.userHandle == self.switchboardSession.remoteUser:
self.switchboardSession.contactTyping()
def sendClientCaps(self):
message.setHeader("Client-Name", "PyMSNt")
message.setHeader("JabberID", str(self.switchboardSession.msncon.session.jabberID)) # FIXME, this is a little deep
self.sendMessage(message)
+
+ def sendMessage(self, message):
+ # A little bit of fancyness to make sure that clientcaps
+ # only gets sent after the first text message.
+ if message.getHeader("Content-Type").startswith("text"):
+ self.sendMessage = type(self.sendMessage)(msn.SwitchboardClient.sendMessage, self, Switchboard)
+ self.sendClientCaps()
+ return self.sendMessage(message)
+ else:
+ return msn.SwitchboardClient.sendMessage(self, message)
+
+ def gotAvatarImage(self, to, image):
+ if self.badConditions(): return
+ self.switchboardSession.gotAvatarImage(to, image)
+
+ def gotSendRequest(self, fileReceive):
+ if self.badConditions():
+ fileReceive.accept(False)
+ return
+ LogEvent(INFO, self.switchboardSession.ident)
+ self.switchboardSession.gotSendRequest(fileReceive)