mirror of
				https://github.com/jlu5/PyLink.git
				synced 2025-11-04 08:57:25 +01:00 
			
		
		
		
	Merge ts6 and p10 handle_events, handle_privmsg into ircs2s_common
This commit is contained in:
		
							parent
							
								
									76ecc60675
								
							
						
					
					
						commit
						69cf21c04e
					
				@ -6,14 +6,103 @@ import time
 | 
			
		||||
 | 
			
		||||
from pylinkirc.classes import Protocol
 | 
			
		||||
from pylinkirc.log import log
 | 
			
		||||
from pylinkirc import utils
 | 
			
		||||
 | 
			
		||||
class IRCS2SProtocol(Protocol):
 | 
			
		||||
    COMMAND_TOKENS = {}
 | 
			
		||||
 | 
			
		||||
    def __init__(self, irc):
 | 
			
		||||
        super().__init__(irc)
 | 
			
		||||
        self.protocol_caps = {'can-spawn-clients', 'has-ts', 'can-host-relay',
 | 
			
		||||
                              'can-track-servers'}
 | 
			
		||||
 | 
			
		||||
    def handle_events(self, data):
 | 
			
		||||
        """Event handler for RFC1459-like protocols.
 | 
			
		||||
 | 
			
		||||
        This passes most commands to the various handle_ABCD() functions
 | 
			
		||||
        elsewhere defined protocol modules, coersing various sender prefixes
 | 
			
		||||
        from nicks and server names to UIDs and SIDs respectively,
 | 
			
		||||
        whenever possible.
 | 
			
		||||
 | 
			
		||||
        Commands sent without an explicit sender prefix will have them set to
 | 
			
		||||
        the SID of the uplink server.
 | 
			
		||||
        """
 | 
			
		||||
        data = data.split(" ")
 | 
			
		||||
        args = self.parseArgs(data)
 | 
			
		||||
 | 
			
		||||
        sender = args[0]
 | 
			
		||||
        sender = sender.lstrip(':')
 | 
			
		||||
 | 
			
		||||
        # If the sender isn't in numeric format, try to convert it automatically.
 | 
			
		||||
        sender_sid = self._getSid(sender)
 | 
			
		||||
        sender_uid = self._getUid(sender)
 | 
			
		||||
 | 
			
		||||
        if sender_sid in self.irc.servers:
 | 
			
		||||
            # Sender is a server (converting from name to SID gave a valid result).
 | 
			
		||||
            sender = sender_sid
 | 
			
		||||
        elif sender_uid in self.irc.users:
 | 
			
		||||
            # Sender is a user (converting from name to UID gave a valid result).
 | 
			
		||||
            sender = sender_uid
 | 
			
		||||
        else:
 | 
			
		||||
            # No sender prefix; treat as coming from uplink IRCd.
 | 
			
		||||
            sender = self.irc.uplink
 | 
			
		||||
            args.insert(0, sender)
 | 
			
		||||
 | 
			
		||||
        if self.irc.isInternalClient(sender) or self.irc.isInternalServer(sender):
 | 
			
		||||
            log.warning("(%s) Received command %s being routed the wrong way!", self.irc.name, command)
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        raw_command = args[1].upper()
 | 
			
		||||
        args = args[2:]
 | 
			
		||||
 | 
			
		||||
        log.debug('(%s) Found message sender as %s', self.irc.name, sender)
 | 
			
		||||
 | 
			
		||||
        # For P10, convert the command token into a regular command, if present.
 | 
			
		||||
        command = self.COMMAND_TOKENS.get(raw_command, raw_command)
 | 
			
		||||
        if command != raw_command:
 | 
			
		||||
            log.debug('(%s) Translating token %s to command %s', self.irc.name, raw_command, command)
 | 
			
		||||
 | 
			
		||||
        if command == 'ENCAP':
 | 
			
		||||
            # Special case for TS6 encapsulated commands (ENCAP), in forms like this:
 | 
			
		||||
            # <- :00A ENCAP * SU 42XAAAAAC :GLolol
 | 
			
		||||
            command = args[1]
 | 
			
		||||
            args = args[2:]
 | 
			
		||||
            log.debug("(%s) Rewriting incoming ENCAP to command %s (args: %s)", self.irc.name, command, args)
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            func = getattr(self, 'handle_'+command.lower())
 | 
			
		||||
        except AttributeError:  # Unhandled command
 | 
			
		||||
            pass
 | 
			
		||||
        else:
 | 
			
		||||
            parsed_args = func(sender, command, args)
 | 
			
		||||
            if parsed_args is not None:
 | 
			
		||||
                return [sender, command, parsed_args]
 | 
			
		||||
 | 
			
		||||
    def handle_privmsg(self, source, command, args):
 | 
			
		||||
        """Handles incoming PRIVMSG/NOTICE."""
 | 
			
		||||
        # TS6:
 | 
			
		||||
        # <- :70MAAAAAA PRIVMSG #dev :afasfsa
 | 
			
		||||
        # <- :70MAAAAAA NOTICE 0ALAAAAAA :afasfsa
 | 
			
		||||
        # P10:
 | 
			
		||||
        # <- ABAAA P AyAAA :privmsg text
 | 
			
		||||
        # <- ABAAA O AyAAA :notice text
 | 
			
		||||
        target = args[0]
 | 
			
		||||
 | 
			
		||||
        # Coerse =#channel from Charybdis op moderated +z to @#channel.
 | 
			
		||||
        if target.startswith('='):
 | 
			
		||||
            target = '@' + target[1:]
 | 
			
		||||
 | 
			
		||||
        # We use lowercase channels internally, but uppercase UIDs.
 | 
			
		||||
        # Strip the target of leading prefix modes (for targets like @#channel)
 | 
			
		||||
        # before checking whether it's actually a channel.
 | 
			
		||||
        stripped_target = target.lstrip(''.join(self.irc.prefixmodes.values()))
 | 
			
		||||
        if utils.isChannel(stripped_target):
 | 
			
		||||
            target = self.irc.toLower(target)
 | 
			
		||||
 | 
			
		||||
        return {'target': target, 'text': args[1]}
 | 
			
		||||
 | 
			
		||||
    handle_notice = handle_privmsg
 | 
			
		||||
 | 
			
		||||
    def check_nick_collision(self, nick):
 | 
			
		||||
        """
 | 
			
		||||
        Nick collision checker.
 | 
			
		||||
 | 
			
		||||
@ -824,63 +824,6 @@ class P10Protocol(IRCS2SProtocol):
 | 
			
		||||
        self._send(sid, "EB")
 | 
			
		||||
        self.irc.connected.set()
 | 
			
		||||
 | 
			
		||||
    def handle_events(self, data):
 | 
			
		||||
        """
 | 
			
		||||
        Event handler for the P10 protocol.
 | 
			
		||||
 | 
			
		||||
        This passes most commands to the various handle_ABCD() functions defined elsewhere in the
 | 
			
		||||
        protocol modules, coersing various sender prefixes from nicks and server names to P10
 | 
			
		||||
        "numeric nicks", whenever possible.
 | 
			
		||||
 | 
			
		||||
        Commands sent without an explicit sender prefix are treated as originating from the uplink
 | 
			
		||||
        server.
 | 
			
		||||
        """
 | 
			
		||||
        data = data.split(" ")
 | 
			
		||||
        args = self.parseArgs(data)
 | 
			
		||||
 | 
			
		||||
        sender = args[0]
 | 
			
		||||
        if sender.startswith(':'):
 | 
			
		||||
            # From https://github.com/evilnet/nefarious2/blob/a29b63144/doc/p10.txt#L140:
 | 
			
		||||
            # if source begins with a colon, it (except for the colon) is the name. otherwise, it is
 | 
			
		||||
            # a numeric. a P10 implementation must only send lines with a numeric source prefix.
 | 
			
		||||
            sender = sender[1:]
 | 
			
		||||
 | 
			
		||||
        # If the sender isn't in numeric format, try to convert it automatically.
 | 
			
		||||
        sender_sid = self._getSid(sender)
 | 
			
		||||
        sender_uid = self._getUid(sender)
 | 
			
		||||
        if sender_sid in self.irc.servers:
 | 
			
		||||
            # Sender is a server (converting from name to SID gave a valid result).
 | 
			
		||||
            sender = sender_sid
 | 
			
		||||
        elif sender_uid in self.irc.users:
 | 
			
		||||
            # Sender is a user (converting from name to UID gave a valid result).
 | 
			
		||||
            sender = sender_uid
 | 
			
		||||
        else:
 | 
			
		||||
            # No sender prefix; treat as coming from uplink IRCd.
 | 
			
		||||
            sender = self.irc.uplink
 | 
			
		||||
            args.insert(0, sender)
 | 
			
		||||
 | 
			
		||||
        command_token = args[1].upper()
 | 
			
		||||
        args = args[2:]
 | 
			
		||||
 | 
			
		||||
        log.debug('(%s) Found message sender as %s', self.irc.name, sender)
 | 
			
		||||
        # Convert the token given into a regular command, if present.
 | 
			
		||||
        command = self.COMMAND_TOKENS.get(command_token, command_token)
 | 
			
		||||
        log.debug('(%s) Translating token %s to command %s', self.irc.name, command_token, command)
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            func = getattr(self, 'handle_'+command.lower())
 | 
			
		||||
        except AttributeError:  # Unhandled command, ignore
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        else:  # Send a hook with the hook arguments given by the handler function.
 | 
			
		||||
            if self.irc.isInternalClient(sender) or self.irc.isInternalServer(sender):
 | 
			
		||||
                log.warning("(%s) Received command %s being routed the wrong way!", self.irc.name, command)
 | 
			
		||||
                return
 | 
			
		||||
 | 
			
		||||
            parsed_args = func(sender, command, args)
 | 
			
		||||
            if parsed_args is not None:
 | 
			
		||||
                return [sender, command, parsed_args]
 | 
			
		||||
 | 
			
		||||
    def handle_server(self, source, command, args):
 | 
			
		||||
        """Handles incoming server introductions."""
 | 
			
		||||
        # <- SERVER nefarious.midnight.vpn 1 1460673022 1460673239 J10 ABP]] +h6 :Nefarious2 test server
 | 
			
		||||
@ -1168,22 +1111,6 @@ class P10Protocol(IRCS2SProtocol):
 | 
			
		||||
                self.irc.channels[channel].modes, 'ts': ts or int(time.time())}
 | 
			
		||||
 | 
			
		||||
    handle_create = handle_join
 | 
			
		||||
 | 
			
		||||
    def handle_privmsg(self, source, command, args):
 | 
			
		||||
        """Handles incoming PRIVMSG/NOTICE."""
 | 
			
		||||
        # <- ABAAA P AyAAA :privmsg text
 | 
			
		||||
        # <- ABAAA O AyAAA :notice text
 | 
			
		||||
        target = args[0]
 | 
			
		||||
 | 
			
		||||
        # We use lower case channels internally, but mixed case UIDs.
 | 
			
		||||
        stripped_target = target.lstrip(''.join(self.irc.prefixmodes.values()))
 | 
			
		||||
        if utils.isChannel(stripped_target):
 | 
			
		||||
            target = self.irc.toLower(target)
 | 
			
		||||
 | 
			
		||||
        return {'target': target, 'text': args[1]}
 | 
			
		||||
 | 
			
		||||
    handle_notice = handle_privmsg
 | 
			
		||||
 | 
			
		||||
    def handle_end_of_burst(self, source, command, args):
 | 
			
		||||
        """Handles end of burst from our uplink."""
 | 
			
		||||
        # Send EOB acknowledgement; this is required by the P10 specification,
 | 
			
		||||
 | 
			
		||||
@ -294,83 +294,6 @@ class TS6BaseProtocol(IRCS2SProtocol):
 | 
			
		||||
        self.irc.users[source].away = text
 | 
			
		||||
 | 
			
		||||
    ### HANDLERS
 | 
			
		||||
 | 
			
		||||
    def handle_events(self, data):
 | 
			
		||||
        """Event handler for TS6 protocols.
 | 
			
		||||
 | 
			
		||||
        This passes most commands to the various handle_ABCD() functions
 | 
			
		||||
        elsewhere defined protocol modules, coersing various sender prefixes
 | 
			
		||||
        from nicks and server names to UIDs and SIDs respectively,
 | 
			
		||||
        whenever possible.
 | 
			
		||||
 | 
			
		||||
        Commands sent without an explicit sender prefix will have them set to
 | 
			
		||||
        the SID of the uplink server.
 | 
			
		||||
        """
 | 
			
		||||
        data = data.split(" ")
 | 
			
		||||
        try:  # Message starts with a SID/UID prefix.
 | 
			
		||||
            args = self.parsePrefixedArgs(data)
 | 
			
		||||
            sender = args[0]
 | 
			
		||||
            command = args[1]
 | 
			
		||||
            args = args[2:]
 | 
			
		||||
            # If the sender isn't in UID format, try to convert it automatically.
 | 
			
		||||
            # Unreal's protocol, for example, isn't quite consistent with this yet!
 | 
			
		||||
            sender_server = self._getSid(sender)
 | 
			
		||||
            if sender_server in self.irc.servers:
 | 
			
		||||
                # Sender is a server when converted from name to SID.
 | 
			
		||||
                numeric = sender_server
 | 
			
		||||
            else:
 | 
			
		||||
                # Sender is a user.
 | 
			
		||||
                numeric = self._getUid(sender)
 | 
			
		||||
 | 
			
		||||
        # parsePrefixedArgs() will raise IndexError if the TS6 sender prefix is missing.
 | 
			
		||||
        except IndexError:
 | 
			
		||||
            # Raw command without an explicit sender; assume it's being sent by our uplink.
 | 
			
		||||
            args = self.parseArgs(data)
 | 
			
		||||
            numeric = self.irc.uplink
 | 
			
		||||
            command = args[0]
 | 
			
		||||
            args = args[1:]
 | 
			
		||||
 | 
			
		||||
        if self.irc.isInternalClient(numeric) or self.irc.isInternalServer(numeric):
 | 
			
		||||
            log.warning("(%s) Received command %s being routed the wrong way!", self.irc.name, command)
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if command == 'ENCAP':
 | 
			
		||||
            # Special case for encapsulated commands (ENCAP), in forms like this:
 | 
			
		||||
            # <- :00A ENCAP * SU 42XAAAAAC :GLolol
 | 
			
		||||
            command = args[1]
 | 
			
		||||
            args = args[2:]
 | 
			
		||||
            log.debug("(%s) Rewriting incoming ENCAP to command %s (args: %s)", self.irc.name, command, args)
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            func = getattr(self, 'handle_'+command.lower())
 | 
			
		||||
        except AttributeError:  # unhandled command
 | 
			
		||||
            pass
 | 
			
		||||
        else:
 | 
			
		||||
            parsed_args = func(numeric, command, args)
 | 
			
		||||
            if parsed_args is not None:
 | 
			
		||||
                return [numeric, command, parsed_args]
 | 
			
		||||
 | 
			
		||||
    def handle_privmsg(self, source, command, args):
 | 
			
		||||
        """Handles incoming PRIVMSG/NOTICE."""
 | 
			
		||||
        # <- :70MAAAAAA PRIVMSG #dev :afasfsa
 | 
			
		||||
        # <- :70MAAAAAA NOTICE 0ALAAAAAA :afasfsa
 | 
			
		||||
        target = args[0]
 | 
			
		||||
 | 
			
		||||
        # Coerse =#channel from Charybdis op moderated +z to @#channel.
 | 
			
		||||
        if target.startswith('='):
 | 
			
		||||
            target = '@' + target[1:]
 | 
			
		||||
 | 
			
		||||
        # We use lowercase channels internally, but uppercase UIDs.
 | 
			
		||||
        # Strip the target of leading prefix modes (for targets like @#channel)
 | 
			
		||||
        # before checking whether it's actually a channel.
 | 
			
		||||
        stripped_target = target.lstrip(''.join(self.irc.prefixmodes.values()))
 | 
			
		||||
        if utils.isChannel(stripped_target):
 | 
			
		||||
            target = self.irc.toLower(target)
 | 
			
		||||
 | 
			
		||||
        return {'target': target, 'text': args[1]}
 | 
			
		||||
 | 
			
		||||
    handle_notice = handle_privmsg
 | 
			
		||||
 | 
			
		||||
    def handle_kick(self, source, command, args):
 | 
			
		||||
        """Handles incoming KICKs."""
 | 
			
		||||
        # :70MAAAAAA KICK #test 70MAAAAAA :some reason
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user