mirror of
https://github.com/jlu5/PyLink.git
synced 2024-11-01 01:09:22 +01:00
Tests for FMODE/FJOIN, and bugfixes
This commit is contained in:
parent
87781abc82
commit
2cbd6fd851
33
main.py
33
main.py
@ -8,11 +8,11 @@ import sys
|
||||
from collections import defaultdict
|
||||
|
||||
from log import log
|
||||
from conf import conf
|
||||
import conf
|
||||
import classes
|
||||
|
||||
class Irc():
|
||||
def __init__(self, proto):
|
||||
def __init__(self, proto, conf):
|
||||
# Initialize some variables
|
||||
self.connected = False
|
||||
self.name = conf['server']['netname']
|
||||
@ -26,21 +26,30 @@ class Irc():
|
||||
self.cmodes = {'op': 'o', 'secret': 's', 'private': 'p',
|
||||
'noextmsg': 'n', 'moderated': 'm', 'inviteonly': 'i',
|
||||
'topiclock': 't', 'limit': 'l', 'ban': 'b',
|
||||
'voice': 'v', 'key': 'k'}
|
||||
'voice': 'v', 'key': 'k',
|
||||
# Type A, B, and C modes
|
||||
'*A': 'b',
|
||||
'*B': 'k',
|
||||
'*C': 'l',
|
||||
'*D': 'imnpstr'}
|
||||
self.umodes = {'invisible': 'i', 'snomask': 's', 'wallops': 'w',
|
||||
'oper': 'o'}
|
||||
'oper': 'o',
|
||||
'*A': '', '*B': '', '*C': 's', '*D': 'iow'}
|
||||
self.maxnicklen = 30
|
||||
self.prefixmodes = 'ov'
|
||||
|
||||
self.serverdata = conf['server']
|
||||
self.sid = self.serverdata["sid"]
|
||||
self.proto = proto
|
||||
self.connect()
|
||||
|
||||
def connect(self):
|
||||
ip = self.serverdata["ip"]
|
||||
port = self.serverdata["port"]
|
||||
self.sid = self.serverdata["sid"]
|
||||
log.info("Connecting to network %r on %s:%s", self.name, ip, port)
|
||||
|
||||
self.socket = socket.socket()
|
||||
self.socket.connect((ip, port))
|
||||
self.proto = proto
|
||||
proto.connect(self)
|
||||
self.proto.connect(self)
|
||||
self.loaded = []
|
||||
self.load_plugins()
|
||||
self.connected = True
|
||||
@ -70,7 +79,7 @@ class Irc():
|
||||
self.socket.send(data)
|
||||
|
||||
def load_plugins(self):
|
||||
to_load = conf['plugins']
|
||||
to_load = conf.conf['plugins']
|
||||
plugins_folder = [os.path.join(os.getcwd(), 'plugins')]
|
||||
# Here, we override the module lookup and import the plugins
|
||||
# dynamically depending on which were configured.
|
||||
@ -87,11 +96,11 @@ class Irc():
|
||||
|
||||
if __name__ == '__main__':
|
||||
log.info('PyLink starting...')
|
||||
if conf['login']['password'] == 'changeme':
|
||||
if conf.conf['login']['password'] == 'changeme':
|
||||
log.critical("You have not set the login details correctly! Exiting...")
|
||||
sys.exit(2)
|
||||
|
||||
protoname = conf['server']['protocol']
|
||||
protoname = conf.conf['server']['protocol']
|
||||
protocols_folder = [os.path.join(os.getcwd(), 'protocols')]
|
||||
try:
|
||||
moduleinfo = imp.find_module(protoname, protocols_folder)
|
||||
@ -103,4 +112,4 @@ if __name__ == '__main__':
|
||||
log.critical('Failed to load protocol module: import error %s', protoname, str(e))
|
||||
sys.exit(2)
|
||||
else:
|
||||
irc_obj = Irc(proto)
|
||||
irc_obj = Irc(proto, conf.conf)
|
||||
|
@ -8,31 +8,24 @@ import classes
|
||||
from collections import defaultdict
|
||||
import unittest
|
||||
|
||||
class FakeIRC(main.Irc):
|
||||
def __init__(self, proto):
|
||||
self.connected = False
|
||||
self.users = {}
|
||||
self.channels = defaultdict(classes.IrcChannel)
|
||||
self.name = 'fakeirc'
|
||||
self.servers = {}
|
||||
self.proto = proto
|
||||
global testconf
|
||||
testconf = {'server':
|
||||
{'netname': 'fakeirc',
|
||||
'ip': '0.0.0.0',
|
||||
'port': 7000,
|
||||
'recvpass': "abcd",
|
||||
'sendpass': "abcd",
|
||||
'protocol': "null",
|
||||
'hostname': "pylink.unittest",
|
||||
'sid': "9PY",
|
||||
'channels': ["#pylink"],
|
||||
}
|
||||
}
|
||||
|
||||
self.serverdata = {'netname': 'fakeirc',
|
||||
'ip': '0.0.0.0',
|
||||
'port': 7000,
|
||||
'recvpass': "abcd",
|
||||
'sendpass': "abcd",
|
||||
'protocol': "testingonly",
|
||||
'hostname': "pylink.unittest",
|
||||
'sid': "9PY",
|
||||
'channels': ["#pylink"],
|
||||
}
|
||||
self.conf = {'server': self.serverdata}
|
||||
ip = self.serverdata["ip"]
|
||||
port = self.serverdata["port"]
|
||||
self.sid = self.serverdata["sid"]
|
||||
self.socket = None
|
||||
class FakeIRC(main.Irc):
|
||||
def connect(self):
|
||||
self.messages = []
|
||||
self.socket = None
|
||||
|
||||
def run(self, data):
|
||||
"""Queues a message to the fake IRC server."""
|
||||
|
@ -11,7 +11,7 @@ import utils
|
||||
|
||||
class TestInspIRCdProtocol(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.irc = test_proto_common.FakeIRC(inspircd)
|
||||
self.irc = test_proto_common.FakeIRC(inspircd, test_proto_common.testconf)
|
||||
self.proto = self.irc.proto
|
||||
self.sdata = self.irc.serverdata
|
||||
# This is to initialize ourself as an internal PseudoServer, so we can spawn clients
|
||||
@ -153,20 +153,70 @@ class TestInspIRCdProtocol(unittest.TestCase):
|
||||
|
||||
def testHandleKill(self):
|
||||
self.irc.takeMsgs() # Ignore the initial connect messages
|
||||
self.irc.run(':9PYAAAAAA KILL 9PYAAAAAA :killed')
|
||||
olduid = self.irc.pseudoclient.uid
|
||||
self.irc.run(':{u} KILL {u} :killed'.format(u=olduid))
|
||||
msgs = self.irc.takeMsgs()
|
||||
commands = self.irc.takeCommands(msgs)
|
||||
# Make sure we're respawning our PseudoClient when its killed
|
||||
self.assertIn('UID', commands)
|
||||
self.assertIn('FJOIN', commands)
|
||||
# Also make sure that we're updating the irc.pseudoclient field
|
||||
self.assertNotEqual(self.irc.pseudoclient.uid, olduid)
|
||||
|
||||
def testHandleKick(self):
|
||||
self.irc.takeMsgs() # Ignore the initial connect messages
|
||||
self.irc.run(':9PYAAAAAA KICK #pylink 9PYAAAAAA :kicked')
|
||||
self.irc.run(':{u} KICK #pylink {u} :kicked'.format(u=self.irc.pseudoclient.uid))
|
||||
# Ditto above
|
||||
msgs = self.irc.takeMsgs()
|
||||
commands = self.irc.takeCommands(msgs)
|
||||
self.assertIn('FJOIN', commands)
|
||||
|
||||
def testHandleFjoinUsers(self):
|
||||
self.irc.run(':70M FJOIN #Chat 1423790411 + :,10XAAAAAA ,10XAAAAAB')
|
||||
self.assertEqual({'10XAAAAAA', '10XAAAAAB'}, self.irc.channels['#chat'].users)
|
||||
# self.assertIn('10XAAAAAB', self.irc.channels['#chat'].users)
|
||||
# Sequential FJOINs must NOT remove existing users
|
||||
self.irc.run(':70M FJOIN #Chat 1423790412 + :,10XAAAAAC')
|
||||
# Join list can be empty too, in the case of permanent channels with 0 users.
|
||||
self.irc.run(':70M FJOIN #Chat 1423790413 +nt :')
|
||||
|
||||
def testHandleFjoinModes(self):
|
||||
self.irc.run(':70M FJOIN #Chat 1423790411 +nt :,10XAAAAAA ,10XAAAAAB')
|
||||
self.assertEqual({('+n', None), ('+t', None)}, self.irc.channels['#chat'].modes)
|
||||
# Sequential FJOINs must NOT remove existing modes
|
||||
self.irc.run(':70M FJOIN #Chat 1423790412 + :,10XAAAAAC')
|
||||
self.assertEqual({('+n', None), ('+t', None)}, self.irc.channels['#chat'].modes)
|
||||
|
||||
def testHandleFjoinModesWithArgs(self):
|
||||
self.irc.run(':70M FJOIN #Chat 1423790414 +nlks 10 t0psekrit :,10XAAAAAA ,10XAAAAAB')
|
||||
self.assertEqual({('+n', None), ('+s', None), ('+l', '10'), ('+k', 't0psekrit')},
|
||||
self.irc.channels['#chat'].modes)
|
||||
|
||||
def testHandleFjoinPrefixes(self):
|
||||
self.irc.run(':70M FJOIN #Chat 1423790418 +nt :ov,10XAAAAAA v,10XAAAAAB ,10XAAAAAC')
|
||||
self.assertEqual({('+n', None), ('+t', None)}, self.irc.channels['#chat'].modes)
|
||||
self.assertEqual({'10XAAAAAA', '10XAAAAAB', '10XAAAAAC'}, self.irc.channels['#chat'].users)
|
||||
self.assertIn('10XAAAAAA', self.irc.channels['#chat'].prefixmodes['ops'])
|
||||
self.assertEqual({'10XAAAAAA', '10XAAAAAB'}, self.irc.channels['#chat'].prefixmodes['voices'])
|
||||
|
||||
def testHandleFmode(self):
|
||||
self.irc.run(':70M FJOIN #pylink 1423790411 +n :o,10XAAAAAA ,10XAAAAAB')
|
||||
self.irc.run(':70M FMODE #pylink 1423790412 +ikl herebedragons 100')
|
||||
self.assertEqual({('+i', None), ('+k', 'herebedragons'), ('+l', '100'), ('+n', None)}, self.irc.channels['#pylink'].modes)
|
||||
self.irc.run(':70M FMODE #pylink 1423790413 -ilk+m herebedragons')
|
||||
self.assertEqual({('+m', None), ('+n', None)}, self.irc.channels['#pylink'].modes)
|
||||
|
||||
def testHandleFmodeWithPrefixes(self):
|
||||
self.irc.run(':70M FJOIN #pylink 1423790411 +n :o,10XAAAAAA ,10XAAAAAB')
|
||||
# Prefix modes are stored separately, so they should never show up in .modes
|
||||
self.assertNotIn(('+o', '10XAAAAAA'), self.irc.channels['#pylink'].modes)
|
||||
self.assertEqual({'10XAAAAAA'}, self.irc.channels['#pylink'].prefixmodes['ops'])
|
||||
self.irc.run(':70M FMODE #pylink 1423790412 +lot 50 %s' % self.u)
|
||||
self.assertIn(self.u, self.irc.channels['#pylink'].prefixmodes['ops'])
|
||||
modes = {('+l', '50'), ('+n', None), ('+t', None)}
|
||||
self.assertEqual(modes, self.irc.channels['#pylink'].modes)
|
||||
self.irc.run(':70M FMODE #pylink 1423790413 -o %s' % self.u)
|
||||
self.assertEqual(modes, self.irc.channels['#pylink'].modes)
|
||||
self.assertNotIn(self.u, self.irc.channels['#pylink'].prefixmodes['ops'])
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
15
utils.py
15
utils.py
@ -111,6 +111,7 @@ def parseModes(irc, target, args):
|
||||
prefix = mode
|
||||
else:
|
||||
arg = None
|
||||
log.debug('Current mode: %s%s; args left: %s', prefix, mode, args)
|
||||
if mode in (supported_modes['*A'] + supported_modes['*B']):
|
||||
# Must have parameter.
|
||||
log.debug('Mode %s: This mode must have parameter.', mode)
|
||||
@ -150,16 +151,24 @@ def applyModes(irc, target, changedmodes):
|
||||
log.debug('(%s) Final prefixmodes list: %s', irc.name, irc.channels[target].prefixmodes)
|
||||
if mode[0][1] in irc.prefixmodes:
|
||||
# Ignore other prefix modes such as InspIRCd's +Yy
|
||||
log.debug('(%s) Not adding mode %s to IrcChannel.modes because it\'s a prefix mode', irc.name, str(mode))
|
||||
continue
|
||||
if mode[0][0] == '+':
|
||||
# We're adding a mode
|
||||
modelist.add(mode)
|
||||
log.debug('(%s) Adding mode %r on %s', irc.name, mode, target)
|
||||
else:
|
||||
# We're removing a mode
|
||||
mode[0] = mode[0].replace('-', '+')
|
||||
modelist.discard(mode)
|
||||
log.debug('(%s) Removing mode %r on %s', irc.name, mode, target)
|
||||
# We're removing a mode
|
||||
if mode[1] is None:
|
||||
# We're removing a mode that only takes arguments when setting.
|
||||
for oldmode in modelist.copy():
|
||||
if oldmode[0][1] == mode[0][1]:
|
||||
modelist.discard(oldmode)
|
||||
else:
|
||||
# Swap the - for a + and then remove it from the list.
|
||||
mode = ('+' + mode[0][1], mode[1])
|
||||
modelist.discard(mode)
|
||||
log.debug('(%s) Final modelist: %s', irc.name, modelist)
|
||||
|
||||
def joinModes(modes):
|
||||
|
Loading…
Reference in New Issue
Block a user