started removing bullshit magic
This commit is contained in:
parent
c6fd9e1f55
commit
7e4ea3a9ff
6 changed files with 44 additions and 59 deletions
11
cloudbot.py
11
cloudbot.py
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# we import bot as _bot for now, for legacy reasons
|
# we import bot as _bot for now, for legacy reasons
|
||||||
from core import bot as _bot
|
from core import bot as _bot
|
||||||
|
from core import loader, main
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import Queue
|
import Queue
|
||||||
|
@ -16,20 +17,14 @@ print 'CloudBot REFRESH <http://git.io/cloudbotirc>'
|
||||||
bot = _bot.Bot("cloudbot")
|
bot = _bot.Bot("cloudbot")
|
||||||
bot.logger.debug("Bot initalized.")
|
bot.logger.debug("Bot initalized.")
|
||||||
|
|
||||||
# bootstrap the reloader
|
|
||||||
bot.logger.debug("Bootstrapping reloader.")
|
|
||||||
eval(compile(open(os.path.join('core', 'reload.py'), 'U').read(),
|
|
||||||
os.path.join('core', 'reload.py'), 'exec'))
|
|
||||||
reload(init=True)
|
|
||||||
|
|
||||||
bot.logger.debug("Starting main loop.")
|
bot.logger.debug("Starting main loop.")
|
||||||
while True:
|
while True:
|
||||||
reload() # these functions only do things
|
loader.reload(bot) # these functions only do things
|
||||||
|
|
||||||
for connection in bot.connections.itervalues():
|
for connection in bot.connections.itervalues():
|
||||||
try:
|
try:
|
||||||
out = connection.out.get_nowait()
|
out = connection.out.get_nowait()
|
||||||
main(connection, out)
|
main.main(bot, connection, out)
|
||||||
except Queue.Empty:
|
except Queue.Empty:
|
||||||
pass
|
pass
|
||||||
while all(connection.out.empty() for connection in bot.connections.itervalues()):
|
while all(connection.out.empty() for connection in bot.connections.itervalues()):
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"ssl": false,
|
"ssl": false,
|
||||||
"ignore_cert": true
|
"ignore_cert": true
|
||||||
},
|
},
|
||||||
"nick": "MyCloudBot",
|
"nick": "MyCloueqerdBot",
|
||||||
"user": "cloudbot",
|
"user": "cloudbot",
|
||||||
"real_name": "CloudBot - http://git.io/cloudbotirc",
|
"real_name": "CloudBot - http://git.io/cloudbotirc",
|
||||||
"channels": ["#cloudbot", "#cloudbot2"],
|
"channels": ["#cloudbot", "#cloudbot2"],
|
||||||
|
@ -52,5 +52,6 @@
|
||||||
"rdio_key": "",
|
"rdio_key": "",
|
||||||
"rdio_secret": "",
|
"rdio_secret": "",
|
||||||
"steam_key": ""
|
"steam_key": ""
|
||||||
}
|
},
|
||||||
|
"disabled_plugins": []
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import logging
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from core import config, irc
|
from core import config, irc, loader
|
||||||
|
|
||||||
|
|
||||||
def clean_name(n):
|
def clean_name(n):
|
||||||
|
@ -25,6 +25,11 @@ class Bot(object):
|
||||||
self.connections = {}
|
self.connections = {}
|
||||||
self.connect()
|
self.connect()
|
||||||
|
|
||||||
|
# run plugin loader
|
||||||
|
self.logger.debug("Bootstrapping reloader.")
|
||||||
|
loader.reload(self, init=True)
|
||||||
|
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
"""connect to all the networks defined in the bot config"""
|
"""connect to all the networks defined in the bot config"""
|
||||||
for conf in self.config['connections']:
|
for conf in self.config['connections']:
|
||||||
|
|
49
core/reload.py → core/loader.py
Executable file → Normal file
49
core/reload.py → core/loader.py
Executable file → Normal file
|
@ -3,8 +3,11 @@ import glob
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import Queue
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
from core import main
|
||||||
|
|
||||||
|
|
||||||
if 'mtimes' not in globals():
|
if 'mtimes' not in globals():
|
||||||
mtimes = {}
|
mtimes = {}
|
||||||
|
@ -31,40 +34,18 @@ def format_plug(plug, kind='', lpad=0):
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
def reload(init=False):
|
def reload(bot, init=False):
|
||||||
changed = False
|
changed = False
|
||||||
|
|
||||||
if init:
|
if init:
|
||||||
bot.plugs = collections.defaultdict(list)
|
bot.plugins = collections.defaultdict(list)
|
||||||
bot.threads = {}
|
bot.threads = {}
|
||||||
|
|
||||||
core_fileset = set(glob.glob(os.path.join("core", "*.py")))
|
|
||||||
|
|
||||||
for filename in core_fileset:
|
|
||||||
mtime = os.stat(filename).st_mtime
|
|
||||||
if mtime != mtimes.get(filename):
|
|
||||||
mtimes[filename] = mtime
|
|
||||||
|
|
||||||
changed = True
|
|
||||||
|
|
||||||
try:
|
|
||||||
eval(compile(open(filename, 'U').read(), filename, 'exec'),
|
|
||||||
globals())
|
|
||||||
except Exception:
|
|
||||||
traceback.print_exc()
|
|
||||||
if init: # stop if there's an error (syntax?) in a core
|
|
||||||
sys.exit() # script on startup
|
|
||||||
continue
|
|
||||||
|
|
||||||
if filename == os.path.join('core', 'reload.py'):
|
|
||||||
reload(init=init)
|
|
||||||
return
|
|
||||||
|
|
||||||
fileset = set(glob.glob(os.path.join('plugins', '*.py')))
|
fileset = set(glob.glob(os.path.join('plugins', '*.py')))
|
||||||
|
|
||||||
# remove deleted/moved plugins
|
# remove deleted/moved plugins
|
||||||
for name, data in bot.plugs.iteritems():
|
for name, data in bot.plugins.iteritems():
|
||||||
bot.plugs[name] = [x for x in data if x[0]._filename in fileset]
|
bot.plugins[name] = [x for x in data if x[0]._filename in fileset]
|
||||||
|
|
||||||
for filename in list(mtimes):
|
for filename in list(mtimes):
|
||||||
if filename not in fileset and filename not in core_fileset:
|
if filename not in fileset and filename not in core_fileset:
|
||||||
|
@ -72,7 +53,7 @@ def reload(init=False):
|
||||||
|
|
||||||
for func, handler in list(bot.threads.iteritems()):
|
for func, handler in list(bot.threads.iteritems()):
|
||||||
if func._filename not in fileset:
|
if func._filename not in fileset:
|
||||||
handler.stop()
|
main.handler.stop()
|
||||||
del bot.threads[func]
|
del bot.threads[func]
|
||||||
|
|
||||||
# compile new plugins
|
# compile new plugins
|
||||||
|
@ -92,8 +73,8 @@ def reload(init=False):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# remove plugins already loaded from this filename
|
# remove plugins already loaded from this filename
|
||||||
for name, data in bot.plugs.iteritems():
|
for name, data in bot.plugins.iteritems():
|
||||||
bot.plugs[name] = [x for x in data
|
bot.plugins[name] = [x for x in data
|
||||||
if x[0]._filename != filename]
|
if x[0]._filename != filename]
|
||||||
|
|
||||||
for func, handler in list(bot.threads.iteritems()):
|
for func, handler in list(bot.threads.iteritems()):
|
||||||
|
@ -104,10 +85,10 @@ def reload(init=False):
|
||||||
for obj in namespace.itervalues():
|
for obj in namespace.itervalues():
|
||||||
if hasattr(obj, '_hook'): # check for magic
|
if hasattr(obj, '_hook'): # check for magic
|
||||||
if obj._thread:
|
if obj._thread:
|
||||||
bot.threads[obj] = Handler(obj)
|
bot.threads[obj] = main.Handler(bot, obj)
|
||||||
|
|
||||||
for type, data in obj._hook:
|
for type, data in obj._hook:
|
||||||
bot.plugs[type] += [data]
|
bot.plugins[type] += [data]
|
||||||
|
|
||||||
if not init:
|
if not init:
|
||||||
print '### new plugin (type: %s) loaded:' % \
|
print '### new plugin (type: %s) loaded:' % \
|
||||||
|
@ -115,7 +96,7 @@ def reload(init=False):
|
||||||
|
|
||||||
if changed:
|
if changed:
|
||||||
bot.commands = {}
|
bot.commands = {}
|
||||||
for plug in bot.plugs['command']:
|
for plug in bot.plugins['command']:
|
||||||
name = plug[1]['name'].lower()
|
name = plug[1]['name'].lower()
|
||||||
if not re.match(r'^\w+$', name):
|
if not re.match(r'^\w+$', name):
|
||||||
print '### ERROR: invalid command name "{}" ({})'.format(name, format_plug(plug))
|
print '### ERROR: invalid command name "{}" ({})'.format(name, format_plug(plug))
|
||||||
|
@ -128,7 +109,7 @@ def reload(init=False):
|
||||||
bot.commands[name] = plug
|
bot.commands[name] = plug
|
||||||
|
|
||||||
bot.events = collections.defaultdict(list)
|
bot.events = collections.defaultdict(list)
|
||||||
for func, args in bot.plugs['event']:
|
for func, args in bot.plugins['event']:
|
||||||
for event in args['events']:
|
for event in args['events']:
|
||||||
bot.events[event].append((func, args))
|
bot.events[event].append((func, args))
|
||||||
|
|
||||||
|
@ -151,7 +132,7 @@ def reload(init=False):
|
||||||
out += ' ' * (50 - len(out)) + ', '.join(names)
|
out += ' ' * (50 - len(out)) + ', '.join(names)
|
||||||
print out
|
print out
|
||||||
|
|
||||||
for kind, plugs in sorted(bot.plugs.iteritems()):
|
for kind, plugs in sorted(bot.plugins.iteritems()):
|
||||||
if kind == 'command':
|
if kind == 'command':
|
||||||
continue
|
continue
|
||||||
print ' {}:'.format(kind)
|
print ' {}:'.format(kind)
|
29
core/main.py
29
core/main.py
|
@ -1,12 +1,14 @@
|
||||||
import thread
|
import thread
|
||||||
import traceback
|
import traceback
|
||||||
|
import Queue
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
thread.stack_size(1024 * 512) # reduce vm size
|
thread.stack_size(1024 * 512) # reduce vm size
|
||||||
|
|
||||||
|
|
||||||
class Input(dict):
|
class Input(dict):
|
||||||
def __init__(self, conn, raw, prefix, command, params,
|
def __init__(self, bot, conn, raw, prefix, command, params,
|
||||||
nick, user, host, mask, paraml, msg):
|
nick, user, host, mask, paraml, msg):
|
||||||
|
|
||||||
chan = paraml[0].lower()
|
chan = paraml[0].lower()
|
||||||
|
@ -84,8 +86,9 @@ def do_sieve(sieve, bot, input, func, type, args):
|
||||||
class Handler(object):
|
class Handler(object):
|
||||||
"""Runs plugins in their own threads (ensures order)"""
|
"""Runs plugins in their own threads (ensures order)"""
|
||||||
|
|
||||||
def __init__(self, func):
|
def __init__(self, func, bot):
|
||||||
self.func = func
|
self.func = func
|
||||||
|
self.bot = bot
|
||||||
self.input_queue = Queue.Queue()
|
self.input_queue = Queue.Queue()
|
||||||
thread.start_new_thread(self.start, ())
|
thread.start_new_thread(self.start, ())
|
||||||
|
|
||||||
|
@ -101,7 +104,7 @@ class Handler(object):
|
||||||
if uses_db:
|
if uses_db:
|
||||||
db = db_conns.get(input.conn)
|
db = db_conns.get(input.conn)
|
||||||
if db is None:
|
if db is None:
|
||||||
db = bot.get_db_connection(input.conn)
|
db = self.bot.get_db_connection(input.conn)
|
||||||
db_conns[input.conn] = db
|
db_conns[input.conn] = db
|
||||||
input.db = db
|
input.db = db
|
||||||
|
|
||||||
|
@ -119,8 +122,8 @@ class Handler(object):
|
||||||
self.input_queue.put(value)
|
self.input_queue.put(value)
|
||||||
|
|
||||||
|
|
||||||
def dispatch(input, kind, func, args, autohelp=False):
|
def dispatch(bot, input, kind, func, args, autohelp=False):
|
||||||
for sieve, in bot.plugs['sieve']:
|
for sieve, in bot.plugins['sieve']:
|
||||||
input = do_sieve(sieve, bot, input, func, kind, args)
|
input = do_sieve(sieve, bot, input, func, kind, args)
|
||||||
if input is None:
|
if input is None:
|
||||||
return
|
return
|
||||||
|
@ -135,7 +138,7 @@ def dispatch(input, kind, func, args, autohelp=False):
|
||||||
thread.start_new_thread(run, (func, input))
|
thread.start_new_thread(run, (func, input))
|
||||||
|
|
||||||
|
|
||||||
def match_command(command):
|
def match_command(bot, command):
|
||||||
commands = list(bot.commands)
|
commands = list(bot.commands)
|
||||||
|
|
||||||
# do some fuzzy matching
|
# do some fuzzy matching
|
||||||
|
@ -148,13 +151,13 @@ def match_command(command):
|
||||||
return command
|
return command
|
||||||
|
|
||||||
|
|
||||||
def main(conn, out):
|
def main(bot, conn, out):
|
||||||
inp = Input(conn, *out)
|
inp = Input(bot, conn, *out)
|
||||||
command_prefix = conn.conf.get('command_prefix', '.')
|
command_prefix = conn.conf.get('command_prefix', '.')
|
||||||
|
|
||||||
# EVENTS
|
# EVENTS
|
||||||
for func, args in bot.events[inp.command] + bot.events['*']:
|
for func, args in bot.events[inp.command] + bot.events['*']:
|
||||||
dispatch(Input(conn, *out), "event", func, args)
|
dispatch(bot, Input(bot, conn, *out), "event", func, args)
|
||||||
|
|
||||||
if inp.command == 'PRIVMSG':
|
if inp.command == 'PRIVMSG':
|
||||||
# COMMANDS
|
# COMMANDS
|
||||||
|
@ -170,23 +173,23 @@ def main(conn, out):
|
||||||
|
|
||||||
if m:
|
if m:
|
||||||
trigger = m.group(1).lower()
|
trigger = m.group(1).lower()
|
||||||
command = match_command(trigger)
|
command = match_command(bot, trigger)
|
||||||
|
|
||||||
if isinstance(command, list): # multiple potential matches
|
if isinstance(command, list): # multiple potential matches
|
||||||
input = Input(conn, *out)
|
input = Input(conn, *out)
|
||||||
input.notice("Did you mean {} or {}?".format
|
input.notice("Did you mean {} or {}?".format
|
||||||
(', '.join(command[:-1]), command[-1]))
|
(', '.join(command[:-1]), command[-1]))
|
||||||
elif command in bot.commands:
|
elif command in bot.commands:
|
||||||
input = Input(conn, *out)
|
input = Input(bot, conn, *out)
|
||||||
input.trigger = trigger
|
input.trigger = trigger
|
||||||
input.inp_unstripped = m.group(2)
|
input.inp_unstripped = m.group(2)
|
||||||
input.inp = input.inp_unstripped.strip()
|
input.inp = input.inp_unstripped.strip()
|
||||||
|
|
||||||
func, args = bot.commands[command]
|
func, args = bot.commands[command]
|
||||||
dispatch(input, "command", func, args, autohelp=True)
|
dispatch(bot, input, "command", func, args, autohelp=True)
|
||||||
|
|
||||||
# REGEXES
|
# REGEXES
|
||||||
for func, args in bot.plugs['regex']:
|
for func, args in bot.plugins['regex']:
|
||||||
m = args['re'].search(inp.lastparam)
|
m = args['re'].search(inp.lastparam)
|
||||||
if m:
|
if m:
|
||||||
input = Input(conn, *out)
|
input = Input(conn, *out)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from util import hook, http
|
from util import hook, http
|
||||||
|
from lib import pygeoip
|
||||||
import os.path
|
import os.path
|
||||||
import pygeoip
|
|
||||||
import json
|
import json
|
||||||
import gzip
|
import gzip
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
|
|
Reference in a new issue