def main(): args = _getParser().parse_args() token = input().encode('ascii') logPrefix = args.logPrefix + '-bots' if args.logPrefix else 'bots' if os.name == 'nt': logpath = data.getPath(data.user, 'authserver', 'logs') data.makeDirs(logpath) initLogging( logFile=os.path.join(logpath, 'log{}.txt'.format(logPrefix))) else: initLogging(prefix='[{}] '.format(logPrefix)) reactor.callWhenRunning(_twisted_main, args, token) reactor.run()
def getFilename(alias, directory, ext, multipleFiles = True): # Figure out the filename to use for the main file gamePath = getPath(user, directory) makeDirs(gamePath) copyCount = 0 succeeded = False if multipleFiles: while not succeeded: filename = '%s (%s)%s' % (alias, str(copyCount), ext) filePath = os.path.join(gamePath, filename) succeeded = not os.path.exists(filePath) copyCount += 1 else: filename = '%s%s' % (alias, ext) filePath = os.path.join(gamePath, filename) return filePath
def saveMap(self, filename, force=False): ''' Saves the current map layout to the .trosnoth/maps directory. @param filename: The filename of the map (with extension) @param force: Overwrites the file if it already exists ''' mapDir = getPath(user, 'maps') makeDirs(mapDir) filename = os.path.join(mapDir, filename) if os.path.exists(filename) and not force: return 'File already exists (use "force" parameter to overwrite)' with open(filename, 'w') as f: f.write(repr(self.getWorld().layout.dumpState())) return 'Map saved to %s' % (filename,)
def __init__(self, dataPath=None, manholePassword=None): if dataPath is None: dataPath = getPath(data.user, 'authserver') makeDirs(dataPath) self.dataPath = dataPath self.manholePassword = None self.authManager = self.authManagerClass(dataPath) self.pubKey, self.privKey = self.loadKeys() self.arenaProxies = {} self.arenaAMPListener = None self.adminTokens = set() self.onArenaStarting = Event(['proxy']) self.onArenaStopped = Event(['proxy']) AuthenticationFactory.instance = self
def __init__(self, dataPath=None): if dataPath is None: dataPath = getPath(data.user, 'authserver') makeDirs(dataPath) self.dataPath = dataPath self.onPrimaryGameChanged = Event() self.primaryGameId = None self.authManager = self.authManagerClass(dataPath) self.pubKey, self.privKey = self.loadKeys() self.servers = {} # Game id -> game. self.nextId = 0 self.registeredGames = [] self.gameStats = {} self.layoutDatabase = LayoutDatabase() self.notifier = self.settings.createNotificationClient() if self.notifier is not None: self.notifier.startService()
def _addDatastoreByPaths(self, *paths): for path in paths: try: makeDirs(path) except (OSError, WindowsError): log.warning('Could not create datastore path') return store = LayoutDatastore(pathGetter=self.pathGetter) self.datastores.append(store) # Read map blocks from files. for path in paths: filenames = os.listdir(path) # Go through all files in the blocks directory. for fn in filenames: # Check for files with a .block extension. if os.path.splitext(fn)[1] == '.block': store.addLayoutAtFilename(os.path.join(path, fn)) return store
def refresh(self): # Get a list of files with the name '*.tros' logDir = getPath(user, gameDir) makeDirs(logDir) self.games = [] for fname in os.listdir(logDir): if os.path.splitext(fname)[1] != gameExt: continue try: game = RecordedGame(os.path.join(logDir, fname)) except RecordedGameException: continue if game.recordedGameVersion != recordedGameVersion: continue self.games.append(game) self.games.sort(key=lambda game: (-game.unixTimestamp, game.filename))
def generateHtml(htmlPath, statPath): def plural(value): if value == 1: return '' else: return 's' def add(value, statName=None, altText=None, spacing=True, className=None): if altText is not None: points = POINT_VALUES[altText] * value if type(points) == float: points = '%2.2f' % points altText = ' title="%s point%s\"' % (points, plural(points)) else: altText = '' if className is not None: classText = ' class="%s"' % (className) else: classText = '' if type(value) == float: value = '%2.2f' % value if statName is None: html.append('\t\t\t\t<td%s%s>%s</td>' % (altText, classText, value)) else: nbsp = '' if spacing is False: pluralStr = '' else: nbsp = ' ' pluralStr = plural(value) html.append('\t\t\t\t<td%s>%s%s%s%s</td>' % (altText, value, nbsp, statName, pluralStr)) def addList(title, data): html.append('\t\t\t\t\t<li><b>%s:</b> ' % title) if len(data) == 0: html.append('\t\t\t\t\t\tNone') else: data = sorted(list(data.items()), key=operator.itemgetter(1), reverse=True) string = [] for details in data: string.append('%s (%d)' % details) html.append('\t\t\t\t\t\t' + ', '.join(string)) html.append('\t\t\t\t\t</li>') def accuracy(shotsHit, shotsFired): try: return ((shotsHit**2) / (shotsFired + 0.0)) * 30 except ZeroDivisionError: return 0 from trosnoth.gamerecording.gamerecorder import statDir makeDirs(statDir) if statPath == '': files = os.listdir(statDir) else: files = [statPath] playerStats = {} statNames = [ 'aliveStreak', 'deaths', 'killStreak', 'kills', 'roundsLost', 'roundsWon', 'shotsFired', 'shotsHit', 'coinsEarned', 'coinsUsed', 'coinsWasted', 'tagStreak', 'timeAlive', 'timeDead', 'zoneAssists', 'zoneTags' ] statEnemies = ['playerDeaths', 'playerKills', 'upgradesUsed'] leaders = list( map(str.lower, list(leaderAchievements.keys()) + list(additionalLeaders.keys()))) tableHeaders = [ [ '#', 'Nick', 'Kills', 'Deaths', 'KDR', 'Zone Tags', 'Shots Fired', 'Shots Hit', 'Accuracy', 'Coins Used', 'Killed the most:', 'Died the most to:', 'Points' ], [ '#', 'Nick', 'Coins Earned', 'Coins Used', 'Coins Wasted', 'Favourite Upgrade', 'Time Alive', 'Time Dead', 'ADR', 'Longest Life', 'Points' ], [ '#', 'Nick', 'Kills', 'Kill Streak', 'Zone Tags', 'Zone Assists', 'Tag Streak', 'Points' ], ] tableNames = ['General Overview', 'Coins and Time', 'Kills and Tags'] for x in range(0, len(tableNames)): style = '' if x == 0: style = " style='color: black;'" tableNames[x] = ('<span class="name topLink" id="link%s" ' 'onClick="navigate(\'%s\', %d)"%s>%s</span>' % (x, x, len(tableHeaders[x]), style, tableNames[x])) navigation = ' – '.join(tableNames) html = [] fileMatrix = {} for filename in files: if filename[-9:] != '.trosstat': filename = filename + '.trosstat' statLocation = os.path.join(statPath, filename) try: statFile = open(statLocation) except IOError: raise Exception("'%s' does not exist!" % filename) loadedStats = simplejson.load(statFile) for nick in loadedStats['players']: if nick not in playerStats: playerStats[nick] = loadedStats['players'][nick] fileMatrix[nick] = [filename] else: for stat in statNames: playerStats[nick][stat] += ( loadedStats['players'][nick][stat]) for stat in statEnemies: for enemy in loadedStats['players'][nick][stat]: if enemy not in playerStats[nick][stat]: playerStats[nick][stat][enemy] = 0 playerStats[nick][stat][enemy] += ( loadedStats['players'][nick][stat][enemy]) fileMatrix[nick].append(filename) ranking = {} allData = {} for nick in playerStats: data = playerStats[nick] try: data['accuracy'] = (100.0 * data['shotsHit']) / data['shotsFired'] except ZeroDivisionError: data['accuracy'] = 0 for stat in statEnemies: data[stat + 'Full'] = data[stat].copy() highest = 0 highestName = '----' names = data[stat] for k, v in list(names.items()): if v > highest: highest = v highestName = k if highest == 0: data[stat] = highestName else: data[stat] = '%s (%s)' % (highestName, highest) data['score'] = 0 for stat, value in list(POINT_VALUES.items()): points = data[stat] * value data['score'] += points try: data['kdr'] = '%2.2f' % (float(data['kills']) / data['deaths']) except ZeroDivisionError: data['kdr'] = '----' try: data['adr'] = '%2.2f' % (float(data['timeAlive']) / data['timeDead']) except ZeroDivisionError: data['adr'] = '----' ranking[nick] = data['score'] allData[nick] = data rankingList = sorted(list(ranking.items()), key=operator.itemgetter(1), reverse=True) ranking = {} rankCount = 0 html.append("\t\t<table class='ladder'>") for count in range(0, len(tableNames)): style = '' if count != 0: style = " style='display: none;'" html.append("\t\t\t<tr class='allRows group%s'%s>" % (count, style)) for caption in tableHeaders[count]: html.append('\t\t\t\t<th>%s</th>' % caption) html.append('\t\t\t</tr>') teamNames = ('Blue', 'Red') if 'winningTeamId' in loadedStats: winningTeamId = loadedStats['winningTeamId'] if winningTeamId == b'A': winText = '%s Team won' % (teamNames[0], ) colour = 'navy' elif winningTeamId == b'B': winText = '%s Team won' % (teamNames[1], ) colour = 'maroon' else: winText = 'Game was a draw' colour = 'green' else: winText = 'Game was not finished' colour = 'gray' html.append('<p class="wintext" style="color: %s;">%s</p>' % (colour, winText)) for pair in rankingList: nick = pair[0] rankCount += 1 rankStr = str(rankCount) classy = '' if stripPunctuation(nick).lower() in leaders: classy = ' leader' rankCount -= 1 rankStr = '--' data = allData[nick] if data['bot']: classy = ' bot' rankCount -= 1 rankStr = 'B' if sys.version_info.major == 2: nickId = ''.join('{:02x}'.format(ord(c)) for c in 'abc'.encode('utf-8')) else: nickId = ''.join('{:02x}'.format(c for c in 'abc'.encode('utf-8'))) for count in range(0, len(tableNames)): style = '' if count != 0: style = " style='display: none;'" html.append("\t\t\t<tr class='allRows group%s%s'%s>" % (count, classy, style)) if (data['team'] == b'A'): bgColour = 'blueteam' elif (data['team'] == b'B'): bgColour = 'redteam' elif (data['team'] == NEUTRAL_TEAM_ID): bgColour = 'rogue' add('<strong>%s</strong>' % rankStr, className=bgColour) add('<span class="name" onClick="toggle(\'details-%s\')">%s</span>' % (nickId, nick)) if count == 0: add(data['kills'], 'kill', 'kills') add(data['deaths'], 'death', 'deaths') add(data['kdr']) add(data['zoneTags'], 'tag', 'zoneTags') add(data['shotsFired'], 'shot') add(data['shotsHit'], 'shot') add(data['accuracy'], '%', 'accuracy', False) add(data['coinsUsed'], 'coin', 'coinsUsed') add(data['playerKills']) add(data['playerDeaths']) elif count == 1: add(data['coinsEarned'], 'coin') add(data['coinsUsed'], 'coin', 'coinsUsed') add(data['coinsWasted'], 'coin') add(data['upgradesUsed']) add(int(data['timeAlive']), 'second') add(int(data['timeDead']), 'second') add(data['adr']) add(int(data['aliveStreak']), 'second') elif count == 2: add(data['kills'], 'kill', 'kills') add(data['killStreak'], 'kill') add(data['zoneTags'], 'tag', 'zoneTags') add(data['zoneAssists'], 'assist', 'zoneAssists') add(data['tagStreak'], 'zone') elif count == 3: add(data['shotsFired'], 'shot') add(data['shotsHit'], 'shot') add(data['accuracy'], '%', spacing=False) old = data['accuracy'] * 20 new = accuracy(data['shotsHit'], data['shotsFired']) add(old, 'point') add(new, 'point') add(new - old) add('<strong>%2.2f</strong>' % data['score']) html.append('\t\t\t</tr>') if count == len(tableNames) - 1: html.append( "\t\t\t<tr id='details-%s' style='display: none;'>" % nickId) html.append("\t\t\t\t<td colspan='%d' class='details'" "style='text-align: left;'>" % len(tableHeaders[0])) html.append('\t\t\t\t\t<ul>') addList('Players killed', data['playerKillsFull']) addList('Players died to', data['playerDeathsFull']) addList('Upgrades used', data['upgradesUsedFull']) html.append('\t\t\t\t\t</ul>') html.append('\t\t\t\t</td>') html.append('\t\t\t</tr>') html.append('\t\t</table>') html = '\n' + '\n'.join(html) + '\n' baseHTML = open(getPath(statGeneration, 'statGenerationBase.htm'), 'r').read() html = baseHTML.replace('[[TABLE]]', html) html = html.replace('[[NAVIGATION]]', navigation) with open(htmlPath, 'w') as f: f.write(html)
def populateList(self): defaultTheme = { "name": "Default Theme", "filename": "default", "author": "Trosnoth Team", "content": None, "source": "internal" } # Clear out the sidebar self.themeNameText.setText('') self.themeAuthorText.setText('') for element in self.contents: element.setText('') self.useThemeButton.setText('') self.restartButton.setText('') self.listHeaderText.setText('available themes:') self.themeList.index = -1 userThemeDir = getPath(user, 'themes') internalThemeDir = getPath(themes) makeDirs(userThemeDir) themeList = [] # Get a list of internal themes for dirName in os.listdir(internalThemeDir): if os.path.isdir(os.path.join(internalThemeDir, dirName)): themeList.append("i/%s" % dirName) # Get a list of user-defined themes for dirName in os.listdir(userThemeDir): if os.path.isdir(os.path.join(userThemeDir, dirName)): # Internal themes overrule user-defined themes if "i/" + dirName not in themeList and dirName != "default": themeList.append("u/%s" % dirName) # Assume all themes are valid for now validThemes = themeList[:] self.themeInfo = {} for themeName in themeList: themeInfo = {"content": {}} if themeName.startswith("i/"): themeInfo['source'] = 'internal' directory = internalThemeDir else: themeInfo['source'] = 'user-defined' directory = userThemeDir themeNameList = themeName themeName = themeName[2:] themeInfo['filename'] = themeName[2:] anyContent = False for contentType in list(self.contentTypes.keys()): if themeInfo['source'] == 'internal': contentDir = os.path.join(directory, themeName, contentType) else: contentDir = os.path.join(directory, themeName, contentType) if not os.path.isdir(contentDir): continue else: fileCount = len([ f for f in os.listdir(contentDir) if os.path.isfile(os.path.join(contentDir, f)) ]) if fileCount > 0: anyContent = True themeInfo["content"][contentType] = fileCount if not anyContent: validThemes.remove(themeNameList) continue infoFile = os.path.join(directory, themeName, "info.txt") if os.path.isfile(infoFile): infoFile = open(infoFile) infoContents = infoFile.readlines() else: infoContents = [] if len(infoContents) >= 2: themeInfo["author"] = infoContents[1].strip() else: themeInfo["author"] = None if len(infoContents) >= 1: themeInfo["name"] = infoContents[0].strip() else: themeInfo["name"] = themeName self.themeInfo[themeName] = themeInfo self.themeInfo["default"] = defaultTheme # Sort the themes alphabetically items = [(v['filename'], n) for n, v in self.themeInfo.items()] items.sort() items = [n for v, n in items] self.themeList.setItems(items) if len(self.themeInfo) == 1: self.listHeaderText.setText("1 available theme:") self.themeList.index = 0 self.updateSidebar(0) else: self.listHeaderText.setText("%d available themes:" % len(self.themeInfo))
def startServer(port=6787, dataPath=None, manholePort=6799, password=None, webPort=None): # Ensure that the authserver directories exist authDir = getPath(user, 'authserver', 'accounts') makeDirs(authDir) # Ensure that any database migrations have happened management.call_command('migrate') # If murmur communication is enabled, try to connect if murmur.init() == 'initialised': reactor.addSystemEventTrigger('before', 'shutdown', murmur.tearDownRooms) dbqueue.init() pf = AuthenticationFactory(dataPath) def getManholeFactory(namespace, password): realm = manhole_ssh.TerminalRealm() # If we don't do this, the server will generate an exception when # you resize the SSH window def windowChanged(self, size): pass realm.sessionFactory.windowChanged = windowChanged def getManhole(_): return Manhole(namespace) realm.chainedProtocolFactory.protocolFactory = getManhole p = portal.Portal(realm) # Username/Password authentication passwordDB = checkers.InMemoryUsernamePasswordDatabaseDontUse() passwordDB.addUser('trosnoth', password) p.registerChecker(passwordDB) factory = manhole_ssh.ConchFactory(p) privatePath = getPath(user, 'authserver', 'manhole_rsa') if os.path.isfile(privatePath): factory.privateKeys[b'ssh-rsa'] = keys.Key.fromFile(privatePath) publicPath = privatePath + '.pub' if os.path.isfile(publicPath): factory.publicKeys[b'ssh-rsa'] = keys.Key.fromFile(publicPath) return factory if password is None: password = ''.join(random.choice('0123456789') for i in range(6)) namespace = {} namespace['authFactory'] = pf namespace['helper'] = AuthServerManholeHelper(pf) factory = getManholeFactory(namespace, password) try: reactor.listenTCP(manholePort, factory) except CannotListenError: log.error('Error starting manhole on port %d', manholePort) except ConchError as e: log.error('Error starting manhole on port %d: %s', manholePort, e.value) else: log.warning('SSH manhole started on port %d with password %r', manholePort, password) if webPort is not None: from trosnoth.web.server import startWebServer startWebServer(pf, webPort) try: reactor.listenTCP(port, pf) except CannotListenError: log.error('Error listening on port %d.', port) else: log.info('Started Trosnoth authentication server on port %d.', port) reactor.run()
''' from configparser import ConfigParser import logging import os import socket from django.core.management.utils import get_random_secret_key from trosnoth import data log = logging.getLogger(__name__) # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) data.makeDirs(data.getPath(data.user, 'authserver')) CONFIG_PATH = data.getPath(data.user, 'authserver', 'config') config = ConfigParser(interpolation=None) config.add_section('security') config.add_section('web') config.read(CONFIG_PATH) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = config.get('security', 'key', fallback=None) if not SECRET_KEY: SECRET_KEY = get_random_secret_key().replace('%', '-') config.set('security', 'key', SECRET_KEY) with open(CONFIG_PATH, 'w') as f:
def populateList(self, sender=None): # Clear out the sidebar for item in self.dynamicText: item.setText('') self.listHeaderText.setText('available game files:') self.gameList.index = -1 self.elements = self.elementsFiles[:] # Get a list of files with the name '*.tros' logDir = getPath(user, gameDir) makeDirs(logDir) fileList = [] for fname in os.listdir(logDir): if os.path.splitext(fname)[1] == gameExt: fileList.append(fname) # Assume all files are valid for now validFiles = fileList[:] self.gameInfo = {} oldFound = False for fname in fileList: try: game = RecordedGame(os.path.join(logDir, fname)) except RecordedGameException: validFiles.remove(fname) continue except: log.warning('invalid file: %s', fname) continue else: if game.recordedGameVersion != recordedGameVersion: validFiles.remove(fname) oldFound = True self.gameInfo[os.path.splitext(fname)[0]] = game # Sort the games with most recent first. items = [(v.unixTimestamp, n) for n, v in self.gameInfo.iteritems()] items.sort(reverse=True) items = [n for v, n in items] self.gameList.setItems(items) if len(self.gameInfo) == 0: self.elements = self.elementsNoFiles[:] self.listHeaderText.setText('0 available game files:') if oldFound: self.noFiles1Text.setText('Some games were found from') self.noFiles2Text.setText('previous Trosnoth versions') else: self.noFiles1Text.setText('You have not yet run any') self.noFiles2Text.setText('games on this computer') else: self.gameList.setIndex(0) self.updateSidebar(0) if len(self.gameInfo) == 1: self.listHeaderText.setText('1 available game file:') else: self.listHeaderText.setText('{} available game files:'.format( len(self.gameInfo)))