separate YAML config file & multiple connections
This commit is contained in:
parent
161426f276
commit
55f4b5aa95
|
@ -4,6 +4,7 @@ syntax: glob
|
||||||
*.orig
|
*.orig
|
||||||
iambuttbot_password
|
iambuttbot_password
|
||||||
persist
|
persist
|
||||||
|
config
|
||||||
pep8.py
|
pep8.py
|
||||||
.project
|
.project
|
||||||
.pydevproject
|
.pydevproject
|
||||||
|
|
29
bot.py
29
bot.py
|
@ -1,9 +1,5 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
network = "localhost"
|
|
||||||
nick = "skybot"
|
|
||||||
channel = "#test"
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import Queue
|
import Queue
|
||||||
|
@ -27,19 +23,28 @@ reload(init=True)
|
||||||
|
|
||||||
print 'Connecting to IRC'
|
print 'Connecting to IRC'
|
||||||
|
|
||||||
bot.nick = nick
|
bot.conns = {}
|
||||||
bot.channel = channel
|
|
||||||
bot.network = network
|
for connection in bot.config['connections']:
|
||||||
bot.irc = irc(network, nick)
|
for name, conf in connection.iteritems():
|
||||||
bot.irc.join(channel)
|
if name in bot.conns:
|
||||||
|
print 'ERROR: more than one connection named "%s"' % name
|
||||||
|
raise ValueError
|
||||||
|
bot.conns[name] = irc(conf['server'], conf['nick'])
|
||||||
|
for channel in conf.get('channels', []):
|
||||||
|
bot.conns[name].join(channel)
|
||||||
|
|
||||||
bot.persist_dir = os.path.abspath('persist')
|
bot.persist_dir = os.path.abspath('persist')
|
||||||
|
|
||||||
print 'Running main loop'
|
print 'Running main loop'
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
out = bot.irc.out.get(timeout=1)
|
reload() # these functions only do things
|
||||||
reload()
|
config() # if changes have occured
|
||||||
main(out)
|
|
||||||
|
for conn in bot.conns.itervalues():
|
||||||
|
out = conn.out.get(timeout=1)
|
||||||
|
main(conn, out)
|
||||||
except Queue.Empty:
|
except Queue.Empty:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
from util import yaml
|
||||||
|
|
||||||
|
if not os.path.exists('config'):
|
||||||
|
conf = {'connections': [
|
||||||
|
{'local irc': {'nick': 'skybot',
|
||||||
|
'server': 'localhost',
|
||||||
|
'channels': ["#test"]}}]}
|
||||||
|
yaml.dump(conf, open('config', 'w'))
|
||||||
|
del conf
|
||||||
|
|
||||||
|
bot.config = yaml.load(open('config'))
|
||||||
|
bot._config_dirty = False
|
||||||
|
bot._config_mtime = os.stat('config').st_mtime
|
||||||
|
|
||||||
|
def config_dirty(self):
|
||||||
|
"signals that config has changed and should be written to disk"
|
||||||
|
self._config_dirty = True
|
||||||
|
|
||||||
|
bot.config_dirty = config_dirty
|
||||||
|
|
||||||
|
def config():
|
||||||
|
# reload config from file if file has changed
|
||||||
|
if bot._config_mtime != os.stat('config').st_mtime:
|
||||||
|
bot.config = yaml.load(open('config'))
|
||||||
|
bot._config_dirty = False
|
||||||
|
|
||||||
|
# save config to file if config has changed
|
||||||
|
if bot._config_dirty:
|
||||||
|
yaml.dump(bot.config, open('config', 'w'))
|
10
core/irc.py
10
core/irc.py
|
@ -62,13 +62,15 @@ class irc(object):
|
||||||
"handles the IRC protocol"
|
"handles the IRC protocol"
|
||||||
#see the docs/ folder for more information on the protocol
|
#see the docs/ folder for more information on the protocol
|
||||||
|
|
||||||
def __init__(self, network, nick, port=6667):
|
def __init__(self, server, nick, port=6667):
|
||||||
self.conn = crlf_tcp(network, port)
|
self.server = server
|
||||||
|
self.conn = crlf_tcp(server, port)
|
||||||
thread.start_new_thread(self.conn.run, ())
|
thread.start_new_thread(self.conn.run, ())
|
||||||
self.out = Queue.Queue() #responses from the server are placed here
|
self.out = Queue.Queue() #responses from the server are placed here
|
||||||
# format: [rawline, prefix, command, params,
|
# format: [rawline, prefix, command, params,
|
||||||
# nick, user, host, paramlist, msg]
|
# nick, user, host, paramlist, msg]
|
||||||
self.nick(nick)
|
self.nick = nick
|
||||||
|
self.set_nick(nick)
|
||||||
self.cmd("USER", ["skybot v0.01", "0", "bot"])
|
self.cmd("USER", ["skybot v0.01", "0", "bot"])
|
||||||
thread.start_new_thread(self.parse_loop, ())
|
thread.start_new_thread(self.parse_loop, ())
|
||||||
|
|
||||||
|
@ -89,7 +91,7 @@ class irc(object):
|
||||||
if command == "PING":
|
if command == "PING":
|
||||||
self.cmd("PONG", [params])
|
self.cmd("PONG", [params])
|
||||||
|
|
||||||
def nick(self, nick):
|
def set_nick(self, nick):
|
||||||
self.cmd("NICK", [nick])
|
self.cmd("NICK", [nick])
|
||||||
|
|
||||||
def join(self, channel):
|
def join(self, channel):
|
||||||
|
|
26
core/main.py
26
core/main.py
|
@ -3,8 +3,9 @@ import traceback
|
||||||
|
|
||||||
class Input(object):
|
class Input(object):
|
||||||
|
|
||||||
def __init__(self, raw, prefix, command,
|
def __init__(self, conn, raw, prefix, command,
|
||||||
params, nick, user, host, paraml, msg):
|
params, nick, user, host, paraml, msg):
|
||||||
|
self.conn = conn
|
||||||
self.raw = raw
|
self.raw = raw
|
||||||
self.prefix = prefix
|
self.prefix = prefix
|
||||||
self.command = command
|
self.command = command
|
||||||
|
@ -15,7 +16,7 @@ class Input(object):
|
||||||
self.paraml = paraml
|
self.paraml = paraml
|
||||||
self.msg = msg
|
self.msg = msg
|
||||||
self.chan = paraml[0]
|
self.chan = paraml[0]
|
||||||
if self.chan == bot.nick:
|
if self.chan == conn.nick:
|
||||||
self.chan = nick
|
self.chan = nick
|
||||||
elif command =='JOIN':
|
elif command =='JOIN':
|
||||||
self.chan = msg
|
self.chan = msg
|
||||||
|
@ -23,20 +24,21 @@ class Input(object):
|
||||||
|
|
||||||
class FakeBot(object):
|
class FakeBot(object):
|
||||||
|
|
||||||
def __init__(self, bot, input, func):
|
def __init__(self, bot, conn, input, func):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
self.conn = conn
|
||||||
self.persist_dir = bot.persist_dir
|
self.persist_dir = bot.persist_dir
|
||||||
self.network = bot.network
|
self.server = conn.server
|
||||||
self.input = input
|
self.input = input
|
||||||
self.msg = bot.irc.msg
|
self.msg = conn.msg
|
||||||
self.cmd = bot.irc.cmd
|
self.cmd = conn.cmd
|
||||||
self.join = bot.irc.join
|
self.join = conn.join
|
||||||
self.func = func
|
self.func = func
|
||||||
self.doreply = True
|
self.doreply = True
|
||||||
self.chan = input.chan
|
self.chan = input.chan
|
||||||
|
|
||||||
def say(self, msg):
|
def say(self, msg):
|
||||||
self.bot.irc.msg(self.chan, msg)
|
self.conn.msg(self.chan, msg)
|
||||||
|
|
||||||
def reply(self, msg):
|
def reply(self, msg):
|
||||||
self.say(self.input.nick + ': ' + msg)
|
self.say(self.input.nick + ': ' + msg)
|
||||||
|
@ -53,9 +55,9 @@ class FakeBot(object):
|
||||||
else:
|
else:
|
||||||
self.say(unicode(out))
|
self.say(unicode(out))
|
||||||
|
|
||||||
def main(out):
|
def main(conn, out):
|
||||||
for csig, func, args in (bot.plugs['command'] + bot.plugs['event']):
|
for csig, func, args in (bot.plugs['command'] + bot.plugs['event']):
|
||||||
input = Input(*out)
|
input = Input(conn, *out)
|
||||||
for fsig, sieve in bot.plugs['sieve']:
|
for fsig, sieve in bot.plugs['sieve']:
|
||||||
try:
|
try:
|
||||||
input = sieve(bot, input, func, args)
|
input = sieve(bot, input, func, args)
|
||||||
|
@ -67,4 +69,4 @@ def main(out):
|
||||||
break
|
break
|
||||||
if input == None:
|
if input == None:
|
||||||
continue
|
continue
|
||||||
thread.start_new_thread(FakeBot(bot, input, func).run, ())
|
thread.start_new_thread(FakeBot(bot, conn, input, func).run, ())
|
||||||
|
|
|
@ -30,8 +30,8 @@ ctcp_formats = {'ACTION': '* %(nick)s %(ctcpmsg)s'}
|
||||||
irc_color_re = re.compile(r'(\x03(\d+,\d+|\d)|[\x0f\x02\x16\x1f])')
|
irc_color_re = re.compile(r'(\x03(\d+,\d+|\d)|[\x0f\x02\x16\x1f])')
|
||||||
|
|
||||||
|
|
||||||
def get_log_filename(dir, network, chan):
|
def get_log_filename(dir, server, chan):
|
||||||
return os.path.join(dir, 'log', gmtime('%Y'), network,
|
return os.path.join(dir, 'log', gmtime('%Y'), server,
|
||||||
gmtime('%%s.%m-%d.log') % chan).lower()
|
gmtime('%%s.%m-%d.log') % chan).lower()
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,9 +63,9 @@ def beautify(input):
|
||||||
return format % args
|
return format % args
|
||||||
|
|
||||||
|
|
||||||
def get_log_fd(dir, network, chan):
|
def get_log_fd(dir, server, chan):
|
||||||
fn = get_log_filename(dir, network, chan)
|
fn = get_log_filename(dir, server, chan)
|
||||||
cache_key = '%s %s' % (network, chan)
|
cache_key = '%s %s' % (server, chan)
|
||||||
filename, fd = log_fds.get(cache_key, ('', 0))
|
filename, fd = log_fds.get(cache_key, ('', 0))
|
||||||
|
|
||||||
if fn != filename: # we need to open a file for writing
|
if fn != filename: # we need to open a file for writing
|
||||||
|
@ -86,7 +86,7 @@ def log(bot, input):
|
||||||
with lock:
|
with lock:
|
||||||
timestamp = gmtime(timestamp_format)
|
timestamp = gmtime(timestamp_format)
|
||||||
|
|
||||||
fd = get_log_fd(bot.persist_dir, bot.network, 'raw')
|
fd = get_log_fd(bot.persist_dir, bot.server, 'raw')
|
||||||
fd.write(timestamp + ' ' + input.raw + '\n')
|
fd.write(timestamp + ' ' + input.raw + '\n')
|
||||||
|
|
||||||
if input.command == 'QUIT': # these are temporary fixes until proper
|
if input.command == 'QUIT': # these are temporary fixes until proper
|
||||||
|
@ -99,5 +99,5 @@ def log(bot, input):
|
||||||
print '%s %s %s' % (timestamp, input.chan, beau)
|
print '%s %s %s' % (timestamp, input.chan, beau)
|
||||||
|
|
||||||
if input.chan:
|
if input.chan:
|
||||||
fd = get_log_fd(bot.persist_dir, bot.network, input.chan)
|
fd = get_log_fd(bot.persist_dir, bot.server, input.chan)
|
||||||
fd.write(timestamp + ' ' + beau + '\n')
|
fd.write(timestamp + ' ' + beau + '\n')
|
||||||
|
|
|
@ -16,8 +16,9 @@ def sieve_suite(bot, input, func, args):
|
||||||
hook = args.get('hook', r'(.*)')
|
hook = args.get('hook', r'(.*)')
|
||||||
|
|
||||||
if args.get('prefix', True):
|
if args.get('prefix', True):
|
||||||
|
# add a prefix, unless it's a private message
|
||||||
hook = (r'^(?:[.!]|' if input.chan != input.nick else r'^(?:[.!]?|') \
|
hook = (r'^(?:[.!]|' if input.chan != input.nick else r'^(?:[.!]?|') \
|
||||||
+ bot.nick +r'[:,]*\s*)' + hook
|
+ input.conn.nick + r'[:,]*\s*)' + hook
|
||||||
|
|
||||||
input.re = re.match(hook, input.msg, flags=re.I)
|
input.re = re.match(hook, input.msg, flags=re.I)
|
||||||
if input.re is None:
|
if input.re is None:
|
||||||
|
|
Loading…
Reference in New Issue