ubot2/rtmbot.py

177 lines
5.5 KiB
Python
Raw Normal View History

2014-12-08 15:31:55 -08:00
#!/usr/bin/env python
2014-11-17 17:07:52 -08:00
2014-11-17 21:17:37 -08:00
import sys
sys.dont_write_bytecode = True
2014-11-17 17:07:52 -08:00
import glob
import yaml
import json
import os
import sys
import time
2014-12-11 16:25:41 -08:00
import logging
2014-11-17 17:07:52 -08:00
from slackclient import SlackClient
2014-11-17 17:27:40 -08:00
def dbg(debug_string):
if debug:
2014-12-11 16:25:41 -08:00
logging.info(debug_string)
2014-11-17 17:27:40 -08:00
2014-11-17 17:07:52 -08:00
class RtmBot(object):
def __init__(self, token):
self.token = token
self.bot_plugins = []
self.slack_client = None
def connect(self):
"""Convenience method that creates Server instance"""
self.slack_client = SlackClient(self.token)
self.slack_client.rtm_connect()
2014-11-17 17:07:52 -08:00
def start(self):
self.connect()
self.load_plugins()
while True:
for reply in self.slack_client.rtm_read():
2014-11-17 17:07:52 -08:00
self.input(reply)
self.crons()
self.output()
time.sleep(.1)
def input(self, data):
if "type" in data:
function_name = "process_" + data["type"]
dbg("got {}".format(function_name))
2014-11-17 17:07:52 -08:00
for plugin in self.bot_plugins:
plugin.do(function_name, data)
def output(self):
for plugin in self.bot_plugins:
2014-12-02 18:34:52 -08:00
limiter = False
2014-11-17 17:07:52 -08:00
for output in plugin.do_output():
channel = self.slack_client.server.channels.find(output[0])
2014-12-02 18:34:52 -08:00
if channel != None and output[1] != None:
if limiter == True:
time.sleep(1)
limiter = False
channel.send_message("{}".format(output[1]))
2014-12-02 18:34:52 -08:00
limiter = True
2014-11-17 17:07:52 -08:00
def crons(self):
for plugin in self.bot_plugins:
plugin.do_jobs()
def load_plugins(self):
2014-12-11 16:25:41 -08:00
for plugin in glob.glob(directory+'/plugins/*'):
2014-11-17 21:17:37 -08:00
sys.path.insert(0, plugin)
2014-12-11 16:25:41 -08:00
sys.path.insert(0, directory+'/plugins/')
for plugin in glob.glob(directory+'/plugins/*.py') + glob.glob(directory+'/plugins/*/*.py'):
logging.info(plugin)
name = plugin.split('/')[-1][:-3]
2014-11-17 21:17:37 -08:00
# try:
self.bot_plugins.append(Plugin(name))
# except:
# print "error loading plugin %s" % name
2014-11-17 17:07:52 -08:00
class Plugin(object):
2014-12-11 16:25:41 -08:00
def __init__(self, name, plugin_config={}):
2014-11-17 17:07:52 -08:00
self.name = name
self.jobs = []
self.module = __import__(name)
self.register_jobs()
self.outputs = []
2014-12-11 16:25:41 -08:00
if name in config:
logging.info("config found for: " + name)
self.module.config = config[name]
if 'setup' in dir(self.module):
self.module.setup()
2014-11-17 17:07:52 -08:00
def register_jobs(self):
if 'crontable' in dir(self.module):
for interval, function in self.module.crontable:
self.jobs.append(Job(interval, eval("self.module."+function)))
2014-12-11 16:25:41 -08:00
logging.info(self.module.crontable)
2014-11-18 09:55:23 -08:00
else:
self.module.crontable = []
2014-11-17 17:07:52 -08:00
def do(self, function_name, data):
if function_name in dir(self.module):
#this makes the plugin fail with stack trace in debug mode
if not debug:
try:
eval("self.module."+function_name)(data)
except:
dbg("problem in module {} {}".format(function_name, data))
else:
2014-11-17 22:26:36 -08:00
eval("self.module."+function_name)(data)
if "catch_all" in dir(self.module):
try:
self.module.catch_all(data)
except:
dbg("problem in catch all")
2014-11-17 17:07:52 -08:00
def do_jobs(self):
for job in self.jobs:
job.check()
def do_output(self):
output = []
while True:
if 'outputs' in dir(self.module):
if len(self.module.outputs) > 0:
2014-12-11 16:25:41 -08:00
logging.info("output from {}".format(self.module))
2014-11-17 17:07:52 -08:00
output.append(self.module.outputs.pop(0))
else:
break
2014-11-18 09:55:23 -08:00
else:
self.module.outputs = []
2014-11-17 17:07:52 -08:00
return output
class Job(object):
def __init__(self, interval, function):
self.function = function
self.interval = interval
self.lastrun = 0
def __str__(self):
return "{} {} {}".format(self.function, self.interval, self.lastrun)
2014-11-17 17:07:52 -08:00
def __repr__(self):
return self.__str__()
def check(self):
if self.lastrun + self.interval < time.time():
2014-11-24 19:01:41 -08:00
if not debug:
try:
self.function()
except:
dbg("problem")
else:
self.function()
2014-11-17 17:07:52 -08:00
self.lastrun = time.time()
pass
2014-11-21 13:35:15 -08:00
class UnknownChannel(Exception):
pass
2014-11-17 17:07:52 -08:00
2014-12-11 16:25:41 -08:00
def main_loop():
2014-12-11 16:31:32 -08:00
if "LOGFILE" in config:
logging.basicConfig(filename=config["LOGFILE"], level=logging.INFO, format='%(asctime)s %(message)s')
2014-12-11 16:25:41 -08:00
logging.info(directory)
try:
bot.start()
except KeyboardInterrupt:
sys.exit(0)
except:
logging.exception('OOPS')
2014-11-17 17:07:52 -08:00
if __name__ == "__main__":
2014-12-11 16:25:41 -08:00
directory = os.path.dirname(sys.argv[0])
if not directory.startswith('/'):
directory = os.path.abspath("{}/{}".format(os.getcwd(),
directory
))
2014-11-17 17:07:52 -08:00
config = yaml.load(file('rtmbot.conf', 'r'))
2014-11-17 17:27:40 -08:00
debug = config["DEBUG"]
2014-11-17 17:07:52 -08:00
bot = RtmBot(config["SLACK_TOKEN"])
2014-12-11 16:25:41 -08:00
site_plugins = []
files_currently_downloading = []
job_hash = {}
if config.has_key("DAEMON"):
if config["DAEMON"]:
import daemon
with daemon.DaemonContext():
main_loop()
main_loop()
2014-11-17 17:07:52 -08:00