Files
Blitz-Proxy/core/traffic.py
Whispering Wind 94c485bdba Add no-gui flag and improve traffic status output control
- Added --no-gui flag to traffic-status command
- Modified traffic.py to accept no_gui parameter
- Updated cli_api.traffic_status() to control output display
- Ensured silent operation when called from remove-user command
- Improved function return values for programmatic use
- Added proper parameter handling throughout the call chain
2025-04-14 11:29:09 +03:30

116 lines
3.8 KiB
Python

#!/usr/bin/env python3
import json
import os
import json
from hysteria2_api import Hysteria2Client
# Define static variables for paths and URLs
CONFIG_FILE = '/etc/hysteria/config.json'
USERS_FILE = '/etc/hysteria/users.json'
API_BASE_URL = 'http://127.0.0.1:25413'
def traffic_status(no_gui=False):
green = '\033[0;32m'
cyan = '\033[0;36m'
NC = '\033[0m'
try:
with open(CONFIG_FILE, 'r') as config_file:
config = json.load(config_file)
secret = config.get('trafficStats', {}).get('secret')
except (json.JSONDecodeError, FileNotFoundError) as e:
print(f"Error: Failed to read secret from {CONFIG_FILE}. Details: {e}")
return
if not secret:
print("Error: Secret not found in config.json")
return
client = Hysteria2Client(base_url=API_BASE_URL, secret=secret)
try:
traffic_stats = client.get_traffic_stats(clear=True)
online_status = client.get_online_clients()
except Exception as e:
print(f"Error communicating with Hysteria2 API: {e}")
return
users_data = {}
if os.path.exists(USERS_FILE):
try:
with open(USERS_FILE, 'r') as users_file:
users_data = json.load(users_file)
except json.JSONDecodeError:
print("Error: Failed to parse existing users data JSON file.")
return
for user in users_data:
users_data[user]["status"] = "Offline"
for user_id, status in online_status.items():
if user_id in users_data:
users_data[user_id]["status"] = "Online" if status.is_online else "Offline"
else:
users_data[user_id] = {
"upload_bytes": 0,
"download_bytes": 0,
"status": "Online" if status.is_online else "Offline"
}
for user_id, stats in traffic_stats.items():
if user_id in users_data:
users_data[user_id]["upload_bytes"] = users_data[user_id].get("upload_bytes", 0) + stats.upload_bytes
users_data[user_id]["download_bytes"] = users_data[user_id].get("download_bytes", 0) + stats.download_bytes
else:
online = user_id in online_status and online_status[user_id].is_online
users_data[user_id] = {
"upload_bytes": stats.upload_bytes,
"download_bytes": stats.download_bytes,
"status": "Online" if online else "Offline"
}
with open(USERS_FILE, 'w') as users_file:
json.dump(users_data, users_file, indent=4)
if not no_gui:
display_traffic_data(users_data, green, cyan, NC)
return users_data
def display_traffic_data(data, green, cyan, NC):
if not data:
print("No traffic data to display.")
return
print("Traffic Data:")
print("-------------------------------------------------")
print(f"{'User':<15} {'Upload (TX)':<15} {'Download (RX)':<15} {'Status':<10}")
print("-------------------------------------------------")
for user, entry in data.items():
upload_bytes = entry.get("upload_bytes", 0)
download_bytes = entry.get("download_bytes", 0)
status = entry.get("status", "Offline")
formatted_tx = format_bytes(upload_bytes)
formatted_rx = format_bytes(download_bytes)
print(f"{user:<15} {green}{formatted_tx:<15}{NC} {cyan}{formatted_rx:<15}{NC} {status:<10}")
print("-------------------------------------------------")
def format_bytes(bytes):
if bytes < 1024:
return f"{bytes}B"
elif bytes < 1048576:
return f"{bytes / 1024:.2f}KB"
elif bytes < 1073741824:
return f"{bytes / 1048576:.2f}MB"
elif bytes < 1099511627776:
return f"{bytes / 1073741824:.2f}GB"
else:
return f"{bytes / 1099511627776:.2f}TB"
if __name__ == "__main__":
traffic_status()