move log-parse and template-render into own functions
This commit is contained in:
parent
acd8c27f1c
commit
bd9be87867
220
tsstats.py
220
tsstats.py
|
@ -115,124 +115,130 @@ class Client:
|
||||||
'pbans': self.pbans,
|
'pbans': self.pbans,
|
||||||
}[item]
|
}[item]
|
||||||
|
|
||||||
# check cmdline-args
|
|
||||||
abspath = sep.join(__file__.split(sep)[:-1]) + sep
|
|
||||||
config_path = argv[1] if len(argv) >= 2 else 'config.ini'
|
|
||||||
config_path = abspath + config_path
|
|
||||||
id_map_path = argv[2] if len(argv) >= 3 else 'id_map.json'
|
|
||||||
id_map_path = abspath + id_map_path
|
|
||||||
|
|
||||||
if not exists(config_path):
|
|
||||||
raise Exception('Couldn\'t find config-file at {}'.format(config_path))
|
|
||||||
|
|
||||||
if exists(id_map_path):
|
|
||||||
# read id_map
|
|
||||||
id_map = json.load(open(id_map_path))
|
|
||||||
else:
|
|
||||||
id_map = {}
|
|
||||||
|
|
||||||
# parse config
|
|
||||||
config = configparser.ConfigParser()
|
|
||||||
config.read(config_path)
|
|
||||||
# check keys
|
|
||||||
if 'General' not in config:
|
|
||||||
raise Exception('Invalid config! Section "General" missing!')
|
|
||||||
general = config['General']
|
|
||||||
html = config['HTML'] if 'HTML' in config.sections() else {}
|
|
||||||
if not ('logfile' in general or 'outputfile' in general):
|
|
||||||
raise Exception('Invalid config! "logfile" and/or "outputfile" missing!')
|
|
||||||
log_path = general['logfile']
|
|
||||||
output_path = general['outputfile']
|
|
||||||
debug = general.get('debug', 'false') in ['true', 'True']
|
|
||||||
debug_file = general.get('debugfile', str(debug)) in ['true', 'True']
|
|
||||||
title = html.get('title', 'TeamspeakStats')
|
|
||||||
|
|
||||||
# setup logging
|
|
||||||
log = logging.getLogger()
|
|
||||||
log.setLevel(logging.DEBUG)
|
|
||||||
# create handler
|
|
||||||
if debug and debug_file:
|
|
||||||
file_handler = logging.FileHandler('debug.txt', 'w', 'UTF-8')
|
|
||||||
file_handler.setFormatter(logging.Formatter('%(message)s'))
|
|
||||||
file_handler.setLevel(logging.DEBUG)
|
|
||||||
log.addHandler(file_handler)
|
|
||||||
|
|
||||||
# stream handler
|
|
||||||
stream_handler = logging.StreamHandler()
|
|
||||||
stream_handler.setLevel(logging.INFO)
|
|
||||||
log.addHandler(stream_handler)
|
|
||||||
|
|
||||||
re_dis_connect = re.compile(r"'(.*)'\(id:(\d*)\)")
|
re_dis_connect = re.compile(r"'(.*)'\(id:(\d*)\)")
|
||||||
re_disconnect_invoker = re.compile(r"invokername=(.*)\ invokeruid=(.*)\ reasonmsg")
|
re_disconnect_invoker = re.compile(r"invokername=(.*)\ invokeruid=(.*)\ reasonmsg")
|
||||||
|
abspath = sep.join(__file__.split(sep)[:-1]) + sep
|
||||||
# find all log-files and collect lines
|
|
||||||
log_files = [file_name for file_name in glob.glob(log_path) if exists(file_name)]
|
|
||||||
log_lines = []
|
|
||||||
for log_file in log_files:
|
|
||||||
for line in open(log_file, 'r'):
|
|
||||||
log_lines.append(line)
|
|
||||||
|
|
||||||
|
|
||||||
def get_client(clid):
|
def parse_logs(logpath, file_log=False):
|
||||||
if clid in id_map:
|
# setup logging
|
||||||
clid = id_map[clid]
|
log = logging.getLogger()
|
||||||
client = clients[clid]
|
log.setLevel(logging.DEBUG)
|
||||||
client.nick = nick
|
if file_log:
|
||||||
return client
|
# file logger
|
||||||
|
file_handler = logging.FileHandler('debug.txt', 'w', 'UTF-8')
|
||||||
|
file_handler.setFormatter(logging.Formatter('%(message)s'))
|
||||||
|
file_handler.setLevel(logging.DEBUG)
|
||||||
|
log.addHandler(file_handler)
|
||||||
|
# stream logger (unused)
|
||||||
|
stream_handler = logging.StreamHandler()
|
||||||
|
stream_handler.setLevel(logging.INFO)
|
||||||
|
log.addHandler(stream_handler)
|
||||||
|
|
||||||
# process lines
|
# find all log-files and collect lines
|
||||||
for line in log_lines:
|
log_files = [file_name for file_name in glob.glob(log_path) if exists(file_name)]
|
||||||
parts = line.split('|')
|
log_lines = []
|
||||||
logdatetime = int(datetime.datetime.strptime(parts[0], '%Y-%m-%d %H:%M:%S.%f').timestamp())
|
for log_file in log_files:
|
||||||
data = '|'.join(parts[4:]).strip()
|
for line in open(log_file, 'r'):
|
||||||
if data.startswith('client'):
|
log_lines.append(line)
|
||||||
nick, clid = re_dis_connect.findall(data)[0]
|
|
||||||
if data.startswith('client connected'):
|
|
||||||
client = get_client(clid)
|
|
||||||
client.connect(logdatetime)
|
|
||||||
elif data.startswith('client disconnected'):
|
|
||||||
client = get_client(clid)
|
|
||||||
client.disconnect(logdatetime)
|
|
||||||
if 'invokeruid' in data:
|
|
||||||
re_disconnect_data = re_disconnect_invoker.findall(data)
|
|
||||||
invokernick, invokeruid = re_disconnect_data[0]
|
|
||||||
invoker = clients[invokeruid]
|
|
||||||
invoker.nick = invokernick
|
|
||||||
if 'bantime' in data:
|
|
||||||
invoker.ban(client)
|
|
||||||
else:
|
|
||||||
invoker.kick(client)
|
|
||||||
|
|
||||||
# render template
|
def get_client(clid, nick):
|
||||||
template = Environment(loader=FileSystemLoader(abspath)).get_template('template.html')
|
if clid in id_map:
|
||||||
|
clid = id_map[clid]
|
||||||
|
client = clients[clid]
|
||||||
|
client.nick = nick
|
||||||
|
return client
|
||||||
|
|
||||||
# sort all values desc
|
# process lines
|
||||||
cl_by_id = clients.clients_by_id
|
for line in log_lines:
|
||||||
cl_by_uid = clients.clients_by_uid
|
parts = line.split('|')
|
||||||
|
logdatetime = int(datetime.datetime.strptime(parts[0], '%Y-%m-%d %H:%M:%S.%f').timestamp())
|
||||||
|
data = '|'.join(parts[4:]).strip()
|
||||||
|
if data.startswith('client'):
|
||||||
|
nick, clid = re_dis_connect.findall(data)[0]
|
||||||
|
if data.startswith('client connected'):
|
||||||
|
client = get_client(clid, nick)
|
||||||
|
client.connect(logdatetime)
|
||||||
|
elif data.startswith('client disconnected'):
|
||||||
|
client = get_client(clid, nick)
|
||||||
|
client.disconnect(logdatetime)
|
||||||
|
if 'invokeruid' in data:
|
||||||
|
re_disconnect_data = re_disconnect_invoker.findall(data)
|
||||||
|
invokernick, invokeruid = re_disconnect_data[0]
|
||||||
|
invoker = clients[invokeruid]
|
||||||
|
invoker.nick = invokernick
|
||||||
|
if 'bantime' in data:
|
||||||
|
invoker.ban(client)
|
||||||
|
else:
|
||||||
|
invoker.kick(client)
|
||||||
|
|
||||||
|
|
||||||
def get_sorted(key, uid):
|
def render_template(output, template_name='template.html', title='TeamspeakStats', debug=False):
|
||||||
clients = cl_by_uid.values() if uid else cl_by_id.values()
|
# render template
|
||||||
return sorted([(client, client[key]) for client in clients if client[key] > 0], key=lambda data: data[1], reverse=True)
|
template = Environment(loader=FileSystemLoader(abspath)).get_template('template.html')
|
||||||
|
cl_by_id = clients.clients_by_id
|
||||||
|
cl_by_uid = clients.clients_by_uid
|
||||||
|
|
||||||
clients_onlinetime_ = get_sorted('onlinetime', False)
|
def get_sorted(key, uid):
|
||||||
clients_onlinetime = []
|
clients = cl_by_uid.values() if uid else cl_by_id.values()
|
||||||
for client, onlinetime in clients_onlinetime_:
|
return sorted([(client, client[key]) for client in clients if client[key] > 0], key=lambda data: data[1], reverse=True)
|
||||||
minutes, seconds = divmod(client.onlinetime, 60)
|
|
||||||
hours, minutes = divmod(minutes, 60)
|
clients_onlinetime_ = get_sorted('onlinetime', False)
|
||||||
hours = str(hours) + 'h ' if hours > 0 else ''
|
clients_onlinetime = []
|
||||||
minutes = str(minutes) + 'm ' if minutes > 0 else ''
|
for client, onlinetime in clients_onlinetime_:
|
||||||
seconds = str(seconds) + 's' if seconds > 0 else ''
|
minutes, seconds = divmod(client.onlinetime, 60)
|
||||||
clients_onlinetime.append((client, hours + minutes + seconds))
|
hours, minutes = divmod(minutes, 60)
|
||||||
|
hours = str(hours) + 'h ' if hours > 0 else ''
|
||||||
|
minutes = str(minutes) + 'm ' if minutes > 0 else ''
|
||||||
|
seconds = str(seconds) + 's' if seconds > 0 else ''
|
||||||
|
clients_onlinetime.append((client, hours + minutes + seconds))
|
||||||
|
|
||||||
|
clients_kicks = get_sorted('kicks', True)
|
||||||
|
clients_pkicks = get_sorted('pkicks', False)
|
||||||
|
clients_bans = get_sorted('bans', True)
|
||||||
|
clients_pbans = get_sorted('pbans', False)
|
||||||
|
objs = [('Onlinetime', clients_onlinetime), ('Kicks', clients_kicks),
|
||||||
|
('passive Kicks', clients_pkicks),
|
||||||
|
('Bans', clients_bans), ('passive Bans', clients_pbans)] # (headline, list)
|
||||||
|
|
||||||
|
with open(output_path, 'w') as f:
|
||||||
|
f.write(template.render(title=title, objs=objs, debug=debug))
|
||||||
|
|
||||||
|
|
||||||
clients_kicks = get_sorted('kicks', True)
|
def main():
|
||||||
clients_pkicks = get_sorted('pkicks', False)
|
# check cmdline-args
|
||||||
clients_bans = get_sorted('bans', True)
|
config_path = argv[1] if len(argv) >= 2 else 'config.ini'
|
||||||
clients_pbans = get_sorted('pbans', False)
|
config_path = abspath + config_path
|
||||||
objs = [('Onlinetime', clients_onlinetime), ('Kicks', clients_kicks),
|
id_map_path = argv[2] if len(argv) >= 3 else 'id_map.json'
|
||||||
('passive Kicks', clients_pkicks),
|
id_map_path = abspath + id_map_path
|
||||||
('Bans', clients_bans), ('passive Bans', clients_pbans)] # (headline, list)
|
|
||||||
|
|
||||||
with open(output_path, 'w') as f:
|
if not exists(config_path):
|
||||||
f.write(template.render(title=title, objs=objs, debug=debug))
|
raise Exception('Couldn\'t find config-file at {}'.format(config_path))
|
||||||
|
|
||||||
|
if exists(id_map_path):
|
||||||
|
# read id_map
|
||||||
|
id_map = json.load(open(id_map_path))
|
||||||
|
else:
|
||||||
|
id_map = {}
|
||||||
|
|
||||||
|
# parse config
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read(config_path)
|
||||||
|
# check keys
|
||||||
|
if 'General' not in config:
|
||||||
|
raise Exception('Invalid config! Section "General" missing!')
|
||||||
|
general = config['General']
|
||||||
|
html = config['HTML'] if 'HTML' in config.sections() else {}
|
||||||
|
if not ('logfile' in general or 'outputfile' in general):
|
||||||
|
raise Exception('Invalid config! "logfile" and/or "outputfile" missing!')
|
||||||
|
log_path = general['logfile']
|
||||||
|
output_path = general['outputfile']
|
||||||
|
debug = general.get('debug', 'false') in ['true', 'True']
|
||||||
|
debug_file = general.get('debugfile', str(debug)) in ['true', 'True']
|
||||||
|
title = html.get('title', 'TeamspeakStats')
|
||||||
|
|
||||||
|
render_template(output=output_path, title=title, debug=debug)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
Loading…
Reference in New Issue