from core.services.helpers.setup_sudo_scripts import auto_install_sudo_script, test_if_in_sudo_folder, is_singbox_wrapper_ready from core.services.helpers.install_dependencies import setup_singbox_binary from core.services.helpers.manage_assets import sudo_assets_folder_setup from core.observers.ApplicationVersionObserver import ApplicationVersionObserver from core.observers.ConnectionObserver import ConnectionObserver from core.models.Result import Result, ResultError import sys connection_error = "Connection problems downloading singbox or related data. Please disable Tor or try again with a better connection." def update_status(message: str): print(message) def manual_setup(): results = sudo_assets_folder_setup() print("Okay it copied the scripts to your Downloads folder in a folder named 'hydraveil_sudo_scripts'. Please review the scripts. Then when you're ready, run 'sudo bash setup.sh'") ran_it = input("Hit enter after you ran it to confirm it worked.") confirmed = test_if_in_sudo_folder() if confirmed.valid: print("Confirmed it worked.") else: print(f"I'm sorry it did not work, {confirmed.message}") def automated_setup(): results = auto_install_sudo_script() if results.valid: print("The setup script ran successfully. Testing..") confirmed = test_if_in_sudo_folder() if confirmed.valid: print("Confirmed it worked.") else: print(f"I'm sorry it did not work, {confirmed.message}") else: print(f"Setup script did NOT work because {results.message}") choice = input(""" The setup of the firewall & managed-DNS is just moving two bash scripts to a sudo protected folder. What would you like to do? a) Run the script manually yourself, with "sudo bash setup.sh" b) Get an automated installer. c) Install Singbox """) if choice == "a": manual_setup() elif choice == "b": automated_setup() elif choice == "c": print("First checking if you have the sudo wrapper script") if not is_singbox_wrapper_ready(): second_choice = input("""You do NOT have the sudo wrapper script setup. What would you like to do? a) Run the script manually yourself, with "sudo bash setup.sh" b) Get an automated installer. """) if second_choice == "a": manual_setup() elif second_choice == "b": automated_setup() else: print(f"Invalid choice! You can't pick {second_choice}.") sys.exit() if not is_singbox_wrapper_ready(): print("I'm sorry, but you must setup the sudo wrapper script to use Singbox") sys.exit() print("Sudo wrapper scripts are setup.") print("Now we are now setting up the singbox binary, also in a sudo folder.") # OBSERVERS application_version_observer = ApplicationVersionObserver() connection_observer = ConnectionObserver() application_version_observer.subscribe('downloading', lambda event: update_status( f'{event.subject if event.subject else "Downloading.."}')) application_version_observer.subscribe('download_progressing', lambda event: update_status( f'{event.subject if event.subject else "Downloading.."}')) application_version_observer.subscribe('downloaded', lambda event: update_status( f'{event.subject if event.subject else "Downloaded"}')) connection_observer.subscribe('connecting', lambda event: update_status( f'[{event.subject.get("attempt_count")}/{event.subject.get("maximum_number_of_attempts")}] Performing connection attempt...')) connection_observer.subscribe('tor_bootstrapping', lambda event: update_status( 'Establishing Tor connection...')) connection_observer.subscribe( 'tor_bootstrap_progressing', lambda event: update_status(f'{event.subject if event.subject else "Tor Bootstrapping.."}')) connection_observer.subscribe( 'message', lambda event: update_status(f'{event.subject if event.subject else "Connecting.."}')) connection_observer.subscribe( 'tor_bootstrapped', lambda event: update_status('Tor connection established.')) # Actual Binary Setup: try: setup_result = setup_singbox_binary(application_version_observer, connection_observer) except ConnectionError as e: print(f"{connection_error}: {str(e)}") sys.exit() except ValueError as e: print(f"Your configuration files may be corrupted, or a server-side error giving bad data: {str(e)}") sys.exit() except Exception as e: print(f"Unknown error: {str(e)}") sys.exit() # Error handling: if not setup_result.valid: error_reason = setup_result.error_type if error_reason == ResultError.NEED_SYNC: print("You must sync to find out which Singbox version is supported.") elif error_reason == ResultError.FILE_SYSTEM: print("Please check the configuration file, space on your computer, permissions, and make sure your filesystem is not corrupted.") elif error_reason == ResultError.CONNECTION: print(connection_error) elif error_reason == ResultError.INVALID_INPUT: print("This is a rare bug. Please check the error logs, and run the program again from the terminal with DEBUG=true") elif error_reason == ResultError.PERMISSION: print("Singbox requires sudo to setup. Then the script wrapper allows it be run without sudo on a continued basis.") elif error_reason == ResultError.UNKNOWN: print(f"Unknown error: {setup_result.message}") sys.exit() else: print("Setup done! You're all set to proceed with Singbox.") else: print(f"Invalid choice! You can't pick {choice}. Please run the script again, and pick 'a' or 'b'") sys.exit()