From 00e56ba155195ded6662a8629921ce127c40e277 Mon Sep 17 00:00:00 2001 From: fusion44 Date: Sun, 18 Feb 2024 12:10:35 +0100 Subject: [PATCH] feat(#237): implement app_status_advanced endpoint (#238) Some apps might give status information that is computationally to expensive to include in the normal status endpoint which can be polled more often. closes #237 --- app/apps/impl/apps_base.py | 4 ++ app/apps/impl/native_python.py | 3 ++ app/apps/impl/raspiblitz.py | 70 ++++++++++++++++++++++++++++++++++ app/apps/router.py | 19 ++++++++- app/apps/service.py | 4 ++ 5 files changed, 99 insertions(+), 1 deletion(-) diff --git a/app/apps/impl/apps_base.py b/app/apps/impl/apps_base.py index c6ec4bf..91a280f 100644 --- a/app/apps/impl/apps_base.py +++ b/app/apps/impl/apps_base.py @@ -10,6 +10,10 @@ class AppsBase: async def get_app_status(self): raise NotImplementedError() + @abstractmethod + async def get_app_status_advanced(self, app_id: str): + raise NotImplementedError() + @abstractmethod async def get_app_status_sub(self): raise NotImplementedError() diff --git a/app/apps/impl/native_python.py b/app/apps/impl/native_python.py index fe50afe..ea099f8 100644 --- a/app/apps/impl/native_python.py +++ b/app/apps/impl/native_python.py @@ -18,6 +18,9 @@ class NativePythonApps(AppsBase): async def get_app_status(self): raise _NotImplemented() + async def get_app_status_advanced(self, app_id: str): + raise _NotImplemented() + async def get_app_status_sub(self): raise _NotImplemented() diff --git a/app/apps/impl/raspiblitz.py b/app/apps/impl/raspiblitz.py index 31044a7..12144eb 100644 --- a/app/apps/impl/raspiblitz.py +++ b/app/apps/impl/raspiblitz.py @@ -25,6 +25,7 @@ available_app_ids = { "mempool", "thunderhub", "jam", + "electrs", } @@ -97,6 +98,7 @@ class RaspiBlitzApps(AppsBase): "isIndexed": data["isIndexed"], "indexInfo": data["indexInfo"], } + return { "id": app_id, "version": version, @@ -125,6 +127,18 @@ class RaspiBlitzApps(AppsBase): "error": f"script result processing error: {script_call}", } + async def get_app_status_advanced(self, app_id): + if app_id not in available_app_ids: + raise HTTPException( + status.HTTP_400_BAD_REQUEST, + detail=f"App id invalid. Available app ids: {available_app_ids}", + ) + + if app_id == "electrs": + return await _do_electrs_status_advanced() + + return {} + async def get_app_status(self): appStatusList: List = [] for appID in available_app_ids: @@ -346,3 +360,59 @@ class RaspiBlitzApps(AppsBase): logging.debug(f"updatedAppData: {updatedAppData}") logging.debug(f"params: {params}") return + + +async def _do_electrs_status_advanced(): + app_id = "electrs" + script_call = ( + os.path.join(SHELL_SCRIPT_PATH, "config.scripts", f"bonus.{app_id}.sh") + + " status showAddress" + ) + + try: + result = await call_sudo_script(script_call) + except: + # script had error or was not able to deliver all requested data fields + logging.warning(f"error on calling: {script_call}") + return { + "id": f"{app_id}", + "error": f"script not working for api: {script_call}", + } + + try: + data = parse_key_value_text(result) + except: + logging.warning(f"error on parsing: {result}") + return { + "id": f"{app_id}", + "error": f"script result parsing error: {script_call}", + } + + if data["serviceInstalled"] == "0": + return { + "id": app_id, + "error": "Service not installed.", + } + + if data["serviceRunning"] == "0": + return { + "id": app_id, + "error": "Service installed, but not running.", + } + + if "initialSynced" not in data: + logging.warning(f"error on calling: {script_call}") + return { + "id": app_id, + "error": f"script not working for api: {script_call}", + } + + return { + "version": data["version"], + "localIP": data["localIP"], + "publicIP": data["publicIP"], + "portTCP": data["portTCP"], + "portSSL": data["portSSL"], + "TORaddress": data["TORaddress"], + "initialSyncDone": data["initialSynced"] == "1", + } diff --git a/app/apps/router.py b/app/apps/router.py index 47607e5..e34bae1 100644 --- a/app/apps/router.py +++ b/app/apps/router.py @@ -1,4 +1,4 @@ -from fastapi import APIRouter, HTTPException +from fastapi import APIRouter, HTTPException, Path from fastapi.params import Depends from loguru import logger from pydantic import BaseModel @@ -36,6 +36,23 @@ async def get_single_status(id): return await repo.get_app_status_single(id) +@router.get( + "/status_advanced/{id}", + name=f"{_PREFIX}/status_advanced", + summary="Get the advanced status of a single app by id.", + description="""Some apps might give status information that is computationally + to expensive to include in the normal status endpoint. + +> ℹ️ _This endpoint is not implemented on all platforms_ + """, + dependencies=[Depends(JWTBearer())], + responses={400: {"description": ("If no or invalid app id is given.")}}, +) +@logger.catch(exclude=(HTTPException,)) +async def get_single_status_advanced(id: str = Path(..., required=True)): + return await repo.get_app_status_advanced(id) + + @router.get( "/status-sub", name=f"{_PREFIX}/status-sub", diff --git a/app/apps/service.py b/app/apps/service.py index 52e4787..12faba5 100644 --- a/app/apps/service.py +++ b/app/apps/service.py @@ -24,6 +24,10 @@ async def get_app_status(): return await apps.get_app_status() +async def get_app_status_advanced(app_id: str): + return await apps.get_app_status_advanced(app_id) + + async def get_app_status_sub(): return await apps.get_app_status_sub()