#!/usr/bin/env nix-shell #!nix-shell -i python3 -p "python3.withPackages(ps: with ps; [ tqdm psycopg2-bin ])" from tqdm import tqdm from pprint import pprint from pathlib import Path from datetime import datetime, timedelta from dataclasses import dataclass import gzip # Currently not mysql lol import sqlite3 @dataclass class LoginLogoutEvent: username: str timestamp: datetime is_login: bool # if false, it is a logout event def parse_login_logout_events_from_file(path: Path) -> list[LoginLogoutEvent]: date = path.name[:10] result = [] with gzip.open(path, 'r') as file: for line in file: if b'joined the game' in line or b'left the game' in line: split = line.decode().split() result.append(LoginLogoutEvent( username = split[3], is_login = split[4] == 'joined', timestamp = datetime.fromisoformat(f"{date} {split[0][1:9]}"), )) return result @dataclass class LoginSpan: username: str start_time: datetime duration: int def conjoin_sessions(event_log: list[LoginLogoutEvent]) -> list[LoginSpan]: result = [] login_session_table = dict() for e in event_log: if e.is_login: login_session_table[e.username] = e.timestamp elif e.username in login_session_table: result.append(LoginSpan( username = e.username, start_time = e.timestamp, duration = (e.timestamp - login_session_table[e.username]).total_seconds(), )) del login_session_table[e.username] else: print(f"warn: loose session found for {e.username} at {e.timestamp}") return result def insert_sessions_into_db(session_log: list[LoginSpan]) -> None: con = sqlite3.connect("test.db") cur = con.cursor() cur.execute("DROP TABLE IF EXISTS minecraft_login_sessions") cur.execute(""" CREATE TABLE minecraft_login_sessions( username TEXT NOT NULL, start DATETIME, duration INTEGER ) """) cur.executemany( "INSERT INTO minecraft_login_sessions(username, start, duration) VALUES(?, ?, ?)", [(e.username, e.start_time, e.duration) for e in session_log], ) con.commit() if __name__ == "__main__": event_log = [] files = list(Path(__file__).parent.glob(r"*.log.gz")) for file in (pbar:=tqdm(files)): pbar.set_postfix_str(str(file)) event_log += parse_login_logout_events_from_file(file) session_log = conjoin_sessions(event_log) insert_sessions_into_db(session_log)