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)
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)
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 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
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)
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)
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)
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)
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)
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)