This commit is contained in:
ilyastar9999
2025-12-03 10:41:24 +03:00
parent 54c5dc9821
commit e8213d7e9f
2 changed files with 96 additions and 42 deletions

View File

@@ -11,6 +11,9 @@ SERVICES_DIR=/root/services
# Scoreboard Configuration # Scoreboard Configuration
SCOREBOARD_WS_URL=ws://10.60.0.1:8080/api/events 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 OUR_TEAM_ID=1
ALERT_THRESHOLD_POINTS=100 ALERT_THRESHOLD_POINTS=100
ALERT_THRESHOLD_TIME=300 ALERT_THRESHOLD_TIME=300

View File

@@ -189,51 +189,78 @@ async def send_telegram_alert(message: str):
async def http_polling_listener(): async def http_polling_listener():
"""Poll scoreboard HTTP API for attacks as alternative to WebSocket""" """Poll scoreboard HTTP API for attacks as alternative to WebSocket"""
last_round = 0 last_check_time = datetime.utcnow()
while True: while True:
try: try:
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
# Try to fetch scoreboard data # ForcAD API endpoints that should return JSON
# Common ForcAD endpoints: /api/scoreboard, /api/teams, /api/attacks # Try different possible paths
endpoints_to_try = [ endpoints_to_try = [
f"{SCOREBOARD_API_URL}/attacks", ('/api/client/attack_data', 'GET'),
f"{SCOREBOARD_API_URL}/scoreboard", ('/api/client/attacks', 'GET'),
f"{SCOREBOARD_API_URL}/flag_stats" ('/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: try:
async with session.get(endpoint, timeout=aiohttp.ClientTimeout(total=5)) as resp: async with session.get(endpoint, timeout=aiohttp.ClientTimeout(total=5)) as resp:
if resp.status == 200: if resp.status == 200:
content_type = resp.headers.get('Content-Type', '')
# Skip HTML responses
if 'text/html' in content_type:
continue
try:
data = await resp.json() data = await resp.json()
print(f"✓ Fetched data from {endpoint}") print(f"✓ Fetched JSON from {endpoint}")
data_found = True
# Process based on response structure # Process based on response structure
if isinstance(data, list): if isinstance(data, list):
# List of attacks/events # List of attacks/events
for item in data: for item in data:
if isinstance(item, dict):
await process_attack_event(item) await process_attack_event(item)
elif isinstance(data, dict): elif isinstance(data, dict):
# Could be scoreboard with nested data # Try common keys for attack data
# Try common keys for key in ['attacks', 'stolen_flags', 'flags', 'events', 'data', 'rows']:
for key in ['attacks', 'flags', 'events', 'data']: if key in data:
if key in data and isinstance(data[key], list): items = data[key]
for item in 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) await process_attack_event(item)
break break
else: else:
# Might be a single event # 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) await process_attack_event(data)
break # Success, no need to try other endpoints 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: except aiohttp.ClientError as e:
print(f"Failed to fetch from {endpoint}: {e}")
continue continue
except json.JSONDecodeError: except Exception as e:
print(f"Invalid JSON from {endpoint}") print(f"Error fetching {endpoint}: {e}")
continue 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: except Exception as e:
print(f"HTTP polling error: {e}") print(f"HTTP polling error: {e}")
@@ -497,27 +524,51 @@ async def debug_scoreboard():
except Exception as e: except Exception as e:
results["websocket_status"] = f"unreachable: {str(e)}" results["websocket_status"] = f"unreachable: {str(e)}"
# Test HTTP endpoints # Test HTTP endpoints - both HTML and API paths
results["http_api_url"] = SCOREBOARD_API_URL base_url = SCOREBOARD_API_URL.rstrip('/api')
endpoints = [ endpoints = [
"/attacks", "/api/client/attack_data",
"/scoreboard", "/api/client/attacks",
"/flag_stats", "/api/flag/info",
"/teams", "/api/info",
"/events" "/api/game_state",
"/api/attacks",
"/api/scoreboard",
"/api/teams",
"/api/events"
] ]
for endpoint in endpoints: for endpoint in endpoints:
url = f"{SCOREBOARD_API_URL}{endpoint}" url = f"{base_url}{endpoint}"
try: try:
async with session.get(url, timeout=aiohttp.ClientTimeout(total=5)) as resp: async with session.get(url, timeout=aiohttp.ClientTimeout(total=5)) as resp:
data = await resp.text() content_type = resp.headers.get('Content-Type', '')
results["endpoints_tested"].append({ is_json = 'application/json' in content_type
is_html = 'text/html' in content_type
result = {
"url": url, "url": url,
"status": resp.status, "status": resp.status,
"reachable": resp.status == 200, "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: except Exception as e:
results["endpoints_tested"].append({ results["endpoints_tested"].append({
"url": url, "url": url,