This repository has been archived on 2023-04-13. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
CloudBot/core/bot.py
2014-03-06 11:45:00 +13:00

167 lines
No EOL
5.4 KiB
Python

import time
import logging
import re
import os
import queue
import collections
import threading
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy import create_engine
from core import config, irc, main
from core.permissions import PermissionManager
from core.loader import PluginLoader
def clean_name(n):
"""strip all spaces and capitalization"""
return re.sub('[^A-Za-z0-9_]+', '', n.replace(" ", "_"))
def get_logger():
"""create and return a new logger object"""
# create logger
logger = logging.getLogger("cloudbot")
logger.setLevel(logging.DEBUG)
# add a file handler
log_name = "bot.log"
fh = logging.FileHandler(log_name)
fh.setLevel(logging.INFO)
# stdout handler
sh = logging.StreamHandler()
sh.setLevel(logging.DEBUG)
# create a formatter and set the formatter for the handler.
frmt = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s')
fh.setFormatter(frmt)
simple_frmt = logging.Formatter('[%(levelname)s] %(message)s')
sh.setFormatter(simple_frmt)
# add the Handlers to the logger
logger.addHandler(fh)
logger.addHandler(sh)
return logger
class Bot(threading.Thread):
def __init__(self):
# basic variables
self.start_time = time.time()
self.running = True
self.do_restart = False
self.connections = []
# set up config and logging
self.setup()
self.logger.debug("Bot setup completed.")
# start IRC connections
self.connect()
print(self.connections)
for conn in self.connections:
conn.permissions = PermissionManager(self, conn)
print(conn)
# run plugin loader
self.plugins = collections.defaultdict(list)
self.threads = {}
self.loader = PluginLoader(self)
threading.Thread.__init__(self)
def run(self):
"""recieves input from the IRC engine and processes it"""
self.logger.info("Starting main thread.")
while self.running:
for conn in self.connections:
try:
incoming = conn.parsed_queue.get_nowait()
if incoming == StopIteration:
print("StopIteration")
# IRC engine has signalled timeout, so reconnect (ugly)
conn.connection.reconnect()
main.main(self, conn, incoming)
except queue.Empty:
pass
# if no messages are in the incoming queue, sleep
while self.running and all(c.parsed_queue.empty() for c in self.connections):
time.sleep(.1)
def setup(self):
"""create the logger and config objects"""
# logging
self.logger = get_logger()
self.logger.debug("Logging system initalised.")
# data folder
self.data_dir = os.path.abspath('persist')
if not os.path.exists(self.data_dir):
self.logger.debug("Data folder not found, creating.")
os.mkdir(self.data_dir)
# config
self.config = config.Config(self)
self.logger.debug("Config system initalised.")
# db
engine = create_engine('sqlite:///cloudbot.db')
db_factory = sessionmaker(bind=engine)
self.db_session = scoped_session(db_factory)
self.logger.debug("Database system initalised.")
def connect(self):
"""connect to all the networks defined in the bot config"""
for conf in self.config['connections']:
# strip all spaces and capitalization from the connection name
name = clean_name(conf['name'])
nick = conf['nick']
server = conf['connection']['server']
port = conf['connection'].get('port', 6667)
self.logger.debug("({}) Creating connection to {}.".format(name, server))
if conf['connection'].get('ssl'):
self.connections.append(irc.SSLIRC(name, server, nick, config=conf,
port=port, logger=self.logger, channels=conf['channels'],
ignore_certificate_errors=conf['connection'].get('ignore_cert', True)))
self.logger.debug("({}) Created SSL connection.".format(name))
else:
self.connections.append(irc.IRC(name, server, nick, config=conf,
port=port, logger=self.logger, channels=conf['channels']))
self.logger.debug("({}) Created connection.".format(name))
def stop(self, reason=None):
"""quits all networks and shuts the bot down"""
self.logger.info("Stopping bot.")
self.config.observer.stop()
self.logger.debug("Stopping config reloader.")
self.loader.stop()
self.logger.debug("Stopping plugin loader.")
for connection in self.connections:
self.logger.debug("({}) Closing connection.".format(connection.name))
if reason:
connection.cmd("QUIT", [reason])
else:
connection.cmd("QUIT")
connection.stop()
self.logger.debug("Logging engine stopped")
logging.shutdown()
self.running = False
def restart(self, reason=None):
"""shuts the bot down and restarts it"""
self.do_restart = True
self.stop(reason)