def __init__(self, config): self.config = config self.rooms = {} self.host = self.config['xmpp.muc.host'] self.smokey = SmokeyTheBear(self) # every campfire.update.interval seconds, tell smokey to check on the fires self.smokey.startFireDuty(self.config['campfire.update.interval'])
def __init__(self, config): self.last_topic = None self.config = config self.rooms = {} self.host = self.config['xmpp.muc.host'] self.smokey = SmokeyTheBear(self) # every campfire.update.interval seconds, tell smokey to check on the fires self.smokey.startFireDuty(self.config['campfire.update.interval'])
class MUCService(component.Service): implements(IService) def __init__(self, config): self.last_topic = None self.config = config self.rooms = {} self.host = self.config['xmpp.muc.host'] self.smokey = SmokeyTheBear(self) # every campfire.update.interval seconds, tell smokey to check on the fires self.smokey.startFireDuty(self.config['campfire.update.interval']) def iq(self, type='get', id=None): r = xmlstream.IQ(self.xmlstream, type) r['from'] = self.host if id is not None: r['id'] = id return r def componentConnected(self, xmlstream): self.jabberId = xmlstream.authenticator.otherHost self.xmlstream = xmlstream self.xmlstream.addObserver(DISCO_INFO, self.onDiscoInfo) self.xmlstream.addObserver(PRESENCE, self.onPresence) self.xmlstream.addObserver(MESSAGE, self.onMessage) log.msg("muc component connected") def onDiscoInfo(self, iq): response = self.iq('result', iq['id']) query = getattr(iq, 'query', None) if query is not None: query = response.addElement('query', DISCO_NS_INFO) identity = domish.Element( (None, 'identity'), attribs={ 'category': "conference", 'name': 'campfirenow.com interface MUC', 'type': "text" }) query.addChild(identity) query.addChild( domish.Element((None, 'feature'), attribs={'var': NS_MUC})) response.send(iq['from']) def parseCampfireName(self, jid): room_parts = jid.user.split(".") roomname = ".".join(room_parts[1:]) account = room_parts[0] return (account, roomname) # <presence from='[email protected]/hm-min' to='[email protected]/bmuller'> # <x xmlns='http://jabber.org/protocol/muc'><password>password</password></x></presence> def onPresence(self, pres): to = jid.JID(pres['to']) fr = jid.JID(pres['from']) account, roomname = self.parseCampfireName(to) def handleAuth(campfire): if campfire is None: self.sendErrorPresence(pres, "not-allowed", "cancel", NS_MUC) else: self.initializeRoom(campfire, roomname, to, jid.JID(pres['from'])) password = xpath.queryForString("/presence/x/password", pres) if pres.getAttribute('type') == "unavailable": self.smokey.putCampfireOut(account, to) elif password == "": self.sendErrorPresence(pres, "not-authorized") else: log.msg("attempting to auth %s for room %s on account %s" % (to.resource, roomname, account)) self.smokey.initCampfire(account, fr, to, password).addCallback(handleAuth) def initializeRoom(self, campfire, roomname, participant_jid, source_jid): log.msg("initializing room %s" % roomname) def initParticipants(room): if room is None: return room.setJIDs(source_jid, participant_jid) return room.update() campfire.getRoom(roomname).addCallback(initParticipants) def handleRoomUpdate(self, room): for username in room.participants.getJustJoined().values(): mfrom = room.participant_jid.userhostJID() mfrom.resource = username.replace(" ", "") if username == room.campfire_name: # if sending presence to same user that is logged in, send status codes 110 and 210 # per example 21 in section 7.1.3 of XEP 0045 self.sendPresence(mfrom, room.source_jid, statuses=['110', '210']) else: self.sendPresence(mfrom, room.source_jid) for msg in room.msgs: mfrom = room.participant_jid.userhostJID() mfrom.resource = msg.user.replace(" ", "") self.sendMessage(mfrom, msg.body, room.source_jid, msg.tstamp) if room.topic != self.last_topic: self.last_topic = room.topic topic = domish.Element( (None, 'message'), attribs={ 'from': room.participant_jid.userhost(), 'to': room.source_jid.full(), 'type': 'groupchat' }) topic.addElement('subject', content=room.topic) self.xmlstream.send(topic) def sendPresence(self, pfrom, pto, statuses=None): log.msg("sending presence from %s to %s" % (pfrom, pto)) statuses = statuses or [] p = domish.Element((None, 'presence'), attribs={ 'from': pfrom.full(), 'to': pto.full() }) x = p.addElement('x', NS_MUC_USER) x.addChild( domish.Element((None, 'item'), attribs={ 'affiliation': 'member', 'role': 'participant' })) for status in statuses: x.addChild( domish.Element((None, 'status'), attribs={'code': status})) self.xmlstream.send(p) def sendErrorPresence(self, pres, reason, type="auth", ns=NS_MUC_USER): to = jid.JID(pres['to']) p = domish.Element((None, 'presence')) p['from'] = to.userhost() p['to'] = pres['from'] p.addElement('x', ns) p.addChild(Error(reason, type)) self.xmlstream.send(p) def sendMessage(self, mfrom, msgBody, mto, tstamp, type="groupchat"): log.msg("sending message from %s to %s" % (mfrom, mto)) m = domish.Element((None, 'message'), attribs={ 'from': mfrom.full(), 'to': mto.full(), 'type': type }) m.addElement('body', content=msgBody) delay = domish.Element((DELAY_NS, 'delay'), attribs={ 'from': mfrom.userhost(), 'stamp': tstamp }) m.addChild(delay) self.xmlstream.send(m) def onMessage(self, msg): if msg['type'] != "groupchat": m = domish.Element((None, 'message'), attribs={ 'from': msg['to'], 'to': msg['from'], 'type': 'chat' }) m.addElement('body', content="You cannot send messages directly to users.") self.xmlstream.send(m) to = jid.JID(msg['to']) fr = jid.JID(msg['from']) account, roomname = self.parseCampfireName(to) def sendMsgRoom(room): if room is not None: room.say(xpath.queryForString("/message/body", msg)) def sendMsg(campfire): if campfire is not None: campfire.getRoom(roomname).addCallback(sendMsgRoom) self.smokey.getCampfire(account, fr).addCallback(sendMsg)
class MUCService(component.Service): implements(IService) def __init__(self, config): self.last_topic = None self.config = config self.rooms = {} self.host = self.config['xmpp.muc.host'] self.smokey = SmokeyTheBear(self) # every campfire.update.interval seconds, tell smokey to check on the fires self.smokey.startFireDuty(self.config['campfire.update.interval']) def iq(self, type='get', id=None): r = xmlstream.IQ(self.xmlstream, type) r['from'] = self.host if id is not None: r['id'] = id return r def componentConnected(self, xmlstream): self.jabberId = xmlstream.authenticator.otherHost self.xmlstream = xmlstream self.xmlstream.addObserver(DISCO_INFO, self.onDiscoInfo) self.xmlstream.addObserver(PRESENCE, self.onPresence) self.xmlstream.addObserver(MESSAGE, self.onMessage) log.msg("muc component connected") def onDiscoInfo(self, iq): response = self.iq('result', iq['id']) query = getattr(iq, 'query', None) if query is not None: query = response.addElement('query', DISCO_NS_INFO) identity = domish.Element((None, 'identity'), attribs={'category': "conference", 'name': 'campfirenow.com interface MUC', 'type': "text"}) query.addChild(identity) query.addChild(domish.Element((None, 'feature'), attribs={'var': NS_MUC})) response.send(iq['from']) def parseCampfireName(self, jid): room_parts = jid.user.split(".") roomname = ".".join(room_parts[1:]) account = room_parts[0] return (account, roomname) # <presence from='[email protected]/hm-min' to='[email protected]/bmuller'> # <x xmlns='http://jabber.org/protocol/muc'><password>password</password></x></presence> def onPresence(self, pres): to = jid.JID(pres['to']) fr = jid.JID(pres['from']) account, roomname = self.parseCampfireName(to) def handleAuth(campfire): if campfire is None: self.sendErrorPresence(pres, "not-allowed", "cancel", NS_MUC) else: self.initializeRoom(campfire, roomname, to, jid.JID(pres['from'])) password = xpath.queryForString("/presence/x/password", pres) if pres.getAttribute('type') == "unavailable": self.smokey.putCampfireOut(account, to) elif password == "": self.sendErrorPresence(pres, "not-authorized") else: log.msg("attempting to auth %s for room %s on account %s" % (to.resource, roomname, account)) self.smokey.initCampfire(account, fr, to, password).addCallback(handleAuth) def initializeRoom(self, campfire, roomname, participant_jid, source_jid): log.msg("initializing room %s" % roomname) def initParticipants(room): if room is None: return room.setJIDs(source_jid, participant_jid) return room.update() campfire.getRoom(roomname).addCallback(initParticipants) def handleRoomUpdate(self, room): for username in room.participants.getJustJoined().values(): mfrom = room.participant_jid.userhostJID() mfrom.resource = username.replace(" ", "") if username == room.campfire_name: # if sending presence to same user that is logged in, send status codes 110 and 210 # per example 21 in section 7.1.3 of XEP 0045 self.sendPresence(mfrom, room.source_jid, statuses=['110', '210']) else: self.sendPresence(mfrom, room.source_jid) for msg in room.msgs: mfrom = room.participant_jid.userhostJID() mfrom.resource = msg.user.replace(" ", "") self.sendMessage(mfrom, msg.body, room.source_jid, msg.tstamp) if room.topic != self.last_topic: self.last_topic = room.topic topic = domish.Element((None, 'message'), attribs = {'from': room.participant_jid.userhost(), 'to': room.source_jid.full(), 'type': 'groupchat'}) topic.addElement('subject', content=room.topic) self.xmlstream.send(topic) def sendPresence(self, pfrom, pto, statuses=None): log.msg("sending presence from %s to %s" % (pfrom, pto)) statuses = statuses or [] p = domish.Element((None, 'presence'), attribs = {'from': pfrom.full(), 'to': pto.full()}) x = p.addElement('x', NS_MUC_USER) x.addChild(domish.Element((None, 'item'), attribs = {'affiliation': 'member', 'role': 'participant'})) for status in statuses: x.addChild(domish.Element((None, 'status'), attribs = {'code': status})) self.xmlstream.send(p) def sendErrorPresence(self, pres, reason, type="auth", ns=NS_MUC_USER): to = jid.JID(pres['to']) p = domish.Element((None, 'presence')) p['from'] = to.userhost() p['to'] = pres['from'] p.addElement('x', ns) p.addChild(Error(reason, type)) self.xmlstream.send(p) def sendMessage(self, mfrom, msgBody, mto, tstamp, type="groupchat"): log.msg("sending message from %s to %s" % (mfrom, mto)) m = domish.Element((None, 'message'), attribs = {'from': mfrom.full(), 'to': mto.full(), 'type': type}) m.addElement('body', content=msgBody) delay = domish.Element((DELAY_NS, 'delay'), attribs = {'from': mfrom.userhost(), 'stamp': tstamp}) m.addChild(delay) self.xmlstream.send(m) def onMessage(self, msg): if msg['type'] != "groupchat": m = domish.Element((None, 'message'), attribs = {'from': msg['to'], 'to': msg['from'], 'type': 'chat'}) m.addElement('body', content="You cannot send messages directly to users.") self.xmlstream.send(m) to = jid.JID(msg['to']) fr = jid.JID(msg['from']) account, roomname = self.parseCampfireName(to) def sendMsgRoom(room): if room is not None: room.say(xpath.queryForString("/message/body", msg)) def sendMsg(campfire): if campfire is not None: campfire.getRoom(roomname).addCallback(sendMsgRoom) self.smokey.getCampfire(account, fr).addCallback(sendMsg)