feat(api): Integrate uptime and reboot traffic stats into server API
This commit is contained in:
@ -5,22 +5,35 @@ from pydantic import BaseModel
|
|||||||
# It's better to chnage the underlying script to return bytes instead of changing it here
|
# It's better to chnage the underlying script to return bytes instead of changing it here
|
||||||
# Because of this problem we use str type instead of int as type
|
# Because of this problem we use str type instead of int as type
|
||||||
class ServerStatusResponse(BaseModel):
|
class ServerStatusResponse(BaseModel):
|
||||||
# disk_usage: int
|
# System Info
|
||||||
|
uptime: str
|
||||||
|
boot_time: str
|
||||||
cpu_usage: str
|
cpu_usage: str
|
||||||
total_ram: str
|
|
||||||
ram_usage: str
|
ram_usage: str
|
||||||
|
total_ram: str
|
||||||
online_users: int
|
online_users: int
|
||||||
|
|
||||||
uploaded_traffic: str
|
# Real-time Network
|
||||||
downloaded_traffic: str
|
upload_speed: str
|
||||||
total_traffic: str
|
download_speed: str
|
||||||
|
tcp_connections: int
|
||||||
|
udp_connections: int
|
||||||
|
|
||||||
|
# Traffic Since Reboot
|
||||||
|
reboot_uploaded_traffic: str
|
||||||
|
reboot_downloaded_traffic: str
|
||||||
|
reboot_total_traffic: str
|
||||||
|
|
||||||
|
# User Traffic (All Time)
|
||||||
|
user_uploaded_traffic: str
|
||||||
|
user_downloaded_traffic: str
|
||||||
|
user_total_traffic: str
|
||||||
|
|
||||||
|
|
||||||
class ServerServicesStatusResponse(BaseModel):
|
class ServerServicesStatusResponse(BaseModel):
|
||||||
hysteria_server: bool
|
hysteria_server: bool
|
||||||
hysteria_webpanel: bool
|
hysteria_webpanel: bool
|
||||||
hysteria_iplimit: bool
|
hysteria_iplimit: bool
|
||||||
# hysteria_singbox: bool
|
|
||||||
hysteria_normal_sub: bool
|
hysteria_normal_sub: bool
|
||||||
hysteria_telegram_bot: bool
|
hysteria_telegram_bot: bool
|
||||||
hysteria_warp: bool
|
hysteria_warp: bool
|
||||||
|
|||||||
@ -11,7 +11,7 @@ async def server_status_api():
|
|||||||
Retrieve the server status.
|
Retrieve the server status.
|
||||||
|
|
||||||
This endpoint provides information about the current server status,
|
This endpoint provides information about the current server status,
|
||||||
including CPU usage, RAM usage, online users, and traffic statistics.
|
including uptime, CPU usage, RAM usage, online users, and traffic statistics.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
ServerStatusResponse: A response model containing server status details.
|
ServerStatusResponse: A response model containing server status details.
|
||||||
@ -30,7 +30,6 @@ async def server_status_api():
|
|||||||
|
|
||||||
|
|
||||||
def __parse_server_status(server_info: str) -> ServerStatusResponse:
|
def __parse_server_status(server_info: str) -> ServerStatusResponse:
|
||||||
# Initial data with default values
|
|
||||||
"""
|
"""
|
||||||
Parse the server information provided by cli_api.server_info()
|
Parse the server information provided by cli_api.server_info()
|
||||||
and return a ServerStatusResponse instance.
|
and return a ServerStatusResponse instance.
|
||||||
@ -45,57 +44,87 @@ def __parse_server_status(server_info: str) -> ServerStatusResponse:
|
|||||||
ValueError: If the server information is invalid or incomplete.
|
ValueError: If the server information is invalid or incomplete.
|
||||||
"""
|
"""
|
||||||
data = {
|
data = {
|
||||||
|
'uptime': 'N/A',
|
||||||
|
'boot_time': 'N/A',
|
||||||
'cpu_usage': '0%',
|
'cpu_usage': '0%',
|
||||||
'total_ram': '0MB',
|
'total_ram': '0MB',
|
||||||
'ram_usage': '0MB',
|
'ram_usage': '0MB',
|
||||||
'online_users': 0,
|
'online_users': 0,
|
||||||
'uploaded_traffic': '0KB',
|
'upload_speed': '0 B/s',
|
||||||
'downloaded_traffic': '0KB',
|
'download_speed': '0 B/s',
|
||||||
'total_traffic': '0KB'
|
'tcp_connections': 0,
|
||||||
|
'udp_connections': 0,
|
||||||
|
'reboot_uploaded_traffic': '0 B',
|
||||||
|
'reboot_downloaded_traffic': '0 B',
|
||||||
|
'reboot_total_traffic': '0 B',
|
||||||
|
'user_uploaded_traffic': '0 B',
|
||||||
|
'user_downloaded_traffic': '0 B',
|
||||||
|
'user_total_traffic': '0 B'
|
||||||
}
|
}
|
||||||
|
|
||||||
# Example output(server_info) from cli_api.server_info():
|
current_section = 'general'
|
||||||
# 📈 CPU Usage: 9.4%
|
|
||||||
# 📋 Total RAM: 3815MB
|
|
||||||
# 💻 Used RAM: 2007MB
|
|
||||||
# 👥 Online Users: 0
|
|
||||||
#
|
|
||||||
# 🔼 Uploaded Traffic: 0 KB
|
|
||||||
# 🔽 Downloaded Traffic: 0 KB
|
|
||||||
# 📊 Total Traffic: 0 KB
|
|
||||||
|
|
||||||
for line in server_info.splitlines():
|
for line in server_info.splitlines():
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if 'Traffic Since Last Reboot' in line:
|
||||||
|
current_section = 'reboot'
|
||||||
|
continue
|
||||||
|
elif 'User Traffic (All Time)' in line:
|
||||||
|
current_section = 'user'
|
||||||
|
continue
|
||||||
|
|
||||||
key, _, value = line.partition(":")
|
key, _, value = line.partition(":")
|
||||||
key = key.strip().lower()
|
key = key.strip().lower()
|
||||||
value = value.strip()
|
value = value.strip()
|
||||||
|
|
||||||
if not key or not value:
|
if not key or not value:
|
||||||
continue # Skip empty or malformed lines
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if 'cpu usage' in key:
|
if 'uptime' in key:
|
||||||
|
uptime_part, _, boottime_part = value.partition('(')
|
||||||
|
data['uptime'] = uptime_part.strip()
|
||||||
|
data['boot_time'] = boottime_part.replace('since ', '').replace(')', '').strip()
|
||||||
|
elif 'cpu usage' in key:
|
||||||
data['cpu_usage'] = value
|
data['cpu_usage'] = value
|
||||||
elif 'total ram' in key:
|
|
||||||
data['total_ram'] = value
|
|
||||||
elif 'used ram' in key:
|
elif 'used ram' in key:
|
||||||
data['ram_usage'] = value
|
parts = value.split('/')
|
||||||
|
if len(parts) == 2:
|
||||||
|
data['ram_usage'] = parts[0].strip()
|
||||||
|
data['total_ram'] = parts[1].strip()
|
||||||
elif 'online users' in key:
|
elif 'online users' in key:
|
||||||
data['online_users'] = int(value)
|
data['online_users'] = int(value)
|
||||||
elif 'uploaded traffic' in key:
|
elif 'upload speed' in key:
|
||||||
value = value.replace(' ', '')
|
data['upload_speed'] = value
|
||||||
data['uploaded_traffic'] = value
|
elif 'download speed' in key:
|
||||||
elif "downloaded traffic" in key:
|
data['download_speed'] = value
|
||||||
value = value.replace(' ', '')
|
elif 'tcp connections' in key:
|
||||||
data['downloaded_traffic'] = value
|
data['tcp_connections'] = int(value)
|
||||||
elif 'total traffic' in key:
|
elif 'udp connections' in key:
|
||||||
value = value.replace(' ', '')
|
data['udp_connections'] = int(value)
|
||||||
data["total_traffic"] = value
|
elif 'total uploaded' in key or 'uploaded traffic' in key:
|
||||||
except ValueError as e:
|
if current_section == 'reboot':
|
||||||
|
data['reboot_uploaded_traffic'] = value
|
||||||
|
elif current_section == 'user':
|
||||||
|
data['user_uploaded_traffic'] = value
|
||||||
|
elif 'total downloaded' in key or 'downloaded traffic' in key:
|
||||||
|
if current_section == 'reboot':
|
||||||
|
data['reboot_downloaded_traffic'] = value
|
||||||
|
elif current_section == 'user':
|
||||||
|
data['user_downloaded_traffic'] = value
|
||||||
|
elif 'combined traffic' in key or 'total traffic' in key:
|
||||||
|
if current_section == 'reboot':
|
||||||
|
data['reboot_total_traffic'] = value
|
||||||
|
elif current_section == 'user':
|
||||||
|
data['user_total_traffic'] = value
|
||||||
|
except (ValueError, IndexError) as e:
|
||||||
raise ValueError(f'Error parsing line \'{line}\': {e}')
|
raise ValueError(f'Error parsing line \'{line}\': {e}')
|
||||||
|
|
||||||
# Validate required fields
|
|
||||||
try:
|
try:
|
||||||
return ServerStatusResponse(**data) # type: ignore
|
return ServerStatusResponse(**data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ValueError(f'Invalid or incomplete server info: {e}')
|
raise ValueError(f'Invalid or incomplete server info: {e}')
|
||||||
|
|
||||||
@ -141,8 +170,6 @@ def __parse_services_status(services_status: dict[str, bool]) -> ServerServicesS
|
|||||||
parsed_services_status['hysteria_telegram_bot'] = status
|
parsed_services_status['hysteria_telegram_bot'] = status
|
||||||
elif 'hysteria-normal-sub' in service:
|
elif 'hysteria-normal-sub' in service:
|
||||||
parsed_services_status['hysteria_normal_sub'] = status
|
parsed_services_status['hysteria_normal_sub'] = status
|
||||||
# elif 'hysteria-singbox' in service:
|
|
||||||
# parsed_services_status['hysteria_singbox'] = status
|
|
||||||
elif 'wg-quick' in service:
|
elif 'wg-quick' in service:
|
||||||
parsed_services_status['hysteria_warp'] = status
|
parsed_services_status['hysteria_warp'] = status
|
||||||
return ServerServicesStatusResponse(**parsed_services_status)
|
return ServerServicesStatusResponse(**parsed_services_status)
|
||||||
|
|||||||
Reference in New Issue
Block a user