예제 #1
0
파일: muc.py 프로젝트: legoscia/campfirer
 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'])
예제 #2
0
파일: muc.py 프로젝트: bmuller/campfirer
 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'])
예제 #3
0
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)
예제 #4
0
파일: muc.py 프로젝트: bmuller/campfirer
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)