mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
/data and /tmp standarization
This commit is contained in:
@@ -6,26 +6,27 @@ import shutil
|
||||
import os
|
||||
from flask import jsonify
|
||||
|
||||
# Register NetAlertX directories
|
||||
INSTALL_PATH = "/app"
|
||||
sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
# Resolve speedtest-cli path once at module load and validate it.
|
||||
# We do this once to avoid repeated PATH lookups and to fail fast when
|
||||
# the binary isn't available or executable.
|
||||
SPEEDTEST_CLI_PATH = None
|
||||
|
||||
|
||||
def _get_speedtest_cli_path():
|
||||
"""Resolve and validate the speedtest-cli executable path."""
|
||||
path = shutil.which("speedtest-cli")
|
||||
if path is None:
|
||||
raise RuntimeError(
|
||||
"speedtest-cli not found in PATH. Please install it: pip install speedtest-cli"
|
||||
"speedtest-cli not found in PATH. Please install it: "
|
||||
"pip install speedtest-cli"
|
||||
)
|
||||
if not os.access(path, os.X_OK):
|
||||
raise RuntimeError(f"speedtest-cli found at {path} but is not executable")
|
||||
raise RuntimeError(
|
||||
f"speedtest-cli found at {path} but is not executable"
|
||||
)
|
||||
return path
|
||||
|
||||
|
||||
try:
|
||||
SPEEDTEST_CLI_PATH = _get_speedtest_cli_path()
|
||||
except Exception as e:
|
||||
@@ -33,22 +34,32 @@ except Exception as e:
|
||||
print(f"Warning: {e}", file=sys.stderr)
|
||||
SPEEDTEST_CLI_PATH = None
|
||||
|
||||
def wakeonlan(mac):
|
||||
|
||||
def wakeonlan(mac):
|
||||
# Validate MAC
|
||||
if not re.match(r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$', mac):
|
||||
if not re.match(r"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$", mac):
|
||||
return jsonify({"success": False, "error": f"Invalid MAC: {mac}"}), 400
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["wakeonlan", mac],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
["wakeonlan", mac], capture_output=True, text=True, check=True
|
||||
)
|
||||
return jsonify(
|
||||
{
|
||||
"success": True,
|
||||
"message": "WOL packet sent",
|
||||
"output": result.stdout.strip(),
|
||||
}
|
||||
)
|
||||
return jsonify({"success": True, "message": "WOL packet sent", "output": result.stdout.strip()})
|
||||
except subprocess.CalledProcessError as e:
|
||||
return jsonify({"success": False, "error": "Failed to send WOL packet", "details": e.stderr.strip()}), 500
|
||||
return jsonify(
|
||||
{
|
||||
"success": False,
|
||||
"error": "Failed to send WOL packet",
|
||||
"details": e.stderr.strip(),
|
||||
}
|
||||
), 500
|
||||
|
||||
|
||||
def traceroute(ip):
|
||||
"""
|
||||
@@ -77,10 +88,10 @@ def traceroute(ip):
|
||||
# --------------------------
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["traceroute", ip], # Command and argument
|
||||
capture_output=True, # Capture stdout/stderr
|
||||
text=True, # Return output as string
|
||||
check=True # Raise CalledProcessError on non-zero exit
|
||||
["traceroute", ip], # Command and argument
|
||||
capture_output=True, # Capture stdout/stderr
|
||||
text=True, # Return output as string
|
||||
check=True, # Raise CalledProcessError on non-zero exit
|
||||
)
|
||||
# Return success response with traceroute output
|
||||
return jsonify({"success": True, "output": result.stdout.strip()})
|
||||
@@ -90,11 +101,13 @@ def traceroute(ip):
|
||||
# --------------------------
|
||||
except subprocess.CalledProcessError as e:
|
||||
# Return 500 if traceroute fails
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "Traceroute failed",
|
||||
"details": e.stderr.strip()
|
||||
}), 500
|
||||
return jsonify(
|
||||
{
|
||||
"success": False,
|
||||
"error": "Traceroute failed",
|
||||
"details": e.stderr.strip(),
|
||||
}
|
||||
), 500
|
||||
|
||||
|
||||
def speedtest():
|
||||
@@ -105,10 +118,12 @@ def speedtest():
|
||||
# If the CLI wasn't found at module load, return a 503 so the caller
|
||||
# knows the service is unavailable rather than failing unpredictably.
|
||||
if SPEEDTEST_CLI_PATH is None:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "speedtest-cli is not installed or not found in PATH"
|
||||
}), 503
|
||||
return jsonify(
|
||||
{
|
||||
"success": False,
|
||||
"error": "speedtest-cli is not installed or not found in PATH",
|
||||
}
|
||||
), 503
|
||||
|
||||
try:
|
||||
# Run speedtest-cli command using the resolved absolute path
|
||||
@@ -116,7 +131,7 @@ def speedtest():
|
||||
[SPEEDTEST_CLI_PATH, "--secure", "--simple"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
check=True,
|
||||
)
|
||||
|
||||
# Return each line as a list
|
||||
@@ -124,18 +139,22 @@ def speedtest():
|
||||
return jsonify({"success": True, "output": output_lines})
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "Speedtest failed",
|
||||
"details": e.stderr.strip()
|
||||
}), 500
|
||||
return jsonify(
|
||||
{
|
||||
"success": False,
|
||||
"error": "Speedtest failed",
|
||||
"details": e.stderr.strip(),
|
||||
}
|
||||
), 500
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "Failed to run speedtest",
|
||||
"details": str(e)
|
||||
}), 500
|
||||
return jsonify(
|
||||
{
|
||||
"success": False,
|
||||
"error": "Failed to run speedtest",
|
||||
"details": str(e),
|
||||
}
|
||||
), 500
|
||||
|
||||
|
||||
def nslookup(ip):
|
||||
@@ -147,29 +166,25 @@ def nslookup(ip):
|
||||
try:
|
||||
ipaddress.ip_address(ip)
|
||||
except ValueError:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "Invalid IP address"
|
||||
}), 400
|
||||
return jsonify({"success": False, "error": "Invalid IP address"}), 400
|
||||
|
||||
try:
|
||||
# Run nslookup command
|
||||
result = subprocess.run(
|
||||
["nslookup", ip],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
["nslookup", ip], capture_output=True, text=True, check=True
|
||||
)
|
||||
|
||||
output_lines = result.stdout.strip().split("\n")
|
||||
return jsonify({"success": True, "output": output_lines})
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "nslookup failed",
|
||||
"details": e.stderr.strip()
|
||||
}), 500
|
||||
return jsonify(
|
||||
{
|
||||
"success": False,
|
||||
"error": "nslookup failed",
|
||||
"details": e.stderr.strip(),
|
||||
}
|
||||
), 500
|
||||
|
||||
|
||||
def nmap_scan(ip, mode):
|
||||
@@ -186,24 +201,20 @@ def nmap_scan(ip, mode):
|
||||
try:
|
||||
ipaddress.ip_address(ip)
|
||||
except ValueError:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "Invalid IP address"
|
||||
}), 400
|
||||
return jsonify({"success": False, "error": "Invalid IP address"}), 400
|
||||
|
||||
# Map scan modes to nmap arguments
|
||||
mode_args = {
|
||||
"fast": ["-F"],
|
||||
"normal": [],
|
||||
"detail": ["-A"],
|
||||
"skipdiscovery": ["-Pn"]
|
||||
"skipdiscovery": ["-Pn"],
|
||||
}
|
||||
|
||||
if mode not in mode_args:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": f"Invalid scan mode '{mode}'"
|
||||
}), 400
|
||||
return jsonify(
|
||||
{"success": False, "error": f"Invalid scan mode '{mode}'"}
|
||||
), 400
|
||||
|
||||
try:
|
||||
# Build and run nmap command
|
||||
@@ -212,23 +223,22 @@ def nmap_scan(ip, mode):
|
||||
cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
check=True,
|
||||
)
|
||||
|
||||
output_lines = result.stdout.strip().split("\n")
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"mode": mode,
|
||||
"ip": ip,
|
||||
"output": output_lines
|
||||
})
|
||||
return jsonify(
|
||||
{"success": True, "mode": mode, "ip": ip, "output": output_lines}
|
||||
)
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "nmap scan failed",
|
||||
"details": e.stderr.strip()
|
||||
}), 500
|
||||
return jsonify(
|
||||
{
|
||||
"success": False,
|
||||
"error": "nmap scan failed",
|
||||
"details": e.stderr.strip(),
|
||||
}
|
||||
), 500
|
||||
|
||||
|
||||
def internet_info():
|
||||
@@ -242,7 +252,7 @@ def internet_info():
|
||||
["curl", "-s", "https://ipinfo.io"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
check=True,
|
||||
)
|
||||
|
||||
output = result.stdout.strip()
|
||||
@@ -250,13 +260,20 @@ def internet_info():
|
||||
raise ValueError("Empty response from ipinfo.io")
|
||||
|
||||
# Clean up the JSON-like string by removing { } , and "
|
||||
cleaned_output = output.replace("{", "").replace("}", "").replace(",", "").replace('"', "")
|
||||
cleaned_output = (
|
||||
output.replace("{", "")
|
||||
.replace("}", "")
|
||||
.replace(",", "")
|
||||
.replace('"', "")
|
||||
)
|
||||
|
||||
return jsonify({"success": True, "output": cleaned_output})
|
||||
|
||||
except (subprocess.CalledProcessError, ValueError) as e:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "Failed to fetch internet info",
|
||||
"details": str(e)
|
||||
}), 500
|
||||
return jsonify(
|
||||
{
|
||||
"success": False,
|
||||
"error": "Failed to fetch internet info",
|
||||
"details": str(e),
|
||||
}
|
||||
), 500
|
||||
|
||||
Reference in New Issue
Block a user