updayz
This commit is contained in:
94
qlpycon.py
94
qlpycon.py
@ -15,6 +15,10 @@ import logging
|
|||||||
logger = logging.getLogger('logger')
|
logger = logging.getLogger('logger')
|
||||||
logger.setLevel(logging.DEBUG)
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
# Separate logger for all JSON events when --json flag is used
|
||||||
|
all_json_logger = logging.getLogger('all_json')
|
||||||
|
all_json_logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
# Separate logger for unknown JSON events
|
# Separate logger for unknown JSON events
|
||||||
unknown_json_logger = logging.getLogger('unknown_json')
|
unknown_json_logger = logging.getLogger('unknown_json')
|
||||||
unknown_json_logger.setLevel(logging.DEBUG)
|
unknown_json_logger.setLevel(logging.DEBUG)
|
||||||
@ -246,12 +250,80 @@ def get_team_color(player_name):
|
|||||||
'SPECTATOR': '^3(SPEC)^7'
|
'SPECTATOR': '^3(SPEC)^7'
|
||||||
}.get(team, '')
|
}.get(team, '')
|
||||||
|
|
||||||
|
def format_powerup_message(msg_str):
|
||||||
|
"""Format powerup pickup and kill messages with colors"""
|
||||||
|
|
||||||
|
if msg_str.startswith("broadcast:"):
|
||||||
|
msg_str = msg_str[11:].strip()
|
||||||
|
|
||||||
|
# Check for powerup pickup: "PlayerName got the PowerupName!"
|
||||||
|
pickup_match = re.match(r'^(.+?)\s+got the\s+(.+?)!', msg_str)
|
||||||
|
if pickup_match:
|
||||||
|
player_name = pickup_match.group(1).strip()
|
||||||
|
powerup_name = pickup_match.group(2).strip()
|
||||||
|
|
||||||
|
# Get team color for player
|
||||||
|
player_clean = re.sub(r'\^\d', '', player_name)
|
||||||
|
team_prefix = get_team_color(player_clean)
|
||||||
|
|
||||||
|
# Color code powerups
|
||||||
|
powerup_colors = {
|
||||||
|
'Quad Damage': '^5Quad Damage^7',
|
||||||
|
'Battle Suit': '^3Battle Suit^7',
|
||||||
|
'Regeneration': '^1Regeneration^7',
|
||||||
|
'Haste': '^3Haste^7',
|
||||||
|
'Invisibility': '^5Invisibility^7',
|
||||||
|
'Flight': '^5Flight^7',
|
||||||
|
'Medkit': '^1Medkit^7',
|
||||||
|
'MegaHealth': '^4MegaHealth^7'
|
||||||
|
}
|
||||||
|
|
||||||
|
colored_powerup = powerup_colors.get(powerup_name, f'^6{powerup_name}^7')
|
||||||
|
|
||||||
|
return f"{team_prefix}{player_name} ^7got the {colored_powerup}!\n"
|
||||||
|
|
||||||
|
# Check for powerup carrier kill: "PlayerName killed the PowerupName carrier!"
|
||||||
|
carrier_match = re.match(r'^(.+?)\s+killed the\s+(.+?)\s+carrier!', msg_str)
|
||||||
|
if carrier_match:
|
||||||
|
player_name = carrier_match.group(1).strip()
|
||||||
|
powerup_name = carrier_match.group(2).strip()
|
||||||
|
|
||||||
|
# Get team color for player
|
||||||
|
player_clean = re.sub(r'\^\d', '', player_name)
|
||||||
|
team_prefix = get_team_color(player_clean)
|
||||||
|
|
||||||
|
# Color code powerups (same as above)
|
||||||
|
powerup_colors = {
|
||||||
|
'Quad Damage': '^5Quad Damage^7',
|
||||||
|
'Battle Suit': '^3Battle Suit^7',
|
||||||
|
'Regeneration': '^1Regeneration^7',
|
||||||
|
'Haste': '^3Haste^7',
|
||||||
|
'Invisibility': '^5Invisibility^7',
|
||||||
|
'Flight': '^5Flight^7',
|
||||||
|
'Medkit': '^1Medkit^7',
|
||||||
|
'MegaHealth': '^4MegaHealth^7'
|
||||||
|
}
|
||||||
|
|
||||||
|
colored_powerup = powerup_colors.get(powerup_name, f'^6{powerup_name}^7')
|
||||||
|
|
||||||
|
return f"{team_prefix}{player_name} ^7killed the {colored_powerup} ^7carrier!\n"
|
||||||
|
|
||||||
|
# Not a powerup message
|
||||||
|
return None
|
||||||
|
|
||||||
def ParseGameEvent(message):
|
def ParseGameEvent(message):
|
||||||
"""Parse JSON game events and return formatted message"""
|
"""Parse JSON game events and return formatted message"""
|
||||||
global current_gametype, recent_events
|
global current_gametype, recent_events
|
||||||
|
|
||||||
try:
|
try:
|
||||||
jObject = json.loads(message)
|
jObject = json.loads(message)
|
||||||
|
|
||||||
|
# Log ALL JSON events to file if --json flag was provided
|
||||||
|
if all_json_logger.handlers:
|
||||||
|
all_json_logger.info('JSON Event received:')
|
||||||
|
all_json_logger.info(json.dumps(jObject, indent=2))
|
||||||
|
all_json_logger.info('---')
|
||||||
|
|
||||||
if 'TYPE' not in jObject or 'DATA' not in jObject:
|
if 'TYPE' not in jObject or 'DATA' not in jObject:
|
||||||
logger.debug('JSON missing TYPE or DATA fields')
|
logger.debug('JSON missing TYPE or DATA fields')
|
||||||
return None
|
return None
|
||||||
@ -279,7 +351,7 @@ def ParseGameEvent(message):
|
|||||||
recent_events.pop(0)
|
recent_events.pop(0)
|
||||||
|
|
||||||
warmup = data.get('WARMUP', False)
|
warmup = data.get('WARMUP', False)
|
||||||
warmup_suffix = " ^7(^3warmup^7)" if warmup else ""
|
warmup_suffix = " ^3(warmup)" if warmup else ""
|
||||||
|
|
||||||
if event_type == 'PLAYER_SWITCHTEAM':
|
if event_type == 'PLAYER_SWITCHTEAM':
|
||||||
if 'KILLER' not in data:
|
if 'KILLER' not in data:
|
||||||
@ -366,7 +438,7 @@ def ParseGameEvent(message):
|
|||||||
}
|
}
|
||||||
weapon_name = weapon_names.get(weapon, 'the %s' % weapon)
|
weapon_name = weapon_names.get(weapon, 'the %s' % weapon)
|
||||||
|
|
||||||
return "%s%s ^8fragged^7 %s%s ^7with %s%s\n" % (
|
return "%s%s ^7fragged^7 %s%s ^7with %s%s\n" % (
|
||||||
killer_team_prefix, killer_name,
|
killer_team_prefix, killer_name,
|
||||||
victim_team_prefix, victim_name,
|
victim_team_prefix, victim_name,
|
||||||
weapon_name, warmup_suffix
|
weapon_name, warmup_suffix
|
||||||
@ -459,6 +531,7 @@ def InitWindows(screen, args):
|
|||||||
curses.initscr()
|
curses.initscr()
|
||||||
screen.nodelay(1)
|
screen.nodelay(1)
|
||||||
curses.start_color()
|
curses.start_color()
|
||||||
|
curses.use_default_colors()
|
||||||
curses.cbreak()
|
curses.cbreak()
|
||||||
curses.setsyx(-1, -1)
|
curses.setsyx(-1, -1)
|
||||||
screen.addstr("Quake Live rcon: %s" % args.host)
|
screen.addstr("Quake Live rcon: %s" % args.host)
|
||||||
@ -514,6 +587,7 @@ def main(screen):
|
|||||||
parser.add_argument( '--identity', default = uuid.uuid1().hex, help = 'Specify the socket identity. Random UUID used by default' )
|
parser.add_argument( '--identity', default = uuid.uuid1().hex, help = 'Specify the socket identity. Random UUID used by default' )
|
||||||
parser.add_argument( '-v', '--verbose', action='count', default=0, help = 'Increase verbosity (use -v for INFO, -vv for DEBUG)' )
|
parser.add_argument( '-v', '--verbose', action='count', default=0, help = 'Increase verbosity (use -v for INFO, -vv for DEBUG)' )
|
||||||
parser.add_argument( '--unknown-log', default='unknown_events.log', help = 'File to log unknown JSON events. Defaults to unknown_events.log' )
|
parser.add_argument( '--unknown-log', default='unknown_events.log', help = 'File to log unknown JSON events. Defaults to unknown_events.log' )
|
||||||
|
parser.add_argument('--json', '-j', dest='json_log', default=None, help='File to log all JSON events. If specified, all JSON messages from server will be captured')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Set logging level based on verbosity
|
# Set logging level based on verbosity
|
||||||
@ -689,6 +763,15 @@ def main(screen):
|
|||||||
|
|
||||||
stats_connected = True
|
stats_connected = True
|
||||||
PrintMessageFormatted(output_window, "Stats stream connected - ready for game events\n")
|
PrintMessageFormatted(output_window, "Stats stream connected - ready for game events\n")
|
||||||
|
|
||||||
|
# Set up file handler for all JSON events if --json flag is provided
|
||||||
|
if args.json_log:
|
||||||
|
json_file_handler = logging.FileHandler(args.json_log, mode='a')
|
||||||
|
json_file_formatter = logging.Formatter('%(asctime)s - %(message)s', '%Y-%m-%d %H:%M:%S')
|
||||||
|
json_file_handler.setFormatter(json_file_formatter)
|
||||||
|
all_json_logger.addHandler(json_file_handler)
|
||||||
|
all_json_logger.propagate = False
|
||||||
|
PrintMessageFormatted(output_window, f"*** JSON capture enabled: {args.json_log} ***\n")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
timestamp = time.strftime('%H:%M:%S')
|
timestamp = time.strftime('%H:%M:%S')
|
||||||
PrintMessageFormatted(output_window, f"^1[^7{timestamp}^1] Error: Stats connection failed: {e}^7\n", add_timestamp=False)
|
PrintMessageFormatted(output_window, f"^1[^7{timestamp}^1] Error: Stats connection failed: {e}^7\n", add_timestamp=False)
|
||||||
@ -728,6 +811,13 @@ def main(screen):
|
|||||||
# It's JSON but we didn't parse it - already logged to file
|
# It's JSON but we didn't parse it - already logged to file
|
||||||
logger.debug('Unparsed JSON event')
|
logger.debug('Unparsed JSON event')
|
||||||
else:
|
else:
|
||||||
|
# Check for powerup messages
|
||||||
|
formatted_powerup = format_powerup_message(msg_str)
|
||||||
|
if formatted_powerup:
|
||||||
|
PrintMessageFormatted(output_window, formatted_powerup)
|
||||||
|
curses.setsyx(y,x)
|
||||||
|
curses.doupdate()
|
||||||
|
continue
|
||||||
# Not JSON - check if it's a bot debug message (filter unless verbose)
|
# Not JSON - check if it's a bot debug message (filter unless verbose)
|
||||||
is_bot_debug = ' entered ' in msg_str and (' seek ' in msg_str or ' battle ' in msg_str or ' chase' in msg_str or ' fight' in msg_str)
|
is_bot_debug = ' entered ' in msg_str and (' seek ' in msg_str or ' battle ' in msg_str or ' chase' in msg_str or ' fight' in msg_str)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user