import shlex import subprocess import sys import time from datetime import datetime from .portal import PortalCaptureError from .reader import read_image_once, read_portal_window_once APP_NAME = "Anti Prestige Tool" NOTIFY_TITLE = "Arma Reforger Queue" def notify_queue_position(notify_command, position): command = [ *shlex.split(notify_command), "-a", APP_NAME, "-u", "critical", NOTIFY_TITLE, f"Queue position is {position}", ] try: result = subprocess.run(command, check=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) except FileNotFoundError: return False, f"missing notification command: {command[0]}" if result.returncode != 0: message = result.stderr.strip() or result.stdout.strip() or f"exit status {result.returncode}" return False, f"notification command failed: {message}" return True, "" def queue_position(number): try: position = int(number) except ValueError: return None if position < 1: return None return position def should_alert(number, threshold, notified_positions): position = queue_position(number) if position is None or position > threshold or position in notified_positions: return None return position def timestamp(): return datetime.now().astimezone().isoformat(timespec="seconds") def print_poll_status(number, alert_state, message=""): if number: line = f"{timestamp()} number={number} alert={alert_state}" else: line = f"{timestamp()} no digits found alert={alert_state}" if message: line = f"{line} {message}" print(line, flush=True) def read_once(args): if args.image: return read_image_once(args, args.image) return read_portal_window_once(args) def run_watch(args): notified_positions = set() try: while True: try: result = read_once(args) except PortalCaptureError as exc: print(str(exc), file=sys.stderr) if exc.used_restore_token: print( "Portal restore token appears stale; rerun with --portal-reselect.", file=sys.stderr, ) return 1 if args.portal_reselect: args.portal_reselect = False if not result.number: print_poll_status("", "no") else: position = should_alert(result.number, args.alert_threshold, notified_positions) if position is None: print_poll_status(result.number, "no") else: fired, error = notify_queue_position(args.notify_command, position) if fired: notified_positions.add(position) print_poll_status(result.number, "yes") else: print_poll_status(result.number, "failed", error) time.sleep(args.watch_interval) except KeyboardInterrupt: print(f"{timestamp()} watch stopped", flush=True) return 130