mirror of
https://github.com/jlu5/PyLink.git
synced 2024-12-25 12:12:53 +01:00
commit
dba20d4efc
23
classes.py
23
classes.py
@ -67,17 +67,18 @@ testconf = {'bot':
|
|||||||
'realname': 'PyLink Service Client',
|
'realname': 'PyLink Service Client',
|
||||||
'loglevel': 'DEBUG',
|
'loglevel': 'DEBUG',
|
||||||
},
|
},
|
||||||
'server':
|
'servers':
|
||||||
{
|
{'unittest':
|
||||||
'netname': 'fakeirc',
|
{
|
||||||
'ip': '0.0.0.0',
|
'ip': '0.0.0.0',
|
||||||
'port': 7000,
|
'port': 7000,
|
||||||
'recvpass': "abcd",
|
'recvpass': "abcd",
|
||||||
'sendpass': "abcd",
|
'sendpass': "abcd",
|
||||||
'protocol': "null",
|
'protocol': "null",
|
||||||
'hostname': "pylink.unittest",
|
'hostname': "pylink.unittest",
|
||||||
'sid': "9PY",
|
'sid': "9PY",
|
||||||
'channels': ["#pylink"],
|
'channels': ["#pylink"],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
55
main.py
55
main.py
@ -6,16 +6,19 @@ import socket
|
|||||||
import time
|
import time
|
||||||
import sys
|
import sys
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
import threading
|
||||||
|
|
||||||
from log import log
|
from log import log
|
||||||
import conf
|
import conf
|
||||||
import classes
|
import classes
|
||||||
|
import utils
|
||||||
|
|
||||||
class Irc():
|
class Irc():
|
||||||
def __init__(self, proto, conf):
|
def __init__(self, netname, proto, conf):
|
||||||
|
# threading.Thread.__init__(self)
|
||||||
# Initialize some variables
|
# Initialize some variables
|
||||||
self.connected = False
|
self.connected = False
|
||||||
self.name = conf['server']['netname']
|
self.name = netname
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
# Server, channel, and user indexes to be populated by our protocol module
|
# Server, channel, and user indexes to be populated by our protocol module
|
||||||
self.servers = {}
|
self.servers = {}
|
||||||
@ -38,7 +41,7 @@ class Irc():
|
|||||||
self.maxnicklen = 30
|
self.maxnicklen = 30
|
||||||
self.prefixmodes = 'ov'
|
self.prefixmodes = 'ov'
|
||||||
|
|
||||||
self.serverdata = conf['server']
|
self.serverdata = conf['servers'][netname]
|
||||||
self.sid = self.serverdata["sid"]
|
self.sid = self.serverdata["sid"]
|
||||||
self.botdata = conf['bot']
|
self.botdata = conf['bot']
|
||||||
self.proto = proto
|
self.proto = proto
|
||||||
@ -49,12 +52,20 @@ class Irc():
|
|||||||
port = self.serverdata["port"]
|
port = self.serverdata["port"]
|
||||||
log.info("Connecting to network %r on %s:%s", self.name, ip, port)
|
log.info("Connecting to network %r on %s:%s", self.name, ip, port)
|
||||||
self.socket = socket.socket()
|
self.socket = socket.socket()
|
||||||
|
self.socket.setblocking(0)
|
||||||
|
self.socket.settimeout(60)
|
||||||
self.socket.connect((ip, port))
|
self.socket.connect((ip, port))
|
||||||
self.proto.connect(self)
|
self.proto.connect(self)
|
||||||
self.loaded = []
|
self.loaded = []
|
||||||
self.load_plugins()
|
self.load_plugins()
|
||||||
|
reading_thread = threading.Thread(target = self.run)
|
||||||
self.connected = True
|
self.connected = True
|
||||||
self.run()
|
reading_thread.start()
|
||||||
|
|
||||||
|
def disconnect(self):
|
||||||
|
self.connected = False
|
||||||
|
self.socket.shutdown()
|
||||||
|
self.socket.close()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
buf = ""
|
buf = ""
|
||||||
@ -67,19 +78,19 @@ class Irc():
|
|||||||
break
|
break
|
||||||
while '\n' in buf:
|
while '\n' in buf:
|
||||||
line, buf = buf.split('\n', 1)
|
line, buf = buf.split('\n', 1)
|
||||||
log.debug("<- %s", line)
|
log.debug("(%s) <- %s", self.name, line)
|
||||||
proto.handle_events(self, line)
|
proto.handle_events(self, line)
|
||||||
except socket.error as e:
|
except (socket.error, classes.ProtocolError) as e:
|
||||||
log.error('Received socket.error: %s, exiting.', str(e))
|
log.error('Disconnected from network %r: %s: %s, exiting.',
|
||||||
break
|
self.name, type(e).__name__, str(e))
|
||||||
sys.exit(1)
|
self.disconnect()
|
||||||
|
|
||||||
def send(self, data):
|
def send(self, data):
|
||||||
# Safeguard against newlines in input!! Otherwise, each line gets
|
# Safeguard against newlines in input!! Otherwise, each line gets
|
||||||
# treated as a separate command, which is particularly nasty.
|
# treated as a separate command, which is particularly nasty.
|
||||||
data = data.replace('\n', ' ')
|
data = data.replace('\n', ' ')
|
||||||
data = data.encode("utf-8") + b"\n"
|
data = data.encode("utf-8") + b"\n"
|
||||||
log.debug("-> %s", data.decode("utf-8").strip("\n"))
|
log.debug("(%s) -> %s", self.name, data.decode("utf-8").strip("\n"))
|
||||||
self.socket.send(data)
|
self.socket.send(data)
|
||||||
|
|
||||||
def load_plugins(self):
|
def load_plugins(self):
|
||||||
@ -103,17 +114,17 @@ if __name__ == '__main__':
|
|||||||
if conf.conf['login']['password'] == 'changeme':
|
if conf.conf['login']['password'] == 'changeme':
|
||||||
log.critical("You have not set the login details correctly! Exiting...")
|
log.critical("You have not set the login details correctly! Exiting...")
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
protoname = conf.conf['server']['protocol']
|
|
||||||
protocols_folder = [os.path.join(os.getcwd(), 'protocols')]
|
protocols_folder = [os.path.join(os.getcwd(), 'protocols')]
|
||||||
try:
|
for network in conf.conf['servers']:
|
||||||
moduleinfo = imp.find_module(protoname, protocols_folder)
|
protoname = conf.conf['servers'][network]['protocol']
|
||||||
proto = imp.load_source(protoname, moduleinfo[1])
|
try:
|
||||||
except ImportError as e:
|
moduleinfo = imp.find_module(protoname, protocols_folder)
|
||||||
if str(e).startswith('No module named'):
|
proto = imp.load_source(protoname, moduleinfo[1])
|
||||||
log.critical('Failed to load protocol module %r: the file could not be found.', protoname)
|
except ImportError as e:
|
||||||
|
if str(e).startswith('No module named'):
|
||||||
|
log.critical('Failed to load protocol module %r: the file could not be found.', protoname)
|
||||||
|
else:
|
||||||
|
log.critical('Failed to load protocol module: import error %s', protoname, str(e))
|
||||||
|
sys.exit(2)
|
||||||
else:
|
else:
|
||||||
log.critical('Failed to load protocol module: import error %s', protoname, str(e))
|
utils.networkobjects[network] = Irc(network, proto, conf.conf)
|
||||||
sys.exit(2)
|
|
||||||
else:
|
|
||||||
irc_obj = Irc(proto, conf.conf)
|
|
||||||
|
@ -150,9 +150,31 @@ def modeServer(irc, numeric, target, modes):
|
|||||||
a list of (mode, arg) tuples, in the format of utils.parseModes() output.
|
a list of (mode, arg) tuples, in the format of utils.parseModes() output.
|
||||||
"""
|
"""
|
||||||
if not utils.isInternalServer(irc, numeric):
|
if not utils.isInternalServer(irc, numeric):
|
||||||
raise LookupError('No such PyLink PseudoClient exists.')
|
raise LookupError('No such PyLink PseudoServer exists.')
|
||||||
_sendModes(irc, numeric, target, modes)
|
_sendModes(irc, numeric, target, modes)
|
||||||
|
|
||||||
|
def killServer(irc, numeric, target, reason):
|
||||||
|
"""<irc object> <server SID> <target> <reason>
|
||||||
|
|
||||||
|
Sends a kill to <target> from a PyLink PseudoServer.
|
||||||
|
"""
|
||||||
|
if not utils.isInternalServer(irc, numeric):
|
||||||
|
raise LookupError('No such PyLink PseudoServer exists.')
|
||||||
|
_sendFromServer(irc, numeric, 'KILL %s :%s' % (target, reason))
|
||||||
|
# We don't need to call removeClient here, since the remote server
|
||||||
|
# will send a QUIT from the target if the command succeeds.
|
||||||
|
|
||||||
|
def killClient(irc, numeric, target, reason):
|
||||||
|
"""<irc object> <client numeric> <target> <reason>
|
||||||
|
|
||||||
|
Sends a kill to <target> from a PyLink PseudoClient.
|
||||||
|
"""
|
||||||
|
if not utils.isInternalClient(irc, numeric):
|
||||||
|
raise LookupError('No such PyLink PseudoClient exists.')
|
||||||
|
_sendFromServer(irc, numeric, 'KILL %s :%s' % (target, reason))
|
||||||
|
# We don't need to call removeClient here, since the remote server
|
||||||
|
# will send a QUIT from the target if the command succeeds.
|
||||||
|
|
||||||
def messageClient(irc, numeric, target, text):
|
def messageClient(irc, numeric, target, text):
|
||||||
"""<irc object> <client numeric> <text>
|
"""<irc object> <client numeric> <text>
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import unittest
|
|||||||
# Yes, we're going to even test the testing classes. Testception? I think so.
|
# Yes, we're going to even test the testing classes. Testception? I think so.
|
||||||
class TestFakeIRC(unittest.TestCase):
|
class TestFakeIRC(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.irc = classes.FakeIRC(classes.FakeProto(), classes.testconf)
|
self.irc = classes.FakeIRC('unittest', classes.FakeProto(), classes.testconf)
|
||||||
|
|
||||||
def testFakeIRC(self):
|
def testFakeIRC(self):
|
||||||
self.irc.run('this should do nothing')
|
self.irc.run('this should do nothing')
|
||||||
|
@ -11,7 +11,7 @@ import utils
|
|||||||
|
|
||||||
class TestProtoInspIRCd(unittest.TestCase):
|
class TestProtoInspIRCd(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.irc = classes.FakeIRC(inspircd, classes.testconf)
|
self.irc = classes.FakeIRC('unittest', inspircd, classes.testconf)
|
||||||
self.proto = self.irc.proto
|
self.proto = self.irc.proto
|
||||||
self.sdata = self.irc.serverdata
|
self.sdata = self.irc.serverdata
|
||||||
# This is to initialize ourself as an internal PseudoServer, so we can spawn clients
|
# This is to initialize ourself as an internal PseudoServer, so we can spawn clients
|
||||||
@ -56,8 +56,6 @@ class TestProtoInspIRCd(unittest.TestCase):
|
|||||||
self.assertIn(u, self.irc.channels['#channel'].users)
|
self.assertIn(u, self.irc.channels['#channel'].users)
|
||||||
# Non-existant user.
|
# Non-existant user.
|
||||||
self.assertRaises(LookupError, self.proto.joinClient, self.irc, '9PYZZZZZZ', '#test')
|
self.assertRaises(LookupError, self.proto.joinClient, self.irc, '9PYZZZZZZ', '#test')
|
||||||
# Invalid channel.
|
|
||||||
self.assertRaises(ValueError, self.proto.joinClient, self.irc, u, 'aaaa')
|
|
||||||
|
|
||||||
def testPartClient(self):
|
def testPartClient(self):
|
||||||
u = self.u
|
u = self.u
|
||||||
|
1
utils.py
1
utils.py
@ -8,6 +8,7 @@ global bot_commands, command_hooks
|
|||||||
# This should be a mapping of command names to functions
|
# This should be a mapping of command names to functions
|
||||||
bot_commands = {}
|
bot_commands = {}
|
||||||
command_hooks = defaultdict(list)
|
command_hooks = defaultdict(list)
|
||||||
|
networkobjects = {}
|
||||||
|
|
||||||
class TS6UIDGenerator():
|
class TS6UIDGenerator():
|
||||||
"""TS6 UID Generator module, adapted from InspIRCd source
|
"""TS6 UID Generator module, adapted from InspIRCd source
|
||||||
|
Loading…
Reference in New Issue
Block a user