def _getpath(self, path): """Return an absolute path name and expand the user prefix (~), @b3 and @conf""" if path[0:3] == '@b3': path = "%s/%s" % (b3.getB3Path(), path[3:]) elif path[0:6] == '@conf/' or path[0:6] == '@conf\\': path = "%s/%s" % (b3.getConfPath(), path[5:]) return os.path.normpath(os.path.expanduser(path))
def __init__(self, console): """ Object constructor. :param console: The console instance """ self._console = console self._outputDir = getConfPath() self._adminPlugin = self._console.getPlugin('admin') if self._adminPlugin is None: raise Exception('AUTODOC: cannot generate documentation without the admin plugin') if self._console.config.has_section('autodoc'): if self._console.config.has_option('autodoc', 'destination'): dest = self._console.config.get('autodoc', 'destination') if dest is None: self._console.warning('AUTODOC: destination found but empty: using default') else: if dest.startswith('ftp://') or dest.startswith('file://'): self._outputUrl = dest else: # assume file self._outputUrl = 'file://' + self._console.config.getpath('autodoc', 'destination') if self._console.config.has_option('autodoc', 'type'): self._outputType = self._console.config.get('autodoc', 'type') if self._console.config.has_option('autodoc', 'maxlevel'): self._maxlevel = self._console.config.getint('autodoc', 'maxlevel')
def _configloader(self, configfile): """ Process each line of a config file """ with open(os.path.join(b3.getConfPath(), configfile), 'r') as f: for line in f: if not line.startswith('//') and not line.startswith('\r\n'): self.console.write(line, maxRetries=5) time.sleep(1)
def getpath(self, section, setting): """Return an absolute path name and expand the user prefix (~)""" path = self.get(section, setting) if path[0:3] == '@b3': path = "%s/%s" % (b3.getB3Path(), path[3:]) elif path[0:6] == '@conf/' or path[0:6] == '@conf\\': path = os.path.join(b3.getConfPath(), path[6:]) return os.path.normpath(os.path.expanduser(path))
def getpath(self, section, setting): """Return an absolute path name and expand the user prefix (~)""" path = self.get(section, setting) if path[0:3] == "@b3": path = "%s/%s" % (b3.getB3Path(), path[3:]) elif path[0:6] == "@conf/" or path[0:6] == "@conf\\": path = "%s/%s" % (b3.getConfPath(), path[5:]) return os.path.normpath(os.path.expanduser(path))
def getpath(self, section, setting): """Return an absolute path name and expand the user prefix (~)""" path = self.get(section, setting) if path[0:3] == '@b3': # relative path to the b3 module directory path = path[1:] elif path[0:6] == '@conf/' or path[0:6] == '@conf\\': path = "%s/%s" % (b3.getConfPath(), path[5:]) return os.path.normpath(os.path.expanduser(path))
def getpath(self, section, setting): """Return an absolute path name and expand the user prefix (~)""" path = self.get(section, setting) if path[0:3] == "@b3": # releative path to the b3 module directory # TODO: use actual module path path = path[1:] elif path[0:6] == "@conf/" or path[0:6] == "@conf\\": path = "%s/%s" % (b3.getConfPath(), path[5:]) return os.path.normpath(os.path.expanduser(path))
def cmd_palistcfg(self, data, client, cmd): """ List available server config files in b3 conf folder (You can safely use the command without the 'pa' at the beginning) """ config_files = [] filenames = os.listdir(b3.getConfPath()) for filename in filenames: if filename.endswith('.cfg'): config_files.append(filename) if not config_files: client.message('No server config files found') else: client.message('^3Available config files are:^7 %s' % string.join(config_files, ', '))
def load(fileName): if os.path.splitext(fileName)[1].lower() == '.xml': config = XmlConfigParser() else: config = CfgConfigParser() fileName = os.path.normpath(fileName) if fileName[0:4] == '@b3\\' or fileName[0:4] == '@b3/': fileName = os.path.normpath("%s/%s" % (b3.getB3Path(), fileName[3:])) elif fileName[0:6] == '@conf\\' or fileName[0:6] == '@conf/': fileName = os.path.normpath("%s/%s" % (b3.getConfPath(), fileName[5:])) if config.load(fileName): return config else: return None
def load(fileName): if os.path.splitext(fileName)[1].lower() == ".xml": config = XmlConfigParser() else: config = CfgConfigParser() fileName = os.path.normpath(fileName) if fileName[0:4] == "@b3\\" or fileName[0:4] == "@b3/": fileName = os.path.normpath("%s/%s" % (b3.getB3Path(), fileName[3:])) elif fileName[0:6] == "@conf\\" or fileName[0:6] == "@conf/": fileName = os.path.normpath("%s/%s" % (b3.getConfPath(), fileName[5:])) if config.load(fileName): return config else: return None
def load_html_template(self, template): """ Loads template file from the file system. """ # build template file path _template_path = os.path.join(getConfPath(), 'templates/autodoc/') _template_file = _template_path + template self._console.verbose('AUTODOC: looking for %s' % _template_file) if not os.path.isfile(_template_file): _template_path = os.path.join(getB3Path(), 'conf/templates/autodoc/') _template_file = _template_path + template self._console.verbose('AUTODOC: looking for %s' % _template_file) self._console.debug('AUTODOC: Template = %s' % _template_file) # open template with open(_template_file, 'r') as template_file: template_data = template_file.read() return template_data
def cmd_paload(self, data, client, cmd=None): """ <configfile.cfg> - Load a server configfile. (You can safely use the command without the 'pa' at the beginning) """ if not data: client.message('^7Invalid or missing data, try !help paload') return if not data.endswith('.cfg'): client.message('%s is not a valid server config file!' % data) return else: if not os.path.isfile(os.path.join(b3.getConfPath(), data)): client.message("Cannot find file %s in B3 config folder" % data) else: self.info("Config loader thread is starting") client.message("^1Loading %s. This may take a while depending on the file size, please wait..." % data) thread_configloader = threading.Thread(target=self._configloader(data)) thread_configloader.start() client.message("^1%s successfully loaded!" % data)
def cmd_paload(self, data, client, cmd=None): """ <configfile.cfg> - Load a server configfile. (You can safely use the command without the 'pa' at the beginning) """ if not data: client.message('^7Invalid or missing data, try !help paload') return if not data.endswith('.cfg'): client.message('%s is not a valid server config file!' % data) return else: if not os.path.isfile(os.path.join(b3.getConfPath(), data)): client.message("Cannot find file %s in B3 config folder" % data) else: self.info("Config loader thread is starting") client.message( "^1Loading %s. This may take a while depending on the file size, please wait..." % data) thread_configloader = threading.Thread( target=self._configloader(data)) thread_configloader.start() client.message("^1%s successfully loaded!" % data)
def test_getConfPath(self): self.console.config.fileName = "/some/where/conf/b3.xml" self.assertEqual('/some/where/conf', b3.getConfPath()) self.console.config.fileName = "./b3.xml" self.assertEqual('.', b3.getConfPath())
class DocBuilder: _supportedExportType = ['xml', 'html', 'oldhtml', 'htmltable', 'json'] _console = None _adminPlugin = None _outputType = 'html' _outputUrl = 'file://' + getConfPath() + '/b3doc.html' _maxlevel = None def __init__(self, console): """ Object constructor. :param console: The console instance """ self._console = console self._outputDir = getConfPath() self._adminPlugin = self._console.getPlugin('admin') if self._adminPlugin is None: raise Exception('AUTODOC: cannot generate documentation without the admin plugin') if self._console.config.has_section('autodoc'): if self._console.config.has_option('autodoc', 'destination'): dest = self._console.config.get('autodoc', 'destination') if dest is None: self._console.warning('AUTODOC: destination found but empty: using default') else: if dest.startswith('ftp://') or dest.startswith('file://'): self._outputUrl = dest else: # assume file self._outputUrl = 'file://' + self._console.config.getpath('autodoc', 'destination') if self._console.config.has_option('autodoc', 'type'): self._outputType = self._console.config.get('autodoc', 'type') if self._console.config.has_option('autodoc', 'maxlevel'): self._maxlevel = self._console.config.getint('autodoc', 'maxlevel') def save(self): """ Save the documentation. """ if self._outputType not in self._supportedExportType: self._console.error('AUTODOC: %s type of doc unsupported' % self._outputType) self._console.info('AUTODOC: supported doc types are : %s' % ", ".join(self._supportedExportType)) else: self._console.debug('AUTODOC: saving %s documentation' % self._outputType) if self._outputType == 'xml': self._write(self.getXml()) elif self._outputType == 'html': from string import Template doc_template = Template(self.load_html_template(template='b3doc-ng_template.html')) self._write(doc_template.safe_substitute(json_data=self.get_json())) elif self._outputType == 'oldhtml': from string import Template doc_template = Template(self.load_html_template(template='b3doc_template.html')) self._write(doc_template.safe_substitute( commandsTable=self.getHtmlTable(), dateUpdated=time.asctime(), server=self._console._publicIp + ':' + str(self._console._port))) elif self._outputType == 'htmltable': self._write(self.getHtmlTable()) elif self._outputType == 'json': self._write(self.get_json(indent=4)) def load_html_template(self, template): """ Loads template file from the file system. """ # build template file path _template_path = os.path.join(getConfPath(), 'templates/autodoc/') _template_file = _template_path + template self._console.verbose('AUTODOC: looking for %s' % _template_file) if not os.path.isfile(_template_file): _template_path = os.path.join(getB3Path(), 'conf/templates/autodoc/') _template_file = _template_path + template self._console.verbose('AUTODOC: looking for %s' % _template_file) self._console.debug('AUTODOC: Template = %s' % _template_file) # open template with open(_template_file, 'r') as template_file: template_data = template_file.read() return template_data def get_json(self, indent=None): import json output = { 'commands': self._getCommandsDict(), 'updated': datetime.datetime.now().isoformat(), 'level_info': {}, 'server_info': { 'ip': self._console._publicIp, 'port': self._console._port, } } # add group level info to output for g in self._console.storage.getGroups(): output['level_info'].update({ g.level: { 'name': g.name, 'keyword': g.keyword, 'level': g.level } }) return json.dumps(output, indent=indent) def getXml(self): xml = Document() xDoc = xml.createElement("b3doc") xDoc.setAttribute("time", time.asctime()) xDoc.setAttribute("game", self._console.game.gameName) xDoc.setAttribute("address", self._console._publicIp + ':' + str(self._console._port)) xCommands = xml.createElement("b3commands") for cmd in self._getCommandsDict(): xCommand = xml.createElement("b3command") xCommand.setAttribute("name", cmd['name']) if 'alias' in cmd and cmd['alias'] != '' : xCommand.setAttribute("alias", cmd['alias']) xCommand.setAttribute("plugin", cmd['plugin']) xCommand.setAttribute("help", cmd['description']) xCommand.setAttribute("minlevel", cmd['minlevel']) xCommand.setAttribute("maxlevel", cmd['maxlevel']) xCommands.appendChild(xCommand) xDoc.appendChild(xCommands) xml.appendChild(xDoc) return xml.toprettyxml(indent="\t") def getHtmlTable(self): text = """ <table id="b3commands"> <thead> <tr> <th class="b3Plugin">plugin</th> <th class="b3MinLevel">min level</th> <th class="b3MaxLevel">max level</th> <th class="b3Name">command</th> <th class="b3Alias">alias</th> <th class="b3Desc">description</th> </tr> </thead> <tbody> %(commandsTablerow)s </tbody> </table> """ def friendlyLevel(level): try: intlevel = int(level) if intlevel <= 0: return '<span title="%s - Everyone">All</span>' % level elif intlevel == 1: return '<span title="%s - Registered players">user</span>' % level elif intlevel < 20: return '<span title="%s - Regular players">reg</span>' % level elif intlevel < 40: return '<span title="%s - Moderators">mod</span>' % level elif intlevel < 60: return '<span title="%s - Admins">admin</span>' % level elif intlevel < 80: return '<span title="%s - Full admins">fulladmin</span>' % level elif intlevel < 100: return '<span title="%s - Senior admins">senioradmin</span>' % level elif intlevel >= 100: return '<span title="%s - Super admins">superadmin</span>' % level else: return level except: return level htmlCommands = "" for cmd in self._getCommandsDict(): html = """<tr class="b3command"> <td class="b3Plugin">%(plugin)s</td> <td class="b3MinLevel">%(minlevel)s</td> <td class="b3MaxLevel">%(maxlevel)s</td> <td class="b3Name">%(name)s</td> <td class="b3Alias">%(alias)s</td> <td class="b3Desc">%(description)s</td> </tr> """ cmd['minlevel'] = friendlyLevel(cmd['minlevel']) cmd['maxlevel'] = friendlyLevel(cmd['maxlevel']) htmlCommands += html % cmd return text % {'commandsTablerow': htmlCommands} def _getCommandsDict(self): if self._maxlevel is not None: self._console.debug('AUTODOC: get commands with level <= %s' % self._maxlevel) commands = {} for cmd in self._adminPlugin._commands.values(): if cmd in commands or \ cmd.level is None: continue if self._maxlevel is not None and cmd.level[0] > self._maxlevel: continue #self._console.debug('AUTODOC: making command doc for %s'%cmd.command) tmp = {'name': cmd.prefix + cmd.command, 'alias': ""} if cmd.alias is not None and cmd.alias != '' : tmp['alias'] = cmd.prefix + cmd.alias tmp['plugin'] = re.sub('Plugin$', '', cmd.plugin.__class__.__name__) _cmd_help = escape(cmd.help) if _cmd_help.startswith('-'): tmp['description'] = _cmd_help[1:] else: tmp['description'] = _cmd_help tmp['minlevel'] = str(cmd.level[0]) if self._outputType != 'json' else cmd.level[0] tmp['maxlevel'] = str(cmd.level[1]) if self._outputType != 'json' else cmd.level[1] commands[cmd] = tmp def commands_compare(x, y): if x['plugin'] < y['plugin']: return -1 elif x['plugin'] > y['plugin']: return 1 elif int(x['minlevel']) < int(y['minlevel']): return -1 elif int(x['minlevel']) > int(y['minlevel']): return 1 elif x['name'] < y['name']: return -1 elif x['name'] > y['name']: return 1 else: return 0 listCommands = commands.values() listCommands.sort(commands_compare) return listCommands def _write(self, text): if text.strip() == '': self._console.warning('AUTODOC: nothing to write') dsn = splitDSN(self._outputUrl) if dsn['protocol'] == 'ftp': self._console.debug('AUTODOC: uploading to FTP server %s' % dsn['host']) ftp = FTP(dsn['host'], dsn['user'], passwd=dsn['password']) ftp.cwd(os.path.dirname(dsn['path'])) ftpfile = StringIO.StringIO() ftpfile.write(text) ftpfile.seek(0) ftp.storbinary('STOR ' + os.path.basename(dsn['path']), ftpfile) elif dsn['protocol'] == 'file': path = getWritableFilePath(dsn['path'], True) self._console.debug('AUTODOC: writing to %s', path) f = file(path, 'w') f.write(text) f.close() else: self._console.error('AUTODOC: protocol [%s] is not supported' % dsn['protocol'])