Changeset 56

Show
Ignore:
Timestamp:
02/14/04 20:19:13 (5 years ago)
Author:
jajcus
Message:

- IRCUser.descr() - "nick(user@host)"
- improved request handling
- more IRC error responses handled
- basic kicking (no <iq type="response"/> yet)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/jjigw.py

    r54 r56  
    1818import pyxmpp.jabberd 
    1919from pyxmpp.jabber.muc import MucPresence,MucX,MucUserX,MucItem,MUC_NS,MucStatus 
     20from pyxmpp.jabber.muc import MucIq,MucAdminQuery,MUC_ADMIN_NS 
    2021 
    2122class JJIGWFatalError(RuntimeError): 
     
    187188        self.current_thread=None 
    188189 
    189     def sync_in_channel(self,channel): 
     190    def descr(self): 
     191        if self.user and self.host: 
     192            return "%s(%s@%s)" % (self.nick,self.user,self.host) 
     193        else: 
     194            return self.nick 
     195 
     196    def sync_in_channel(self,channel,status=None): 
    190197        if self.sync_delay>0: 
    191198            return 
    192199        elif self.sync_delay<0: 
    193200            self.debug("Warning: %r.sync_delay<0" % (self,)) 
    194         return channel.sync_user(self
     201        return channel.sync_user(self,status=status
    195202 
    196203    def join_channel(self,channel): 
     
    198205        self.sync_in_channel(channel) 
    199206 
    200     def leave_channel(self,channel): 
     207    def leave_channel(self,channel,status=None): 
    201208        try: 
    202209            del self.channels[normalize(channel.name)] 
    203             self.sync_in_channel(channel
     210            self.sync_in_channel(channel,status=status
    204211        except KeyError: 
    205212            pass 
     
    282289        self.users=[] 
    283290        self.muc=0 
    284         self.requests={} 
    285  
    286     def sync_user(self,user): 
     291        self.requests=[] 
     292 
     293    def get_request(self,commands): 
     294        for command,stanza in self.requests: 
     295            if command in commands: 
     296                try: 
     297                    self.requests.remove((command,stanza)) 
     298                except ValueError: 
     299                    pass 
     300                return command,stanza 
     301        return None,None 
     302 
     303    def add_request(self,command,stanza): 
     304        self.requests.append((command,stanza.copy())) 
     305        if len(self.requests)>10: 
     306            self.requests=self.requests[-10:] 
     307 
     308    def sync_user(self,user,status=None): 
    287309        if user.channels.has_key(normalize(self.name)): 
    288310            if user not in self.users: 
     
    298320                        % (unicode(user.nick,self.encoding,"replace"),)) 
    299321        if self.state: 
    300             p=self.get_user_presence(user
     322            p=self.get_user_presence(user,status=status
    301323            self.session.component.send(p) 
    302324 
     
    316338        self.debug("Joining channel %r" % (self.name,)) 
    317339        self.session.send("JOIN %s" % (self.name,)) 
    318         self.requests["JOIN"]=stanza.copy(
     340        self.add_request("JOIN",stanza
    319341        self.state="join" 
    320342        if stanza.get_join_info(): 
     
    422444         
    423445    def irc_cmd_482(self,prefix,command,params): # ERR_CHANOPRIVSNEEDED 
    424         stanza=self.requests.get("TOPIC") 
    425         if stanza: 
    426             m=stanza.make_error_response("forbidden") 
    427             try: 
    428                 del self.requests["TOPIC"] 
    429             except KeyError: 
    430                 pass 
     446        self.irc_error_response(prefix,command,params,["TOPIC","KICK"],"forbidden") 
     447 
     448    def irc_cmd_461(self,prefix,command,params): # ERR_NEEDMOREPARAMS 
     449        self.irc_error_response(prefix,command,params,["TOPIC","KICK"],"bad-request") 
     450 
     451    def irc_cmd_403(self,prefix,command,params): # ERR_NOSUCHCHANNEL 
     452        self.irc_error_response(prefix,command,params,["KICK"],"recipient-unavailable") 
     453     
     454    def irc_cmd_476(self,prefix,command,params): # ERR_BADCHANMASK 
     455        self.irc_error_response(prefix,command,params,["KICK"],"bad-request") 
     456     
     457    def irc_cmd_441(self,prefix,command,params): # ERR_USERNOTINCHANNEL 
     458        self.irc_error_response(prefix,command,params,["KICK"],"item-not-found") 
     459         
     460    def irc_cmd_442(self,prefix,command,params): # ERR_NOTONCHANNEL 
     461        self.irc_error_response(prefix,command,params,["TOPIC","KICK"],"forbidden") 
     462 
     463    def irc_cmd_477(self,prefix,command,params): # ERR_NOCHANMODES 
     464        self.irc_error_response(prefix,command,params,["TOPIC"],"not-acceptable") 
     465 
     466    def irc_error_response(self,prefix,command,params,requests,condition): 
     467        command,stanza=self.get_request(requests) 
     468        if command: 
     469            m=stanza.make_error_response(condition) 
    431470        else: 
    432471            m=Message(fr=self.room_jid.bare(),to=self.session.jid, 
    433                     type="error", error_cond="forbidden"
     472                    type="error", error_cond=condition
    434473        self.session.component.send(m) 
    435474 
     475    def irc_cmd_331(self,prefix,command,params): # RPL_NOTOPIC 
     476        m=Message(fr=self.room_jid.bare(),to=self.session.jid, type="groupchat", subject=u"") 
     477        self.session.component.send(m) 
     478         
    436479    def irc_cmd_332(self,prefix,command,params): # RPL_TOPIC 
    437480        topic=remove_evil_characters(params[1]) 
     
    439482                type="groupchat", subject=unicode(topic,self.encoding,"replace")) 
    440483        self.session.component.send(m) 
    441          
     484 
    442485    def irc_cmd_TOPIC(self,prefix,command,params): 
    443         if self.session.check_prefix(prefix): 
    444             try: 
    445                 del self.requests["TOPIC"] 
    446             except KeyError: 
    447                 pass 
     486        self.get_request(("TOPIC",)) 
    448487        topic=remove_evil_characters(params[1]) 
    449488        m=Message(fr=self.prefix_to_jid(prefix),to=self.session.jid, 
     
    458497        if params_str: 
    459498            params_str=" "+params_str 
    460         self.send_notice_message(u"Mode chage: [%s%s] by %s"  
     499        if "!" in prefix: 
     500            nick,iuser=prefix.split("!",1) 
     501            iuser="(%s)" % (user,) 
     502        else: 
     503            nick,iuser=prefix,"" 
     504        self.send_notice_message(u"Mode chage: [%s%s] by %s%s"  
    461505                % (unicode(params[1],self.encoding,"replace"), 
    462506                        unicode(params_str,self.encoding,"replace"), 
    463                         unicode(prefix,self.encoding,"replace")), 
     507                        unicode(nick,self.encoding,"replace"), 
     508                        unicode(iuser,self.encoding,"replace")), 
    464509                0) 
    465510        self.irc_mode_changed(prefix,command,params) 
     
    535580                    self.session.user.sync_delay-=1 
    536581                self.state="joined" 
    537                 try: 
    538                     del self.requests["JOIN"] 
    539                 except KeyError: 
    540                     pass 
     582                self.get_request(("JOIN",)) 
    541583                self.session.send("MODE %s" % (self.name,)) 
    542584                self.session.send("WHO %s" % (self.name,)) 
     
    557599        self.send_notice_message(u"%s has left"  
    558600                % (unicode(user.nick,self.encoding,"replace"),)) 
     601 
     602    def irc_cmd_KICK(self,prefix,command,params): 
     603        actor=self.session.get_user(prefix) 
     604        user=self.session.get_user(params[1]) 
     605        try: 
     606            self.users.remove(user) 
     607        except ValueError: 
     608            pass 
     609        self.send_notice_message(u"%s was kicked by %s"  
     610                % (unicode(user.descr(),self.encoding,"replace"), 
     611                    unicode(actor.descr(),self.encoding,"replace")), 
     612                0) 
     613        user.leave_channel(self,status=307) 
    559614 
    560615    def irc_cmd_PRIVMSG(self,prefix,command,params): 
     
    587642        topic=topic.replace("\n"," ").replace("\r"," ") 
    588643        self.session.send("TOPIC %s :%s" % (self.name,topic)) 
    589         self.requests["TOPIC"]=stanza 
     644        self.add_request("TOPIC",stanza) 
     645 
     646    def kick_user(self,nick,reason,stanza): 
     647        self.session.send("KICK %s %s :%s" % (self.name,nick,reason)) 
     648        self.add_request("KICK",stanza) 
    590649    
    591650    def __repr__(self): 
     
    10561115        self.channels[normalize(channel.name)]=channel 
    10571116 
     1117    def get_channel(self,jid): 
     1118        channel_name=jid.node 
     1119        channel_name=node_to_channel(channel_name,self.default_encoding) 
     1120        if not channel_re.match(channel_name): 
     1121            self.debug("Bad channel name: %r" % (channel_name,)) 
     1122            return None 
     1123        return self.channels.get(normalize(channel_name)) 
     1124 
    10581125    def message_to_channel(self,stanza): 
    10591126        self.debug("message_to_channel(%r)" % (stanza,)) 
     
    10651132        finally: 
    10661133            self.cond.release() 
    1067         self.debug("message_to_channel: no need to wait") 
    1068         channel_name=stanza.get_to().node 
    1069         self.debug("channel_name: %r" % (channel_name,)) 
    1070         channel_name=node_to_channel(channel_name,self.default_encoding) 
    1071         self.debug("channel_name: %r" % (channel_name,)) 
    1072         if not channel_re.match(channel_name): 
    1073             self.debug("Bad channel name: %r" % (channel_name,)) 
    1074             return 
    1075         channel=self.channels.get(normalize(channel_name)) 
     1134        channel=self.get_channel(stanza.get_to()) 
     1135        if not channel: 
     1136            e=stanza.make_error_response("bad-request") 
     1137            self.component.send(e) 
     1138            return 
    10761139        self.debug("channel: %r" % (channel,)) 
    10771140        if channel: 
     
    10921155            if body.startswith("/me "): 
    10931156                body="\001ACTION "+body[4:]+"\001" 
    1094             self.send("PRIVMSG %s :%s" % (channel_name,body)) 
    1095             if channel: 
    1096                 channel.irc_cmd_PRIVMSG(self.nick,"PRIVMSG",[channel_name,body]) 
     1157            self.send("PRIVMSG %s :%s" % (channel.name,body)) 
     1158            channel.irc_cmd_PRIVMSG(self.nick,"PRIVMSG",[channel.name,body]) 
    10971159        self.debug("message_to_channel: done") 
    10981160 
     
    12631325        self.stream.set_iq_get_handler("query","jabber:iq:register",self.get_register) 
    12641326        self.stream.set_iq_set_handler("query","jabber:iq:register",self.set_register) 
     1327        self.stream.set_iq_set_handler("query",MUC_ADMIN_NS,self.set_muc_admin) 
    12651328        self.disco_info.add_feature("jabber:iq:version") 
    12661329        self.disco_info.add_feature("jabber:iq:register") 
     
    12721335        self.stream.set_message_handler("normal",self.message) 
    12731336 
     1337    def set_muc_admin(self,iq): 
     1338        to=iq.get_to() 
     1339        fr=iq.get_from() 
     1340        if not to.node: 
     1341            self.debug("admin request sent to JID without a node") 
     1342            iq=iq.make_error_response("feature-not-implemented") 
     1343            self.stream.send(iq) 
     1344            return 1 
     1345        if to.resource or not (to.node[0] in "#+!" or to.node.startswith(",amp,")): 
     1346            self.debug("admin request sent not to a channel") 
     1347            iq=iq.make_error_response("not-acceptable") 
     1348            self.stream.send(iq) 
     1349            return 1 
     1350             
     1351        iq=MucIq(iq) 
     1352        sess=self.irc_sessions.get(fr.as_unicode()) 
     1353        if not sess: 
     1354            self.debug("User session not found") 
     1355            iq=iq.make_error_response("recipient-unavailable") 
     1356            self.stream.send(iq) 
     1357            return 1 
     1358 
     1359        channel=sess.get_channel(to) 
     1360        if not channel: 
     1361            self.debug("Channel not found") 
     1362            iq=iq.make_error_response("recipient-unavailable") 
     1363            self.stream.send(iq) 
     1364            return 1 
     1365 
     1366        query=iq.get_muc_child() 
     1367        if not isinstance(query,MucAdminQuery): 
     1368            self.debug("Bad query content") 
     1369            iq=iq.make_error_response("bad-request") 
     1370            self.stream.send(iq) 
     1371            return 1 
     1372 
     1373        items=query.get_items() 
     1374        if not items: 
     1375            self.debug("No items in query") 
     1376            iq=iq.make_error_response("bad-request") 
     1377            self.stream.send(iq) 
     1378            return 1 
     1379        item=items[0]  
     1380        if item.role=="none": 
     1381            channel.kick_user(item.nick,item.reason,iq) 
     1382        else: 
     1383            self.debug("Unknown admin action") 
     1384            iq=iq.make_error_response("feature-not-implemented") 
     1385            self.stream.send(iq) 
     1386            return 1 
     1387  
    12741388    def get_version(self,iq): 
    12751389        iq=iq.make_result_response()