forked from Support/sp-hydra-veil-gui
321 lines
14 KiB
Python
Executable file
321 lines
14 KiB
Python
Executable file
import shlex
|
|
import subprocess
|
|
|
|
from PyQt6.QtCore import QThread, pyqtSignal
|
|
|
|
from core.controllers.ApplicationVersionController import ApplicationVersionController
|
|
from core.controllers.ClientController import ClientController
|
|
from core.controllers.ConfigurationController import ConfigurationController
|
|
from core.controllers.InvoiceController import InvoiceController
|
|
from core.controllers.LocationController import LocationController
|
|
from core.controllers.ProfileController import ProfileController
|
|
from core.controllers.SubscriptionController import SubscriptionController
|
|
from core.controllers.SubscriptionPlanController import SubscriptionPlanController
|
|
from core.models.session.SessionConnection import SessionConnection
|
|
from core.models.session.SessionProfile import SessionProfile
|
|
from core.models.system.SystemConnection import SystemConnection
|
|
from core.models.BaseProfile import ProfileType
|
|
from core.models.system.SystemProfile import SystemProfile
|
|
|
|
from gui.v2.infrastructure.setup_observers import (
|
|
client_observer,
|
|
connection_observer,
|
|
invoice_observer,
|
|
profile_observer,
|
|
)
|
|
|
|
|
|
class WorkerThread(QThread):
|
|
text_output = pyqtSignal(str)
|
|
sync_output = pyqtSignal(list, list, bool, bool, list, list)
|
|
invoice_output = pyqtSignal(object, str)
|
|
invoice_finished = pyqtSignal(bool)
|
|
profiles_output = pyqtSignal(dict)
|
|
special_output = pyqtSignal(str)
|
|
finished = pyqtSignal(bool)
|
|
update_finished = pyqtSignal(dict)
|
|
|
|
def __init__(self, action=None, profile_data=None, profile_type=None, package_name=None, package_command=None):
|
|
super().__init__()
|
|
self.action = action
|
|
self.profile_data = profile_data
|
|
self.profile_type = profile_type
|
|
self.package_name = package_name
|
|
self.package_command = package_command
|
|
self.is_running = True
|
|
self.is_disabling = False
|
|
|
|
def run(self):
|
|
if self.action == 'LIST_PROFILES':
|
|
self.list_profiles()
|
|
elif self.action == 'CREATE_SESSION_PROFILE':
|
|
self.create_profile(self.profile_type)
|
|
elif self.action == 'CREATE_SYSTEM_PROFILE':
|
|
self.create_profile(self.profile_type)
|
|
elif self.action == 'GET_SUBSCRIPTION':
|
|
self.get_subscription()
|
|
elif self.action == 'DISABLE_PROFILE':
|
|
self.disable_profile()
|
|
elif self.action == 'SYNC' or self.action == 'SYNC_TOR':
|
|
self.sync()
|
|
elif self.action == 'DESTROY_PROFILE':
|
|
self.destroy_profile()
|
|
elif self.action == 'DISABLE_ALL_PROFILES':
|
|
self.disable_all_profiles()
|
|
elif self.action == 'INSTALL_PACKAGE':
|
|
self.install_package()
|
|
elif self.action == 'CHECK_FOR_UPDATE':
|
|
self.check_for_update()
|
|
elif self.action == 'DOWNLOAD_UPDATE':
|
|
self.download_update()
|
|
elif self.action == 'CHECK_INVOICE_STATUS':
|
|
self.check_invoice_status()
|
|
|
|
def check_invoice_status(self):
|
|
try:
|
|
invoice = InvoiceController.get(self.profile_data['billing_code'])
|
|
if invoice:
|
|
status = invoice.status
|
|
if status == "expired":
|
|
self.invoice_finished.emit(False)
|
|
else:
|
|
self.invoice_finished.emit(True)
|
|
else:
|
|
self.invoice_finished.emit(False)
|
|
except Exception as e:
|
|
print(f"Error retrieving invoice: {str(e)}")
|
|
self.invoice_finished.emit(False)
|
|
|
|
def download_update(self):
|
|
self.text_output.emit("Starting update process...")
|
|
ClientController.update(client_observer=client_observer)
|
|
client_observer.subscribe('update_progressing', lambda event: self.text_output.emit(
|
|
f"Downloading: {event.meta.get('progress'):.1f}%"))
|
|
client_observer.subscribe(
|
|
'updated', lambda event: self.text_output.emit("Update process completed"))
|
|
|
|
def check_for_update(self):
|
|
self.text_output.emit("Checking for updates...")
|
|
ClientController.sync(client_observer=client_observer,
|
|
connection_observer=connection_observer)
|
|
update_available = ClientController.can_be_updated()
|
|
if update_available:
|
|
self.text_output.emit("An update is available. Downloading...")
|
|
self.finished.emit(True)
|
|
else:
|
|
self.text_output.emit("No updates available.")
|
|
self.finished.emit(False)
|
|
|
|
def install_package(self):
|
|
try:
|
|
self.text_output.emit(f"Installing {self.package_name}...")
|
|
subprocess.run(shlex.split(self.package_command), check=True)
|
|
self.text_output.emit(f"{self.package_name} installed!")
|
|
self.finished.emit(True)
|
|
except subprocess.CalledProcessError:
|
|
self.text_output.emit("Installation failed")
|
|
self.finished.emit(False)
|
|
except Exception as e:
|
|
self.text_output.emit(
|
|
f"An error occurred when installing {self.package_name}: {e}")
|
|
self.finished.emit(False)
|
|
|
|
def disable_all_profiles(self):
|
|
try:
|
|
for profile_id in self.profile_data:
|
|
profile = ProfileController.get(int(profile_id))
|
|
if isinstance(profile, SessionProfile):
|
|
ProfileController.disable(
|
|
profile, ignore=True, profile_observer=profile_observer)
|
|
for profile_id in self.profile_data:
|
|
profile = ProfileController.get(int(profile_id))
|
|
if isinstance(profile, SystemProfile):
|
|
ProfileController.disable(
|
|
profile, ignore=True, profile_observer=profile_observer)
|
|
self.text_output.emit("All profiles were successfully disabled")
|
|
except Exception:
|
|
self.text_output.emit("An error occurred when disabling profile")
|
|
finally:
|
|
self.finished.emit(True)
|
|
|
|
def destroy_profile(self):
|
|
profile_id = int(self.profile_data['id'])
|
|
profile = ProfileController.get(profile_id)
|
|
|
|
if profile is not None:
|
|
try:
|
|
ProfileController.destroy(profile)
|
|
except Exception as e:
|
|
error_name = type(e).__name__
|
|
error_text = str(e) or 'Unknown deletion error'
|
|
self.text_output.emit(
|
|
f'Could not delete profile {profile_id}: {error_name}: {error_text}')
|
|
self.finished.emit(False)
|
|
return
|
|
self.text_output.emit(f'Profile {profile_id} deleted')
|
|
self.finished.emit(True)
|
|
else:
|
|
self.text_output.emit(f'Profile {profile_id} does not exist')
|
|
self.finished.emit(False)
|
|
|
|
def list_profiles(self):
|
|
profiles = ProfileController.get_all()
|
|
self.profiles_output.emit(profiles)
|
|
|
|
def create_profile(self, profile_type):
|
|
location = LocationController.get(
|
|
self.profile_data['country_code'], self.profile_data['code'])
|
|
if location is None:
|
|
self.text_output.emit(
|
|
f"Invalid location code: {self.profile_data['location_code']}")
|
|
return
|
|
|
|
profile_id = int(
|
|
self.profile_data['id']) if self.profile_data['id'] else None
|
|
name = self.profile_data['name']
|
|
connection_type = self.profile_data['connection_type']
|
|
|
|
if profile_type == "session":
|
|
|
|
application_details = self.profile_data['application'].split(
|
|
':', 1)
|
|
application_version = ApplicationVersionController.get(
|
|
application_details[0], application_details[1] if len(application_details) > 1 else None)
|
|
if application_version is None:
|
|
self.text_output.emit(
|
|
f"Invalid application: {self.profile_data['application']}")
|
|
return
|
|
|
|
mask_connection = True if connection_type == 'tor' or connection_type == 'system' else False
|
|
resolution = self.profile_data['resolution']
|
|
connection = SessionConnection(connection_type, mask_connection)
|
|
profile = SessionProfile(
|
|
id=profile_id,
|
|
name=name,
|
|
subscription=None,
|
|
type=ProfileType.SESSION,
|
|
location=location,
|
|
resolution=resolution,
|
|
application_version=application_version,
|
|
connection=connection)
|
|
elif profile_type == "system":
|
|
connection = SystemConnection(connection_type)
|
|
profile = SystemProfile(
|
|
id=profile_id,
|
|
name=name,
|
|
type=ProfileType.SYSTEM,
|
|
subscription=None,
|
|
location=location,
|
|
connection=connection)
|
|
else:
|
|
self.text_output.emit(f"Invalid profile type: {profile_type}")
|
|
return
|
|
try:
|
|
ProfileController.create(
|
|
profile, profile_observer=profile_observer)
|
|
except Exception as e:
|
|
self.text_output.emit(
|
|
f"An error occurred when creating profile {profile.id}")
|
|
|
|
self.text_output.emit(
|
|
f"{profile_type.capitalize()} Profile created with ID: {profile.id}")
|
|
|
|
def disable_profile(self):
|
|
try:
|
|
profile = ProfileController.get(int(self.profile_data['id']))
|
|
if profile:
|
|
ProfileController.disable(
|
|
profile, profile_observer=profile_observer)
|
|
else:
|
|
self.text_output.emit(
|
|
f"No profile found with ID: {self.profile_data['id']}")
|
|
except Exception as e:
|
|
self.text_output.emit("An error occurred when disabling profile")
|
|
finally:
|
|
self.finished.emit(True)
|
|
|
|
def sync(self):
|
|
try:
|
|
if self.action == 'SYNC_TOR':
|
|
ConfigurationController.set_connection('tor')
|
|
else:
|
|
ConfigurationController.set_connection('system')
|
|
self.check_for_update()
|
|
|
|
locations = LocationController.get_all()
|
|
|
|
|
|
browser = ApplicationVersionController.get_all()
|
|
# print('the browser is: ', browser)
|
|
all_browser_versions = [
|
|
f"{browser.application_code}:{browser.version_number}" for browser in browser if browser.supported]
|
|
all_location_codes = [
|
|
f"{location.country_code}_{location.code}" for location in locations]
|
|
self.sync_output.emit(
|
|
all_location_codes, all_browser_versions, True, False, locations, browser)
|
|
except Exception as e:
|
|
print(f'the error is: {e}')
|
|
self.sync_output.emit([], [], False, False, [], [])
|
|
|
|
def get_connection(self):
|
|
connection = ConfigurationController.get_connection()
|
|
self.text_output.emit(f"Current connection: {connection}")
|
|
|
|
def set_connection(self):
|
|
ConfigurationController.set_connection(
|
|
self.profile_data['connection_type'])
|
|
self.text_output.emit(
|
|
f"Connection set to '{self.profile_data['connection_type']}'")
|
|
|
|
def get_subscription(self):
|
|
try:
|
|
invoice_observer.subscribe('retrieved', lambda event: self.handle_event(
|
|
event, self.profile_data['currency']))
|
|
invoice_observer.subscribe('processing', lambda event: self.text_output.emit(
|
|
'A payment has been detected and is being verified...'))
|
|
invoice_observer.subscribe('settled', lambda event: self.text_output.emit(
|
|
'The payment has been successfully verified.'))
|
|
|
|
profile = ProfileController.get(int(self.profile_data['id']))
|
|
subscription_plan = SubscriptionPlanController.get(
|
|
profile.connection, self.profile_data['duration'])
|
|
if subscription_plan is None:
|
|
self.text_output.emit(
|
|
'No compatible subscription plan was found.')
|
|
return
|
|
potential_subscription = SubscriptionController.create(
|
|
subscription_plan, profile, connection_observer=connection_observer)
|
|
if potential_subscription is not None:
|
|
ProfileController.attach_subscription(
|
|
profile, potential_subscription)
|
|
else:
|
|
self.text_output.emit(
|
|
'The subscription could not be created. Try again later.')
|
|
return
|
|
|
|
subscription = InvoiceController.handle_payment(
|
|
potential_subscription.billing_code, invoice_observer=invoice_observer, connection_observer=connection_observer)
|
|
if subscription is not None:
|
|
ProfileController.attach_subscription(profile, subscription)
|
|
self.text_output.emit(
|
|
'Successfully activated the subscription')
|
|
self.invoice_finished.emit(True)
|
|
else:
|
|
self.text_output.emit(
|
|
'The subscription could not be activated. Try again later.')
|
|
self.invoice_finished.emit(False)
|
|
|
|
except Exception as e:
|
|
self.text_output.emit('An unknown error occurred')
|
|
self.invoice_finished.emit(False)
|
|
|
|
def handle_connection_events(self, event):
|
|
self.text_output.emit(f'Profile disabled')
|
|
|
|
def handle_event(self, event, currency=None):
|
|
invoice = event.subject
|
|
if isinstance(invoice, object):
|
|
self.invoice_output.emit(invoice, '')
|
|
self.text_output.emit("Invoice generated. Awaiting payment...")
|
|
else:
|
|
self.text_output.emit("Invalid invoice data received.")
|