def presence(self, conn, presence): user = self.user # Decode who sent to us # Note it can be somebody we haven't heard about; presence # can arrive before our roster request is fulfilled. # XMPP is a beast. n = presence.attrs.get("from") if not n: return sender = n.node senddom = n.domain if (not sender) or (not senddom): return who = sender + "@" + senddom # Decode status (i.e., "show") update print "presence", who anystat = False for kid in presence.kids: # Decode initial part of data d0 = None if len(kid.data) > 0: d0 = toascii(kid.data[0]) if not isinstance(d0, str): d0 = None # Away status kn = toascii(kid.name) print kn, d0 if kn == "priority": # If they're actually online, this'll show anystat = True if kn == "show": if d0 is None: continue if user.status.get(who, "NEW") != d0: print " updated" user.status[who] = d0 user.rgen += 1 break # TBD, "status" is a descriptive string # If "show" didn't break the loop, they're available else: if anystat: newstat = "xa" else: newstat = "offline" if newstat != user.status.get(who, "NEW"): print "no show, updating to assume %s" % (newstat,) user.rgen += 1 user.status[who] = newstat
def message(self, conn, msg): sender = msg.getFrom() recip = msg.getTo() body = msg.getBody() if body is None: # No data; typing, paused, etc. return print "Message received from %s for %s" % (sender, self.acct) print " Body: %s" % (body,) self.user.add(aname(sender), aname(recip), toascii(body))
def post_msg(self, buf): # Burst from JSON msg = json.loads(buf) towhom = toascii(msg.get("recipient", "")) body = toascii(msg.get("body", "")) # Malformed? if (not towhom) or (not body): self.send_error(404) return None # Recipient known? user = self.user acct = user.roster.get(towhom) if acct is None: self.send_error(404) return None # Send message with user.exclusion: print "Send msg", towhom, body acct.send(towhom, body) # Log a message on our own display for tup in reversed(user.msgs): if tup[1] != '>': break if towhom == tup[1]: # "mFrom" is what gets displayed, so populate it with # either '>' (last sender) or actual name user.add('>', towhom, body) else: user.add('> ' + towhom, towhom, body) # Empty result body self.send_result("") return ""
def start(self): # Connect to the actual XMPP account acct = self.acct server = acct.split("@")[-1] jid = xmpp.JID(acct) self.conn = conn = xmpp.Client(server, debug=[]) conn.connect() result = conn.auth(jid.getNode(), self.pw, "webXMPP%d" % (os.getpid(),)) if not result: print "Account %s XMPP start failed" % (self.acct,) sys.exit(0) # Announce ourselves conn.sendInitPresence() conn.RegisterHandler('message', self.message) conn.RegisterHandler('presence', self.presence) # Fold in roster r = conn.getRoster() buds = set() for bud in r.getItems(): budstr = toascii(bud) if '@' not in budstr: # Ignore aliases continue if r[bud].get("subscription"): buds.add(budstr) self.buddies = frozenset(buds) user = self.user for bud in buds: user.roster[bud] = self del buds # And dispatch incoming messages while conn.Process(10): # No single XMPP destination will chew us up time.sleep(0.2) # Cleanly terminate if so flagged if self.stopping: for bud in self.buddies: del acct.roster[bud] conn.disconnect() sys.exit(0)
def aname(jid): u = toascii(jid.node) d = toascii(jid.domain) return "%s@%s" % (u, d)