def update(self):
     self.debug('Sending heartbeat to B3 master...')
     socket.setdefaulttimeout(10)
     
     plugins = []
     for pname in self.console._pluginOrder:
         plugins.append("%s/%s" % (pname, getattr(getModule(self.console.getPlugin(pname).__module__), '__version__', 'Unknown Version')))
       
     try:
         database = functions.splitDSN(self.console.storage.dsn)['protocol']
     except:
         database = "unknown"
         
     version = getattr(b3, '__version__', 'Unknown Version')
     if b3.functions.main_is_frozen():
         version += " win32"
         
     info = {
         'action' : 'update',
         'ip' : self.console._publicIp,
         'port' : self.console._port,
         'rconPort' : self.console._rconPort,
         'version' : version,
         'parser' : self.console.gameName,
         'parserversion' : getattr(getModule(self.console.__module__), '__version__', 'Unknown Version'),
         'database' : database,
         'plugins' : ','.join(plugins),
         'os' : os.name,
         'python_version': sys.version
     }
     #self.debug(info)
     self.sendInfo(info)
Example #2
0
    def update(self):
        """send an upate heartbeat to B3 master server"""
        self.debug('Sending heartbeat to B3 master...')
        socket.setdefaulttimeout(10)

        plugins = []
        for pname in self.console._pluginOrder:
            plugins.append(
                "%s/%s" %
                (pname,
                 getattr(getModule(self.console.getPlugin(pname).__module__),
                         '__version__', 'Unknown Version')))

        try:
            database = functions.splitDSN(self.console.storage.dsn)['protocol']
        except:
            database = "unknown"

        version = getattr(b3, '__version__', 'Unknown Version')
        if b3.functions.main_is_frozen():
            version += " win32"

        info = {
            'action':
            'update',
            'ip':
            self.console._publicIp,
            'port':
            self.console._port,
            'rconPort':
            self.console._rconPort,
            'version':
            version,
            'parser':
            self.console.gameName,
            'parserversion':
            getattr(getModule(self.console.__module__), '__version__',
                    'Unknown Version'),
            'database':
            database,
            'plugins':
            ','.join(plugins),
            'os':
            os.name,
            'python_version':
            sys.version
        }

        if self.console.gameName in ('bfbc2', 'moh'):
            try:
                cvarDescription = self.console.getCvar('serverDescription')
                if cvarDescription is not None:
                    info.update({'serverDescription': cvarDescription.value})
                cvarBannerUrl = self.console.getCvar('bannerUrl')
                if cvarBannerUrl is not None:
                    info.update({'bannerUrl': cvarBannerUrl.value})
            except Exception, err:
                self.debug(err)
Example #3
0
    def update(self):
        """send an upate heartbeat to B3 master server"""
        self.debug("Sending heartbeat to B3 master...")
        socket.setdefaulttimeout(10)

        plugins = []
        for pname in self.console._pluginOrder:
            plugins.append(
                "%s/%s"
                % (
                    pname,
                    getattr(getModule(self.console.getPlugin(pname).__module__), "__version__", "Unknown Version"),
                )
            )

        try:
            database = functions.splitDSN(self.console.storage.dsn)["protocol"]
        except:
            database = "unknown"

        version = getattr(b3, "__version__", "Unknown Version")
        if b3.functions.main_is_frozen():
            version += " win32"

        info = {
            "action": "update",
            "ip": self.console._publicIp,
            "port": self.console._port,
            "rconPort": self.console._rconPort,
            "version": version,
            "parser": self.console.gameName,
            "parserversion": getattr(getModule(self.console.__module__), "__version__", "Unknown Version"),
            "database": database,
            "plugins": ",".join(plugins),
            "os": os.name,
            "python_version": sys.version,
            "default_encoding": sys.getdefaultencoding(),
        }

        if self.console.gameName in ("bfbc2", "moh"):
            try:
                cvarDescription = self.console.getCvar("serverDescription")
                if cvarDescription is not None:
                    info.update({"serverDescription": cvarDescription.value})
                cvarBannerUrl = self.console.getCvar("bannerUrl")
                if cvarBannerUrl is not None:
                    info.update({"bannerUrl": cvarBannerUrl.value})
            except Exception, err:
                self.debug(err)
Example #4
0
 def update(self):
     """send an upate heartbeat to B3 master server"""
     self.debug('Sending heartbeat to B3 master...')
     socket.setdefaulttimeout(10)
     
     plugins = []
     for pname in self.console._pluginOrder:
         plugins.append("%s/%s" % (pname, getattr(getModule(self.console.getPlugin(pname).__module__), '__version__', 'Unknown Version')))
       
     try:
         database = functions.splitDSN(self.console.storage.dsn)['protocol']
     except:
         database = "unknown"
         
     version = getattr(b3, '__version__', 'Unknown Version')
     if b3.functions.main_is_frozen():
         version += " win32"
         
     info = {
         'action' : 'update',
         'ip' : self.console._publicIp,
         'port' : self.console._port,
         'rconPort' : self.console._rconPort,
         'version' : version,
         'parser' : self.console.gameName,
         'parserversion' : getattr(getModule(self.console.__module__), '__version__', 'Unknown Version'),
         'database' : database,
         'plugins' : ','.join(plugins),
         'os' : os.name,
         'python_version': sys.version,
         'default_encoding': sys.getdefaultencoding()
     }
     
     if self.console.gameName in ('bfbc2', 'moh'):
         try:
             cvarDescription = self.console.getCvar('serverDescription')
             if cvarDescription is not None:
                 info.update({'serverDescription': cvarDescription.value})
             cvarBannerUrl = self.console.getCvar('bannerUrl')
             if cvarBannerUrl is not None:
                 info.update({'bannerUrl': cvarBannerUrl.value})
         except Exception, err:
             self.debug(err)
 def cmd_listplugins(self, data, client=None, cmd=None):
     """\
     - list all installed plugins.
     """
     plugins = []
     for pname in self.console._pluginOrder:
         plugins.append("^2%s ^7%s" % (pname, getattr(getModule(self.console.getPlugin(pname).__module__), '__version__', '__name__')))
     
     for b in plugins:
         cmd.sayLoudOrPM(client, b)
     return True
Example #6
0
 def update(self):
     """send an upate heartbeat to B3 master server"""
     self.debug('Sending heartbeat to B3 master...')
     socket.setdefaulttimeout(10)
     
     plugins = []
     for pname in self.console._pluginOrder:
         try:
             p = self.console.getPlugin(pname)
             p_module = getModule(p.__module__)
             p_version = getattr(p_module, '__version__', 'Unknown Version')
             plugins.append("%s/%s" % (pname, p_version))
         except Exception, e:
             self.warning("Could not get version for plugin named '%s'" % pname, exc_info=e)
Example #7
0
    def update(self):
        """send an upate heartbeat to B3 master server"""
        self.debug('Sending heartbeat to B3 master...')
        socket.setdefaulttimeout(10)

        plugins = []
        for pname in self.console._pluginOrder:
            try:
                p = self.console.getPlugin(pname)
                p_module = getModule(p.__module__)
                p_version = getattr(p_module, '__version__', 'Unknown Version')
                plugins.append("%s/%s" % (pname, p_version))
            except Exception, e:
                self.warning("Could not get version for plugin named '%s'" %
                             pname,
                             exc_info=e)
Example #8
0
    def __init__(self, config):
        self._timeStart = self.time()

        if not self.loadConfig(config):
            print('CRITICAL ERROR : COULD NOT LOAD CONFIG')
            raise SystemExit(220)

        # set up logging
        logfile = self.config.getpath('b3', 'logfile')
        log2console = self.config.has_option('devmode', 'log2console') and self.config.getboolean('devmode', 'log2console')
        self.log = b3.output.getInstance(logfile, self.config.getint('b3', 'log_level'), log2console)

        # save screen output to self.screen
        self.screen = sys.stdout
        print('Activating log   : %s' % logfile)
        sys.stdout = b3.output.stdoutLogger(self.log)
        sys.stderr = b3.output.stderrLogger(self.log)

        # setup ip addresses
        self._publicIp = self.config.get('server', 'public_ip')
        self._port = self.config.getint('server', 'port')
        self._rconPort = self._port # if rcon port is the same as the game port, rcon_port can be ommited
        self._rconIp = self.config.get('server', 'rcon_ip')
        if self.config.has_option('server', 'rcon_port'):
            self._rconPort = self.config.getint('server', 'rcon_port')
        self._rconPassword = self.config.get('server', 'rcon_password')


        if self._publicIp[0:1] == '~' or self._publicIp[0:1] == '/':
            # load ip from a file
            f = file(self.getAbsolutePath(self._publicIp))
            self._publicIp = f.read().strip()
            f.close()

        if self._rconIp[0:1] == '~' or self._rconIp[0:1] == '/':
            # load ip from a file
            f = file(self.getAbsolutePath(self._rconIp))
            self._rconIp = f.read().strip()
            f.close()

        try:
            # resolve domain names
            self._rconIp = socket.gethostbyname(self._rconIp)
        except:
            pass

        self.bot('%s', b3.getB3versionString())
        self.bot('Python: %s', sys.version)
        self.bot('Starting %s v%s for server %s:%s', self.__class__.__name__, getattr(getModule(self.__module__), '__version__', ' Unknown'), self._rconIp, self._port)

        # get events
        self.Events = b3.events.eventManager

        self.bot('--------------------------------------------')

        # setup bot
        bot_name = self.config.get('b3', 'bot_name')
        if bot_name:
            self.name = bot_name

        bot_prefix = self.config.get('b3', 'bot_prefix')
        if bot_prefix:
            self.prefix = bot_prefix

        self.msgPrefix = self.prefix

        # delay between log reads
        if self.config.has_option('server', 'delay'):
            delay = self.config.getfloat('server', 'delay')
            if self.delay > 0:
                self.delay = delay

        # delay between each log's line processing
        if self.config.has_option('server', 'lines_per_second'):
            delay2 = self.config.getfloat('server', 'lines_per_second')
            if delay2 > 0:
                self.delay2 = 1/delay2

        # demo mode: use log time
        if self.config.has_option('devmode', 'replay'):
            self.replay = self.config.getboolean('devmode', 'replay')
            if self.replay:
                self._timeStart = 0
                self.bot('Replay mode enabled')

        self.storage = b3.storage.getStorage('database', self.config.get('b3', 'database'), self)

        if self.config.has_option('server','game_log'):
            # open log file
            game_log = self.config.get('server','game_log')
            if game_log[0:6] == 'ftp://' or game_log[0:7] == 'sftp://' or game_log[0:7] == 'http://':
                self.remoteLog = True
                self.bot('Working in Remote-Log-Mode : %s' % game_log)
                
                if self.config.has_option('server', 'local_game_log'):
                    f = self.config.getpath('server', 'local_game_log')
                else:
                    f = os.path.normpath(os.path.expanduser('games_mp.log'))

                if self.config.has_option('server', 'log_append'):
                    if not (self.config.getboolean('server', 'log_append') and os.path.isfile(f)):
                        self.screen.write('Creating Gamelog : %s\n' % f)
                        ftptempfile = open(f, "w")
                        ftptempfile.close()
                    else:
                        self.screen.write('Append to Gamelog: %s\n' % f)
                else:
                    self.screen.write('Creating Gamelog : %s\n' % f)
                    ftptempfile = open(f, "w")
                    ftptempfile.close()
                    
            else:
                self.bot('Game log %s', game_log)
                f = self.config.getpath('server', 'game_log')
            self.bot('Starting bot reading file %s', f)
            self.screen.write('Using Gamelog    : %s\n' % f)

            if os.path.isfile(f):
                self.input  = file(f, 'r')
    
                # seek to point in log file?
                if self.replay:
                    pass
                elif self.config.has_option('server', 'seek'):
                    seek = self.config.getboolean('server', 'seek')
                    if seek:
                        self.input.seek(0, os.SEEK_END)
                else:
                    self.input.seek(0, os.SEEK_END)
            else:
                self.error('Error reading file %s', f)
                raise SystemExit('Error reading file %s\n' % f)

        # setup rcon
        self.output = self.OutputClass(self, (self._rconIp, self._rconPort), self._rconPassword)
        
        if self.config.has_option('server','rcon_timeout'):
            custom_socket_timeout = self.config.getfloat('server','rcon_timeout')
            self.output.socket_timeout = custom_socket_timeout
            self.bot('Setting Rcon socket timeout to %0.3f sec' % custom_socket_timeout)
        
        # testing rcon
        if self.rconTest:
            res = self.output.write('status')
            self.output.flush()
            self.screen.write('Testing RCON     : ')
            self.screen.flush()
            _badRconReplies = ['Bad rconpassword.', 'Invalid password.']
            if res in _badRconReplies:
                self.screen.write('>>> Oops: Bad RCON password\n>>> Hint: This will lead to errors and render B3 without any power to interact!\n')
                self.screen.flush()
                time.sleep(2)
            elif res == '':
                self.screen.write('>>> Oops: No response\n>>> Could be something wrong with the rcon connection to the server!\n>>> Hint 1: The server is not running or it is changing maps.\n>>> Hint 2: Check your server-ip and port.\n')
                self.screen.flush()
                time.sleep(2)
            else:
                self.screen.write('OK\n')

        self.loadEvents()
        self.screen.write('Loading Events   : %s events loaded\n' % len(self._events))
        self.clients  = b3.clients.Clients(self)
        self.loadPlugins()
        self.loadArbPlugins()

        self.game = b3.game.Game(self, self.gameName)
        self.queue = Queue.Queue(15)    # event queue

        atexit.register(self.shutdown)

        self.say('%s ^2[ONLINE]' % b3.version)
Example #9
0
    def __init__(self, config):
        self._timeStart = self.time()

        if not self.loadConfig(config):
            print ("CRITICAL ERROR : COULD NOT LOAD CONFIG")
            raise SystemExit(220)

        # set up logging
        logfile = self.config.getpath("b3", "logfile")
        log2console = self.config.has_option("devmode", "log2console") and self.config.getboolean(
            "devmode", "log2console"
        )
        log2both = self.config.has_option("devmode", "log2both") and self.config.getboolean("devmode", "log2both")
        self.log = b3.output.getInstance(logfile, self.config.getint("b3", "log_level"), log2console, log2both)

        # save screen output to self.screen
        self.screen = sys.stdout
        print ("Activating log   : %s" % logfile)
        sys.stdout = b3.output.stdoutLogger(self.log)
        sys.stderr = b3.output.stderrLogger(self.log)

        # setup ip addresses
        self._publicIp = self.config.get("server", "public_ip")
        self._port = self.config.getint("server", "port")
        self._rconPort = self._port  # if rcon port is the same as the game port, rcon_port can be ommited
        self._rconIp = self.config.get("server", "rcon_ip")
        if self.config.has_option("server", "rcon_port"):
            self._rconPort = self.config.getint("server", "rcon_port")
        self._rconPassword = self.config.get("server", "rcon_password")

        if self._publicIp[0:1] == "~" or self._publicIp[0:1] == "/":
            # load ip from a file
            f = file(self.getAbsolutePath(self._publicIp))
            self._publicIp = f.read().strip()
            f.close()

        if self._rconIp[0:1] == "~" or self._rconIp[0:1] == "/":
            # load ip from a file
            f = file(self.getAbsolutePath(self._rconIp))
            self._rconIp = f.read().strip()
            f.close()

        try:
            # resolve domain names
            self._rconIp = socket.gethostbyname(self._rconIp)
        except:
            pass

        self.bot("%s", b3.getB3versionString())
        self.bot("Python: %s", sys.version)
        self.bot(
            "Starting %s v%s for server %s:%s",
            self.__class__.__name__,
            getattr(getModule(self.__module__), "__version__", " Unknown"),
            self._rconIp,
            self._port,
        )

        # get events
        self.Events = b3.events.eventManager

        self.bot("--------------------------------------------")

        # setup bot
        bot_name = self.config.get("b3", "bot_name")
        if bot_name:
            self.name = bot_name

        bot_prefix = self.config.get("b3", "bot_prefix")
        if bot_prefix:
            self.prefix = bot_prefix

        self.msgPrefix = self.prefix

        # delay between log reads
        if self.config.has_option("server", "delay"):
            delay = self.config.getfloat("server", "delay")
            if self.delay > 0:
                self.delay = delay

        # delay between each log's line processing
        if self.config.has_option("server", "lines_per_second"):
            delay2 = self.config.getfloat("server", "lines_per_second")
            if delay2 > 0:
                self.delay2 = 1 / delay2

        # demo mode: use log time
        if self.config.has_option("devmode", "replay"):
            self.replay = self.config.getboolean("devmode", "replay")
            if self.replay:
                self._timeStart = 0
                self.bot("Replay mode enabled")

        self.storage = b3.storage.getStorage("database", self.config.get("b3", "database"), self)

        if self.config.has_option("server", "game_log"):
            # open log file
            game_log = self.config.get("server", "game_log")
            if game_log[0:6] == "ftp://" or game_log[0:7] == "sftp://" or game_log[0:7] == "http://":
                self.remoteLog = True
                self.bot("Working in Remote-Log-Mode : %s" % game_log)

                if self.config.has_option("server", "local_game_log"):
                    f = self.config.getpath("server", "local_game_log")
                else:
                    f = os.path.normpath(os.path.expanduser("games_mp.log"))

                if self.config.has_option("server", "log_append"):
                    if not (self.config.getboolean("server", "log_append") and os.path.isfile(f)):
                        self.screen.write("Creating Gamelog : %s\n" % f)
                        ftptempfile = open(f, "w")
                        ftptempfile.close()
                    else:
                        self.screen.write("Append to Gamelog: %s\n" % f)
                else:
                    self.screen.write("Creating Gamelog : %s\n" % f)
                    ftptempfile = open(f, "w")
                    ftptempfile.close()

            else:
                self.bot("Game log %s", game_log)
                f = self.config.getpath("server", "game_log")
            self.bot("Starting bot reading file %s", f)
            self.screen.write("Using Gamelog    : %s\n" % f)

            if os.path.isfile(f):
                self.input = file(f, "r")

                # seek to point in log file?
                if self.replay:
                    pass
                elif self.config.has_option("server", "seek"):
                    seek = self.config.getboolean("server", "seek")
                    if seek:
                        self.input.seek(0, os.SEEK_END)
                else:
                    self.input.seek(0, os.SEEK_END)
            else:
                self.error("Error reading file %s", f)
                raise SystemExit("Error reading file %s\n" % f)

        # setup rcon
        self.output = self.OutputClass(self, (self._rconIp, self._rconPort), self._rconPassword)

        if self.config.has_option("server", "rcon_timeout"):
            custom_socket_timeout = self.config.getfloat("server", "rcon_timeout")
            self.output.socket_timeout = custom_socket_timeout
            self.bot("Setting Rcon socket timeout to %0.3f sec" % custom_socket_timeout)

        # testing rcon
        if self.rconTest:
            res = self.output.write("status")
            self.output.flush()
            self.screen.write("Testing RCON     : ")
            self.screen.flush()
            _badRconReplies = ["Bad rconpassword.", "Invalid password."]
            if res in _badRconReplies:
                self.screen.write(
                    ">>> Oops: Bad RCON password\n>>> Hint: This will lead to errors and render B3 without any power to interact!\n"
                )
                self.screen.flush()
                time.sleep(2)
            elif res == "":
                self.screen.write(
                    ">>> Oops: No response\n>>> Could be something wrong with the rcon connection to the server!\n>>> Hint 1: The server is not running or it is changing maps.\n>>> Hint 2: Check your server-ip and port.\n"
                )
                self.screen.flush()
                time.sleep(2)
            else:
                self.screen.write("OK\n")

        self.loadEvents()
        self.screen.write("Loading Events   : %s events loaded\n" % len(self._events))
        self.clients = b3.clients.Clients(self)
        self.loadPlugins()
        self.loadArbPlugins()

        self.game = b3.game.Game(self, self.gameName)
        self.queue = Queue.Queue(15)  # event queue

        atexit.register(self.shutdown)

        self.say("%s ^2[ONLINE]" % b3.version)
Example #10
0
class PublistPlugin(b3.plugin.Plugin):
    _cronTab = None
    _url = 'http://www.bigbrotherbot.net/master/serverping.php'
    _secondUrl = None
    requiresConfigFile = False

    _heartbeat_sent = False
    _initial_heartbeat_delay_minutes = 5

    def onLoadConfig(self):
        try:
            self._secondUrl = self.config.get('settings', 'url')
            self.debug('Using second url : %s' % self._secondUrl)
        except:
            pass

        try:
            self._initial_heartbeat_delay_minutes = self.config.getint(
                'settings', 'delay')
            self.debug('delay : %s' % self._initial_heartbeat_delay_minutes)
        except:
            pass

    def onStartup(self):

        # get the plugin so we can register commands
        self._adminPlugin = self.console.getPlugin('admin')
        if not self._adminPlugin:
            # something is wrong, can't start without admin plugin
            self.error('Could not find admin plugin')
            return False

        # set cvar for advertising purposes
        try:
            cvarValue = 'B3 %s' % b3.versionId
            self.console.setCvar('_B3', cvarValue)
        except:
            pass

        if self.console._publicIp == '127.0.0.1':
            self.info(
                "publist will not send heartbeat to master server as publicIp is not public."
            )
            return

        rmin = random.randint(0, 59)
        rhour = random.randint(0, 23)
        self.debug("publist will send heartbeat at %02d:%02d every day" %
                   (rhour, rmin))
        self._cronTab = b3.cron.PluginCronTab(self, self.update, 0, rmin,
                                              rhour, '*', '*', '*')
        self.console.cron + self._cronTab

        # planning initial heartbeat
        # v1.9.1: Changing the threaded timer to a one time crontab to enable quick shutdown of the bot.
        _im = int(time.strftime('%M')) + self._initial_heartbeat_delay_minutes
        if _im >= 60:
            _im -= 60
        self.info(
            'initial heartbeat will be sent to B3 master server at %s minutes'
            % (str(_im).zfill(2)))
        self._cronTab = b3.cron.OneTimeCronTab(self.update, 0, _im, '*', '*',
                                               '*', '*')
        self.console.cron + self._cronTab

    def onEvent(self, event):
        if event.type == b3.events.EVT_STOP and self._heartbeat_sent:
            self.shutdown()

    def removeCrontab(self):
        try:
            self.console.cron - self._cronTab
        except KeyError:
            pass

    def shutdown(self):
        """Send a shutdown heartbeat to B3 master server"""
        self.info('Sending shutdown info to B3 master')
        info = {
            'action': 'shutdown',
            'ip': self.console._publicIp,
            'port': self.console._port,
            'rconPort': self.console._rconPort
        }
        #self.debug(info)
        self.sendInfo(info)

    def update(self):
        """send an upate heartbeat to B3 master server"""
        self.debug('Sending heartbeat to B3 master...')
        socket.setdefaulttimeout(10)

        plugins = []
        for pname in self.console._pluginOrder:
            try:
                p = self.console.getPlugin(pname)
                p_module = getModule(p.__module__)
                p_version = getattr(p_module, '__version__', 'Unknown Version')
                plugins.append("%s/%s" % (pname, p_version))
            except Exception, e:
                self.warning("Could not get version for plugin named '%s'" %
                             pname,
                             exc_info=e)

        try:
            database = functions.splitDSN(self.console.storage.dsn)['protocol']
        except:
            database = "unknown"

        version = getattr(b3, '__version__', 'Unknown Version')
        if b3.functions.main_is_frozen():
            version += " win32"

        info = {
            'action':
            'update',
            'ip':
            self.console._publicIp,
            'port':
            self.console._port,
            'rconPort':
            self.console._rconPort,
            'version':
            version,
            'parser':
            self.console.gameName,
            'parserversion':
            getattr(getModule(self.console.__module__), '__version__',
                    'Unknown Version'),
            'database':
            database,
            'plugins':
            ','.join(plugins),
            'os':
            os.name,
            'python_version':
            sys.version,
            'default_encoding':
            sys.getdefaultencoding()
        }

        if self.console.gameName in ('bfbc2', 'moh'):
            try:
                cvarDescription = self.console.getCvar('serverDescription')
                if cvarDescription is not None:
                    info.update({'serverDescription': cvarDescription.value})
                cvarBannerUrl = self.console.getCvar('bannerUrl')
                if cvarBannerUrl is not None:
                    info.update({'bannerUrl': cvarBannerUrl.value})
            except Exception, err:
                self.debug(err)
class PublistPlugin(b3.plugin.Plugin):

    requiresConfigFile = False

    _cronTab = None
    _url = 'http://www.bigbrotherbot.net/master/serverping.php'
    _secondUrl = None
    _heartbeat_sent = False
    _initial_heartbeat_delay_minutes = 5

    ####################################################################################################################
    #                                                                                                                  #
    #    STARTUP                                                                                                       #
    #                                                                                                                  #
    ####################################################################################################################

    def onLoadConfig(self):
        """
        Load plugin configuration
        """
        if self.config is None:
            return

        try:
            self._secondUrl = self.config.get('settings', 'url')
            self.debug('using second url: %s' % self._secondUrl)
        except NoOptionError:
            pass

        try:
            self._initial_heartbeat_delay_minutes = self.config.getint(
                'settings', 'delay')
            self.debug('loaded settings/delay: %s' %
                       self._initial_heartbeat_delay_minutes)
        except (NoOptionError, ValueError):
            pass

    def onStartup(self):
        """
        Initialize the plugin.
        """
        try:
            # set cvar for advertising purposes
            self.console.setCvar('_B3', 'B3 %s' % b3.versionId)
        except Exception:
            pass  # some B3 parser have no cvar and no setCvar method (Q3 specific method)

        if self.console._publicIp == '127.0.0.1':
            self.info(
                "publist will not send heartbeat to master server as publicIp is not public"
            )
            return

        rmin = random.randint(0, 59)
        rhour = random.randint(0, 23)
        self.debug("publist will send heartbeat at %02d:%02d every day" %
                   (rhour, rmin))
        self._cronTab = b3.cron.PluginCronTab(self, self.update, 0, rmin,
                                              rhour, '*', '*', '*')
        self.console.cron + self._cronTab

        # planning initial heartbeat
        # v1.9.1: Changing the threaded timer to a one time crontab to enable quick shutdown of the bot.
        _im = int(strftime('%M')) + self._initial_heartbeat_delay_minutes
        if _im >= 60:
            _im -= 60

        self.info(
            'initial heartbeat will be sent to B3 master server at %s minutes'
            % (str(_im).zfill(2)))
        self._cronTab = b3.cron.OneTimeCronTab(self.update, 0, _im, '*', '*',
                                               '*', '*')
        self.console.cron + self._cronTab

    ####################################################################################################################
    #                                                                                                                  #
    #    EVENTS                                                                                                        #
    #                                                                                                                  #
    ####################################################################################################################

    def onStop(self, event):
        """
        Handle intercepted events
        """
        if self._heartbeat_sent:
            self.shutdown()

    ####################################################################################################################
    #                                                                                                                  #
    #    FUNCTIONS                                                                                                     #
    #                                                                                                                  #
    ####################################################################################################################

    def removeCrontab(self):
        """
        Removes the current crontab.
        """
        try:
            self.console.cron - self._cronTab
        except KeyError:
            pass

    def shutdown(self):
        """
        Send a shutdown heartbeat to B3 master server.
        """
        self.info('Sending shutdown info to B3 master')
        info = {
            'action': 'shutdown',
            'ip': self.console._publicIp,
            'port': self.console._port,
            'rconPort': self.console._rconPort
        }
        # self.debug(info)
        self.sendInfo(info)

    def update(self):
        """
        Send an update heartbeat to B3 master server.
        """
        self.debug('sending heartbeat to B3 master...')
        socket.setdefaulttimeout(10)

        plugins = []
        for pname in self.console._plugins:
            try:
                pl = self.console.getPlugin(pname)
                p_module = getModule(pl.__module__)
                p_version = getattr(p_module, '__version__', 'unknown')
                plugins.append("%s/%s" % (pname, p_version))
            except Exception, e:
                self.warning("could not get version for plugin named '%s'" %
                             pname,
                             exc_info=e)

        try:
            database = functions.splitDSN(self.console.storage.dsn)['protocol']
        except Exception:
            database = "unknown"

        version = getattr(b3, '__version__', 'unknown')
        if b3.functions.main_is_frozen():
            version_info = b3.getB3versionInfo()
            version = '%s %s%s' % (version, version_info[1], version_info[2])

        info = {
            'action':
            'update',
            'ip':
            self.console._publicIp,
            'port':
            self.console._port,
            'rconPort':
            self.console._rconPort,
            'version':
            version,
            'parser':
            self.console.gameName,
            'parserversion':
            getattr(getModule(self.console.__module__), '__version__',
                    'unknown'),
            'database':
            database,
            'plugins':
            ','.join(plugins),
            'os':
            os.name,
            'python_version':
            sys.version,
            'default_encoding':
            sys.getdefaultencoding()
        }

        if self.console.gameName in ('bfbc2', 'moh', 'bf3'):
            try:
                cvar_description = self.console.getCvar('serverDescription')
                if cvar_description is not None:
                    info.update({'serverDescription': cvar_description.value})
                cvar_banner_url = self.console.getCvar('bannerUrl')
                if cvar_banner_url is not None:
                    info.update({'bannerUrl': cvar_banner_url.value})
            except Exception, e:
                self.debug(e)
Example #12
0
    def update(self):
        """
        Send an update heartbeat to B3 master server.
        """
        self.debug('sending heartbeat to B3 master...')
        socket.setdefaulttimeout(10)

        plugins = []
        for pname in self.console._plugins:
            try:
                pl = self.console.getPlugin(pname)
                p_module = getModule(pl.__module__)
                p_version = getattr(p_module, '__version__', 'unknown')
                plugins.append("%s/%s" % (pname, p_version))
            except Exception as e:
                self.warning("could not get version for plugin named '%s'" %
                             pname,
                             exc_info=e)

        try:
            database = functions.splitDSN(self.console.storage.dsn)['protocol']
        except Exception:
            database = "unknown"

        version = getattr(b3, '__version__', 'unknown')
        if b3.functions.main_is_frozen():
            version_info = b3.getB3versionInfo()
            version = '%s %s%s' % (version, version_info[1], version_info[2])

        info = {
            'action':
            'update',
            'ip':
            self.console._publicIp,
            'port':
            self.console._port,
            'rconPort':
            self.console._rconPort,
            'version':
            version,
            'parser':
            self.console.gameName,
            'parserversion':
            getattr(getModule(self.console.__module__), '__version__',
                    'unknown'),
            'database':
            database,
            'plugins':
            ','.join(plugins),
            'os':
            os.name,
            'python_version':
            sys.version,
            'default_encoding':
            sys.getdefaultencoding()
        }

        if self.console.gameName in ('bfbc2', 'moh', 'bf3'):
            try:
                cvar_description = self.console.getCvar('serverDescription')
                if cvar_description is not None:
                    info.update({'serverDescription': cvar_description.value})
                cvar_banner_url = self.console.getCvar('bannerUrl')
                if cvar_banner_url is not None:
                    info.update({'bannerUrl': cvar_banner_url.value})
            except Exception as e:
                self.debug(e)

        self.debug(info)
        self.sendInfo(info)
Example #13
0
    def __init__(self, config):
        self._timeStart = self.time()

        if not self.loadConfig(config):
            print('CRITICAL ERROR : COULD NOT LOAD CONFIG')
            raise SystemExit(220)

        # set up logging
        logfile = self.config.getpath('b3', 'logfile')
        log2console = self.config.has_option('devmode', 'log2console') and self.config.getboolean('devmode', 'log2console')
        log2both = self.config.has_option('devmode', 'log2both') and self.config.getboolean('devmode', 'log2both')
        self.log = b3.output.getInstance(logfile, self.config.getint('b3', 'log_level'), log2console, log2both)

        # save screen output to self.screen
        self.screen = sys.stdout
        print('Activating log   : %s' % logfile)
        sys.stdout = b3.output.stdoutLogger(self.log)
        sys.stderr = b3.output.stderrLogger(self.log)

        # setup ip addresses
        self._publicIp = self.config.get('server', 'public_ip')
        self._port = self.config.getint('server', 'port')
        self._rconPort = self._port # if rcon port is the same as the game port, rcon_port can be ommited
        self._rconIp = self.config.get('server', 'rcon_ip')
        if self.config.has_option('server', 'rcon_port'):
            self._rconPort = self.config.getint('server', 'rcon_port')
        self._rconPassword = self.config.get('server', 'rcon_password')


        if self._publicIp[0:1] == '~' or self._publicIp[0:1] == '/':
            # load ip from a file
            f = file(self.getAbsolutePath(self._publicIp))
            self._publicIp = f.read().strip()
            f.close()

        if self._rconIp[0:1] == '~' or self._rconIp[0:1] == '/':
            # load ip from a file
            f = file(self.getAbsolutePath(self._rconIp))
            self._rconIp = f.read().strip()
            f.close()

        try:
            # resolve domain names
            self._rconIp = socket.gethostbyname(self._rconIp)
        except:
            pass

        self.bot('%s', b3.getB3versionString())
        self.bot('Python: %s', sys.version)
        self.bot('Starting %s v%s for server %s:%s', self.__class__.__name__, getattr(getModule(self.__module__), '__version__', ' Unknown'), self._rconIp, self._port)

        # get events
        self.Events = b3.events.eventManager

        self.bot('--------------------------------------------')

        # setup bot
        bot_name = self.config.get('b3', 'bot_name')
        if bot_name:
            self.name = bot_name

        bot_prefix = self.config.get('b3', 'bot_prefix')
        if bot_prefix:
            self.prefix = bot_prefix

        self.msgPrefix = self.prefix

        # delay between log reads
        if self.config.has_option('server', 'delay'):
            delay = self.config.getfloat('server', 'delay')
            if self.delay > 0:
                self.delay = delay

        # delay between each log's line processing
        if self.config.has_option('server', 'lines_per_second'):
            delay2 = self.config.getfloat('server', 'lines_per_second')
            if delay2 > 0:
                self.delay2 = 1/delay2

        # demo mode: use log time
        if self.config.has_option('devmode', 'replay'):
            self.replay = self.config.getboolean('devmode', 'replay')
            if self.replay:
                self._timeStart = 0
                self.bot('Replay mode enabled')

        self.storage = b3.storage.getStorage('database', self.config.get('b3', 'database'), self)

        if self.config.has_option('server','game_log'):
            # open log file
            game_log = self.config.get('server','game_log')
            if game_log[0:6] == 'ftp://' or game_log[0:7] == 'sftp://' or game_log[0:7] == 'http://':
                self.remoteLog = True
                self.bot('Working in Remote-Log-Mode : %s' % game_log)
                
                if self.config.has_option('server', 'local_game_log'):
                    f = self.config.getpath('server', 'local_game_log')
                else:
                    f = os.path.normpath(os.path.expanduser('games_mp.log'))

                if self.config.has_option('server', 'log_append'):
                    if not (self.config.getboolean('server', 'log_append') and os.path.isfile(f)):
                        self.screen.write('Creating Gamelog : %s\n' % f)
                        ftptempfile = open(f, "w")
                        ftptempfile.close()
                    else:
                        self.screen.write('Append to Gamelog: %s\n' % f)
                else:
                    self.screen.write('Creating Gamelog : %s\n' % f)
                    ftptempfile = open(f, "w")
                    ftptempfile.close()
                    
            else:
                self.bot('Game log %s', game_log)
                f = self.config.getpath('server', 'game_log')
            self.bot('Starting bot reading file %s', f)
            self.screen.write('Using Gamelog    : %s\n' % f)

            if os.path.isfile(f):
                self.input  = file(f, 'r')
    
                # seek to point in log file?
                if self.replay:
                    pass
                elif self.config.has_option('server', 'seek'):
                    seek = self.config.getboolean('server', 'seek')
                    if seek:
                        self.input.seek(0, os.SEEK_END)
                else:
                    self.input.seek(0, os.SEEK_END)
            else:
                self.error('Error reading file %s', f)
                raise SystemExit('Error reading file %s\n' % f)

        # setup rcon
        self.output = self.OutputClass(self, (self._rconIp, self._rconPort), self._rconPassword)
        
        if self.config.has_option('server','rcon_timeout'):
            custom_socket_timeout = self.config.getfloat('server','rcon_timeout')
            self.output.socket_timeout = custom_socket_timeout
            self.bot('Setting Rcon socket timeout to %0.3f sec' % custom_socket_timeout)
        
        # testing rcon
        if self.rconTest:
            res = self.output.write('status')
            self.output.flush()
            self.screen.write('Testing RCON     : ')
            self.screen.flush()
            _badRconReplies = ['Bad rconpassword.', 'Invalid password.']
            if res in _badRconReplies:
                self.screen.write('>>> Oops: Bad RCON password\n>>> Hint: This will lead to errors and render B3 without any power to interact!\n')
                self.screen.flush()
                time.sleep(2)
            elif res == '':
                self.screen.write('>>> Oops: No response\n>>> Could be something wrong with the rcon connection to the server!\n>>> Hint 1: The server is not running or it is changing maps.\n>>> Hint 2: Check your server-ip and port.\n')
                self.screen.flush()
                time.sleep(2)
            else:
                self.screen.write('OK\n')

        self.loadEvents()
        self.screen.write('Loading Events   : %s events loaded\n' % len(self._events))
        self.clients  = b3.clients.Clients(self)
        self.loadPlugins()
        self.loadArbPlugins()

        self.game = b3.game.Game(self, self.gameName)
        self.queue = Queue.Queue(15)    # event queue

        atexit.register(self.shutdown)

        self.say('%s ^2[ONLINE]' % b3.version)