From 7620cd7433d9dc53dda1bdb06f6a9c673757f1f6 Mon Sep 17 00:00:00 2001 From: James Lu Date: Sun, 30 Aug 2015 23:16:39 -0700 Subject: [PATCH 1/3] pr/inspircd: fix compatibility with channel mode +q (~) InspIRCd's defaults use "founder" as the mode name for cmode +q, not "owner". My config was different, so I overlooked this. --- protocols/inspircd.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/protocols/inspircd.py b/protocols/inspircd.py index 3e8adf7..9312463 100644 --- a/protocols/inspircd.py +++ b/protocols/inspircd.py @@ -528,11 +528,15 @@ def handle_events(irc, data): # <- CAPAB CHANMODES :admin=&a allowinvite=A autoop=w ban=b banexception=e blockcolor=c c_registered=r exemptchanops=X filter=g flood=f halfop=%h history=H invex=I inviteonly=i joinflood=j key=k kicknorejoin=J limit=l moderated=m nickflood=F noctcp=C noextmsg=n nokick=Q noknock=K nonick=N nonotice=T official-join=!Y op=@o operonly=O opmoderated=U owner=~q permanent=P private=p redirect=L reginvite=R regmoderated=M secret=s sslonly=z stripcolor=S topiclock=t voice=+v # Named modes are essential for a cross-protocol IRC service. We - # can use InspIRCd as a model here and assign their mode map to our cmodes list. + # can use InspIRCd as a model here and assign a similar mode map to our cmodes list. for modepair in args[2:]: name, char = modepair.split('=') if name == 'reginvite': # Reginvite? That's a dumb name. name = 'regonly' + if name == 'founder': # Channel mode +q + # Founder, owner; same thing. m_customprefix allows you to name it anything you like + # (the former is config default, but I personally prefer the latter.) + name = 'owner' # We don't really care about mode prefixes; just the mode char irc.cmodes[name.lstrip(':')] = char[-1] elif args[1] == 'USERMODES': From 9f0f4cb1246c95335f42a24f7c5016175e6fba66 Mon Sep 17 00:00:00 2001 From: James Lu Date: Mon, 31 Aug 2015 09:28:14 -0700 Subject: [PATCH 2/3] relay: burst the right set of modes It's moments like this where I wonder what I'm even doing with my life... --- plugins/relay.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/relay.py b/plugins/relay.py index 87af3c8..64ae956 100644 --- a/plugins/relay.py +++ b/plugins/relay.py @@ -232,7 +232,6 @@ def initializeChannel(irc, channel): log.debug('(%s) initializeChannel: all_links: %s', irc.name, all_links) # Iterate over all the remote channels linked in this relay. for link in all_links: - modes = [] remotenet, remotechan = link if remotenet == irc.name: continue @@ -245,7 +244,7 @@ def initializeChannel(irc, channel): # Join their (remote) users and set their modes. relayJoins(remoteirc, remotechan, rc.users, rc.ts) relayModes(remoteirc, irc, remoteirc.sid, remotechan, rc.modes) - relayModes(irc, remoteirc, irc.sid, channel, modes) + relayModes(irc, remoteirc, irc.sid, channel, c.modes) topic = remoteirc.channels[remotechan].topic # Only update the topic if it's different from what we already have, # and topic bursting is complete. From 37eecd7d69cec794186024bf715a8ba55902d0e8 Mon Sep 17 00:00:00 2001 From: James Lu Date: Mon, 31 Aug 2015 10:31:50 -0700 Subject: [PATCH 3/3] pr/inspircd: use OPERTYPE to oper up clients correctly, and handle the metadata accordingly --- protocols/inspircd.py | 28 +++++++++++++++++++++++++--- protocols/ts6.py | 2 +- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/protocols/inspircd.py b/protocols/inspircd.py index 9312463..52a9171 100644 --- a/protocols/inspircd.py +++ b/protocols/inspircd.py @@ -23,7 +23,7 @@ def _send(irc, sid, msg): irc.send(':%s %s' % (sid, msg)) def spawnClient(irc, nick, ident='null', host='null', realhost=None, modes=set(), - server=None, ip='0.0.0.0', realname=None, ts=None): + server=None, ip='0.0.0.0', realname=None, ts=None, opertype=None): server = server or irc.sid if not utils.isInternalServer(irc, server): raise ValueError('Server %r is not a PyLink internal PseudoServer!' % server) @@ -45,6 +45,8 @@ def spawnClient(irc, nick, ident='null', host='null', realhost=None, modes=set() nick=nick, ident=ident, uid=uid, modes=raw_modes, ip=ip, realname=realname, realhost=realhost)) + if ('o', None) in modes or ('+o', None) in modes: + _operUp(irc, uid, opertype=opertype or 'IRC_Operator') return u def joinClient(irc, client, channel): @@ -182,11 +184,30 @@ def nickClient(irc, numeric, newnick): _send(irc, numeric, 'NICK %s %s' % (newnick, int(time.time()))) irc.users[numeric].nick = newnick +def _operUp(irc, target, opertype=None): + userobj = irc.users[target] + try: + otype = opertype or userobj.opertype + except AttributeError: + log.debug('(%s) opertype field for %s (%s) isn\'t filled yet!', + irc.name, target, userobj.nick) + # whatever, this is non-standard anyways. + otype = 'IRC_Operator' + log.debug('(%s) Sending OPERTYPE from %s to oper them up.', + irc.name, target) + _send(irc, target, 'OPERTYPE %s' % otype) + def _sendModes(irc, numeric, target, modes, ts=None): # -> :9PYAAAAAA FMODE #pylink 1433653951 +os 9PYAAAAAA # -> :9PYAAAAAA MODE 9PYAAAAAA -i+w - joinedmodes = utils.joinModes(modes) + log.debug('(%s) inspircd._sendModes: received %r for mode list', irc.name, modes) + if ('+o', None) in modes and not utils.isChannel(target): + # https://github.com/inspircd/inspircd/blob/master/src/modules/m_spanningtree/opertype.cpp#L26-L28 + # Servers need a special command to set umode +o on people. + # Why isn't this documented anywhere, InspIRCd? + _operUp(irc, target) utils.applyModes(irc, target, modes) + joinedmodes = utils.joinModes(modes) if utils.isChannel(target): ts = ts or irc.channels[target.lower()].ts _send(irc, numeric, 'FMODE %s %s %s' % (target, ts, joinedmodes)) @@ -680,8 +701,9 @@ def handle_opertype(irc, numeric, command, args): # command sent for it. # <- :70MAAAAAB OPERTYPE Network_Owner omode = [('+o', None)] + irc.users[numeric].opertype = opertype = args[0] utils.applyModes(irc, numeric, omode) - return {'target': numeric, 'modes': omode} + return {'target': numeric, 'modes': omode, 'text': opertype} def handle_fident(irc, numeric, command, args): # :70MAAAAAB FHOST test diff --git a/protocols/ts6.py b/protocols/ts6.py index f0a06f3..e41d27d 100644 --- a/protocols/ts6.py +++ b/protocols/ts6.py @@ -23,7 +23,7 @@ def _send(irc, sid, msg): irc.send(':%s %s' % (sid, msg)) def spawnClient(irc, nick, ident='null', host='null', realhost=None, modes=set(), - server=None, ip='0.0.0.0', realname=None, ts=None): + server=None, ip='0.0.0.0', realname=None, ts=None, opertype=None): server = server or irc.sid if not utils.isInternalServer(irc, server): raise ValueError('Server %r is not a PyLink internal PseudoServer!' % server)