Skip to content

Instantly share code, notes, and snippets.

@bochsdbg
Created April 17, 2020 21:50
Show Gist options
  • Save bochsdbg/cb9cd2b54082d6e139bf033072ec4a83 to your computer and use it in GitHub Desktop.
Save bochsdbg/cb9cd2b54082d6e139bf033072ec4a83 to your computer and use it in GitHub Desktop.
CreepTD server status parser script
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import urllib.request
import re
def to_int(s):
s = s.strip()
try:
return int(s) if s else 0
except ValueError:
return 0
def get_int(list, idx):
try:
return to_int(list[idx])
except IndexError:
return 0
def get_str(list, idx):
try:
return list[idx].strip()
except IndexError:
return ''
def get_bool(list, idx):
s = get_str(list, idx)
if s == 'yes':
return '+'
return ' '
def get_location(list, idx):
s = get_str(list, idx)
if s == '':
return ' '
if s == 'SPECTATOR':
return 'S'
if s == 'TOPLEFT':
return '1'
if s == 'TOPRIGHT':
return '2'
if s == 'BOTTOMLEFT':
return '4'
if s == 'BOTTOMRIGHT':
return '3'
return '??'
def get_game_mode(list, idx):
s = get_str(list, idx)
return s
def get_round(list, idx):
s = get_str(list, idx)
if s == 'over':
return 'over'
if s == '':
return '---'
i = get_int(list, idx)
return '{:>}.{:0>3}'.format(i // 300, i % 300)
resource = urllib.request.urlopen('http://gs1.creeptd.com:4748')
data = resource.read().decode(resource.headers.get_content_charset())
# ID Delay Player Language Points Skill Permission Game ID Connected Location Lives
clients_table = re.findall(r'<table class="clients">(.*?)</table>', data, re.RegexFlag.DOTALL | re.RegexFlag.IGNORECASE)
# ID Name State Map Mode #Players/#Connected #Clients #Contexts Round ID
games_table = re.findall(r'<table class="games">(.*?)</table>', data, re.RegexFlag.DOTALL | re.RegexFlag.IGNORECASE)
game_players = {}
clients = []
if len(clients_table) > 0:
client_lines = re.findall(r'<tr>(.*?)</tr>', clients_table[0], re.RegexFlag.DOTALL | re.RegexFlag.IGNORECASE)
for i in range(1, len(client_lines)):
info = re.findall(r'<td\b[^>]*>(.*?)</td>', client_lines[i], re.RegexFlag.DOTALL | re.RegexFlag.IGNORECASE)
client = {
'id': get_int(info, 0),
'ping': get_str(info, 1),
'name': get_str(info, 2),
'lang': get_str(info, 3),
'points': get_int(info, 4),
'skill': get_int(info, 5),
'perm': get_str(info, 6),
'game_id': get_int(info, 7),
'connected': get_bool(info, 8),
'location_str': get_str(info, 9),
'location': get_location(info, 9),
'lives': get_int(info, 10),
}
clients.append(client)
game_id = get_int(info, 7)
if not game_id in game_players:
game_players[game_id] = []
# game_players[game_id].append((get_str(info, 2), get_location(info, 9), get_int(info, 10)))
game_player = get_str(info, 2)
if client['location'] != ' ':
game_player = game_player + '(' + str(client['lives']) + ')'
game_players[game_id].append(game_player)
games = []
if len(games_table) > 0:
game_lines = re.findall(r'<tr[^>]*>(.*?)</tr>', games_table[0], re.RegexFlag.DOTALL | re.RegexFlag.IGNORECASE)
for i in range(1, len(game_lines)):
info = re.findall(r'<td\b[^>]*>(.*?)</td>', game_lines[i], re.RegexFlag.DOTALL | re.RegexFlag.IGNORECASE)
game_id = get_int(info, 0)
if not game_id in game_players:
continue
games.append({
'id': game_id,
'name': get_str(info, 1),
'state': get_str(info, 2),
'map': get_str(info, 3),
'mode': get_str(info, 4),
'roundId': get_round(info, 8),
})
clients.sort(key=lambda x: x['skill'], reverse=True)
summary = 'Total: {}'.format(len(clients))
if len(clients) > 0:
for i in range(min(3, len(clients))):
summary = summary + ', {}({})'.format(clients[i]['name'], clients[i]['skill'])
print(summary)
for c in clients:
print('{:>7} {:>5} {:>2} {:>1}{:>1} {:<15}'.format(
c['ping'], c['skill'], c['lang'], c['connected'], c['location'], c['name']
))
print('')
for g in games:
print('{:<30} {:<10} {:>7} {:<50}'.format(
g['map'], g['mode'], g['roundId'], ', '.join(game_players[g['id']])
))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment