mirror of
https://github.com/jlu5/PyLink.git
synced 2024-12-25 20:22:45 +01:00
Merge branch 'wip/protocol-cleanup' into devel
This commit is contained in:
commit
a32d937b91
@ -6,14 +6,103 @@ import time
|
|||||||
|
|
||||||
from pylinkirc.classes import Protocol
|
from pylinkirc.classes import Protocol
|
||||||
from pylinkirc.log import log
|
from pylinkirc.log import log
|
||||||
|
from pylinkirc import utils
|
||||||
|
|
||||||
class IRCS2SProtocol(Protocol):
|
class IRCS2SProtocol(Protocol):
|
||||||
|
COMMAND_TOKENS = {}
|
||||||
|
|
||||||
def __init__(self, irc):
|
def __init__(self, irc):
|
||||||
super().__init__(irc)
|
super().__init__(irc)
|
||||||
self.protocol_caps = {'can-spawn-clients', 'has-ts', 'can-host-relay',
|
self.protocol_caps = {'can-spawn-clients', 'has-ts', 'can-host-relay',
|
||||||
'can-track-servers'}
|
'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):
|
def check_nick_collision(self, nick):
|
||||||
"""
|
"""
|
||||||
Nick collision checker.
|
Nick collision checker.
|
||||||
|
@ -824,63 +824,6 @@ class P10Protocol(IRCS2SProtocol):
|
|||||||
self._send(sid, "EB")
|
self._send(sid, "EB")
|
||||||
self.irc.connected.set()
|
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):
|
def handle_server(self, source, command, args):
|
||||||
"""Handles incoming server introductions."""
|
"""Handles incoming server introductions."""
|
||||||
# <- SERVER nefarious.midnight.vpn 1 1460673022 1460673239 J10 ABP]] +h6 :Nefarious2 test server
|
# <- 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())}
|
self.irc.channels[channel].modes, 'ts': ts or int(time.time())}
|
||||||
|
|
||||||
handle_create = handle_join
|
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):
|
def handle_end_of_burst(self, source, command, args):
|
||||||
"""Handles end of burst from our uplink."""
|
"""Handles end of burst from our uplink."""
|
||||||
# Send EOB acknowledgement; this is required by the P10 specification,
|
# Send EOB acknowledgement; this is required by the P10 specification,
|
||||||
|
@ -294,83 +294,6 @@ class TS6BaseProtocol(IRCS2SProtocol):
|
|||||||
self.irc.users[source].away = text
|
self.irc.users[source].away = text
|
||||||
|
|
||||||
### HANDLERS
|
### 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):
|
def handle_kick(self, source, command, args):
|
||||||
"""Handles incoming KICKs."""
|
"""Handles incoming KICKs."""
|
||||||
# :70MAAAAAA KICK #test 70MAAAAAA :some reason
|
# :70MAAAAAA KICK #test 70MAAAAAA :some reason
|
||||||
|
Loading…
Reference in New Issue
Block a user