Changeset 110:ddf5580b7128


Ignore:
Timestamp:
Oct 1, 2008, 11:11:06 PM (13 years ago)
Author:
Christopher Zorn <tofu@…>
Branch:
wokkel-muc-client-support-24
Convert:
svn:b33ecbfc-034c-dc11-8662-000475d9059e/branches/wokkel-muc-client-support-24@71
Message:

add some history and other things, plus some test stubs

Location:
wokkel
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • wokkel/muc.py

    r108 r110  
    1010U{XEP-0045<http://www.xmpp.org/extensions/xep-0045.html>}.
    1111"""
     12import datetime
    1213
    1314from zope.interface import implements
     
    2829NS_ROOMINFO = NS + '#roominfo'
    2930NS_CONFIG   = NS + '#roomconfig'
     31NS_REQUEST  = NS + '#request'
     32
     33NS_DELAY    = 'urn:xmpp:delay'
    3034
    3135# ad hoc commands
     
    5963CHAT      = MESSAGE +'[@type="chat"]'
    6064
    61 GROUPCHAT    = MESSAGE +'[@type="groupchat"]'
     65GROUPCHAT     = MESSAGE +'[@type="groupchat"]/body'
     66SUBJECT       = MESSAGE +'[@type="groupchat"]/body'
    6267MESSAGE_ERROR = MESSAGE +'[@type="error"]'
    6368
     69STATUS_CODES = { # see http://www.xmpp.org/extensions/xep-0045.html#registrar-statuscodes
     70    100:
     71        {'name':'fulljid',
     72         'stanza':'presence',
     73         
     74         },
     75    201:
     76        {'name':'created',
     77         'stanza': 'presence',
     78         'context':'Entering a room',
     79         'purpose':'Inform user that a new room has been created'
     80         },   
     81}
     82
     83STATUS_CODE_CREATED = 201
    6484
    6585
     
    95115
    96116
     117class ConfigureRequest(xmlstream.IQ):
     118    """
     119    Configure MUC room request.
     120
     121    @ivar namespace: Request namespace.
     122    @type namespace: C{str}
     123    @ivar method: Type attribute of the IQ request. Either C{'set'} or C{'get'}
     124    @type method: C{str}
     125    """
     126
     127    def __init__(self, xs, method='get', fields=[]):
     128        xmlstream.IQ.__init__(self, xs, method)
     129        q = self.addElement((NS_OWNER, 'query'))
     130        if method == 'set':
     131            # build data form
     132            form = data_form.Form('submit', formNamespace=NS_CONFIG)
     133            q.addChild(form.toElement())
     134           
     135            for f in fields:
     136                # create a field
     137                form.addField(f)
     138
     139
     140class GroupChat(domish.Element):
     141    """
     142    """
     143    def __init__(self, to, body=None, subject=None, frm=None):
     144        """To needs to be a string
     145        """
     146        domish.Element.__init__(self, (None, 'message'))
     147        self['type'] = 'groupchat'
     148        self['to']   = to
     149        if frm:
     150            self['from'] = frm
     151        if body:
     152            self.addElement('body',None, body)
     153        if subject:
     154            self.addElement('subject',None, subject)
     155           
     156
     157
    97158class Room(object):
    98159    """
     
    108169        self.server = server
    109170        self.nick   = nick
    110        
     171        self.status = None
     172
    111173        self.entity_id = jid.internJID(name+'@'+server+'/'+nick)
    112174               
     
    146208
    147209
     210class PasswordPresence(BasicPresence):
     211    """
     212    """
     213    def __init__(self, to, password):
     214        BasicPresence.__init__(self, to)
     215       
     216        self.x.addElement('password', None, password)
     217
     218
     219class MessageVoice(GroupChat):
     220    """
     221    """
     222    def __init__(self, to=None, frm=None):
     223        GroupChat.__init__(self, to=to, frm=frm)
     224        # build data form
     225        form = data_form.Form('submit', formNamespace=NS_REQUEST)
     226        form.addField(data_form.Field(var='muc#role',
     227                                      value='participant',
     228                                      label='Requested role'))
     229        self.addChild(form.toElement())           
     230
    148231class PresenceError(BasicPresence):
    149232    """
     
    169252    implements(IMUCClient)
    170253
     254    rooms = {}
    171255
    172256    def connectionInitialized(self):
    173         self.rooms = {}
    174        
     257        self.xmlstream.addObserver(PRESENCE+"/x", self._onXPresence)
     258        self.xmlstream.addObserver(GROUPCHAT, self._onGroupChat)
     259        self.xmlstream.addObserver(SUBJECT, self._onSubject)
     260        # add history
    175261
    176262    def _setRoom(self, room):
     
    180266        return self.rooms.get(room_jid.full().lower())
    181267
     268
     269    def _onXPresence(self, prs):
     270        """
     271        """
     272        if prs.x.uri == NS_USER:
     273            self.receivedUserPresence(prs)
     274           
     275
     276    def _onGroupChat(self, msg):
     277        """
     278        """
     279        self.receivedGroupChat(msg)
     280
     281
     282
     283    def _onSubject(self, msg):
     284        """
     285        """
     286        self.receivedSubject(msg)
     287
     288
     289    def _makeTimeStamp(self, stamp=None):
     290        if stamp is None:
     291            stamp = datetime.datetime.now()
     292           
     293        return stamp.strftime('%Y%m%dT%H:%M:%S')
    182294
    183295
     
    193305            # change the state of the room
    194306            r = self._getRoom(room_jid)
     307            if r is None:
     308                raise
    195309            r.state = 'joined'
     310           
     311            # grab status
     312            status = getattr(prs.x,'status',None)
     313            if status:
     314                r.status = status.getAttribute('code', None)
     315
    196316            d.callback(r)
    197317
    198     def userPresence(self, prs):
     318    def receivedUserPresence(self, prs):
    199319        """User Presence has been received
    200320        """
    201321        pass
    202322       
     323
     324    def receivedSubject(self, msg):
     325        """
     326        """
     327        pass
    203328
    204329    def _cbDisco(self, iq):
    205330        # grab query
    206331       
    207         return iq.query
     332        return getattr(iq,'query', None)
    208333       
    209334    def disco(self, entity, type='info'):
     
    214339        iq['to'] = entity
    215340
    216         return iq.send().addCallback(self._cbDisco)
    217        
     341        return iq.send().addBoth(self._cbDisco)
     342       
     343
     344    def configure(self, room_jid, **kwargs):
     345        """Configure a room
     346        """
     347        request = ConfigureRequest(self.xmlstream, method='set', **kwargs)
     348        request['to'] = room_jid
     349       
     350        return request.send()
     351
     352    def getConfigureForm(self, room_jid):
     353        request = ConfigureRequest(self.xmlstream)
     354        request['to'] = room_jid
     355        return request.send()
     356
    218357
    219358    def join(self, server, room, nick):
     
    235374   
    236375
     376    def groupChat(self, to, message, children=None):
     377        """Send a groupchat message
     378        """
     379        msg = GroupChat(to, body=message)
     380
     381        if children:
     382            for c in children:
     383                msg.addChild(c)
     384       
     385        self.xmlstream.send(msg)
     386
     387   
     388    def subject(self, to, subject):
     389        """
     390        """
     391        msg = GroupChat(to, subject=subject)
     392        self.xmlstream.send(msg)
     393
     394    def voice(self, to):
     395        """
     396        """
     397        msg = MessageVoice(to=to)
     398        self.xmlstream.send(msg)
     399
     400
     401    def history(self, to, message_list):
     402        """
     403        """
     404       
     405        for m in message_list:
     406            m['type'] = 'groupchat'
     407            mto = m['to']
     408            frm = m.getAttribute('from', None)
     409            m['to'] = to
     410
     411            d = m.addElement('delay', NS_DELAY)
     412            d['stamp'] = self._makeTimeStamp()
     413            d['from'] = mto
     414
     415            self.xmlstream.send(m)
     416
  • wokkel/test/test_muc.py

    r109 r110  
    4949        self.protocol.xmlstream = self.stub.xmlstream
    5050        self.protocol.connectionInitialized()
    51 
     51        self.test_room = 'test'
     52        self.test_srv  = 'conference.example.org'
     53        self.test_nick = 'Nick'
     54
     55        self.room_jid = JID(self.test_room+'@'+self.test_srv+'/'+self.test_nick)
    5256
    5357    def test_interface(self):
     
    120124        """Test joining a room
    121125        """
    122         test_room = 'test'
    123         test_srv  = 'conference.example.org'
    124         test_nick = 'Nick'
     126       
    125127
    126128        def cb(room):
    127             self.assertEquals(test_room, room.name)
    128 
    129         d = self.protocol.join(test_srv, test_room, test_nick)
     129            self.assertEquals(self.test_room, room.name)
     130
     131        d = self.protocol.join(self.test_srv, self.test_room, self.test_nick)
    130132        d.addCallback(cb)
    131133
     
    135137
    136138        # send back user presence, they joined       
    137         response = muc.UserPresence(frm=test_room+'@'+test_srv+'/'+test_nick)
     139        response = muc.UserPresence(frm=self.test_room+'@'+self.test_srv+'/'+self.test_nick)
    138140        self.stub.send(response)
    139141        return d
     
    143145        """Test joining a room and getting an error
    144146        """
    145         test_room = 'test'
    146         test_srv  = 'conference.example.org'
    147         test_nick = 'Nick'
    148147
    149148        def cb(error):
     
    152151           
    153152           
    154         d = self.protocol.join(test_srv, test_room, test_nick)
     153        d = self.protocol.join(self.test_srv, self.test_room, self.test_nick)
    155154        d.addBoth(cb)
    156155
     
    163162                                                        'forbidden'
    164163                                                        ),
    165                                      frm=test_room+'@'+test_srv+'/'+test_nick)
     164                                     frm=self.room_jid.full())
    166165        self.stub.send(response)
    167166        return d       
    168167
     168    def test_partRoom(self):
     169        self.fail('Not Implemented')
     170       
     171
     172    def test_ban(self):
     173       
     174        self.fail('Not Implemented')
     175
     176    def test_kick(self):
     177        self.fail('Not Implemented')
     178       
     179
     180    def test_password(self):
     181        """Test sending a password via presence to a password protected room.
     182        """
     183       
     184       
     185        self.fail('Not Implemented')
     186
     187    def test_history(self):
     188       
     189        self.fail('Not Implemented')
     190
     191
     192    def test_oneToOneChat(self):
     193        """Test converting a one to one chat
     194        """
     195        archive = []
     196        thread = "e0ffe42b28561960c6b12b944a092794b9683a38"
     197        # create messages
     198        msg = domish.Element((None, 'message'))
     199        msg['to'] = 'testing@example.com'
     200        msg['type'] = 'chat'
     201        msg.addElement('body', None, 'test')
     202        msg.addElement('thread', None, thread)
     203
     204        archive.append(msg)
     205
     206        msg = domish.Element((None, 'message'))
     207        msg['to'] = 'testing2@example.com'
     208        msg['type'] = 'chat'
     209        msg.addElement('body', None, 'yo')
     210        msg.addElement('thread', None, thread)
     211
     212        archive.append(msg)
     213
     214        self.protocol.history(self.room_jid.userhost(), archive)
     215
     216
     217        while len(self.stub.output)>0:
     218            m = self.stub.output.pop()
     219            # check for delay element
     220            self.failUnless(m.name=='message', 'Wrong stanza')
     221            self.failUnless(xpath.matches("/message/delay", m), 'Invalid history stanza')
     222       
     223
     224    def test_invite(self):
     225        self.fail('Not Implemented')
     226
     227       
     228    def test_privateMessage(self):
     229        self.fail('Not Implemented')
     230
     231    def test_register(self):
     232        self.fail('Not Implemented')
     233
     234    def test_voice(self):
     235       
     236        self.protocol.voice(self.room_jid.userhost())
     237
     238        m = self.stub.output[-1]
     239        self.failUnless(m.name=='message', "Need to be message stanza")
     240        self.failUnless(getattr(m, 'x', None), 'No muc x element')
     241
     242        self.failUnless(xpath.matches("/message/x[@type='submit']/field/value[text()='%s']" % (muc.NS_REQUEST,), m), 'Invalid voice message stanza')
     243
     244
    169245    def test_roomConfigure(self):
    170246
    171         test_room = 'test'
    172         test_srv  = 'conference.example.org'
    173         test_nick = 'Nick'       
    174 
    175         self.fail('Not Implemented')
    176        
    177 
     247        self.fail('Not Implemented')
     248       
     249
Note: See TracChangeset for help on using the changeset viewer.