mirror of
https://github.com/jlu5/PyLink.git
synced 2024-12-25 04:02:45 +01:00
protocols: move 005 handling code to IRCCommonProtocol
Also enable extended server negotiation for ngIRCd, which really just passes 005 between servers (nifty!)
This commit is contained in:
parent
e9d7ac39ea
commit
ec308acfcb
@ -8,7 +8,6 @@ from pylinkirc.protocols.ircs2s_common import *
|
||||
from pylinkirc.classes import *
|
||||
|
||||
FALLBACK_REALNAME = 'PyLink Relay Mirror Client'
|
||||
COMMON_PREFIXMODES = [('h', 'halfop'), ('a', 'admin'), ('q', 'owner'), ('y', 'owner')]
|
||||
IRCV3_CAPABILITIES = {'multi-prefix', 'sasl'}
|
||||
|
||||
class ClientbotWrapperProtocol(IRCCommonProtocol):
|
||||
@ -25,7 +24,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
|
||||
# This is just a fallback. Actual casemapping is fetched by handle_005()
|
||||
self.casemapping = 'ascii'
|
||||
|
||||
self.caps = {}
|
||||
self._caps = {}
|
||||
self.ircv3_caps = set()
|
||||
self.ircv3_caps_available = {}
|
||||
|
||||
@ -42,9 +41,12 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
|
||||
# are essentially all fatal errors for connections.
|
||||
self.handle_463 = self.handle_464 = self.handle_465 = self.handle_error
|
||||
|
||||
self._use_builtin_005_handling = True
|
||||
|
||||
def post_connect(self):
|
||||
"""Initializes a connection to a server."""
|
||||
# (Re)initialize counter-based pseudo UID generators
|
||||
super().post_connect()
|
||||
self.uidgen = utils.PUIDGenerator('PUID')
|
||||
self.sidgen = utils.PUIDGenerator('ClientbotInternalSID')
|
||||
|
||||
@ -58,7 +60,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
|
||||
# Clear states from last connect
|
||||
self.who_received.clear()
|
||||
self.kick_queue.clear()
|
||||
self.caps.clear()
|
||||
self._caps.clear()
|
||||
self.ircv3_caps.clear()
|
||||
self.ircv3_caps_available.clear()
|
||||
|
||||
@ -576,40 +578,6 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
|
||||
# enumerate our uplink
|
||||
self.uplink = source
|
||||
|
||||
def handle_005(self, source, command, args):
|
||||
"""
|
||||
Handles 005 / RPL_ISUPPORT.
|
||||
"""
|
||||
self.caps.update(self.parse_isupport(args[1:-1]))
|
||||
log.debug('(%s) handle_005: self.caps is %s', self.name, self.caps)
|
||||
|
||||
if 'CHANMODES' in self.caps:
|
||||
self.cmodes['*A'], self.cmodes['*B'], self.cmodes['*C'], self.cmodes['*D'] = \
|
||||
self.caps['CHANMODES'].split(',')
|
||||
log.debug('(%s) handle_005: cmodes: %s', self.name, self.cmodes)
|
||||
|
||||
if 'USERMODES' in self.caps:
|
||||
self.umodes['*A'], self.umodes['*B'], self.umodes['*C'], self.umodes['*D'] = \
|
||||
self.caps['USERMODES'].split(',')
|
||||
log.debug('(%s) handle_005: umodes: %s', self.name, self.umodes)
|
||||
|
||||
self.casemapping = self.caps.get('CASEMAPPING', self.casemapping)
|
||||
log.debug('(%s) handle_005: casemapping set to %s', self.name, self.casemapping)
|
||||
|
||||
if 'PREFIX' in self.caps:
|
||||
self.prefixmodes = prefixmodes = self.parse_isupport_prefixes(self.caps['PREFIX'])
|
||||
log.debug('(%s) handle_005: prefix modes set to %s', self.name, self.prefixmodes)
|
||||
|
||||
# Autodetect common prefix mode names.
|
||||
for char, modename in COMMON_PREFIXMODES:
|
||||
# Don't overwrite existing named mode definitions.
|
||||
if char in self.prefixmodes and modename not in self.cmodes:
|
||||
self.cmodes[modename] = char
|
||||
log.debug('(%s) handle_005: autodetecting mode %s (%s) as %s', self.name,
|
||||
char, self.prefixmodes[char], modename)
|
||||
|
||||
self.connected.set()
|
||||
|
||||
def handle_376(self, source, command, args):
|
||||
"""
|
||||
Handles end of MOTD numerics, used to start things like autoperform.
|
||||
@ -623,6 +591,8 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
|
||||
if not self.has_eob:
|
||||
self.has_eob = True
|
||||
return {'parse_as': 'ENDBURST'}
|
||||
self.connected.set()
|
||||
|
||||
handle_422 = handle_376
|
||||
|
||||
def handle_353(self, source, command, args):
|
||||
|
@ -11,6 +11,18 @@ from pylinkirc.log import log
|
||||
from pylinkirc import utils
|
||||
|
||||
class IRCCommonProtocol(IRCNetwork):
|
||||
|
||||
COMMON_PREFIXMODES = [('h', 'halfop'), ('a', 'admin'), ('q', 'owner'), ('y', 'owner')]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self._caps = {}
|
||||
self._use_builtin_005_handling = False # Disabled by default for greater security
|
||||
|
||||
def post_connect(self):
|
||||
self._caps.clear()
|
||||
|
||||
def validate_server_conf(self):
|
||||
"""Validates that the server block given contains the required keys."""
|
||||
for k in self.conf_keys:
|
||||
@ -163,6 +175,54 @@ class IRCCommonProtocol(IRCNetwork):
|
||||
"""Handles ERROR messages - these mean that our uplink has disconnected us!"""
|
||||
raise ProtocolError('Received an ERROR, disconnecting!')
|
||||
|
||||
def handle_005(self, source, command, args):
|
||||
"""
|
||||
Handles 005 / RPL_ISUPPORT. This is used by at least Clientbot and ngIRCd (for server negotiation).
|
||||
"""
|
||||
# ngIRCd:
|
||||
# <- :ngircd.midnight.local 005 pylink-devel.int NETWORK=ngircd-test :is my network name
|
||||
# <- :ngircd.midnight.local 005 pylink-devel.int RFC2812 IRCD=ngIRCd CHARSET=UTF-8 CASEMAPPING=ascii PREFIX=(qaohv)~&@%+ CHANTYPES=#&+ CHANMODES=beI,k,l,imMnOPQRstVz CHANLIMIT=#&+:10 :are supported on this server
|
||||
# <- :ngircd.midnight.local 005 pylink-devel.int CHANNELLEN=50 NICKLEN=21 TOPICLEN=490 AWAYLEN=127 KICKLEN=400 MODES=5 MAXLIST=beI:50 EXCEPTS=e INVEX=I PENALTY :are supported on this server
|
||||
|
||||
# Regular clientbot, connecting to InspIRCd:
|
||||
# <- :millennium.overdrivenetworks.com 005 ice AWAYLEN=200 CALLERID=g CASEMAPPING=rfc1459 CHANMODES=IXbegw,k,FJLfjl,ACKMNOPQRSTUcimnprstz CHANNELLEN=64 CHANTYPES=# CHARSET=ascii ELIST=MU ESILENCE EXCEPTS=e EXTBAN=,ACNOQRSTUcmprsuz FNC INVEX=I :are supported by this server
|
||||
# <- :millennium.overdrivenetworks.com 005 ice KICKLEN=255 MAP MAXBANS=60 MAXCHANNELS=30 MAXPARA=32 MAXTARGETS=20 MODES=20 NAMESX NETWORK=OVERdrive-IRC NICKLEN=21 OVERRIDE PREFIX=(Yqaohv)*~&@%+ SILENCE=32 :are supported by this server
|
||||
# <- :millennium.overdrivenetworks.com 005 ice SSL=[::]:6697 STARTTLS STATUSMSG=*~&@%+ TOPICLEN=307 UHNAMES USERIP VBANLIST WALLCHOPS WALLVOICES WATCH=32 :are supported by this server
|
||||
|
||||
if not self._use_builtin_005_handling:
|
||||
log.warning("(%s) Got spurious 005 message from %s: %r", self.name, source, args)
|
||||
return
|
||||
|
||||
self._caps.update(self.parse_isupport(args[1:-1]))
|
||||
log.debug('(%s) handle_005: self._caps is %s', self.name, self._caps)
|
||||
|
||||
if 'CHANMODES' in self._caps:
|
||||
self.cmodes['*A'], self.cmodes['*B'], self.cmodes['*C'], self.cmodes['*D'] = \
|
||||
self._caps['CHANMODES'].split(',')
|
||||
log.debug('(%s) handle_005: cmodes: %s', self.name, self.cmodes)
|
||||
|
||||
if 'USERMODES' in self._caps:
|
||||
self.umodes['*A'], self.umodes['*B'], self.umodes['*C'], self.umodes['*D'] = \
|
||||
self._caps['USERMODES'].split(',')
|
||||
log.debug('(%s) handle_005: umodes: %s', self.name, self.umodes)
|
||||
|
||||
self.casemapping = self._caps.get('CASEMAPPING', self.casemapping)
|
||||
log.debug('(%s) handle_005: casemapping set to %s', self.name, self.casemapping)
|
||||
|
||||
if 'PREFIX' in self._caps:
|
||||
self.prefixmodes = prefixmodes = self.parse_isupport_prefixes(self._caps['PREFIX'])
|
||||
log.debug('(%s) handle_005: prefix modes set to %s', self.name, self.prefixmodes)
|
||||
|
||||
# Autodetect common prefix mode names.
|
||||
for char, modename in self.COMMON_PREFIXMODES:
|
||||
# Don't overwrite existing named mode definitions.
|
||||
if char in self.prefixmodes and modename not in self.cmodes:
|
||||
self.cmodes[modename] = char
|
||||
log.debug('(%s) handle_005: autodetecting mode %s (%s) as %s', self.name,
|
||||
char, self.prefixmodes[char], modename)
|
||||
|
||||
self.connected.set()
|
||||
|
||||
def _send_with_prefix(self, source, msg, **kwargs):
|
||||
"""Sends a RFC 459-style raw command from the given sender."""
|
||||
self.send(':%s %s' % (self._expandPUID(source), msg), **kwargs)
|
||||
|
@ -22,21 +22,25 @@ class NgIRCdProtocol(IRCS2SProtocol):
|
||||
super().__init__(irc)
|
||||
|
||||
self.conf_keys -= {'sid', 'sidrange'}
|
||||
self.casemapping = 'rfc1459'
|
||||
self.casemapping = 'ascii' # This is the default; it's actually set on server negotiation
|
||||
|
||||
# Track whether we've received end-of-burst from the uplink.
|
||||
self.has_eob = False
|
||||
|
||||
self.uidgen = utils.PUIDGenerator("PUID")
|
||||
self._caps = {}
|
||||
self._use_builtin_005_handling = True
|
||||
|
||||
### Commands
|
||||
|
||||
def post_connect(self):
|
||||
self.send('PASS %s 0210-IRC+ PyLink|%s:LMoX' % (self.serverdata['sendpass'], __version__))
|
||||
self.send('PASS %s 0210-IRC+ PyLink|%s:HLMoX' % (self.serverdata['sendpass'], __version__))
|
||||
self.send("SERVER %s 1 :%s" % (self.serverdata['hostname'],
|
||||
self.serverdata.get('serverdesc') or conf.conf['pylink']['serverdesc']));
|
||||
self.sid = self.serverdata['hostname']
|
||||
|
||||
self._caps.clear()
|
||||
|
||||
def spawn_client(self, nick, ident='null', host='null', realhost=None, modes=set(),
|
||||
server=None, ip='0.0.0.0', realname=None, ts=None, opertype='IRC Operator',
|
||||
manipulatable=False):
|
||||
|
Loading…
Reference in New Issue
Block a user