mirror of
https://github.com/jlu5/PyLink.git
synced 2024-11-24 11:39:25 +01:00
ts6: use new-style module design (#156)
This commit is contained in:
parent
a220659eaf
commit
814ebc9fe0
152
protocols/ts6.py
152
protocols/ts6.py
@ -25,6 +25,8 @@ class TS6Protocol(TS6BaseProtocol):
|
|||||||
self.sidgen = utils.TS6SIDGenerator(self.irc)
|
self.sidgen = utils.TS6SIDGenerator(self.irc)
|
||||||
self.uidgen = {}
|
self.uidgen = {}
|
||||||
|
|
||||||
|
### OUTGOING COMMANDS
|
||||||
|
|
||||||
def spawnClient(self, nick, ident='null', host='null', realhost=None, modes=set(),
|
def spawnClient(self, nick, ident='null', host='null', realhost=None, modes=set(),
|
||||||
server=None, ip='0.0.0.0', realname=None, ts=None, opertype=None,
|
server=None, ip='0.0.0.0', realname=None, ts=None, opertype=None,
|
||||||
manipulatable=False):
|
manipulatable=False):
|
||||||
@ -235,6 +237,8 @@ class TS6Protocol(TS6BaseProtocol):
|
|||||||
else:
|
else:
|
||||||
self._send(source, 'PING %s' % source)
|
self._send(source, 'PING %s' % source)
|
||||||
|
|
||||||
|
### Core / handlers
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
"""Initializes a connection to a server."""
|
"""Initializes a connection to a server."""
|
||||||
ts = self.irc.start_ts
|
ts = self.irc.start_ts
|
||||||
@ -329,88 +333,60 @@ class TS6Protocol(TS6BaseProtocol):
|
|||||||
f('SERVER %s 0 :%s' % (self.irc.serverdata["hostname"],
|
f('SERVER %s 0 :%s' % (self.irc.serverdata["hostname"],
|
||||||
self.irc.serverdata.get('serverdesc') or self.irc.botdata['serverdesc']))
|
self.irc.serverdata.get('serverdesc') or self.irc.botdata['serverdesc']))
|
||||||
|
|
||||||
def handle_events(self, data):
|
def handle_pass(self, numeric, command, args):
|
||||||
"""Generic event handler for the TS6 protocol: does protocol negotation
|
"""
|
||||||
and passes commands to handle_ABCD() functions elsewhere in this module."""
|
Handles the PASS command, used to send the server's SID and negotiate
|
||||||
# TS6 messages:
|
passwords on connect.
|
||||||
# :42X COMMAND arg1 arg2 :final long arg
|
"""
|
||||||
# :42XAAAAAA PRIVMSG #somewhere :hello!
|
# <- PASS $somepassword TS 6 :42X
|
||||||
args = data.split(" ")
|
|
||||||
if not args:
|
|
||||||
# No data??
|
|
||||||
return
|
|
||||||
if args[0] == 'PASS':
|
|
||||||
# <- PASS $somepassword TS 6 :42X
|
|
||||||
if args[1] != self.irc.serverdata['recvpass']:
|
|
||||||
# Check if recvpass is correct
|
|
||||||
raise ProtocolError('Error: recvpass from uplink server %s does not match configuration!' % servername)
|
|
||||||
if 'TS 6' not in data:
|
|
||||||
raise ProtocolError("Remote protocol version is too old! Is this even TS6?")
|
|
||||||
# Server name and SID are sent in different messages, grr
|
|
||||||
numeric = data.rsplit(':', 1)[1]
|
|
||||||
log.debug('(%s) Found uplink SID as %r', self.irc.name, numeric)
|
|
||||||
self.irc.servers[numeric] = IrcServer(None, 'unknown')
|
|
||||||
self.irc.uplink = numeric
|
|
||||||
return
|
|
||||||
elif args[0] == 'SERVER':
|
|
||||||
# <- SERVER charybdis.midnight.vpn 1 :charybdis test server
|
|
||||||
sname = args[1].lower()
|
|
||||||
log.debug('(%s) Found uplink server name as %r', self.irc.name, sname)
|
|
||||||
self.irc.servers[self.irc.uplink].name = sname
|
|
||||||
self.irc.servers[self.irc.uplink].desc = ' '.join(args).split(':', 1)[1]
|
|
||||||
# According to the TS6 protocol documentation, we should send SVINFO
|
|
||||||
# when we get our uplink's SERVER command.
|
|
||||||
self.irc.send('SVINFO 6 6 0 :%s' % int(time.time()))
|
|
||||||
elif args[0] == 'SQUIT':
|
|
||||||
# What? Charybdis send this in a different format!
|
|
||||||
# <- SQUIT 00A :Remote host closed the connection
|
|
||||||
split_server = args[1]
|
|
||||||
res = self.handle_squit(split_server, 'SQUIT', [split_server])
|
|
||||||
self.irc.callHooks([split_server, 'SQUIT', res])
|
|
||||||
elif args[0] == 'CAPAB':
|
|
||||||
# We only get a list of keywords here. Charybdis obviously assumes that
|
|
||||||
# we know what modes it supports (indeed, this is a standard list).
|
|
||||||
# <- CAPAB :BAN CHW CLUSTER ENCAP EOPMOD EUID EX IE KLN KNOCK MLOCK QS RSFNC SAVE SERVICES TB UNKLN
|
|
||||||
self.irc.caps = caps = data.split(':', 1)[1].split()
|
|
||||||
for required_cap in ('EUID', 'SAVE', 'TB', 'ENCAP', 'QS'):
|
|
||||||
if required_cap not in caps:
|
|
||||||
raise ProtocolError('%s not found in TS6 capabilities list; this is required! (got %r)' % (required_cap, caps))
|
|
||||||
|
|
||||||
if 'EX' in caps:
|
if args[0] != self.irc.serverdata['recvpass']:
|
||||||
self.irc.cmodes['banexception'] = 'e'
|
# Check if recvpass is correct
|
||||||
if 'IE' in caps:
|
raise ProtocolError('Recvpass from uplink server %s does not match configuration!' % servername)
|
||||||
self.irc.cmodes['invex'] = 'I'
|
|
||||||
if 'SERVICES' in caps:
|
|
||||||
self.irc.cmodes['regonly'] = 'r'
|
|
||||||
|
|
||||||
log.debug('(%s) self.irc.connected set!', self.irc.name)
|
if args[1] != 'TS' and args[2] != '6':
|
||||||
self.irc.connected.set()
|
raise ProtocolError("Remote protocol version is too old! Is this even TS6?")
|
||||||
|
|
||||||
# Charybdis doesn't have the idea of an explicit endburst; but some plugins
|
numeric = args[-1]
|
||||||
# like relay require it to know that the network's connected.
|
log.debug('(%s) Found uplink SID as %r', self.irc.name, numeric)
|
||||||
# We'll set a timer to manually call endburst. It's not beautiful,
|
|
||||||
# but it's the best we can do.
|
|
||||||
endburst_timer = threading.Timer(1, self.irc.callHooks, args=([self.irc.uplink, 'ENDBURST', {}],))
|
|
||||||
log.debug('(%s) Starting delay to send ENDBURST', self.irc.name)
|
|
||||||
endburst_timer.start()
|
|
||||||
try:
|
|
||||||
args = self.parseTS6Args(args)
|
|
||||||
|
|
||||||
numeric = args[0]
|
# Server name and SID are sent in different messages, so we fill this
|
||||||
command = args[1]
|
# with dummy information until we get the actual sid.
|
||||||
args = args[2:]
|
self.irc.servers[numeric] = IrcServer(None, '')
|
||||||
except IndexError:
|
self.irc.uplink = numeric
|
||||||
return
|
|
||||||
|
|
||||||
# We will do wildcard command handling here. Unhandled commands are just ignored.
|
def handle_capab(self, numeric, command, args):
|
||||||
try:
|
"""
|
||||||
func = getattr(self, 'handle_'+command.lower())
|
Handles the CAPAB command, used for TS6 capability negotiation.
|
||||||
except AttributeError: # Unhandled command
|
"""
|
||||||
pass
|
# We only get a list of keywords here. Charybdis obviously assumes that
|
||||||
else:
|
# we know what modes it supports (indeed, this is a standard list).
|
||||||
parsed_args = func(numeric, command, args)
|
# <- CAPAB :BAN CHW CLUSTER ENCAP EOPMOD EUID EX IE KLN KNOCK MLOCK QS RSFNC SAVE SERVICES TB UNKLN
|
||||||
if parsed_args is not None:
|
self.irc.caps = caps = args[0].split()
|
||||||
return [numeric, command, parsed_args]
|
|
||||||
|
for required_cap in ('EUID', 'SAVE', 'TB', 'ENCAP', 'QS'):
|
||||||
|
if required_cap not in caps:
|
||||||
|
raise ProtocolError('%s not found in TS6 capabilities list; this is required! (got %r)' % (required_cap, caps))
|
||||||
|
|
||||||
|
if 'EX' in caps:
|
||||||
|
self.irc.cmodes['banexception'] = 'e'
|
||||||
|
if 'IE' in caps:
|
||||||
|
self.irc.cmodes['invex'] = 'I'
|
||||||
|
if 'SERVICES' in caps:
|
||||||
|
self.irc.cmodes['regonly'] = 'r'
|
||||||
|
|
||||||
|
log.debug('(%s) self.irc.connected set!', self.irc.name)
|
||||||
|
self.irc.connected.set()
|
||||||
|
|
||||||
|
# Charybdis doesn't have the idea of an explicit endburst; but some plugins
|
||||||
|
# like relay require it to know that the network's connected.
|
||||||
|
# We'll set a timer to manually call endburst. It's not beautiful,
|
||||||
|
# but it's the best we can do.
|
||||||
|
endburst_timer = threading.Timer(1, self.irc.callHooks,
|
||||||
|
args=([self.irc.uplink, 'ENDBURST', {}],))
|
||||||
|
|
||||||
|
log.debug('(%s) Starting delay to send ENDBURST', self.irc.name)
|
||||||
|
endburst_timer.start()
|
||||||
|
|
||||||
def handle_ping(self, source, command, args):
|
def handle_ping(self, source, command, args):
|
||||||
"""Handles incoming PING commands."""
|
"""Handles incoming PING commands."""
|
||||||
@ -529,10 +505,26 @@ class TS6Protocol(TS6BaseProtocol):
|
|||||||
self.irc.servers[sid] = IrcServer(numeric, servername, desc=sdesc)
|
self.irc.servers[sid] = IrcServer(numeric, servername, desc=sdesc)
|
||||||
return {'name': servername, 'sid': sid, 'text': sdesc}
|
return {'name': servername, 'sid': sid, 'text': sdesc}
|
||||||
|
|
||||||
def handle_server(self, sender, command, args):
|
def handle_server(self, numeric, command, args):
|
||||||
"""Handles incoming legacy (no SID) server introductions."""
|
"""
|
||||||
|
Handles 1) incoming legacy (no SID) server introductions,
|
||||||
|
2) Sending server data in initial connection.
|
||||||
|
"""
|
||||||
|
if numeric == self.irc.uplink and not self.irc.servers[numeric].name:
|
||||||
|
# <- SERVER charybdis.midnight.vpn 1 :charybdis test server
|
||||||
|
sname = args[0].lower()
|
||||||
|
|
||||||
|
log.debug('(%s) Found uplink server name as %r', self.irc.name, sname)
|
||||||
|
self.irc.servers[numeric].name = sname
|
||||||
|
self.irc.servers[numeric].desc = args[-1]
|
||||||
|
|
||||||
|
# According to the TS6 protocol documentation, we should send SVINFO
|
||||||
|
# when we get our uplink's SERVER command.
|
||||||
|
self.irc.send('SVINFO 6 6 0 :%s' % int(time.time()))
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
# <- :services.int SERVER a.bc 2 :(H) [GL] a
|
# <- :services.int SERVER a.bc 2 :(H) [GL] a
|
||||||
numeric = self._getSid(sender) # Convert the server name prefix to a SID.
|
|
||||||
servername = args[0].lower()
|
servername = args[0].lower()
|
||||||
sdesc = args[-1]
|
sdesc = args[-1]
|
||||||
self.irc.servers[servername] = IrcServer(numeric, servername, desc=sdesc)
|
self.irc.servers[servername] = IrcServer(numeric, servername, desc=sdesc)
|
||||||
|
Loading…
Reference in New Issue
Block a user