Linter bug fixes. Mostly undeclared, unused, or missing imports. One or two outright typos. There's still issues with undeclared types that need to be fixed after api connection refactor is fully implemented.
This commit is contained in:
parent
a5f57f4f5e
commit
8da4978498
34 changed files with 228 additions and 150 deletions
|
|
@ -59,86 +59,86 @@ class ClientController:
|
||||||
|
|
||||||
return not ClientVersionController.is_latest(version)
|
return not ClientVersionController.is_latest(version)
|
||||||
|
|
||||||
@staticmethod
|
# @staticmethod
|
||||||
def legacy_sync(client_observer: ClientObserver = None, connection_observer: ConnectionObserver = None):
|
# def legacy_sync(client_observer: ClientObserver = None, connection_observer: ConnectionObserver = None):
|
||||||
if client_observer is not None:
|
# if client_observer is not None:
|
||||||
client_observer.notify('synchronizing', "Fetching list of new data ..")
|
# client_observer.notify('synchronizing', "Fetching list of new data ..")
|
||||||
|
|
||||||
result = coordinate_cache_sync(client_observer, connection_observer)
|
# result = coordinate_cache_sync(client_observer, connection_observer)
|
||||||
|
|
||||||
# Outright Error:
|
# # Outright Error:
|
||||||
if not result["success"]:
|
# if not result["success"]:
|
||||||
error_msg = result["error"]
|
# error_msg = result["error"]
|
||||||
if client_observer is not None:
|
# if client_observer is not None:
|
||||||
client_observer.notify('synchronizing', f'Error! {error_msg}')
|
# client_observer.notify('synchronizing', f'Error! {error_msg}')
|
||||||
return
|
# return
|
||||||
|
|
||||||
# Same:
|
# # Same:
|
||||||
changed_tables = result["changed_tables"]
|
# changed_tables = result["changed_tables"]
|
||||||
if not changed_tables:
|
# if not changed_tables:
|
||||||
if client_observer is not None:
|
# if client_observer is not None:
|
||||||
client_observer.notify('synchronized')
|
# client_observer.notify('synchronized')
|
||||||
return
|
# return
|
||||||
|
|
||||||
# We only make it past this point if there's New Data
|
# # We only make it past this point if there's New Data
|
||||||
|
|
||||||
# flag for after the save,
|
# # flag for after the save,
|
||||||
data_was_saved = False
|
# data_was_saved = False
|
||||||
|
|
||||||
# Fetch and update the real data (no longer metadata)...
|
# # Fetch and update the real data (no longer metadata)...
|
||||||
|
|
||||||
# =================== ORM BASED MODELS ==================
|
# # =================== ORM BASED MODELS ==================
|
||||||
"""
|
# """
|
||||||
Note: for the new ORM based models,
|
# Note: for the new ORM based models,
|
||||||
it does the Tor/system check in the API call itself.
|
# it does the Tor/system check in the API call itself.
|
||||||
"""
|
# """
|
||||||
|
|
||||||
if "locations" in changed_tables:
|
# if "locations" in changed_tables:
|
||||||
logger.info("Sync of Locations")
|
# logger.info("Sync of Locations")
|
||||||
if client_observer is not None:
|
# if client_observer is not None:
|
||||||
client_observer.notify('synchronizing', 'Fetching Locations List..')
|
# client_observer.notify('synchronizing', 'Fetching Locations List..')
|
||||||
|
|
||||||
final_result = sync_one_orm_model(Location, "locations")
|
# final_result = sync_one_orm_model(Location, "locations")
|
||||||
evaluate_errors(final_result)
|
# evaluate_errors(final_result)
|
||||||
|
|
||||||
|
|
||||||
if "operators" in changed_tables:
|
# if "operators" in changed_tables:
|
||||||
logger.info("Sync of Operators")
|
# logger.info("Sync of Operators")
|
||||||
if client_observer is not None:
|
# if client_observer is not None:
|
||||||
client_observer.notify('synchronizing', 'Fetching Operators List..')
|
# client_observer.notify('synchronizing', 'Fetching Operators List..')
|
||||||
|
|
||||||
final_result_two = sync_one_orm_model(Operator, "operators")
|
# final_result_two = sync_one_orm_model(Operator, "operators")
|
||||||
evaluate_errors(final_result_two)
|
# evaluate_errors(final_result_two)
|
||||||
|
|
||||||
# =================== MANUAL-SQL BASED MODELS ==================
|
# # =================== MANUAL-SQL BASED MODELS ==================
|
||||||
try:
|
# try:
|
||||||
from core.controllers.ConnectionController import ConnectionController
|
# from core.controllers.ConnectionController import ConnectionController
|
||||||
ConnectionController.with_preferred_connection(task=ClientController.__sync, changed_tables=changed_tables, client_observer=client_observer, connection_observer=connection_observer)
|
# ConnectionController.with_preferred_connection(task=ClientController.__sync, changed_tables=changed_tables, client_observer=client_observer, connection_observer=connection_observer)
|
||||||
|
|
||||||
# We set the flag to true,
|
# # We set the flag to true,
|
||||||
# the reason we use a flag, and don't just save it right here,
|
# # the reason we use a flag, and don't just save it right here,
|
||||||
# is because we want to isolate the success (or failure) of the real data,
|
# # is because we want to isolate the success (or failure) of the real data,
|
||||||
# from the potential failure of the ORM session metadata.
|
# # from the potential failure of the ORM session metadata.
|
||||||
data_was_saved = True
|
# data_was_saved = True
|
||||||
|
|
||||||
except:
|
# except:
|
||||||
# sync failed here,
|
# # sync failed here,
|
||||||
if client_observer is not None:
|
# if client_observer is not None:
|
||||||
client_observer.notify('synchronizing', 'Fetch Failed, but you can use old data.')
|
# client_observer.notify('synchronizing', 'Fetch Failed, but you can use old data.')
|
||||||
finally:
|
# finally:
|
||||||
if data_was_saved:
|
# if data_was_saved:
|
||||||
filtered_metadata = result["filtered_metadata"] # from the top of the function
|
# filtered_metadata = result["filtered_metadata"] # from the top of the function
|
||||||
save_successful = save_metadata(filtered_metadata) # the "save_data" function is inside sync_service
|
# save_successful = save_metadata(filtered_metadata) # the "save_data" function is inside sync_service
|
||||||
|
|
||||||
if client_observer is None:
|
# if client_observer is None:
|
||||||
logger.error("Error: No client_observer to update the UI, the final part of the sync function skipped")
|
# logger.error("Error: No client_observer to update the UI, the final part of the sync function skipped")
|
||||||
return # can't update their UI
|
# return # can't update their UI
|
||||||
|
|
||||||
if save_successful:
|
# if save_successful:
|
||||||
logger.info("Metadata Saved Successfully")
|
# logger.info("Metadata Saved Successfully")
|
||||||
client_observer.notify('synchronized', "Fetch & Save Complete!")
|
# client_observer.notify('synchronized', "Fetch & Save Complete!")
|
||||||
else:
|
# else:
|
||||||
client_observer.notify('synchronizing', "Saving List of Metadata Failed.")
|
# client_observer.notify('synchronizing', "Saving List of Metadata Failed.")
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
||||||
|
|
@ -136,12 +136,10 @@ class ConnectionController:
|
||||||
try:
|
try:
|
||||||
tor_module = TorModule(Constants.HV_TOR_STATE_HOME)
|
tor_module = TorModule(Constants.HV_TOR_STATE_HOME)
|
||||||
tor_module.create_session(port_number, connection_observer)
|
tor_module.create_session(port_number, connection_observer)
|
||||||
except TorServiceInitializationError as e:
|
|
||||||
logger.error(f"TorServiceInitializationError. Tor Can't Start: {e}")
|
|
||||||
if connection_observer is not None:
|
|
||||||
connection_observer.notify('custom_message', "Tor Can't Initialize")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Tor Can't Start: {e}")
|
logger.error(f"Tor Can't Start: {e}")
|
||||||
|
if connection_observer is not None:
|
||||||
|
connection_observer.notify('custom_message', "Tor Can't Initialize")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def terminate_tor_session_connection(port_number: int):
|
def terminate_tor_session_connection(port_number: int):
|
||||||
|
|
|
||||||
|
|
@ -165,12 +165,19 @@ def new_sync(client_observer: ClientObserver, connection_observer: ConnectionObs
|
||||||
|
|
||||||
if total_skipped == 0:
|
if total_skipped == 0:
|
||||||
client_observer.notify('synchronized', "Fetch & Save Complete!")
|
client_observer.notify('synchronized', "Fetch & Save Complete!")
|
||||||
save_successful = save_metadata(filtered_metadata) # the "save_data" function is inside sync_service
|
save_successful = save_metadata(filtered_metadata)
|
||||||
|
if save_successful:
|
||||||
return Result(valid=True, message="Finshed sync.")
|
return Result(valid=True, message="Finshed sync.")
|
||||||
|
else:
|
||||||
|
error_msg = "Finshed sync, but had issues with the saving of metadata for next time."
|
||||||
|
logger.error(error_msg)
|
||||||
|
return Result(valid=True, message=error_msg)
|
||||||
|
|
||||||
elif total_skipped < quantity_of_entries:
|
elif total_skipped < quantity_of_entries:
|
||||||
error_msg = f"Partial Success. {total_skipped} skipped."
|
error_msg = f"Partial Success. {total_skipped} skipped."
|
||||||
client_observer.notify('synchronized', error_msg)
|
client_observer.notify('synchronized', error_msg)
|
||||||
return Result(valid=True, data=skipped, message=error_msg)
|
return Result(valid=True, data=skipped, message=error_msg)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
error_msg = f"Sync Failed. All {total_skipped} entries were skipped!"
|
error_msg = f"Sync Failed. All {total_skipped} entries were skipped!"
|
||||||
client_observer.notify('synchronized', error_msg)
|
client_observer.notify('synchronized', error_msg)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@ from core.observers.BaseObserver import BaseObserver
|
||||||
from core.services.payment_phase.save_and_send_intitial_billing import save_and_send_intitial_billing
|
from core.services.payment_phase.save_and_send_intitial_billing import save_and_send_intitial_billing
|
||||||
from core.services.networking.api_requests.ApiResponseModel import ApiResponse, ErrorType
|
from core.services.networking.api_requests.ApiResponseModel import ApiResponse, ErrorType
|
||||||
from core.services.networking.api_requests.step5_solve_api_problems import solve_api_problems
|
from core.services.networking.api_requests.step5_solve_api_problems import solve_api_problems
|
||||||
|
from core.errors.logger import logger
|
||||||
|
from core.errors.exceptions import ServerSideError, NetworkingError
|
||||||
|
|
||||||
from core.services.prepare_tickets.ticket_tracker import does_ticket_tracker_exist
|
from core.services.prepare_tickets.ticket_tracker import does_ticket_tracker_exist
|
||||||
|
|
||||||
|
|
@ -132,7 +133,7 @@ def initiate_payment(
|
||||||
|
|
||||||
return invoice_data_object
|
return invoice_data_object
|
||||||
|
|
||||||
except InvalidData as e:
|
except ValueError as e:
|
||||||
error_msg = "Invalid Data."
|
error_msg = "Invalid Data."
|
||||||
ticket_observer.notify("failed_input", subject=error_msg)
|
ticket_observer.notify("failed_input", subject=error_msg)
|
||||||
invoice_data_object.add_error_code("invalid_data")
|
invoice_data_object.add_error_code("invalid_data")
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ from core.services.helpers.get_value_from_config import get_value_from_config
|
||||||
from core.utils.basic_operations.does_file_exist import does_file_exist
|
from core.utils.basic_operations.does_file_exist import does_file_exist
|
||||||
from core.utils.basic_operations.write_or_read_from_json import update_json
|
from core.utils.basic_operations.write_or_read_from_json import update_json
|
||||||
from core.services.prepare_tickets.ticket_tracker import get_all_unused_tickets
|
from core.services.prepare_tickets.ticket_tracker import get_all_unused_tickets
|
||||||
|
from core.errors.logger import logger
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -162,8 +163,10 @@ def use_ticket(
|
||||||
error_msg = f"Ticket is already tied to {location} with the subscription {subscription}"
|
error_msg = f"Ticket is already tied to {location} with the subscription {subscription}"
|
||||||
ticket_observer.notify("failed_input", subject=error_msg)
|
ticket_observer.notify("failed_input", subject=error_msg)
|
||||||
return {"valid": False, "message": error_msg}
|
return {"valid": False, "message": error_msg}
|
||||||
except:
|
except ValueError as e:
|
||||||
error_msg = f"Your local ticket tracker has no value for ticket {which_ticket}"
|
error_msg = f"Your local ticket tracker has no value for ticket {which_ticket}"
|
||||||
|
logger.error(error_msg)
|
||||||
|
logger.error(str(e))
|
||||||
return {"valid": False, "message": error_msg}
|
return {"valid": False, "message": error_msg}
|
||||||
|
|
||||||
# the actual work here, everything else is just handling:
|
# the actual work here, everything else is just handling:
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ class Result():
|
||||||
def user_message(self) -> str:
|
def user_message(self) -> str:
|
||||||
"""Human-readable error for the UI."""
|
"""Human-readable error for the UI."""
|
||||||
messages = {
|
messages = {
|
||||||
DBErrorType.SUCCESS: "Operation completed successfully.",
|
ResultError.SUCCESS: "Operation completed successfully.",
|
||||||
DBErrorType.UNKNOWN: f"Error: {self.message}",
|
ResultError.UNKNOWN: f"Error: {self.message}",
|
||||||
}
|
}
|
||||||
return messages.get(self.error_type, "Unknown error")
|
return messages.get(self.error_type, "Unknown error")
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from core.Constants import Constants
|
from core.Constants import Constants
|
||||||
from core.models.ClientVersion import ClientVersion
|
from core.models.ClientVersion import ClientVersion
|
||||||
# from core.models.Location import Location
|
from core.models.orm_models.Location import Location
|
||||||
# from core.models.Operator import Operator
|
from core.models.orm_models.Operator import Operator
|
||||||
from core.models.Subscription import Subscription
|
from core.models.Subscription import Subscription
|
||||||
from core.models.SubscriptionPlan import SubscriptionPlan
|
from core.models.SubscriptionPlan import SubscriptionPlan
|
||||||
from core.models.invoice.Invoice import Invoice
|
from core.models.invoice.Invoice import Invoice
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ from core.services.failed_verification.test_if_new_key_works import test_if_new_
|
||||||
from core.services.networking.make_url import make_url
|
from core.services.networking.make_url import make_url
|
||||||
from core.services.networking.api_requests.step1_get_or_post import get_data_from_api
|
from core.services.networking.api_requests.step1_get_or_post import get_data_from_api
|
||||||
|
|
||||||
|
from core.services.networking.httpx import connect
|
||||||
|
from core.services.networking.api_requests.ApiResponseModel import ApiResponse, ErrorType
|
||||||
|
|
||||||
# utils
|
# utils
|
||||||
from core.utils.basic_operations.write_or_read_from_json import get_value_from_json_file
|
from core.utils.basic_operations.write_or_read_from_json import get_value_from_json_file
|
||||||
|
|
@ -72,12 +74,21 @@ def get_new_pubkey_from_api(connection_observer: ConnectionObserver) -> dict | N
|
||||||
url = make_url(which_key_plan)
|
url = make_url(which_key_plan)
|
||||||
|
|
||||||
# the result of this is a python dictionary with single '
|
# the result of this is a python dictionary with single '
|
||||||
api_results = get_data_from_server(url, None, connection_observer)
|
# api_results = get_data_from_server(url, None, connection_observer)
|
||||||
|
api_results = connect.single_endpoint(
|
||||||
if "data" in api_results:
|
method="get",
|
||||||
new_public_key = api_results["data"]
|
url=url,
|
||||||
|
observer=connection_observer,
|
||||||
|
payload=None
|
||||||
|
)
|
||||||
|
|
||||||
|
if api_results.valid:
|
||||||
|
new_public_key = api_results.data
|
||||||
return new_public_key
|
return new_public_key
|
||||||
|
else:
|
||||||
|
logger.error(f"API Results returned were invalid for that key.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def are_keys_different(old_public_key, new_public_key) -> bool:
|
def are_keys_different(old_public_key, new_public_key) -> bool:
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ from core.errors.logger import logger
|
||||||
|
|
||||||
# generic
|
# generic
|
||||||
import json, os
|
import json, os
|
||||||
from typing import Any
|
from typing import Any, Optional
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,7 @@ def quad9_proxy_dns_lookup(
|
||||||
domain: str,
|
domain: str,
|
||||||
custom_proxy: str,
|
custom_proxy: str,
|
||||||
timeout: int = 10,
|
timeout: int = 10,
|
||||||
|
client_observer: ClientObserver = None
|
||||||
) -> str:
|
) -> str:
|
||||||
|
|
||||||
logger.debug("Doing a Proxy Quad9 DNS lookup")
|
logger.debug("Doing a Proxy Quad9 DNS lookup")
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,11 @@ from core.services.subscriptions.subscriptions import activate_subscription
|
||||||
|
|
||||||
from core.errors.logger import logger
|
from core.errors.logger import logger
|
||||||
from core.errors.exceptions import *
|
from core.errors.exceptions import *
|
||||||
|
from core.errors.exceptions import FirewallError
|
||||||
from typing import Union, Optional, Callable
|
from typing import Union, Optional, Callable
|
||||||
from core.models.session.SessionProfile import SessionProfile
|
from core.models.session.SessionProfile import SessionProfile
|
||||||
from core.models.system.SystemProfile import SystemProfile
|
from core.models.system.SystemProfile import SystemProfile
|
||||||
from core.Errors import ConnectionTerminationError, InvalidSubscriptionError
|
from core.Errors import ConnectionTerminationError, InvalidSubscriptionError, MissingSubscriptionError
|
||||||
from core.services.WebServiceApiService import WebServiceApiService
|
from core.services.WebServiceApiService import WebServiceApiService
|
||||||
from core.controllers.ConnectionController import ConnectionController
|
from core.controllers.ConnectionController import ConnectionController
|
||||||
from core.models.BaseProfile import ProfileType
|
from core.models.BaseProfile import ProfileType
|
||||||
|
|
|
||||||
|
|
@ -182,4 +182,4 @@ async def switch_get_and_post(method: str, url: str, client: httpx.Client, paylo
|
||||||
else:
|
else:
|
||||||
# nevermind,
|
# nevermind,
|
||||||
logger.info("Our strategy of switching GET/POST did NOT work.")
|
logger.info("Our strategy of switching GET/POST did NOT work.")
|
||||||
return initial_result
|
return second_result
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,6 @@ def single_endpoint(method: str, url: str, observer: ConnectionObserver, payload
|
||||||
Try a request to a single endpoint using either an existing client, or creating a new one, then error handling.
|
Try a request to a single endpoint using either an existing client, or creating a new one, then error handling.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
global _port_used
|
|
||||||
|
|
||||||
connection_type = ConfigurationController.get_connection_enum()
|
connection_type = ConfigurationController.get_connection_enum()
|
||||||
|
|
||||||
client = httpx_client.get_http_session()
|
client = httpx_client.get_http_session()
|
||||||
|
|
@ -62,9 +60,6 @@ def single_endpoint(method: str, url: str, observer: ConnectionObserver, payload
|
||||||
########################################################
|
########################################################
|
||||||
# FROM THIS POINT ON, WE HAVE A CLIENT
|
# FROM THIS POINT ON, WE HAVE A CLIENT
|
||||||
########################################################
|
########################################################
|
||||||
# #### SPOOF
|
|
||||||
# _port_used = 9050
|
|
||||||
# initial_result = ApiResponse(valid=False, error_type=ErrorType.DNS_TEMPORARY)
|
|
||||||
|
|
||||||
initial_result = make_request(
|
initial_result = make_request(
|
||||||
method=method,
|
method=method,
|
||||||
|
|
@ -367,3 +362,7 @@ def custom_dns_resolver_for_SINGLE_ENDPOINT(method: str, url: str, observer: Con
|
||||||
# """Merge two dictionaries. dict1 values take precedence on key collision."""
|
# """Merge two dictionaries. dict1 values take precedence on key collision."""
|
||||||
# return {**dict2, **dict1}
|
# return {**dict2, **dict1}
|
||||||
|
|
||||||
|
def replace_http_with_https(url):
|
||||||
|
if url.startswith("http://"):
|
||||||
|
return url.replace("http://", "https://", 1)
|
||||||
|
return url
|
||||||
|
|
|
||||||
|
|
@ -176,4 +176,4 @@ def switch_get_and_post(method: str, url: str, client: httpx.Client, payload: di
|
||||||
else:
|
else:
|
||||||
# nevermind,
|
# nevermind,
|
||||||
logger.info("Our strategy of switching GET/POST did NOT work.")
|
logger.info("Our strategy of switching GET/POST did NOT work.")
|
||||||
return initial_result
|
return second_result
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ from core.services.networking.regular_get_request import regular_get_request
|
||||||
from core.errors.exceptions import *
|
from core.errors.exceptions import *
|
||||||
from core.errors.logger import logger
|
from core.errors.logger import logger
|
||||||
import traceback
|
import traceback
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
# Generic GET request to an endpoint, filtered by the user's preference of connection type (Tor or Not)
|
# Generic GET request to an endpoint, filtered by the user's preference of connection type (Tor or Not)
|
||||||
|
|
|
||||||
|
|
@ -84,13 +84,13 @@ def orchestrate_dns_check(target_interface: str) -> Result:
|
||||||
else:
|
else:
|
||||||
logger.info(f"[DNS Orchestrator] Some of the DNS checks did NOT work. But this might be because the tunnel is down.")
|
logger.info(f"[DNS Orchestrator] Some of the DNS checks did NOT work. But this might be because the tunnel is down.")
|
||||||
|
|
||||||
targets_not_found = 0
|
target_not_found = 0
|
||||||
|
|
||||||
for each_object in list_of_results_as_objects:
|
for each_object in list_of_results_as_objects:
|
||||||
if each_object.error_type == SearchError.TARGET_MISSING:
|
if each_object.error_type == SearchError.TARGET_MISSING:
|
||||||
target_not_found = target_not_found + 1
|
target_not_found = target_not_found + 1
|
||||||
|
|
||||||
return Result(valid=False, data=targets_not_found)
|
return Result(valid=False, data=target_not_found)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from core.services.networking.systemwide.systemwide_errors import systemwide_hell_raiser
|
from core.services.networking.systemwide.systemwide_errors import systemwide_hell_raiser
|
||||||
from core.utils.basic_operations.wrap_with import wrap_with
|
from core.utils.basic_operations.wrap_with import wrap_with
|
||||||
from core.utils.run_commands import run_generic_command import run_generic_command
|
from core.utils.run_commands import run_generic_command
|
||||||
from core.models.Result import Result, ResultError
|
from core.models.Result import Result, ResultError
|
||||||
from core.errors.logger import logger
|
from core.errors.logger import logger
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ from core.services.networking.systemwide.systemwide_utils import get_firewall_se
|
||||||
from core.services.networking.systemwide import dns
|
from core.services.networking.systemwide import dns
|
||||||
from core.services.networking.systemwide.general_connection_tools.general_firewall_dns_tools import generic_enable_firewall_w_retry
|
from core.services.networking.systemwide.general_connection_tools.general_firewall_dns_tools import generic_enable_firewall_w_retry
|
||||||
from core.errors.exceptions import FirewallError, DNSError
|
from core.errors.exceptions import FirewallError, DNSError
|
||||||
|
from essentials.observers.ConnectionObserver import ConnectionObserver
|
||||||
|
|
||||||
|
|
||||||
# generic
|
# generic
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
@ -106,7 +108,7 @@ def start_singbox(
|
||||||
if not activation_result.valid:
|
if not activation_result.valid:
|
||||||
error_msg = f"Singbox failed to start after {QUANTITY_OF_ATTEMPTS} attempts"
|
error_msg = f"Singbox failed to start after {QUANTITY_OF_ATTEMPTS} attempts"
|
||||||
logger.error(f"[{function_name}] {error_msg}")
|
logger.error(f"[{function_name}] {error_msg}")
|
||||||
return Result(valid=False, error_type=ResultError=PROCESS_WONT_START, message=error_msg)
|
return Result(valid=False, error_type=ResultError.PROCESS_WONT_START, message=error_msg)
|
||||||
|
|
||||||
process_id = activation_result.data
|
process_id = activation_result.data
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
@ -129,7 +131,7 @@ def start_singbox(
|
||||||
)
|
)
|
||||||
|
|
||||||
# ============= FIREWALL =============
|
# ============= FIREWALL =============
|
||||||
logger.info(f"[{function_name}] Attempting to enable the Firewall for {SINGBOX_TUN_IF} and {Constants.SINGBOX_INTERNAL_SUBNET}...")
|
logger.info(f"[{function_name}] Attempting to enable the Firewall for {Constants.SINGBOX_TUN_IF} and {Constants.SINGBOX_INTERNAL_SUBNET}...")
|
||||||
# this is labeled "generic" for being protocol neutral
|
# this is labeled "generic" for being protocol neutral
|
||||||
firewall_result = generic_enable_firewall_w_retry(
|
firewall_result = generic_enable_firewall_w_retry(
|
||||||
interface_name=Constants.SINGBOX_TUN_IF,
|
interface_name=Constants.SINGBOX_TUN_IF,
|
||||||
|
|
|
||||||
|
|
@ -230,6 +230,7 @@ def _establish_connection_with_retry(
|
||||||
|
|
||||||
except ConnectionError as e:
|
except ConnectionError as e:
|
||||||
# Unrecoverable error, fail immediately
|
# Unrecoverable error, fail immediately
|
||||||
|
logger.error(str(e))
|
||||||
raise
|
raise
|
||||||
|
|
||||||
except CalledProcessError as e:
|
except CalledProcessError as e:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
from core.utils.run_commands import run_generic_command
|
from core.utils.run_commands import run_generic_command
|
||||||
from core.models.Result import Result, ResultError
|
from core.models.Result import Result, ResultError
|
||||||
|
from core.errors.logger import logger
|
||||||
|
|
||||||
from subprocess import CalledProcessError
|
from subprocess import CalledProcessError
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
from core.services.networking.tor_tools.monitor_bootstrap import monitor_bootstrap_progress
|
from core.services.networking.tor_tools.monitor_bootstrap import monitor_bootstrap_progress
|
||||||
|
from core.services.networking.tor_tools.install_tor import install_tor
|
||||||
from core.services.networking.api_requests.ApiResponseModel import ApiResponse, ErrorType
|
from core.services.networking.api_requests.ApiResponseModel import ApiResponse, ErrorType
|
||||||
from core.services.networking.tor_tools import ports
|
from core.services.networking.tor_tools import ports
|
||||||
from core.Constants import Constants
|
from core.Constants import Constants
|
||||||
|
|
@ -89,7 +90,7 @@ def bootstrap(
|
||||||
current_port = ports.get_random_available_port()
|
current_port = ports.get_random_available_port()
|
||||||
use_new_folder = True
|
use_new_folder = True
|
||||||
elif strategy == BootstrapStrategy.REINSTALL_AND_RETRY:
|
elif strategy == BootstrapStrategy.REINSTALL_AND_RETRY:
|
||||||
if not install_tor().valid:
|
if not install_tor(observer).valid:
|
||||||
return ApiResponse(valid=False, error_type=ErrorType.INSTALL_FAILED)
|
return ApiResponse(valid=False, error_type=ErrorType.INSTALL_FAILED)
|
||||||
use_new_folder = True
|
use_new_folder = True
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ def get_distro_package_manager() -> Optional[str]:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
async def install_tor() -> ApiResponse:
|
async def install_tor(observer: ConnectionObserver) -> ApiResponse:
|
||||||
"""
|
"""
|
||||||
Prompt user to install Tor with pkexec, detecting distro for correct package manager.
|
Prompt user to install Tor with pkexec, detecting distro for correct package manager.
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,13 @@ from core.Constants import Constants
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
import subprocess
|
import subprocess
|
||||||
import asyncio
|
import asyncio
|
||||||
import subprocess
|
|
||||||
import socket
|
import socket
|
||||||
import httpx
|
import httpx
|
||||||
from httpx_socks import AsyncProxyTransport
|
from httpx_socks import AsyncProxyTransport
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
import os
|
||||||
|
import signal
|
||||||
|
|
||||||
def is_port_in_use(port: int) -> bool:
|
def is_port_in_use(port: int) -> bool:
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ def get_bootstrap_port(port_tried: int, observer: ConnectionObserver):
|
||||||
def diagnose_tor_port(port_tried: int, observer: ConnectionObserver) -> ApiResponse:
|
def diagnose_tor_port(port_tried: int, observer: ConnectionObserver) -> ApiResponse:
|
||||||
# Step 1) Is Tor Installed?
|
# Step 1) Is Tor Installed?
|
||||||
if not is_installed('tor'):
|
if not is_installed('tor'):
|
||||||
installed = install_tor()
|
installed = install_tor(observer)
|
||||||
if installed:
|
if installed:
|
||||||
return ApiResponse(valid=True, error_type=ErrorType.TOR_NOT_INSTALLED, port=Constants.DEFAULT_TOR_PORT)
|
return ApiResponse(valid=True, error_type=ErrorType.TOR_NOT_INSTALLED, port=Constants.DEFAULT_TOR_PORT)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ def establish_tor_connection(observer: ConnectionObserver) -> ApiResponse:
|
||||||
|
|
||||||
# Step 2) Install Tor if needed.
|
# Step 2) Install Tor if needed.
|
||||||
if result.error_type == ErrorType.TOR_NOT_INSTALLED:
|
if result.error_type == ErrorType.TOR_NOT_INSTALLED:
|
||||||
installed = install_tor()
|
installed = install_tor(observer)
|
||||||
if not installed:
|
if not installed:
|
||||||
return ApiResponse(valid=False, error_type=ErrorType.REFUSAL_TO_INSTALL_TOR)
|
return ApiResponse(valid=False, error_type=ErrorType.REFUSAL_TO_INSTALL_TOR)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ from core.services.networking.api_requests.step1_get_or_post import send_data_to
|
||||||
from core.services.networking.api_requests.ApiResponseModel import ApiResponse, ErrorType
|
from core.services.networking.api_requests.ApiResponseModel import ApiResponse, ErrorType
|
||||||
from core.services.networking.api_requests.step5_solve_api_problems import solve_api_problems
|
from core.services.networking.api_requests.step5_solve_api_problems import solve_api_problems
|
||||||
|
|
||||||
|
from core.services.networking.httpx import connect
|
||||||
|
|
||||||
from core.services.networking.make_url import make_url
|
from core.services.networking.make_url import make_url
|
||||||
from core.services.payment_phase.extract_payment_details import extract_payment_details
|
from core.services.payment_phase.extract_payment_details import extract_payment_details
|
||||||
|
|
@ -42,22 +43,33 @@ def save_and_send_intitial_billing(
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Save choices:
|
# Save choices:
|
||||||
save_billing_choices(payload)
|
saved_choices = save_billing_choices(payload)
|
||||||
|
if not saved_choices:
|
||||||
|
error_msg = "Unable to save billing choices locally. Check file permissions and storage space."
|
||||||
|
logger.error(error_msg)
|
||||||
|
return TicketInvoice(is_valid=False, final_error_msg=error_msg)
|
||||||
|
|
||||||
# send them:
|
# send them:
|
||||||
which_endpoint = "start_payment"
|
which_endpoint = "start_payment"
|
||||||
url = make_url(which_endpoint)
|
url = make_url(which_endpoint)
|
||||||
api_reply_object = send_data_to_server(payload, url, connection_observer)
|
# api_reply_object = send_data_to_server(payload, url, connection_observer)
|
||||||
|
|
||||||
if not api_reply_object.valid:
|
api_reply_object = connect.single_endpoint(
|
||||||
api_reply_object = solve_api_problems(
|
method="post",
|
||||||
api_reply_object=api_reply_object,
|
|
||||||
get_or_post="post",
|
|
||||||
url=url,
|
url=url,
|
||||||
payload=payload,
|
observer=connection_observer,
|
||||||
connection_observer=connection_observer,
|
payload=payload
|
||||||
client_observer=None
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# if not api_reply_object.valid:
|
||||||
|
# api_reply_object = solve_api_problems(
|
||||||
|
# api_reply_object=api_reply_object,
|
||||||
|
# get_or_post="post",
|
||||||
|
# url=url,
|
||||||
|
# payload=payload,
|
||||||
|
# connection_observer=connection_observer,
|
||||||
|
# client_observer=None
|
||||||
|
# )
|
||||||
if not api_reply_object.valid:
|
if not api_reply_object.valid:
|
||||||
return api_reply_object
|
return api_reply_object
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,4 @@ def save_billing_choices(payload: dict) -> None:
|
||||||
billing_folder = Constants.HV_TICKETING_CONFIG_HOME
|
billing_folder = Constants.HV_TICKETING_CONFIG_HOME
|
||||||
filepath = f"{billing_folder}/billing_choices.json"
|
filepath = f"{billing_folder}/billing_choices.json"
|
||||||
|
|
||||||
write_json_to_file(payload, filepath)
|
return write_json_to_file(payload, filepath)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ from typing import Any
|
||||||
# services
|
# services
|
||||||
from core.services.networking.make_url import make_url
|
from core.services.networking.make_url import make_url
|
||||||
from core.services.networking.api_requests.step1_get_or_post import get_data_from_api
|
from core.services.networking.api_requests.step1_get_or_post import get_data_from_api
|
||||||
|
from core.services.networking.httpx import connect
|
||||||
|
from core.services.networking.api_requests.ApiResponseModel import ApiResponse, ErrorType
|
||||||
|
|
||||||
# utils
|
# utils
|
||||||
from core.utils.basic_operations.does_file_exist import does_file_exist
|
from core.utils.basic_operations.does_file_exist import does_file_exist
|
||||||
|
|
@ -30,15 +32,17 @@ def get_from_server_and_save(
|
||||||
|
|
||||||
url = make_url(string_form_of_key_name)
|
url = make_url(string_form_of_key_name)
|
||||||
|
|
||||||
# the result of this is a python dictionary with single '
|
# public_key_results = get_data_from_server(url, connection_observer)
|
||||||
public_key_results = get_data_from_server(url, connection_observer)
|
public_key_results = connect.single_endpoint(
|
||||||
|
method="get",
|
||||||
|
url=url,
|
||||||
|
observer=connection_observer,
|
||||||
|
payload=None
|
||||||
|
)
|
||||||
|
|
||||||
if isinstance(public_key_results, dict) and "valid" in public_key_results:
|
if public_key_results.valid:
|
||||||
status = public_key_results.get("valid", False)
|
|
||||||
|
|
||||||
if status == True:
|
|
||||||
# extract:
|
# extract:
|
||||||
public_key = public_key_results.get("data", False)
|
public_key = public_key_results.data
|
||||||
|
|
||||||
# save it:
|
# save it:
|
||||||
did_it_save = write_string_to_text_file(public_key, file_path)
|
did_it_save = write_string_to_text_file(public_key, file_path)
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ def get_public_key_by_config(connection_observer: ConnectionObserver) -> dict:
|
||||||
if reply in list_of_failures:
|
if reply in list_of_failures:
|
||||||
return complete_failure_msg
|
return complete_failure_msg
|
||||||
|
|
||||||
if not instance(reply, dict):
|
if not isinstance(reply, dict):
|
||||||
return {
|
return {
|
||||||
"status": False,
|
"status": False,
|
||||||
"message": f"Server returned an invalid format, and even accessing via local files. Please check {filepath}",
|
"message": f"Server returned an invalid format, and even accessing via local files. Please check {filepath}",
|
||||||
|
|
@ -141,7 +141,7 @@ def get_public_key_from_LOCAL_files_only(
|
||||||
if reply in list_of_failures:
|
if reply in list_of_failures:
|
||||||
return complete_failure_msg
|
return complete_failure_msg
|
||||||
|
|
||||||
if not instance(reply, dict):
|
if not isinstance(reply, dict):
|
||||||
return {
|
return {
|
||||||
"status": False,
|
"status": False,
|
||||||
"message": f"Server returned an invalid format, and even accessing via local files. Please check {filepath}",
|
"message": f"Server returned an invalid format, and even accessing via local files. Please check {filepath}",
|
||||||
|
|
|
||||||
|
|
@ -21,4 +21,4 @@ def setup_ticket_tracker(how_many_profiles: int) -> None:
|
||||||
}
|
}
|
||||||
counter += 1
|
counter += 1
|
||||||
|
|
||||||
write_json_to_file(ticket_data, ticket_tracker_path)
|
return write_json_to_file(ticket_data, ticket_tracker_path)
|
||||||
|
|
|
||||||
|
|
@ -94,9 +94,9 @@ def ticket_prep_orchestrator(
|
||||||
)
|
)
|
||||||
|
|
||||||
# make a json to keep track of which tickets are used:
|
# make a json to keep track of which tickets are used:
|
||||||
setup_ticket_tracker(how_many_profiles)
|
setup_tracker = setup_ticket_tracker(how_many_profiles)
|
||||||
|
|
||||||
if did_prep_work:
|
if did_prep_work and setup_tracker:
|
||||||
# this means it unblinded, & setup the tracker without erroring out,
|
# this means it unblinded, & setup the tracker without erroring out,
|
||||||
# but it does NOT mean that verification of the blind sigs worked.
|
# but it does NOT mean that verification of the blind sigs worked.
|
||||||
return {"valid": True, "message": "worked"}
|
return {"valid": True, "message": "worked"}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
from core.utils.basic_operations.write_or_read_from_json import (
|
from core.utils.basic_operations.write_or_read_from_json import read_entire_json
|
||||||
write_json_to_file,
|
|
||||||
read_entire_json,
|
|
||||||
)
|
|
||||||
from core.errors.exceptions import *
|
from core.errors.exceptions import *
|
||||||
from core.errors.logger import logger
|
from core.errors.logger import logger
|
||||||
from core.Constants import Constants
|
from core.Constants import Constants
|
||||||
|
|
@ -62,7 +59,7 @@ def get_data_for_a_single_ticket(which_ticket_as_int: int) -> tuple:
|
||||||
error_msg = f"Entire file of tickets does not exist. Check the location {ticket_tracker_path}"
|
error_msg = f"Entire file of tickets does not exist. Check the location {ticket_tracker_path}"
|
||||||
logger.error(error_msg, exc_info=True)
|
logger.error(error_msg, exc_info=True)
|
||||||
print(error_msg)
|
print(error_msg)
|
||||||
raise InvalidData(error_msg)
|
raise ValueError(error_msg)
|
||||||
|
|
||||||
# the data is a string for lookups:
|
# the data is a string for lookups:
|
||||||
which_ticket = str(which_ticket_as_int)
|
which_ticket = str(which_ticket_as_int)
|
||||||
|
|
@ -74,6 +71,6 @@ def get_data_for_a_single_ticket(which_ticket_as_int: int) -> tuple:
|
||||||
subscription = data.get(which_ticket, {}).get("subscription")
|
subscription = data.get(which_ticket, {}).get("subscription")
|
||||||
return status, location, subscription
|
return status, location, subscription
|
||||||
else:
|
else:
|
||||||
raise InvalidData(
|
raise ValueError(
|
||||||
f"Key '{which_ticket}' does not exist in JSON file {ticket_tracker_path}"
|
f"Key '{which_ticket}' does not exist in JSON file {ticket_tracker_path}"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
from core.errors.exceptions import *
|
|
||||||
from core.errors.logger import logger
|
from core.errors.logger import logger
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
@ -6,7 +5,7 @@ import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
def write_json_to_file(data: dict, filepath: str) -> None:
|
def write_json_to_file(data: dict, filepath: str) -> bool:
|
||||||
try:
|
try:
|
||||||
# Create directory if it doesn't exist
|
# Create directory if it doesn't exist
|
||||||
directory = os.path.dirname(filepath)
|
directory = os.path.dirname(filepath)
|
||||||
|
|
@ -16,10 +15,20 @@ def write_json_to_file(data: dict, filepath: str) -> None:
|
||||||
with open(filepath, "w") as f:
|
with open(filepath, "w") as f:
|
||||||
json.dump(data, f, indent=4)
|
json.dump(data, f, indent=4)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
raise TypeError(f"Data is not JSON serializable: {e}")
|
logger.error(f"Data is not JSON serializable: {e}")
|
||||||
|
return False
|
||||||
|
except FileNotFoundError:
|
||||||
|
logger.error(f"File not found: {filepath}")
|
||||||
|
return False
|
||||||
|
except IsADirectoryError:
|
||||||
|
logger.error(f"Path is a directory, not a file: {filepath}")
|
||||||
|
return False
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
raise IOError(f"Error writing to file {filepath}: {e}")
|
logger.error(f"Error reading file {filepath}: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def read_entire_json(filepath: str) -> dict:
|
def read_entire_json(filepath: str) -> dict:
|
||||||
|
|
@ -43,13 +52,13 @@ def read_entire_json(filepath: str) -> dict:
|
||||||
f"Invalid JSON in file {filepath}: {e.msg}", e.doc, e.pos
|
f"Invalid JSON in file {filepath}: {e.msg}", e.doc, e.pos
|
||||||
)
|
)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
raise FileNotFoundError(f"File not found: {filepath}")
|
logger.error(f"File not found: {filepath}")
|
||||||
return False
|
return False
|
||||||
except IsADirectoryError:
|
except IsADirectoryError:
|
||||||
raise IsADirectoryError(f"Path is a directory, not a file: {filepath}")
|
logger.error(f"Path is a directory, not a file: {filepath}")
|
||||||
return False
|
return False
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
raise IOError(f"Error reading file {filepath}: {e}")
|
logger.error(f"Error reading file {filepath}: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -103,8 +112,14 @@ def update_value_in_json_with_two_values(
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except:
|
except FileNotFoundError:
|
||||||
raise InvalidData(f"Error reading file {filepath}")
|
logger.error(f"File not found: {filepath}")
|
||||||
|
return False
|
||||||
|
except IsADirectoryError:
|
||||||
|
logger.error(f"Path is a directory, not a file: {filepath}")
|
||||||
|
return False
|
||||||
|
except IOError as e:
|
||||||
|
logger.error(f"Error reading file {filepath}: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -122,6 +137,12 @@ def update_json(filepath, key_to_add, value_to_update):
|
||||||
write_json_to_file(data, filepath)
|
write_json_to_file(data, filepath)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except:
|
except FileNotFoundError:
|
||||||
raise InvalidData(f"Error reading file {filepath}")
|
logger.error(f"File not found: {filepath}")
|
||||||
|
return False
|
||||||
|
except IsADirectoryError:
|
||||||
|
logger.error(f"Path is a directory, not a file: {filepath}")
|
||||||
|
return False
|
||||||
|
except IOError as e:
|
||||||
|
logger.error(f"Error reading file {filepath}: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
|
||||||
|
|
@ -131,14 +131,14 @@ def run_generic_command(
|
||||||
|
|
||||||
try:
|
try:
|
||||||
returncode, stdout = _run_command_via_terminal(command, timeout)
|
returncode, stdout = _run_command_via_terminal(command, timeout)
|
||||||
output_data = stdout
|
# output_data = stdout
|
||||||
|
|
||||||
if returncode == 0:
|
if returncode == 0:
|
||||||
logger.info(f"{human_readable_goal} was successful")
|
logger.info(f"{human_readable_goal} was successful")
|
||||||
return Result(valid=True, data=output_data)
|
return Result(valid=True, data=stdout)
|
||||||
else:
|
else:
|
||||||
# Try stderr first, fallback to stdout for error parsing
|
# Try stderr first, fallback to stdout for error parsing
|
||||||
error_output = (stderr or stdout).strip()
|
error_output = stdout.strip()
|
||||||
error_enum = parse_errors(error_output)
|
error_enum = parse_errors(error_output)
|
||||||
logger.error(f"{human_readable_goal} Failed, error type is {error_enum}.")
|
logger.error(f"{human_readable_goal} Failed, error type is {error_enum}.")
|
||||||
return Result(valid=False, error_type=error_enum, goal=human_readable_goal, message=error_output)
|
return Result(valid=False, error_type=error_enum, goal=human_readable_goal, message=error_output)
|
||||||
|
|
@ -147,3 +147,19 @@ def run_generic_command(
|
||||||
return Result(valid=False, error_type=ResultError.TIMEOUT, goal=human_readable_goal, data=output_data, message=f"Command timed out {e}")
|
return Result(valid=False, error_type=ResultError.TIMEOUT, goal=human_readable_goal, data=output_data, message=f"Command timed out {e}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return Result(valid=False, error_type=ResultError.UNKNOWN, goal=human_readable_goal, data=output_data, message=str(e))
|
return Result(valid=False, error_type=ResultError.UNKNOWN, goal=human_readable_goal, data=output_data, message=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
def parse_errors(error_output: str) -> ResultError:
|
||||||
|
# Interface missing
|
||||||
|
if "No such device" in error_output:
|
||||||
|
error_enum = ResultError.INTERFACE
|
||||||
|
# Permission error
|
||||||
|
elif "No permissions" in error_output:
|
||||||
|
error_enum = ResultError.PERMISSION
|
||||||
|
elif "sudo: a password is required" or "password is required" in error_output:
|
||||||
|
error_enum = ResultError.PERMISSION
|
||||||
|
elif "command not found" in error_output:
|
||||||
|
error_enum = ResultError.MISSING_DEPENDENCY
|
||||||
|
else:
|
||||||
|
error_enum = ResultError.UNKNOWN
|
||||||
|
return error_enum
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue