From e8213d7e9f144eaf7ba3cfbf69f7b7eeb02d91b1 Mon Sep 17 00:00:00 2001 From: ilyastar9999 Date: Wed, 3 Dec 2025 10:41:24 +0300 Subject: [PATCH] asd --- .env.example | 3 + scoreboard_injector/main.py | 135 +++++++++++++++++++++++++----------- 2 files changed, 96 insertions(+), 42 deletions(-) diff --git a/.env.example b/.env.example index 90c83c3..2cbbfdb 100644 --- a/.env.example +++ b/.env.example @@ -11,6 +11,9 @@ SERVICES_DIR=/root/services # Scoreboard Configuration SCOREBOARD_WS_URL=ws://10.60.0.1:8080/api/events +SCOREBOARD_API_URL=http://10.60.0.1:8080/api +USE_HTTP_POLLING=false +POLLING_INTERVAL=10 OUR_TEAM_ID=1 ALERT_THRESHOLD_POINTS=100 ALERT_THRESHOLD_TIME=300 diff --git a/scoreboard_injector/main.py b/scoreboard_injector/main.py index 51583bf..7e63b1d 100644 --- a/scoreboard_injector/main.py +++ b/scoreboard_injector/main.py @@ -189,51 +189,78 @@ async def send_telegram_alert(message: str): async def http_polling_listener(): """Poll scoreboard HTTP API for attacks as alternative to WebSocket""" - last_round = 0 + last_check_time = datetime.utcnow() while True: try: async with aiohttp.ClientSession() as session: - # Try to fetch scoreboard data - # Common ForcAD endpoints: /api/scoreboard, /api/teams, /api/attacks + # ForcAD API endpoints that should return JSON + # Try different possible paths endpoints_to_try = [ - f"{SCOREBOARD_API_URL}/attacks", - f"{SCOREBOARD_API_URL}/scoreboard", - f"{SCOREBOARD_API_URL}/flag_stats" + ('/api/client/attack_data', 'GET'), + ('/api/client/attacks', 'GET'), + ('/api/flag/info', 'GET'), + ('/api/info', 'GET'), + ('/api/game_state', 'GET'), ] - for endpoint in endpoints_to_try: + data_found = False + + for endpoint_path, method in endpoints_to_try: + endpoint = f"{SCOREBOARD_API_URL.rstrip('/api')}{endpoint_path}" try: async with session.get(endpoint, timeout=aiohttp.ClientTimeout(total=5)) as resp: if resp.status == 200: - data = await resp.json() - print(f"✓ Fetched data from {endpoint}") + content_type = resp.headers.get('Content-Type', '') - # Process based on response structure - if isinstance(data, list): - # List of attacks/events - for item in data: - await process_attack_event(item) - elif isinstance(data, dict): - # Could be scoreboard with nested data - # Try common keys - for key in ['attacks', 'flags', 'events', 'data']: - if key in data and isinstance(data[key], list): - for item in data[key]: + # Skip HTML responses + if 'text/html' in content_type: + continue + + try: + data = await resp.json() + print(f"✓ Fetched JSON from {endpoint}") + data_found = True + + # Process based on response structure + if isinstance(data, list): + # List of attacks/events + for item in data: + if isinstance(item, dict): await process_attack_event(item) - break - else: - # Might be a single event - await process_attack_event(data) - - break # Success, no need to try other endpoints + elif isinstance(data, dict): + # Try common keys for attack data + for key in ['attacks', 'stolen_flags', 'flags', 'events', 'data', 'rows']: + if key in data: + items = data[key] + if isinstance(items, list): + print(f" Found {len(items)} items in '{key}'") + for item in items: + if isinstance(item, dict): + await process_attack_event(item) + break + else: + # Might be a single event or game state + # Check if it contains attack-like data + if any(k in data for k in ['attacker_id', 'victim_id', 'team_id', 'flag']): + await process_attack_event(data) + + if data_found: + break # Found valid data, no need to try other endpoints + + except (json.JSONDecodeError, aiohttp.ContentTypeError): + # Not JSON, skip + continue + except aiohttp.ClientError as e: - print(f"Failed to fetch from {endpoint}: {e}") continue - except json.JSONDecodeError: - print(f"Invalid JSON from {endpoint}") + except Exception as e: + print(f"Error fetching {endpoint}: {e}") continue - + + if not data_found: + print(f"No valid JSON data found from scoreboard API (last check: {datetime.utcnow().strftime('%H:%M:%S')})") + except Exception as e: print(f"HTTP polling error: {e}") @@ -497,27 +524,51 @@ async def debug_scoreboard(): except Exception as e: results["websocket_status"] = f"unreachable: {str(e)}" - # Test HTTP endpoints - results["http_api_url"] = SCOREBOARD_API_URL + # Test HTTP endpoints - both HTML and API paths + base_url = SCOREBOARD_API_URL.rstrip('/api') endpoints = [ - "/attacks", - "/scoreboard", - "/flag_stats", - "/teams", - "/events" + "/api/client/attack_data", + "/api/client/attacks", + "/api/flag/info", + "/api/info", + "/api/game_state", + "/api/attacks", + "/api/scoreboard", + "/api/teams", + "/api/events" ] for endpoint in endpoints: - url = f"{SCOREBOARD_API_URL}{endpoint}" + url = f"{base_url}{endpoint}" try: async with session.get(url, timeout=aiohttp.ClientTimeout(total=5)) as resp: - data = await resp.text() - results["endpoints_tested"].append({ + content_type = resp.headers.get('Content-Type', '') + is_json = 'application/json' in content_type + is_html = 'text/html' in content_type + + result = { "url": url, "status": resp.status, "reachable": resp.status == 200, - "data_preview": data[:500] if resp.status == 200 else None - }) + "content_type": content_type, + "is_json": is_json, + "is_html": is_html + } + + if resp.status == 200: + if is_json: + try: + data = await resp.json() + result["json_preview"] = str(data)[:500] + result["json_keys"] = list(data.keys()) if isinstance(data, dict) else "list" + except: + pass + else: + text = await resp.text() + result["data_preview"] = text[:200] + + results["endpoints_tested"].append(result) + except Exception as e: results["endpoints_tested"].append({ "url": url,