separate YAML config file & multiple connections
This commit is contained in:
parent
161426f276
commit
55f4b5aa95
|
@ -4,6 +4,7 @@ syntax: glob
|
|||
*.orig
|
||||
iambuttbot_password
|
||||
persist
|
||||
config
|
||||
pep8.py
|
||||
.project
|
||||
.pydevproject
|
||||
.pydevproject
|
||||
|
|
29
bot.py
29
bot.py
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
#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):
|
||||
|
|
26
core/main.py
26
core/main.py
|
@ -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, ())
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue