示例#1
0
    def __init__(self, ssbot, md, config, MQueue):
        BotInterface.__init__(self, ssbot, md)
        ssbot.register_module_info(
            __name__, "MasterBot", "The Junky",
            "Manages other bots (starts/stops/lists/etc)", "1.0d")
        self.config = config
        self._cmd_handlers = {
            # Cmd_ID, cmd_handler_func
            ssbot.register_command('!startbot', "!sb", 2, COMMAND_LIST_ALL, "Master", "[type] [arena]", '!startbot type arena'):
            self.HCStartBot,
            ssbot.register_command('!killbot', "!kb", 2, COMMAND_LIST_ALL, "Master", "[name]", 'Stop a specific bot'):
            self.HCStopBot,
            ssbot.register_command('!listbots', "!lb", 2, COMMAND_LIST_ALL, "Master", "", 'lists all currently running bots'):
            self.HCListBots,
            ssbot.register_command(
                '!listbottypes', "!lt", 2, COMMAND_LIST_ALL, "Master", "", '!lists all bot types currently defined in config file'):
            self.HCListBotTypes,
            ssbot.register_command('!reloadconf', "!rc", 3, COMMAND_LIST_ALL, "Master", "", 'reload json config file'):
            self.HCLoadConfig,
            ssbot.register_command(
                '!unloadmodule', "!um", 7, COMMAND_LIST_ALL, "Master", "[modulename]", 'unload a specific module from systems.module'):
            self.HCUnloadModule,
            ssbot.register_command(
                '!log', None, 2, COMMAND_LIST_PP, "Master", "[-clear]", 'default shows last 100 lines from the core logger'):
            self.HCLog
        }
        self._last_instance_id = 0
        self._instances = {}
        # this will copy all log entries to a list, so i can use it for !log
        self.max_recs = 40
        self.listhandler = ListHandler(logging.DEBUG, self.max_recs)
        formatter = logging.Formatter(
            '%(asctime)s:%(name)s:%(levelname)s:%(message)s')
        self.listhandler.setFormatter(formatter)
        self.listhandler.load_from_file(os.path.join(os.getcwd(), "Bots.log"))
        self.logger.addHandler(self.listhandler)

        self.logger.info("Master Bot Started")
        if len(config.MasterChats) > 0:
            ssbot.add_chat(config.MasterChats)

        self.__queue = MQueue
示例#2
0
文件: Master.py 项目: prozaker/PyCore
    def __init__(self, ssbot, md, config, MQueue):
        BotInterface.__init__(self, ssbot, md)
        ssbot.register_module_info(
            __name__,
            "MasterBot",
            "The Junky",
            "Manages other bots (starts/stops/lists/etc)",
            "1.0d"
        )
        self.config = config
        self._cmd_handlers = {
            # Cmd_ID, cmd_handler_func
            ssbot.register_command(
                '!startbot',
                "!sb",
                2,
                COMMAND_LIST_ALL,
                "Master",
                "[type] [arena]",
                '!startbot type arena'
            ): self.HCStartBot,
            ssbot.register_command(
                '!killbot',
                "!kb",
                2,
                COMMAND_LIST_ALL,
                "Master",
                "[name]",
                'Stop a specific bot'
            ): self.HCStopBot,
            ssbot.register_command(
                '!listbots',
                "!lb",
                2,
                COMMAND_LIST_ALL,
                "Master",
                "",
                'lists all currently running bots'
            ): self.HCListBots,
            ssbot.register_command(
                '!listbottypes',
                "!lt",
                2,
                COMMAND_LIST_ALL,
                "Master",
                "",
                '!lists all bot types currently defined in config file'
            ): self.HCListBotTypes,
            ssbot.register_command(
                '!reloadconf',
                "!rc",
                3,
                COMMAND_LIST_ALL,
                "Master",
                "",
                'reload json config file'
            ): self.HCLoadConfig,
            ssbot.register_command(
                '!unloadmodule',
                "!um",
                7,
                COMMAND_LIST_ALL,
                "Master",
                "[modulename]",
                'unload a specific module from systems.module'
            ): self.HCUnloadModule,
            ssbot.register_command(
                '!log',
                None,
                2,
                COMMAND_LIST_PP,
                "Master",
                "[-clear]",
                'default shows last 100 lines from the core logger'
            ): self.HCLog
        }
        self._last_instance_id = 0
        self._instances = {}
        # this will copy all log entries to a list, so i can use it for !log
        self.max_recs = 40
        self.listhandler = ListHandler(logging.DEBUG, self.max_recs)
        formatter = logging.Formatter(
            '%(asctime)s:%(name)s:%(levelname)s:%(message)s')
        self.listhandler.setFormatter(formatter)
        self.listhandler.load_from_file(os.path.join(os.getcwd(), "Bots.log"))
        self.logger.addHandler(self.listhandler)

        self.logger.info("Master Bot Started")
        if len(config.MasterChats) > 0:
            ssbot.add_chat(config.MasterChats)

        self.__queue = MQueue
示例#3
0
文件: Master.py 项目: prozaker/PyCore
class Bot(BotInterface):
    def __init__(self, ssbot, md, config, MQueue):
        BotInterface.__init__(self, ssbot, md)
        ssbot.register_module_info(
            __name__,
            "MasterBot",
            "The Junky",
            "Manages other bots (starts/stops/lists/etc)",
            "1.0d"
        )
        self.config = config
        self._cmd_handlers = {
            # Cmd_ID, cmd_handler_func
            ssbot.register_command(
                '!startbot',
                "!sb",
                2,
                COMMAND_LIST_ALL,
                "Master",
                "[type] [arena]",
                '!startbot type arena'
            ): self.HCStartBot,
            ssbot.register_command(
                '!killbot',
                "!kb",
                2,
                COMMAND_LIST_ALL,
                "Master",
                "[name]",
                'Stop a specific bot'
            ): self.HCStopBot,
            ssbot.register_command(
                '!listbots',
                "!lb",
                2,
                COMMAND_LIST_ALL,
                "Master",
                "",
                'lists all currently running bots'
            ): self.HCListBots,
            ssbot.register_command(
                '!listbottypes',
                "!lt",
                2,
                COMMAND_LIST_ALL,
                "Master",
                "",
                '!lists all bot types currently defined in config file'
            ): self.HCListBotTypes,
            ssbot.register_command(
                '!reloadconf',
                "!rc",
                3,
                COMMAND_LIST_ALL,
                "Master",
                "",
                'reload json config file'
            ): self.HCLoadConfig,
            ssbot.register_command(
                '!unloadmodule',
                "!um",
                7,
                COMMAND_LIST_ALL,
                "Master",
                "[modulename]",
                'unload a specific module from systems.module'
            ): self.HCUnloadModule,
            ssbot.register_command(
                '!log',
                None,
                2,
                COMMAND_LIST_PP,
                "Master",
                "[-clear]",
                'default shows last 100 lines from the core logger'
            ): self.HCLog
        }
        self._last_instance_id = 0
        self._instances = {}
        # this will copy all log entries to a list, so i can use it for !log
        self.max_recs = 40
        self.listhandler = ListHandler(logging.DEBUG, self.max_recs)
        formatter = logging.Formatter(
            '%(asctime)s:%(name)s:%(levelname)s:%(message)s')
        self.listhandler.setFormatter(formatter)
        self.listhandler.load_from_file(os.path.join(os.getcwd(), "Bots.log"))
        self.logger.addHandler(self.listhandler)

        self.logger.info("Master Bot Started")
        if len(config.MasterChats) > 0:
            ssbot.add_chat(config.MasterChats)

        self.__queue = MQueue

    def GetBotConfig(self, btype):
        for b in self.config.Bots.values():
            if b.Type.lower() == btype.lower():
                return b
        else:
            return None

    def GenerateValidNames(self, btype):
        bconfig = self.GetBotConfig(btype)
        maxbots = bconfig.MaxBots
        validnames = []
        name = bconfig.Name
        if(maxbots > 1):
            for i in range(1, maxbots):
                validnames.append(name + str(i))
        else:
            validnames.append(name)
        return validnames

    def StopAllBots(self):
        for k, v in self._instances.iteritems():
            if v.is_alive() == 1:
                v.RequestStop()
                self.logger.critical("Requested Stop for "+v.bname)

    def DeleteInactiveBots(self):
        keys2del = []
        for k, v in self._instances.iteritems():
            if v.is_alive() == 1:
                pass
            else:
                keys2del.append(k)
        for k in keys2del:
            del self._instances[k]

    def HCShutdown(self, ssbot, event):
        self.StopAllBots()
        ssbot.reconnect = False
        ssbot.disconnect_from_server()
        ssbot.send_reply(event, "ok")
        self.logger.critical("Master is being Shutdown command issued by: %s" %
                             event.pname)
        # raise ShutDownException(
        #   "Master is being Shutdown command issued by: " + event.pname)

    def StartBot(self, ssbot, pname, btype, arena, args):
        bconfig = self.GetBotConfig(btype)
        if bconfig is not None:
            validname = None
            for n in self.GenerateValidNames(btype):
                if(n.lower() in self._instances):
                    continue
                else:
                    validname = n
                    break
            if validname is not None:
                self._last_instance_id += 1
                newbot = BotInstance.BotInstance(
                    self._last_instance_id,
                    bconfig.Type,
                    bconfig.Description,
                    pname,
                    validname,
                    bconfig.Password,
                    bconfig.ConfigurationFile,
                    self.config.Host,
                    self.config.Port,
                    arena,
                    bconfig.Modules,
                    self.__queue,
                    args,
                    logging.getLogger("ML." + bconfig.Type)
                )
                self._instances[newbot.bname.lower()] = newbot
                newbot.start()
                self.logger.info("%s started to %s by %s" %
                                 (bconfig.Type, arena, pname))
                return 1  # success
            else:
                return -2  # all bots of type used
        else:
            return -1  # type not found

    def HCStartBot(self, ssbot, event):
        self.DeleteInactiveBots()
        if len(event.arguments) >= 2:
            btype = event.arguments[0]
            arena = event.arguments[1]
            args = event.arguments_after[2] if len(event.arguments) > 2 else ""
            r = self.StartBot(ssbot, event.pname, btype, arena, args)
            if r == 1:
                ssbot.send_reply(event, "ok")
            elif r == -1:
                ssbot.send_reply(event, "Error:type(%s) not found" % (type))
            elif r == -2:
                ssbot.send_reply(event, "all %s in use" % (type))
        else:
            ssbot.send_reply(event, "Usage: !startbot type arena")

    def HCStopBot(self, ssbot, event):
        if (len(event.arguments) == 1 and
                event.arguments[0].lower() in self._instances):
            b = self._instances[event.arguments[0].lower()]
            b.RequestStop()
            ssbot.send_reply(event, "Stop Requested")
            self.logger.info("%s killed %s (Stop Requested)",
                             event.pname, event.arguments[0])
        else:
            ssbot.send_reply(event, "Bot Not Found")

    def HCListBots(self, ssbot, event):
        c = 0
        for v in self._instances.values():
            ssbot.send_reply(
                event,
                "ID:%3i Type:%6s Name:%20s Arena:%10s alive:%i" %
                (v.id, v.type, v.bname, v.arena, v.is_alive())
            )
            c += 1
        if c == 0:
            ssbot.send_reply(event, "No Active Bots")

    def HCListBotTypes(self, ssbot, event):
        if len(event.arguments) == 1:
            b = self.config.Bots.get(event.arguments[0].lower(), None)
            if b:
                ssbot.send_reply(event, "Type: " + b.Type)
                ssbot.send_reply(event, "Description: " + b.Description)
                ssbot.send_reply(event, "BotBaseName: " + b.Name)
                ssbot.send_reply(event, "TotalBots: " + str(b.MaxBots))
                ssbot.send_reply(event, "ConfigFile: " + b.ConfigurationFile)
                txt = ""
                c = 0
                ssbot.send_reply(event, "-" * 10 + "Modules" + "-" * 10)
                for b in b.Modules:
                    if c != 0 and c % 2 == 0:
                        ssbot.send_reply(event, "Modules:" + txt[1:])
                        txt = ""
                    txt += ", " + b[0]
                    c += 1

                if len(txt) > 0:
                    ssbot.send_reply(event, "Modules:" + txt[1:])
            else:
                ssbot.send_reply(
                    event, "Error:type(%s) not found" % (event.arguments[0]))
        else:
            c = 0
            txt = ""
            for b in self.config.Bots.values():
                c += 1
                if c % 5 == 0:
                    ssbot.send_reply(event, "Types:" + txt[1:])
                    txt = ""
                txt += ", " + b.Type

            if len(txt) > 0:
                ssbot.send_reply(event, "Types:" + txt[1:])
            if c == 0:
                ssbot.send_reply(event, "No Bot Types Defined")

    def HCUnloadModule(self, ssbot, event):
        if len(event.arguments) > 0:
            name = event.arguments[0]
            if name in sys.modules:
                del sys.modules[name]
                ssbot.send_reply(event, "module unloaded")
            else:
                ssbot.send_reply(event, "module not found")
        else:
            ssbot.send_reply(event, "invalid syntax")

    def HCLog(self, ssbot, event):
        if len(event.arguments) > 0 and event.arguments[0].lower() == "-clear":
            self.listhandler.clear()
            ssbot.send_reply(event, "on screen log cleared")
        else:
            for r in self.listhandler.get_entries():
                ssbot.send_reply(event, r)

    def HCLoadConfig(self, ssbot, event):
        try:
            oc = copy.deepcopy(self.config)
            self.config.Load()
            ssbot.send_reply(event, "Config Reloaded")
            self.logger.info("config file reloaded by %s" % event.pname)
        except:
            self.config = oc
            ssbot.send_reply(event, "failure, still using old configuration")

    def handle_events(self, ssbot, event):
        if event.type == EVENT_COMMAND and event.command.id in \
                self._cmd_handlers:
            self._cmd_handlers[event.command.id](ssbot, event)
        elif event.type == EVENT_TICK:
            self.SendBroadcastsToAttachedBots(ssbot)
        elif event.type == EVENT_LOGIN:
            # for periodic deleting of inactive bots and removing of
            # old list entries from log
            ssbot.set_timer(10, (2, None))
            c = 60  # wait for bot to login
            # stagger the bots to load by 180 sec each
            for b in self.config.AutoLoad:
                c += 180
                ssbot.set_timer(c, (1, b))
                self.logger.info("Queued:[Sb] %s -> %s" % b)
        elif event.type == EVENT_TIMER:
            if event.user_data is not None \
                    and isinstance(event.user_data, tuple) \
                    and len(event.user_data) == 2:

                if event.user_data[0] == 1:  # start a bot
                    t = event.user_data[1]
                    # ssbot.send_public_message("!sb %s %s" % t)
                    r = self.StartBot(ssbot, ssbot.name, t[0], t[1], "")
                    if r == 1:
                        ssbot.send_public_message(
                            "autospawn:successfull spawned %s to %s" % t)
                    elif r == -1:
                        ssbot.send_public_message(
                            "autospawn:Error:type(%s) not found" % t[0])
                    elif r == -2:
                        ssbot.send_public_message(
                            "autospawn:all %s in use" % t[0])
                elif event.user_data[0] == 2:  # do maintenance
                    self.DeleteInactiveBots()
                    self.listhandler.remove_old()
                    ssbot.set_timer(10, (2, None))

    def SendBroadcastsToAttachedBots(self, ssbot):
        if self.__queue.size() > 0:  # broadcasts waiting
                b = self.__queue.dequeue()
                while b:  # broadcasts waiting
                    for bot in self._instances.values():
                        if bot.is_alive():
                            bot.queue_broadcast(b)  # all attached bots
                    ssbot.queue_broadcast(b)  # modules attached to master

                    # will return None if there are none
                    b = self.__queue.dequeue()

    def cleanup(self):
        for v in self._instances.values():
            v.RequestStop()

        for v in self._instances.values():
            v.join(10)
示例#4
0
class Bot(BotInterface):
    def __init__(self, ssbot, md, config, MQueue):
        BotInterface.__init__(self, ssbot, md)
        ssbot.register_module_info(
            __name__, "MasterBot", "The Junky",
            "Manages other bots (starts/stops/lists/etc)", "1.0d")
        self.config = config
        self._cmd_handlers = {
            # Cmd_ID, cmd_handler_func
            ssbot.register_command('!startbot', "!sb", 2, COMMAND_LIST_ALL, "Master", "[type] [arena]", '!startbot type arena'):
            self.HCStartBot,
            ssbot.register_command('!killbot', "!kb", 2, COMMAND_LIST_ALL, "Master", "[name]", 'Stop a specific bot'):
            self.HCStopBot,
            ssbot.register_command('!listbots', "!lb", 2, COMMAND_LIST_ALL, "Master", "", 'lists all currently running bots'):
            self.HCListBots,
            ssbot.register_command(
                '!listbottypes', "!lt", 2, COMMAND_LIST_ALL, "Master", "", '!lists all bot types currently defined in config file'):
            self.HCListBotTypes,
            ssbot.register_command('!reloadconf', "!rc", 3, COMMAND_LIST_ALL, "Master", "", 'reload json config file'):
            self.HCLoadConfig,
            ssbot.register_command(
                '!unloadmodule', "!um", 7, COMMAND_LIST_ALL, "Master", "[modulename]", 'unload a specific module from systems.module'):
            self.HCUnloadModule,
            ssbot.register_command(
                '!log', None, 2, COMMAND_LIST_PP, "Master", "[-clear]", 'default shows last 100 lines from the core logger'):
            self.HCLog
        }
        self._last_instance_id = 0
        self._instances = {}
        # this will copy all log entries to a list, so i can use it for !log
        self.max_recs = 40
        self.listhandler = ListHandler(logging.DEBUG, self.max_recs)
        formatter = logging.Formatter(
            '%(asctime)s:%(name)s:%(levelname)s:%(message)s')
        self.listhandler.setFormatter(formatter)
        self.listhandler.load_from_file(os.path.join(os.getcwd(), "Bots.log"))
        self.logger.addHandler(self.listhandler)

        self.logger.info("Master Bot Started")
        if len(config.MasterChats) > 0:
            ssbot.add_chat(config.MasterChats)

        self.__queue = MQueue

    def GetBotConfig(self, btype):
        for b in self.config.Bots.values():
            if b.Type.lower() == btype.lower():
                return b
        else:
            return None

    def GenerateValidNames(self, btype):
        bconfig = self.GetBotConfig(btype)
        maxbots = bconfig.MaxBots
        validnames = []
        name = bconfig.Name
        if (maxbots > 1):
            for i in range(1, maxbots):
                validnames.append(name + str(i))
        else:
            validnames.append(name)
        return validnames

    def StopAllBots(self):
        for k, v in self._instances.iteritems():
            if v.is_alive() == 1:
                v.RequestStop()
                self.logger.critical("Requested Stop for " + v.bname)

    def DeleteInactiveBots(self):
        keys2del = []
        for k, v in self._instances.iteritems():
            if v.is_alive() == 1:
                pass
            else:
                keys2del.append(k)
        for k in keys2del:
            del self._instances[k]

    def HCShutdown(self, ssbot, event):
        self.StopAllBots()
        ssbot.reconnect = False
        ssbot.disconnect_from_server()
        ssbot.send_reply(event, "ok")
        self.logger.critical("Master is being Shutdown command issued by: %s" %
                             event.pname)
        # raise ShutDownException(
        #   "Master is being Shutdown command issued by: " + event.pname)

    def StartBot(self, ssbot, pname, btype, arena, args):
        bconfig = self.GetBotConfig(btype)
        if bconfig is not None:
            validname = None
            for n in self.GenerateValidNames(btype):
                if (n.lower() in self._instances):
                    continue
                else:
                    validname = n
                    break
            if validname is not None:
                self._last_instance_id += 1
                newbot = BotInstance.BotInstance(
                    self._last_instance_id, bconfig.Type, bconfig.Description,
                    pname, validname, bconfig.Password,
                    bconfig.ConfigurationFile, self.config.Host,
                    self.config.Port, arena, bconfig.Modules, self.__queue,
                    args, logging.getLogger("ML." + bconfig.Type))
                self._instances[newbot.bname.lower()] = newbot
                newbot.start()
                self.logger.info("%s started to %s by %s" %
                                 (bconfig.Type, arena, pname))
                return 1  # success
            else:
                return -2  # all bots of type used
        else:
            return -1  # type not found

    def HCStartBot(self, ssbot, event):
        self.DeleteInactiveBots()
        if len(event.arguments) >= 2:
            btype = event.arguments[0]
            arena = event.arguments[1]
            args = event.arguments_after[2] if len(event.arguments) > 2 else ""
            r = self.StartBot(ssbot, event.pname, btype, arena, args)
            if r == 1:
                ssbot.send_reply(event, "ok")
            elif r == -1:
                ssbot.send_reply(event, "Error:type(%s) not found" % (type))
            elif r == -2:
                ssbot.send_reply(event, "all %s in use" % (type))
        else:
            ssbot.send_reply(event, "Usage: !startbot type arena")

    def HCStopBot(self, ssbot, event):
        if (len(event.arguments) == 1
                and event.arguments[0].lower() in self._instances):
            b = self._instances[event.arguments[0].lower()]
            b.RequestStop()
            ssbot.send_reply(event, "Stop Requested")
            self.logger.info("%s killed %s (Stop Requested)", event.pname,
                             event.arguments[0])
        else:
            ssbot.send_reply(event, "Bot Not Found")

    def HCListBots(self, ssbot, event):
        c = 0
        for v in self._instances.values():
            ssbot.send_reply(
                event, "ID:%3i Type:%6s Name:%20s Arena:%10s alive:%i" %
                (v.id, v.type, v.bname, v.arena, v.is_alive()))
            c += 1
        if c == 0:
            ssbot.send_reply(event, "No Active Bots")

    def HCListBotTypes(self, ssbot, event):
        if len(event.arguments) == 1:
            b = self.config.Bots.get(event.arguments[0].lower(), None)
            if b:
                ssbot.send_reply(event, "Type: " + b.Type)
                ssbot.send_reply(event, "Description: " + b.Description)
                ssbot.send_reply(event, "BotBaseName: " + b.Name)
                ssbot.send_reply(event, "TotalBots: " + str(b.MaxBots))
                ssbot.send_reply(event, "ConfigFile: " + b.ConfigurationFile)
                txt = ""
                c = 0
                ssbot.send_reply(event, "-" * 10 + "Modules" + "-" * 10)
                for b in b.Modules:
                    if c != 0 and c % 2 == 0:
                        ssbot.send_reply(event, "Modules:" + txt[1:])
                        txt = ""
                    txt += ", " + b[0]
                    c += 1

                if len(txt) > 0:
                    ssbot.send_reply(event, "Modules:" + txt[1:])
            else:
                ssbot.send_reply(
                    event, "Error:type(%s) not found" % (event.arguments[0]))
        else:
            c = 0
            txt = ""
            for b in self.config.Bots.values():
                c += 1
                if c % 5 == 0:
                    ssbot.send_reply(event, "Types:" + txt[1:])
                    txt = ""
                txt += ", " + b.Type

            if len(txt) > 0:
                ssbot.send_reply(event, "Types:" + txt[1:])
            if c == 0:
                ssbot.send_reply(event, "No Bot Types Defined")

    def HCUnloadModule(self, ssbot, event):
        if len(event.arguments) > 0:
            name = event.arguments[0]
            if name in sys.modules:
                del sys.modules[name]
                ssbot.send_reply(event, "module unloaded")
            else:
                ssbot.send_reply(event, "module not found")
        else:
            ssbot.send_reply(event, "invalid syntax")

    def HCLog(self, ssbot, event):
        if len(event.arguments) > 0 and event.arguments[0].lower() == "-clear":
            self.listhandler.clear()
            ssbot.send_reply(event, "on screen log cleared")
        else:
            for r in self.listhandler.get_entries():
                ssbot.send_reply(event, r)

    def HCLoadConfig(self, ssbot, event):
        try:
            oc = copy.deepcopy(self.config)
            self.config.Load()
            ssbot.send_reply(event, "Config Reloaded")
            self.logger.info("config file reloaded by %s" % event.pname)
        except:
            self.config = oc
            ssbot.send_reply(event, "failure, still using old configuration")

    def handle_events(self, ssbot, event):
        if event.type == EVENT_COMMAND and event.command.id in \
                self._cmd_handlers:
            self._cmd_handlers[event.command.id](ssbot, event)
        elif event.type == EVENT_TICK:
            self.SendBroadcastsToAttachedBots(ssbot)
        elif event.type == EVENT_LOGIN:
            # for periodic deleting of inactive bots and removing of
            # old list entries from log
            ssbot.set_timer(10, (2, None))
            c = 60  # wait for bot to login
            # stagger the bots to load by 180 sec each
            for b in self.config.AutoLoad:
                c += 180
                ssbot.set_timer(c, (1, b))
                self.logger.info("Queued:[Sb] %s -> %s" % b)
        elif event.type == EVENT_TIMER:
            if event.user_data is not None \
                    and isinstance(event.user_data, tuple) \
                    and len(event.user_data) == 2:

                if event.user_data[0] == 1:  # start a bot
                    t = event.user_data[1]
                    # ssbot.send_public_message("!sb %s %s" % t)
                    r = self.StartBot(ssbot, ssbot.name, t[0], t[1], "")
                    if r == 1:
                        ssbot.send_public_message(
                            "autospawn:successfull spawned %s to %s" % t)
                    elif r == -1:
                        ssbot.send_public_message(
                            "autospawn:Error:type(%s) not found" % t[0])
                    elif r == -2:
                        ssbot.send_public_message("autospawn:all %s in use" %
                                                  t[0])
                elif event.user_data[0] == 2:  # do maintenance
                    self.DeleteInactiveBots()
                    self.listhandler.remove_old()
                    ssbot.set_timer(10, (2, None))

    def SendBroadcastsToAttachedBots(self, ssbot):
        if self.__queue.size() > 0:  # broadcasts waiting
            b = self.__queue.dequeue()
            while b:  # broadcasts waiting
                for bot in self._instances.values():
                    if bot.is_alive():
                        bot.queue_broadcast(b)  # all attached bots
                ssbot.queue_broadcast(b)  # modules attached to master

                # will return None if there are none
                b = self.__queue.dequeue()

    def cleanup(self):
        for v in self._instances.values():
            v.RequestStop()

        for v in self._instances.values():
            v.join(10)