From c1d8c422af3c9a307f6a3999b70ace7d725c6686 Mon Sep 17 00:00:00 2001 From: Whispering Wind <151555003+ReturnFI@users.noreply.github.com> Date: Sat, 26 Apr 2025 13:31:19 +0330 Subject: [PATCH] Add decoy status API --- core/cli_api.py | 19 ++++++++++++++++++- .../routers/api/v1/config/hysteria.py | 15 +++++++++++++-- .../routers/api/v1/schema/response.py | 6 +++++- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/core/cli_api.py b/core/cli_api.py index da5c117..fbd4c46 100644 --- a/core/cli_api.py +++ b/core/cli_api.py @@ -12,7 +12,7 @@ DEBUG = False SCRIPT_DIR = '/etc/hysteria/core/scripts' CONFIG_FILE = '/etc/hysteria/config.json' CONFIG_ENV_FILE = '/etc/hysteria/.configs.env' - +WEBPANEL_ENV_FILE = '/etc/hysteria/core/scripts/webpanel/.env' class Command(Enum): '''Contains path to command's script''' @@ -531,6 +531,23 @@ def stop_webpanel_decoy(): '''Stops and removes the decoy site configuration for the web panel.''' run_cmd(['bash', Command.SHELL_WEBPANEL.value, 'stopdecoy']) +def get_webpanel_decoy_status() -> Dict[str, Any]: + """Checks the status of the webpanel decoy site configuration.""" + try: + if not os.path.exists(WEBPANEL_ENV_FILE): + return {"active": False, "path": None} + + env_vars = dotenv_values(WEBPANEL_ENV_FILE) + decoy_path = env_vars.get('DECOY_PATH') + + if decoy_path and decoy_path.strip(): + return {"active": True, "path": decoy_path.strip()} + else: + return {"active": False, "path": None} + except Exception as e: + print(f"Error checking decoy status: {e}") + return {"active": False, "path": None} + def get_webpanel_url() -> str | None: '''Gets the URL of WebPanel.''' return run_cmd(['bash', Command.SHELL_WEBPANEL.value, 'url']) diff --git a/core/scripts/webpanel/routers/api/v1/config/hysteria.py b/core/scripts/webpanel/routers/api/v1/config/hysteria.py index 08f06cd..20535ea 100644 --- a/core/scripts/webpanel/routers/api/v1/config/hysteria.py +++ b/core/scripts/webpanel/routers/api/v1/config/hysteria.py @@ -1,6 +1,6 @@ from fastapi import APIRouter, BackgroundTasks, HTTPException, UploadFile, File from ..schema.config.hysteria import ConfigFile, GetPortResponse, GetSniResponse -from ..schema.response import DetailResponse, IPLimitConfig, SetupDecoyRequest +from ..schema.response import DetailResponse, IPLimitConfig, SetupDecoyRequest, DecoyStatusResponse from fastapi.responses import FileResponse import shutil import zipfile @@ -373,4 +373,15 @@ async def stop_decoy_api(background_tasks: BackgroundTasks): """ background_tasks.add_task(run_stop_decoy_background) - return DetailResponse(detail='Web Panel decoy site stop initiated. Caddy will restart in the background.') \ No newline at end of file + return DetailResponse(detail='Web Panel decoy site stop initiated. Caddy will restart in the background.') + +@router.get('/webpanel/decoy/status', response_model=DecoyStatusResponse, summary='Get WebPanel Decoy Site Status') +async def get_decoy_status_api(): + """ + Checks if the decoy site is currently configured and active. + """ + try: + status = cli_api.get_webpanel_decoy_status() + return DecoyStatusResponse(**status) + except Exception as e: + raise HTTPException(status_code=500, detail=f'Error retrieving decoy status: {str(e)}') \ No newline at end of file diff --git a/core/scripts/webpanel/routers/api/v1/schema/response.py b/core/scripts/webpanel/routers/api/v1/schema/response.py index 670ad29..22ebbd2 100644 --- a/core/scripts/webpanel/routers/api/v1/schema/response.py +++ b/core/scripts/webpanel/routers/api/v1/schema/response.py @@ -11,4 +11,8 @@ class IPLimitConfig(BaseModel): class SetupDecoyRequest(BaseModel): domain: str = Field(..., description="Domain name associated with the web panel") - decoy_path: str = Field(..., description="Absolute path to the directory containing the decoy website files") \ No newline at end of file + decoy_path: str = Field(..., description="Absolute path to the directory containing the decoy website files") + +class DecoyStatusResponse(BaseModel): + active: bool = Field(..., description="Whether the decoy site is currently configured and active") + path: Optional[str] = Field(None, description="The configured path for the decoy site, if active")