separate YAML config file & multiple connections

This commit is contained in:
Ryan Hitchman 2009-11-17 17:19:26 -07:00
parent 161426f276
commit 55f4b5aa95
7 changed files with 79 additions and 37 deletions

View File

@ -4,6 +4,7 @@ syntax: glob
*.orig
iambuttbot_password
persist
config
pep8.py
.project
.pydevproject
.pydevproject

29
bot.py
View File

@ -1,9 +1,5 @@
#!/usr/bin/python
network = "localhost"
nick = "skybot"
channel = "#test"
import sys
import os
import Queue
@ -27,19 +23,28 @@ reload(init=True)
print 'Connecting to IRC'
bot.nick = nick
bot.channel = channel
bot.network = network
bot.irc = irc(network, nick)
bot.irc.join(channel)
bot.conns = {}
for connection in bot.config['connections']:
for name, conf in connection.iteritems():
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')
print 'Running main loop'
while True:
try:
out = bot.irc.out.get(timeout=1)
reload()
main(out)
reload() # these functions only do things
config() # if changes have occured
for conn in bot.conns.itervalues():
out = conn.out.get(timeout=1)
main(conn, out)
except Queue.Empty:
pass

31
core/config.py Normal file
View File

@ -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'))

View File

@ -62,13 +62,15 @@ class irc(object):
"handles the IRC protocol"
#see the docs/ folder for more information on the protocol
def __init__(self, network, nick, port=6667):
self.conn = crlf_tcp(network, port)
def __init__(self, server, nick, port=6667):
self.server = server
self.conn = crlf_tcp(server, port)
thread.start_new_thread(self.conn.run, ())
self.out = Queue.Queue() #responses from the server are placed here
# format: [rawline, prefix, command, params,
# nick, user, host, paramlist, msg]
self.nick(nick)
self.nick = nick
self.set_nick(nick)
self.cmd("USER", ["skybot v0.01", "0", "bot"])
thread.start_new_thread(self.parse_loop, ())
@ -89,7 +91,7 @@ class irc(object):
if command == "PING":
self.cmd("PONG", [params])
def nick(self, nick):
def set_nick(self, nick):
self.cmd("NICK", [nick])
def join(self, channel):

View File

@ -3,8 +3,9 @@ import traceback
class Input(object):
def __init__(self, raw, prefix, command,
def __init__(self, conn, raw, prefix, command,
params, nick, user, host, paraml, msg):
self.conn = conn
self.raw = raw
self.prefix = prefix
self.command = command
@ -15,7 +16,7 @@ class Input(object):
self.paraml = paraml
self.msg = msg
self.chan = paraml[0]
if self.chan == bot.nick:
if self.chan == conn.nick:
self.chan = nick
elif command =='JOIN':
self.chan = msg
@ -23,20 +24,21 @@ class Input(object):
class FakeBot(object):
def __init__(self, bot, input, func):
def __init__(self, bot, conn, input, func):
self.bot = bot
self.conn = conn
self.persist_dir = bot.persist_dir
self.network = bot.network
self.server = conn.server
self.input = input
self.msg = bot.irc.msg
self.cmd = bot.irc.cmd
self.join = bot.irc.join
self.msg = conn.msg
self.cmd = conn.cmd
self.join = conn.join
self.func = func
self.doreply = True
self.chan = input.chan
def say(self, msg):
self.bot.irc.msg(self.chan, msg)
self.conn.msg(self.chan, msg)
def reply(self, msg):
self.say(self.input.nick + ': ' + msg)
@ -53,9 +55,9 @@ class FakeBot(object):
else:
self.say(unicode(out))
def main(out):
def main(conn, out):
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']:
try:
input = sieve(bot, input, func, args)
@ -67,4 +69,4 @@ def main(out):
break
if input == None:
continue
thread.start_new_thread(FakeBot(bot, input, func).run, ())
thread.start_new_thread(FakeBot(bot, conn, input, func).run, ())

View File

@ -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])')
def get_log_filename(dir, network, chan):
return os.path.join(dir, 'log', gmtime('%Y'), network,
def get_log_filename(dir, server, chan):
return os.path.join(dir, 'log', gmtime('%Y'), server,
gmtime('%%s.%m-%d.log') % chan).lower()
@ -63,9 +63,9 @@ def beautify(input):
return format % args
def get_log_fd(dir, network, chan):
fn = get_log_filename(dir, network, chan)
cache_key = '%s %s' % (network, chan)
def get_log_fd(dir, server, chan):
fn = get_log_filename(dir, server, chan)
cache_key = '%s %s' % (server, chan)
filename, fd = log_fds.get(cache_key, ('', 0))
if fn != filename: # we need to open a file for writing
@ -86,7 +86,7 @@ def log(bot, input):
with lock:
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')
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)
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')

View File

@ -16,8 +16,9 @@ def sieve_suite(bot, input, func, args):
hook = args.get('hook', r'(.*)')
if args.get('prefix', True):
# add a prefix, unless it's a private message
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)
if input.re is None: