Improved Singbox Setup Error handling for edge cases

This commit is contained in:
SimplifiedPrivacy 2026-08-12 15:57:51 -04:00
parent 01bd5f8d3f
commit 951802fe5c
3 changed files with 29 additions and 22 deletions

View file

@ -34,6 +34,7 @@ class ResultError(Enum):
@dataclass
class Result():
valid: bool
goal_result: Optional[bool] = None
error_type: ResultError = ResultError.SUCCESS
data: Optional[Any] = None
message: Optional[str] = None

View file

@ -6,8 +6,6 @@ from core.Constants import Constants
from core.errors.logger import logger
from core.utils.run_commands import run_generic_command
from core.observers.ApplicationVersionObserver import ApplicationVersionObserver
from core.Errors import FileIntegrityError
from core.services.networking.api_requests.subtools.extract_domain import extract_domain
from core.models.orm_models.Dependency import Dependency
from core.models.orm_calls.dependency_calls import get_dependency_version
from core.controllers.ConfigurationController import ConfigurationController
@ -17,13 +15,12 @@ import httpx
from io import BytesIO
from typing import Optional
import hashlib
import shutil
import tarfile
import os
SUDO_SINGBOX_LOCATION = f"{Constants.SUDO_TARGET_FOLDER}/sing-box"
def singbox_setup(application_version_observer: Optional[ApplicationVersionObserver]) -> Result:
def setup_singbox_binary(application_version_observer: Optional[ApplicationVersionObserver]) -> Result:
"""
Rank:
Module's Main Orchestrator
@ -58,13 +55,18 @@ def singbox_setup(application_version_observer: Optional[ApplicationVersionObser
logger.info("Sync is required. We could not access the information on the most current version locally.")
return update_result # (user MUST sync)
# this is blank if the checks worked, but nothing is required,
if already_in_sudo_folder and update_result.goal_result:
# no update required:
no_update = "No update for singbox is required."
logger.info(no_update)
return Result(valid=True, message=no_update)
required_update = update_result.data
# no update required:
if required_update is None and already_in_sudo_folder:
logger.info("No update for singbox is required.")
return update_result
if required_update is None or not isinstance(required_update, Dependency):
error_msg = "You need to Sync, because you lack the dependency data for singbox."
logger.error(error_msg)
return Result(valid=False, error_type=ResultError.NEED_SYNC, message=error_msg)
# UPDATE FROM HERE ON
logger.info("Updating Singbox..")
@ -168,13 +170,9 @@ def update_needed() -> Result:
Returns:
Always a Result Object.
** IMPORTANT**
If an update is NOT needed, but it can complete the check, it returns valid=True, but None for Data.
If an update IS needed, it returns data with the new version.
If it can't complete the checks, it returns False for valid.
No update needed = goal_result=True
Update needed = goal_result=False
Can't complete the checks, valid=False
"""
app_name = "singbox"
rejected_values = [None, False, ""]
@ -200,7 +198,7 @@ def update_needed() -> Result:
logger.info(f"While the version of {app_name} we installed in our configuration is {version_installed}")
if version_installed in rejected_values:
logger.info(f"We need to update to the new {new_version}")
return Result(valid=True, data=version_sql_query)
return Result(valid=True, goal_result=False, data=version_sql_query)
################################################
# EVALUATE
@ -218,6 +216,8 @@ def update_needed() -> Result:
logger.error(f"The version_installed is in the wrong format: {str(e)}. But we can still update to the new version..")
# wipe config:
changed_config = ConfigurationController.update_singbox_version(None) # can make this dynamic if more apps are added.
if not changed_config:
logger.error("Critical Issue with wiping the config version")
need_update = True # the version_sql_query data is still valid.
else:
error_msg = f"Corrupt data, corrupt filesystem, or outright developer bug. Please contact customer support with new_version: {new_version} and version_installed {version_installed} tried to see if it should update but {str(e)}"
@ -225,9 +225,9 @@ def update_needed() -> Result:
return Result(valid=False, error_type=ResultError.INVALID_INPUT, message=error_msg)
if need_update:
return Result(valid=True, data=version_sql_query, message="update")
return Result(valid=True, goal_result=True, data=version_sql_query, message="update")
else:
return Result(valid=True, data=None, message="Not needed.") # BLANK DATA, BUT TRUE
return Result(valid=True, goal_result=False, data=version_sql_query, message="Not needed.")
def already_downloaded(which_version: str) -> bool:
@ -292,8 +292,9 @@ def download_and_verify(
else:
error_msg = f"Could not download {target_app_name} because of a Connection Error."
logger.error(error_msg)
return Return(valid=False, error_type=ResultError.CONNECTION, message=error_msg)
return Result(valid=False, error_type=ResultError.CONNECTION, message=error_msg)
if application_version_observer is not None:
application_version_observer.notify('downloaded', f"Downloaded {target_app_name}")
response_buffer.seek(0)
@ -305,7 +306,7 @@ def download_and_verify(
if real_file_hash != target_file_hash:
error_msg = f'Application version file integrity could not be verified. We are targeting {target_file_hash}, but got {real_file_hash}'
logger.error(error_msg)
return Return(valid=False, error_type=ResultError.INVALID_INPUT, message=error_msg)
return Result(valid=False, error_type=ResultError.INVALID_INPUT, message=error_msg)
################################################
# SAVE IT IN CORRECT STRUCTURE

View file

@ -1,5 +1,6 @@
from core.services.helpers.manage_assets import sudo_assets_folder_setup
from core.utils.basic_operations.confirm_files_exist import confirm_files_and_folders_exist
from core.utils.basic_operations.does_file_exist import does_file_exist
from core.models.Result import Result, ResultError
from core.Constants import Constants
from core.errors.logger import logger
@ -68,3 +69,7 @@ def test_if_in_sudo_folder() -> Result:
logger.error(error_msg)
return Result(valid=False, message=error_msg)
def is_singbox_wrapper_ready() -> bool:
wrapper_location = f"{Constants.SUDO_TARGET_FOLDER}/singbox_wrapper"
return does_file_exist(wrapper_location)