def __init__(self, configFile): self.config = Config(configFile) self.connectionFactory = DesertBotFactory(self) self.log = None self.moduleHandler = ModuleHandler(self) self.servers = {} self.storage = None self.storageSync = None self.startTime = now()
def __init__(self, cmdArgs): self.configs = {} for server in cmdArgs.servers: config = Config("{}.yaml".format(server)) if config.loadConfig(): self.configs[server] = config self.botfactories = {} for server, configObject in self.configs.iteritems(): self.startBotFactory(configObject)
def __init__(self, cmdArgs): self.configs = {} for configFileName in cmdArgs.configs: if not configFileName.endswith(".yaml"): config = Config("{}.yaml".format(configFileName)) else: config = Config(configFileName) if config.loadConfig(): self.configs[config.configFileName] = config self.botfactories = {} for configFileName, configObject in self.configs.iteritems(): self.startBotFactory(configObject) reactor.run()
def __init__(self, section): parser = argparse.ArgumentParser(description='PyHeufyBot shelve parsing tool.') parser.add_argument('-s', '--storage', help='The storage file to use', type=str, default='../../data/heufybot.db') parser.add_argument('-n', '--network', help='The network name to import from', type=str, required=True) parser.add_argument('-c', '--config', help='the config file to read from', type=str, required=True) options = parser.parse_args() self.config = Config(options.config) self.config.loadConfig() with shelve.open(options.storage) as storage: self.data = storage[section][options.network] storage.close() self.rootDir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir)) self.dataPath = os.path.join(self.rootDir, 'data', self.config['server']) if not os.path.exists(self.dataPath): os.makedirs(self.dataPath) self.storage = DataStore(os.path.join(self.dataPath, 'desertbot.json'))
def __init__(self, config: Config): self.logger = logging.getLogger('desertbot.factory') self.exitStatus = 0 self.bot = DesertBot(self, config) self.protocol = self.bot self.server = config['server'] self.port = config.getWithDefault('port', 6667) if config.getWithDefault('tls', False): self.logger.info('Attempting secure connection to {}:{}...' .format(self.server, self.port)) if ssl is not None: reactor.connectSSL(self.server, self.port, self, ssl.ClientContextFactory()) else: self.logger.error('Connection to {}:{} failed;' ' PyOpenSSL is required for secure connections.' .format(self.server, self.port)) else: self.logger.info('Attempting connection to {}:{}'.format(self.server, self.port)) reactor.connectTCP(self.server, self.port, self)
class PyHeufyBotUtil(object): def __init__(self, section): parser = argparse.ArgumentParser(description='PyHeufyBot shelve parsing tool.') parser.add_argument('-s', '--storage', help='The storage file to use', type=str, default='../../data/heufybot.db') parser.add_argument('-n', '--network', help='The network name to import from', type=str, required=True) parser.add_argument('-c', '--config', help='the config file to read from', type=str, required=True) options = parser.parse_args() self.config = Config(options.config) self.config.loadConfig() with shelve.open(options.storage) as storage: self.data = storage[section][options.network] storage.close() self.rootDir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir)) self.dataPath = os.path.join(self.rootDir, 'data', self.config['server']) if not os.path.exists(self.dataPath): os.makedirs(self.dataPath) self.storage = DataStore(os.path.join(self.dataPath, 'desertbot.json'))
def __init__(self, config: Config): self.logger = logging.getLogger('desertbot.factory') self.exitStatus = 0 self.connectionAttempts = 0 self.bot = DesertBot(self, config) self.protocol = self.bot self.server = config['server'] self.port = config.getWithDefault('port', 6667) if config.getWithDefault('tls', False): self.logger.info('Attempting secure connection to {}:{}...' .format(self.server, self.port)) if ssl is not None: reactor.connectSSL(self.server, self.port, self, ssl.ClientContextFactory()) else: self.logger.error('Connection to {}:{} failed;' ' PyOpenSSL is required for secure connections.' .format(self.server, self.port)) else: self.logger.info('Attempting connection to {}:{}'.format(self.server, self.port)) reactor.connectTCP(self.server, self.port, self)
def onTrigger(self, message): """ @type message: IRCMessage """ if message.command == u"connect": if len(message.parameterList) == 0: return IRCResponse(ResponseType.PRIVMSG, u"Connect where?", message.user, message.replyTo) for configFileName in message.parameterList: try: if not configFileName.endswith(".yaml"): config = Config("{}.yaml".format(configFileName)) else: config = Config(configFileName) if config.loadConfig(): message.bot.bothandler.configs[config.configFileName] = config message.bot.bothandler.startBotFactory(config) return IRCResponse(ResponseType.PRIVMSG, u"Using \"{}\" for new connection...".format( config.configFileName), message.user, message.replyTo) else: return IRCResponse(ResponseType.PRIVMSG, u"\"{}\" was not correct. Aborting.".format( config.configFileName), message.user, message.replyTo) except Exception as e: log.err("Connecting with \"{}\" failed. ({})".format(configFileName, e)) return IRCResponse(ResponseType.PRIVMSG, u"Connecting with \"{}\" failed. ({})".format( configFileName, e), message.user, message.replyTo) if message.command == u"quit": if datetime.datetime.utcnow() > message.bot.startTime + datetime.timedelta(seconds=10): message.bot.factory.shouldReconnect = False message.bot.bothandler.stopBotFactory(message.bot.config.configFileName, None) if message.command == u"quitfrom": if len(message.parameterList) == 0: return IRCResponse(ResponseType.PRIVMSG, u"Quit from where?", message.user, message.replyTo) for configFileName in message.parameterList: if not configFileName.endswith(".yaml"): quitFromConfig = "{}.yaml".format(configFileName) else: quitFromConfig = configFileName if quitFromConfig == message.bot.config.configFileName: return IRCResponse(ResponseType.PRIVMSG, u"Can't quit from here with this!", message.user, message.replyTo) else: quitMessage = u"Killed from \"{}\"".format(message.bot.config["server"]) result = message.bot.bothandler.stopBotFactory(quitFromConfig, quitMessage) if result: return IRCResponse(ResponseType.PRIVMSG, u"Successfully quit from \"{}\".".format(configFileName), message.user, message.replyTo) else: return IRCResponse(ResponseType.PRIVMSG, u"I am not on \"{}\"!".format(configFileName), message.user, message.replyTo) if message.command == u"restart": if datetime.datetime.utcnow() > message.bot.startTime + datetime.timedelta(seconds=10): message.bot.bothandler.restart() if message.command == u"shutdown": if datetime.datetime.utcnow() > message.bot.startTime + datetime.timedelta(seconds=10): message.bot.bothandler.shutdown()
# Modules can then just add more handlers to the root logger # to capture all logs to files in various ways rootLogger = logging.getLogger('desertbot') numericLevel = getattr(logging, cmdArgs.loglevel.upper(), None) if isinstance(numericLevel, int): rootLogger.setLevel(numericLevel) else: raise ValueError('Invalid log level {}'.format(cmdArgs.loglevel)) logFormatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s', '%H:%M:%S') streamHandler = logging.StreamHandler(stream=sys.stdout) streamHandler.setFormatter(logFormatter) rootLogger.addHandler(streamHandler) observer = log.PythonLoggingObserver(loggerName='desertbot.twisted') observer.start() config = Config(cmdArgs.config) try: config.loadConfig() except ConfigError: rootLogger.exception("Failed to load configuration file {}".format( cmdArgs.config)) else: factory = DesertBotFactory(config) reactor.run() sys.exit(factory.exitStatus)
class DesertBot(object): def __init__(self, configFile): self.config = Config(configFile) self.connectionFactory = DesertBotFactory(self) self.log = None self.moduleHandler = ModuleHandler(self) self.servers = {} self.storage = None self.storageSync = None self.startTime = now() def startup(self): if ssl is None: self.log.warn( "The PyOpenSSL package was not found. You will not be able to connect to servers using SSL." ) self.log.info("Loading configuration file...") self.config.loadConfig() self.log.info("Loading storage...") self.storage = shelve.open( self.config.itemWithDefault("storage_path", "desertbot.db")) self.storageSync = LoopingCall(self.storage.sync) self.storageSync.start(self.config.itemWithDefault( "storage_sync_interval", 5), now=False) self.log.info("Loading modules...") self.moduleHandler.loadAllModules() self.log.info("Initiating connections...") self._initiateConnections() self.log.info("Starting reactor...") reactor.run() def _initiateConnections(self): for server in self.config["servers"].iterkeys(): self.connectServer(server) def connectServer(self, host): if host in self.servers: error = "A connection to {} was requested, but already exists.".format( host) self.log.warn(error) return error if host not in self.config["servers"]: error = "A connection to {} was requested, but there is no config data for this server.".format( host) self.log.warn(error) return error port = int(self.config.serverItemWithDefault(host, "port", 6667)) if self.config.serverItemWithDefault(host, "ssl", False): self.log.info("Attempting secure connection to {host}/{port}...", host=host, port=port) if ssl is not None: reactor.connectSSL(host, port, self.connectionFactory, ssl.ClientContextFactory()) else: self.log.error( "Can't connect to {host}/{port}; PyOpenSSL is required to allow secure connections.", host=host, port=port) else: self.log.info("Attempting connection to {host}/{port}...", host=host, port=port) reactor.connectTCP(host, port, self.connectionFactory) def disconnectServer(self, host, quitMessage="Quitting..."): if host not in self.servers: error = "A disconnect from {} was requested, but this connection doesn't exist.".format( host) self.log.warn(error) return error self.servers[host].disconnect(quitMessage, True) def reconnectServer(self, host, quitMessage="Reconnecting..."): if host not in self.servers: error = "A reconnect to {} was requested, but this connection doesn't exist.".format( host) self.log.warn(error) return error self.servers[host].disconnect(quitMessage) def shutdown(self, quitMessage="Shutting down..."): serversCopy = self.servers.copy() for server in serversCopy.itervalues(): server.disconnect(quitMessage, True) def restart(self, quitMessage="Restarting..."): reactor.addSystemEventTrigger( "after", "shutdown", lambda: os.execl(sys.executable, sys.executable, *sys.argv)) self.shutdown(quitMessage) def countConnections(self): if len(self.servers) == 0: self.log.info("No more connections alive, shutting down...") # If we have any connections that have been started but never finished, stop trying self.connectionFactory.stopTrying() self.log.info("Closing storage...") if self.storageSync.running: self.storageSync.stop() self.storage.close() self.log.info("Unloading modules...") self.moduleHandler.unloadAllModules() self.log.info("Stopping reactor...") reactor.stop()