3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-11-01 09:19:23 +01:00

Support modes with arguments in our modestring parsers

Closes #27.
This commit is contained in:
James Lu 2015-07-04 23:49:28 -07:00
parent 3749e642f2
commit 8b93b78d13
2 changed files with 51 additions and 16 deletions

View File

@ -6,6 +6,7 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import utils import utils
from copy import copy from copy import copy
import traceback import traceback
import re
from classes import * from classes import *
# Raw commands sent from servers vary from protocol to protocol. Here, we map # Raw commands sent from servers vary from protocol to protocol. Here, we map
@ -134,7 +135,7 @@ def connect(irc):
f('SERVER {host} {Pass} 0 {sid} :PyLink Service'.format(host=host, f('SERVER {host} {Pass} 0 {sid} :PyLink Service'.format(host=host,
Pass=irc.serverdata["sendpass"], sid=irc.sid)) Pass=irc.serverdata["sendpass"], sid=irc.sid))
f(':%s BURST %s' % (irc.sid, ts)) f(':%s BURST %s' % (irc.sid, ts))
irc.pseudoclient = spawnClient(irc, 'PyLink', 'pylink', host, modes=set(["+o"])) irc.pseudoclient = spawnClient(irc, 'PyLink', 'pylink', host, modes=set([("+o", None)]))
f(':%s ENDBURST' % (irc.sid)) f(':%s ENDBURST' % (irc.sid))
for chan in irc.serverdata['channels']: for chan in irc.serverdata['channels']:
joinClient(irc, irc.pseudoclient.uid, chan) joinClient(irc, irc.pseudoclient.uid, chan)
@ -230,7 +231,7 @@ def handle_uid(irc, numeric, command, args):
uid, ts, nick, realhost, host, ident, ip = args[0:7] uid, ts, nick, realhost, host, ident, ip = args[0:7]
realname = args[-1] realname = args[-1]
irc.users[uid] = IrcUser(nick, ts, uid, ident, host, realname, realhost, ip) irc.users[uid] = IrcUser(nick, ts, uid, ident, host, realname, realhost, ip)
parsedmodes = utils.parseModes(args[8:9]) parsedmodes = utils.parseModes(irc, [args[8], args[9]], usermodes=True)
print('Applying modes %s for %s' % (parsedmodes, uid)) print('Applying modes %s for %s' % (parsedmodes, uid))
irc.users[uid].modes = utils.applyModes(irc.users[uid].modes, parsedmodes) irc.users[uid].modes = utils.applyModes(irc.users[uid].modes, parsedmodes)
irc.servers[numeric].users.append(uid) irc.servers[numeric].users.append(uid)
@ -289,7 +290,7 @@ def handle_mode(irc, numeric, command, args):
# <- :70MAAAAAA MODE 70MAAAAAA -i+xc # <- :70MAAAAAA MODE 70MAAAAAA -i+xc
target = args[0] target = args[0]
modestrings = args[1:] modestrings = args[1:]
changedmodes = utils.parseModes(modestrings) changedmodes = utils.parseModes(irc, modestrings, usermodes=True)
irc.users[numeric].modes = utils.applyModes(irc.users[numeric].modes, changedmodes) irc.users[numeric].modes = utils.applyModes(irc.users[numeric].modes, changedmodes)
return {'target': target, 'modes': changedmodes} return {'target': target, 'modes': changedmodes}
@ -382,6 +383,7 @@ def handle_events(irc, data):
= caps['CHANMODES'].split(',') = caps['CHANMODES'].split(',')
irc.umodes['*A'], irc.umodes['*B'], irc.umodes['*C'], irc.umodes['*D'] \ irc.umodes['*A'], irc.umodes['*B'], irc.umodes['*C'], irc.umodes['*D'] \
= caps['USERMODES'].split(',') = caps['USERMODES'].split(',')
irc.prefixmodes = re.search(r'\((.*?)\)', caps['PREFIX']).group(1)
try: try:
real_args = [] real_args = []
for arg in args: for arg in args:

View File

@ -83,21 +83,46 @@ def isServerName(s):
return _isASCII(s) and '.' in s and not s.startswith('.') \ return _isASCII(s) and '.' in s and not s.startswith('.') \
and not s.endswith('.') and not s.endswith('.')
def parseModes(args): def parseModes(irc, args, usermodes=False):
"""['+mitl-o', '3', 'person'] => ['+m', '+i', '+t', '-o'] """Parses a mode string into a list of (mode, argument) tuples.
['+mitl-o', '3', 'person'] => [('+m', None), ('+i', None), ('+t', None), ('+l', '3'), ('-o', 'person')]
TODO: handle modes with extra arguments (mainly channel modes like +beIqlk)
""" """
modes = args[0] # http://www.irc.org/tech_docs/005.html
extramodes = args[1:] # A = Mode that adds or removes a nick or address to a list. Always has a parameter.
if not modes: # B = Mode that changes a setting and always has a parameter.
# C = Mode that changes a setting and only has a parameter when set.
# D = Mode that changes a setting and never has a parameter.
print(args)
modestring = args[0]
if not modestring:
return ValueError('No modes supplied in parseModes query: %r' % modes) return ValueError('No modes supplied in parseModes query: %r' % modes)
args = args[1:]
if usermodes:
supported_modes = irc.umodes
else:
supported_modes = irc.cmodes
print('supported modes: %s' % supported_modes)
res = [] res = []
for mode in modes: for x in ('A', 'B', 'C', 'D'):
print('%s modes: %s' % (x, supported_modes['*'+x]))
for mode in modestring:
if mode in '+-': if mode in '+-':
prefix = mode prefix = mode
else: else:
res.append(prefix + mode) arg = None
if mode in (supported_modes['*A'] + supported_modes['*B']):
# Must have parameter.
print('%s: Must have parameter.' % mode)
arg = args.pop(0)
elif mode in irc.prefixmodes and not usermodes:
# We're setting a prefix mode on someone (e.g. +o user1)
print('%s: prefixmode.' % mode)
arg = args.pop(0)
elif prefix == '+' and mode in supported_modes['*C']:
# Only has parameter when setting.
print('%s: Only has parameter when setting.' % mode)
arg = args.pop(0)
res.append((prefix + mode, arg))
return res return res
def applyModes(modelist, changedmodes): def applyModes(modelist, changedmodes):
@ -105,19 +130,27 @@ def applyModes(modelist, changedmodes):
print('Initial modelist: %s' % modelist) print('Initial modelist: %s' % modelist)
print('Changedmodes: %r' % changedmodes) print('Changedmodes: %r' % changedmodes)
for mode in changedmodes: for mode in changedmodes:
if mode[0] == '+': if mode[0][0] == '+':
# We're adding a mode # We're adding a mode
modelist.add(mode) modelist.add(mode)
print('Adding mode %r' % mode) print('Adding mode %r' % str(mode))
else: else:
# We're removing a mode # We're removing a mode
modelist.discard(mode) modelist.discard(mode)
print('Removing mode %r' % mode) print('Removing mode %r' % str(mode))
print('Final modelist: %s' % modelist) print('Final modelist: %s' % modelist)
return modelist return modelist
def joinModes(modes): def joinModes(modes):
return '+' + ''.join(mode[1] for mode in modes) modelist = ''
args = []
for modepair in modes:
mode, arg = modepair
modelist += mode[1]
if arg is not None:
args.append(arg)
s = '+%s %s' % (modelist, ' '.join(args))
return s
def isInternalClient(irc, numeric): def isInternalClient(irc, numeric):
"""<irc object> <client numeric> """<irc object> <client numeric>