modified: .gitignore

modified:   README.md
	new file:   install.sh
	renamed:    config.py -> lib/constants.py
	renamed:    cvars.py -> lib/cvars.py
	renamed:    formatter.py -> lib/formatter.py
	renamed:    network.py -> lib/network.py
	renamed:    parser.py -> lib/parser.py
	renamed:    qlpycon_config.py -> lib/settings.py
	renamed:    state.py -> lib/state.py
	renamed:    ui.py -> lib/ui.py
	modified:   main.py
	modified:   qlpycon.bash
	new file:   qlpycon.conf.example
This commit is contained in:
xbl
2026-06-13 10:21:29 +02:00
parent be6ae8d137
commit 7ca9795a39
14 changed files with 476 additions and 174 deletions
+58 -29
View File
@@ -16,13 +16,13 @@ import sys
import os
import threading
from config import VERSION, DEFAULT_HOST, POLL_TIMEOUT, QUIT_CONFIRM_TIMEOUT, RESPAWN_DELAY, MAX_COMMAND_HISTORY
from state import GameState
from network import RconConnection, StatsConnection
from parser import EventParser
from formatter import format_message, format_chat_message, format_powerup_message, strip_color_codes
from ui import UIManager
from qlpycon_config import ConfigLoader
from lib.constants import VERSION, DEFAULT_HOST, POLL_TIMEOUT, QUIT_CONFIRM_TIMEOUT, RESPAWN_DELAY, MAX_COMMAND_HISTORY
from lib.state import GameState
from lib.network import RconConnection, StatsConnection
from lib.parser import EventParser
from lib.formatter import format_message, format_chat_message, format_powerup_message, strip_color_codes
from lib.ui import UIManager
from lib.settings import ConfigLoader
# Pre-compiled regex patterns
CVAR_RESPONSE_PATTERN = re.compile(r'"([^"]+)"\s+is:"([^"]*)"')
@@ -299,32 +299,12 @@ def parse_player_events(message, game_state, ui):
return False
def main_loop(screen):
def main_loop(screen, args):
"""Main application loop"""
# Setup signal handler for Ctrl+C with confirmation
signal.signal(signal.SIGINT, signal_handler)
# Load configuration file (optional)
config = ConfigLoader()
config.load()
# Parse arguments (command line overrides config file)
parser = argparse.ArgumentParser(description='Verbose QuakeLive server statistics')
parser.add_argument('--host', default=config.get_host() or DEFAULT_HOST,
help=f'ZMQ URI to connect to. Defaults to {DEFAULT_HOST}')
parser.add_argument('--password', default=config.get_password(), required=False,
help='RCON password')
parser.add_argument('--identity', default=uuid.uuid1().hex,
help='Socket identity (random UUID by default)')
parser.add_argument('-v', '--verbose', action='count', default=0,
help='Increase verbosity (-v INFO, -vv DEBUG)')
parser.add_argument('--unknown-log', default='unknown_events.log',
help='File to log unknown JSON events')
parser.add_argument('-j', '--json', dest='json_log', default=None,
help='File to log all JSON events')
args = parser.parse_args()
# Set logging level
if args.verbose == 0:
logger.setLevel(logging.WARNING)
@@ -356,6 +336,7 @@ def main_loop(screen):
ui.print_message(f"zmq python bindings {zmq.__version__}, libzmq version {zmq.zmq_version()}\n")
# Initialize network connections
ui.print_message(f"Connecting with host={args.host} password={args.password}\n")
rcon = RconConnection(args.host, args.password, args.identity)
rcon.connect()
@@ -546,4 +527,52 @@ def main_loop(screen):
logger.info("Shutdown complete")
if __name__ == '__main__':
curses.wrapper(main_loop)
# Load config
config = ConfigLoader()
config.load()
# Parse arguments
parser = argparse.ArgumentParser(description='Quake Live Python Console')
parser.add_argument('server', nargs='?', default=None,
help='Named server from qlpycon.conf (e.g. ffa, duel)')
parser.add_argument('--host', default=None,
help='ZMQ URI to connect to (e.g. tcp://1.2.3.4:28960)')
parser.add_argument('--password', default=None,
help='RCON password')
parser.add_argument('--list', action='store_true',
help='List configured servers and exit')
parser.add_argument('--identity', default=uuid.uuid1().hex,
help='Socket identity (random UUID by default)')
parser.add_argument('-v', '--verbose', action='count', default=0,
help='Increase verbosity (-v INFO, -vv DEBUG)')
parser.add_argument('--unknown-log', default='unknown_events.log',
help='File to log unknown JSON events')
parser.add_argument('-j', '--json', dest='json_log', default=None,
help='File to log all JSON events')
args = parser.parse_args()
# Handle --list
if args.list:
servers = config.get_servers()
if not servers:
print('No servers configured in qlpycon.conf')
else:
print('Configured servers:')
for name, host in servers.items():
print(f' {name:<12} {host}')
sys.exit(0)
# Resolve host and password
if args.server:
host, password = config.get_server(args.server)
if host is None:
print(f"Error: server '{args.server}' not found in qlpycon.conf")
print("Use 'qlpycon --list' to see configured servers.")
sys.exit(1)
args.host = args.host or host
args.password = args.password or password
else:
args.host = args.host or config.get_host() or DEFAULT_HOST
args.password = args.password or config.get_password()
curses.wrapper(main_loop, args)