mirror of
https://github.com/jlu5/PyLink.git
synced 2024-12-25 20:22:45 +01:00
Merge branch 'devel' into wip/unrealircd
This commit is contained in:
commit
07fce69c5e
@ -1,6 +1,6 @@
|
|||||||
# PyLink
|
# PyLink
|
||||||
|
|
||||||
PyLink is an extensible, plugin-based IRC Services framework written in Python. It aims to be a replacement for the now-defunct Janus.
|
PyLink is an extensible, plugin-based IRC Services framework written in Python. It aims to be 1) a replacement for the now-defunct Janus 2) a versatile framework and gateway to IRC.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
@ -32,6 +32,10 @@ relay_started = True
|
|||||||
|
|
||||||
def initializeAll(irc):
|
def initializeAll(irc):
|
||||||
"""Initializes all relay channels for the given IRC object."""
|
"""Initializes all relay channels for the given IRC object."""
|
||||||
|
# Wait for all IRC objects to initialize first. This prevents
|
||||||
|
# relay servers from being spawned too early (before server authentication),
|
||||||
|
# which would break connections.
|
||||||
|
world.started.wait(2)
|
||||||
for chanpair, entrydata in db.items():
|
for chanpair, entrydata in db.items():
|
||||||
network, channel = chanpair
|
network, channel = chanpair
|
||||||
initializeChannel(irc, channel)
|
initializeChannel(irc, channel)
|
||||||
@ -164,6 +168,8 @@ def getPrefixModes(irc, remoteirc, channel, user, mlist=None):
|
|||||||
def getRemoteSid(irc, remoteirc):
|
def getRemoteSid(irc, remoteirc):
|
||||||
"""Gets the remote server SID representing remoteirc on irc, spawning
|
"""Gets the remote server SID representing remoteirc on irc, spawning
|
||||||
it if it doesn't exist."""
|
it if it doesn't exist."""
|
||||||
|
# Don't spawn servers too early.
|
||||||
|
irc.connected.wait(2)
|
||||||
try:
|
try:
|
||||||
spawnservers = irc.conf['relay']['spawn_servers']
|
spawnservers = irc.conf['relay']['spawn_servers']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@ -183,6 +189,7 @@ def getRemoteSid(irc, remoteirc):
|
|||||||
log.exception('(%s) Failed to spawn server for %r:',
|
log.exception('(%s) Failed to spawn server for %r:',
|
||||||
irc.name, remoteirc.name)
|
irc.name, remoteirc.name)
|
||||||
irc.aborted.set()
|
irc.aborted.set()
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
irc.servers[sid].remote = remoteirc.name
|
irc.servers[sid].remote = remoteirc.name
|
||||||
relayservers[irc.name][remoteirc.name] = sid
|
relayservers[irc.name][remoteirc.name] = sid
|
||||||
@ -996,6 +1003,9 @@ def handle_endburst(irc, numeric, command, args):
|
|||||||
utils.add_hook(handle_endburst, "ENDBURST")
|
utils.add_hook(handle_endburst, "ENDBURST")
|
||||||
|
|
||||||
def handle_disconnect(irc, numeric, command, args):
|
def handle_disconnect(irc, numeric, command, args):
|
||||||
|
"""Handles IRC network disconnections (internal hook)."""
|
||||||
|
# Quit all of our users' representations on other nets, and remove
|
||||||
|
# them from our relay clients index.
|
||||||
for k, v in relayusers.copy().items():
|
for k, v in relayusers.copy().items():
|
||||||
if irc.name in v:
|
if irc.name in v:
|
||||||
del relayusers[k][irc.name]
|
del relayusers[k][irc.name]
|
||||||
@ -1005,11 +1015,15 @@ def handle_disconnect(irc, numeric, command, args):
|
|||||||
del relayusers[k]
|
del relayusers[k]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
for name, ircobj in world.networkobjects.items():
|
# SQUIT all relay pseudoservers spawned for us, and remove them
|
||||||
if name != irc.name:
|
# from our relay subservers index.
|
||||||
rsid = getRemoteSid(ircobj, irc)
|
for name, ircobj in world.networkobjects.copy().items():
|
||||||
# Let's be super extra careful here...
|
if name != irc.name and ircobj.connected.is_set():
|
||||||
if rsid and name in relayservers and irc.name in relayservers[name]:
|
try:
|
||||||
|
rsid = relayservers[ircobj.name][irc.name]
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
ircobj.proto.squitServer(ircobj.sid, rsid, text='Home network lost connection.')
|
ircobj.proto.squitServer(ircobj.sid, rsid, text='Home network lost connection.')
|
||||||
del relayservers[name][irc.name]
|
del relayservers[name][irc.name]
|
||||||
try:
|
try:
|
||||||
|
@ -288,7 +288,7 @@ class TS6Protocol(TS6BaseProtocol):
|
|||||||
def squitServer(self, source, target, text='No reason given'):
|
def squitServer(self, source, target, text='No reason given'):
|
||||||
"""SQUITs a PyLink server."""
|
"""SQUITs a PyLink server."""
|
||||||
# -> SQUIT 9PZ :blah, blah
|
# -> SQUIT 9PZ :blah, blah
|
||||||
self.irc.send('SQUIT %s :%s' % (target, text))
|
self._send(source, 'SQUIT %s :%s' % (target, text))
|
||||||
self.handle_squit(source, 'SQUIT', [target, text])
|
self.handle_squit(source, 'SQUIT', [target, text])
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
@ -588,22 +588,23 @@ class TS6Protocol(TS6BaseProtocol):
|
|||||||
raise ProtocolError("Servers should use EUID instead of UID to send users! "
|
raise ProtocolError("Servers should use EUID instead of UID to send users! "
|
||||||
"This IS a required capability after all...")
|
"This IS a required capability after all...")
|
||||||
|
|
||||||
def handle_server(self, numeric, command, args):
|
def handle_sid(self, numeric, command, args):
|
||||||
"""Handles incoming SERVER introductions."""
|
"""Handles incoming server introductions."""
|
||||||
# parameters: server name, hopcount, sid, server description
|
# parameters: server name, hopcount, sid, server description
|
||||||
servername = args[0].lower()
|
servername = args[0].lower()
|
||||||
try:
|
sid = args[2]
|
||||||
sid = args[2]
|
|
||||||
except IndexError:
|
|
||||||
# It is allowed to send JUPEd servers that exist without a SID.
|
|
||||||
# That's not very fun to handle, though.
|
|
||||||
# XXX: don't just save these by their server names; that's ugly!
|
|
||||||
sid = servername
|
|
||||||
sdesc = args[-1]
|
sdesc = args[-1]
|
||||||
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}
|
||||||
|
|
||||||
handle_sid = handle_server
|
def handle_server(self, sender, command, args):
|
||||||
|
"""Handles incoming legacy (no SID) server introductions."""
|
||||||
|
# <- :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()
|
||||||
|
sdesc = args[-1]
|
||||||
|
self.irc.servers[servername] = IrcServer(numeric, servername, desc=sdesc)
|
||||||
|
return {'name': servername, 'sid': None, 'text': sdesc}
|
||||||
|
|
||||||
def handle_tmode(self, numeric, command, args):
|
def handle_tmode(self, numeric, command, args):
|
||||||
"""Handles incoming TMODE commands (channel mode change)."""
|
"""Handles incoming TMODE commands (channel mode change)."""
|
||||||
|
@ -19,6 +19,13 @@ class TS6BaseProtocol(Protocol):
|
|||||||
args[0] = args[0].split(':', 1)[1]
|
args[0] = args[0].split(':', 1)[1]
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
def _getSid(self, sname):
|
||||||
|
"""Returns the SID of a server with the given name, if present."""
|
||||||
|
nick = sname.lower()
|
||||||
|
for k, v in self.irc.servers.items():
|
||||||
|
if v.name.lower() == nick:
|
||||||
|
return k
|
||||||
|
|
||||||
### OUTGOING COMMANDS
|
### OUTGOING COMMANDS
|
||||||
|
|
||||||
def _sendKick(self, numeric, channel, target, reason=None):
|
def _sendKick(self, numeric, channel, target, reason=None):
|
||||||
@ -162,8 +169,10 @@ class TS6BaseProtocol(Protocol):
|
|||||||
# :70M SQUIT 1ML :Server quit by GL!gl@0::1
|
# :70M SQUIT 1ML :Server quit by GL!gl@0::1
|
||||||
split_server = args[0]
|
split_server = args[0]
|
||||||
affected_users = []
|
affected_users = []
|
||||||
log.info('(%s) Netsplit on server %s', self.irc.name, split_server)
|
log.debug('(%s) Splitting server %s (reason: %s)', self.irc.name, split_server, args[-1])
|
||||||
assert split_server in self.irc.servers, "Tried to split a server (%s) that didn't exist!" % split_server
|
if split_server not in self.irc.servers:
|
||||||
|
log.warning("(%s) Tried to split a server (%s) that didn't exist!", self.irc.name, split_server)
|
||||||
|
return
|
||||||
# Prevent RuntimeError: dictionary changed size during iteration
|
# Prevent RuntimeError: dictionary changed size during iteration
|
||||||
old_servers = self.irc.servers.copy()
|
old_servers = self.irc.servers.copy()
|
||||||
for sid, data in old_servers.items():
|
for sid, data in old_servers.items():
|
||||||
|
Loading…
Reference in New Issue
Block a user