Introduced Assassin Mode in core, and this commit added support for it in the GUI. This involved passing in ticket observers when a profile is enabled or disabled, getting the max screen size via PyQt, and adding a check prior to using a random ticket.

This commit is contained in:
SimplifiedPrivacy 2026-08-18 09:48:42 -04:00
parent db1f903b0b
commit 86fc3ca56c
5 changed files with 64 additions and 17 deletions

View file

@ -31,6 +31,7 @@ from gui.v2.infrastructure import orm
from gui.v2.infrastructure.navigator import Navigator from gui.v2.infrastructure.navigator import Navigator
from gui.v2.infrastructure.setup_observers import setup_observers from gui.v2.infrastructure.setup_observers import setup_observers
from gui.v2.infrastructure.connection_manager import ConnectionManager from gui.v2.infrastructure.connection_manager import ConnectionManager
from gui.v2.infrastructure.screen_size import calculate_max_screensize
from gui.v2.workers.worker_thread import WorkerThread from gui.v2.workers.worker_thread import WorkerThread
from gui.v2.ui.builders.bottom_section import create_bottom_section from gui.v2.ui.builders.bottom_section import create_bottom_section
from gui.v2.ui.builders.top_section import create_top_section from gui.v2.ui.builders.top_section import create_top_section
@ -906,5 +907,6 @@ class CustomWindow(QMainWindow):
def start_ui(force_sync): def start_ui(force_sync):
app = QApplication(sys.argv) app = QApplication(sys.argv)
calculate_max_screensize(app)
window = CustomWindow(force_sync=force_sync) window = CustomWindow(force_sync=force_sync)
sys.exit(app.exec()) sys.exit(app.exec())

View file

@ -0,0 +1,31 @@
from core.errors.logger import logger
from PyQt6.QtWidgets import QApplication
from PyQt6.QtGui import QGuiApplication
import sys
max_screen_size = None
DEFAULT_VALUE = "800x800"
def calculate_max_screensize(app):
global max_screen_size
try:
screen = app.primaryScreen()
available = screen.availableGeometry()
dpi_ratio = screen.devicePixelRatio()
actual_width = int(available.width() * dpi_ratio)
actual_height = int(available.height() * dpi_ratio)
max_screen_size = f"{actual_width}x{actual_height}"
except Exception as e:
logger.error(f"Critical Error with calculating the screen size: {str(e)}")
max_screen_size = DEFAULT_VALUE
def get_max_screensize():
if max_screen_size is not None:
return max_screen_size
else:
return DEFAULT_VALUE

View file

@ -6,6 +6,7 @@ from PyQt6.QtCore import QSize
from PyQt6 import QtCore from PyQt6 import QtCore
from core.controllers.tickets.TicketPayController import check_if_paid from core.controllers.tickets.TicketPayController import check_if_paid
from core.models.Result import Result, ResultError
from gui.v2.infrastructure.setup_observers import connection_observer, ticket_observer from gui.v2.infrastructure.setup_observers import connection_observer, ticket_observer
from gui.v2.ui.pages.Page import Page from gui.v2.ui.pages.Page import Page
@ -103,26 +104,32 @@ class TicketCryptoPickerPage(Page):
self.update_status.update_status("Could not initiate payment.") self.update_status.update_status("Could not initiate payment.")
return return
error_code = getattr(invoice, 'error_code', None) if not invoice.valid:
if error_code == 'already_exists' and not self.bypass_existing: return self._handle_api_errors(invoice)
# error_code = getattr(invoice, 'error_code', None)
self.custom_window.navigator.navigate("payment_details")
payment_page = self.custom_window.navigator.get_cached("payment_details")
if payment_page is not None:
payment_page.set_ticket_invoice(invoice.data, self.selected_plan)
def _handle_api_errors(self, invoice: Result):
error_code = invoice.error_type
if error_code == ResultError.ALREADY_EXISTS and not self.bypass_existing:
self._prompt_wipe_existing(invoice) self._prompt_wipe_existing(invoice)
return return
if error_code == 'billing_code_exists' and not self.bypass_existing: elif error_code == ResultError.BILLING_CODE_EXISTS and not self.bypass_existing:
temp_billing_code = getattr(invoice, 'temp_billing_code', None) temp_billing_code = getattr(invoice_data, 'temp_billing_code', None)
print(f"temp_billing_code is {temp_billing_code}") print(f"temp_billing_code is {temp_billing_code}")
if temp_billing_code: if temp_billing_code:
self._prompt_wipe_billingcode(temp_billing_code) self._prompt_wipe_billingcode(temp_billing_code)
return return
if error_code: else:
msg = getattr(invoice, 'final_error_msg', None) or error_code error_msg = invoice.message
self.update_status.update_status(f"Payment error: {msg}") # msg = getattr(invoice, 'final_error_msg', None) or error_code
self.update_status.update_status(error_msg)
return return
self.custom_window.navigator.navigate("payment_details")
payment_page = self.custom_window.navigator.get_cached("payment_details")
if payment_page is not None:
payment_page.set_ticket_invoice(invoice, self.selected_plan)
def _prompt_wipe_existing(self, invoice): def _prompt_wipe_existing(self, invoice):
msg = QMessageBox(self) msg = QMessageBox(self)
msg.setWindowTitle("Existing tickets found") msg.setWindowTitle("Existing tickets found")

View file

@ -26,6 +26,7 @@ from core.Errors import (
from gui.v2.actions.locations import location_candidates from gui.v2.actions.locations import location_candidates
from gui.v2.actions.database_health import GuiStorageDatabaseError from gui.v2.actions.database_health import GuiStorageDatabaseError
from gui.v2.infrastructure.screen_size import get_max_screensize
from gui.v2.infrastructure.setup_observers import ( from gui.v2.infrastructure.setup_observers import (
application_version_observer, application_version_observer,
connection_observer, connection_observer,
@ -106,9 +107,10 @@ class Worker(QObject):
if self.profile_data.get('ignore_profile_state_conflict', False): if self.profile_data.get('ignore_profile_state_conflict', False):
ignore_exceptions.append(ProfileStateConflictError) ignore_exceptions.append(ProfileStateConflictError)
ignore_tuple = tuple(ignore_exceptions) ignore_tuple = tuple(ignore_exceptions)
max_resolution = get_max_screensize()
ProfileController.enable(self.profile, ignore=ignore_tuple, profile_observer=profile_observer, ProfileController.enable(self.profile, ignore=ignore_tuple, profile_observer=profile_observer,
application_version_observer=application_version_observer, application_version_observer=application_version_observer,
connection_observer=connection_observer) connection_observer=connection_observer, ticket_observer=ticket_observer, max_resolution=max_resolution)
except EndpointVerificationError: except EndpointVerificationError:
self.update_signal.emit( self.update_signal.emit(
"ENDPOINT_VERIFICATION_ERROR", False, self.profile_data['id'], None, None) "ENDPOINT_VERIFICATION_ERROR", False, self.profile_data['id'], None, None)
@ -193,7 +195,11 @@ class Worker(QObject):
print(error_msg) print(error_msg)
return None return None
if self.profile.assassin:
print("skipping random ticket use for the assassin, as it already has it baked in.")
return None
try: try:
print("using a random ticket from GUI...")
which_ticket, error_msg = do_we_use_a_random_ticket(ticket_observer) which_ticket, error_msg = do_we_use_a_random_ticket(ticket_observer)
except Exception: except Exception:
return None return None

View file

@ -26,6 +26,7 @@ from gui.v2.infrastructure.setup_observers import (
connection_observer, connection_observer,
invoice_observer, invoice_observer,
profile_observer, profile_observer,
ticket_observer,
) )
@ -129,12 +130,12 @@ class WorkerThread(QThread):
profile = ProfileController.get(int(profile_id)) profile = ProfileController.get(int(profile_id))
if isinstance(profile, SessionProfile): if isinstance(profile, SessionProfile):
ProfileController.disable( ProfileController.disable(
profile, ignore=True, profile_observer=profile_observer) profile, ignore=True, profile_observer=profile_observer, ticket_observer=ticket_observer, connection_observer=connection_observer)
for profile_id in self.profile_data: for profile_id in self.profile_data:
profile = ProfileController.get(int(profile_id)) profile = ProfileController.get(int(profile_id))
if isinstance(profile, SystemProfile): if isinstance(profile, SystemProfile):
ProfileController.disable( ProfileController.disable(
profile, ignore=True, profile_observer=profile_observer) profile, ignore=True, profile_observer=profile_observer, ticket_observer=ticket_observer, connection_observer=connection_observer)
self.text_output.emit("All profiles were successfully disabled") self.text_output.emit("All profiles were successfully disabled")
except SudoScript as e: except SudoScript as e:
self.text_output.emit(str(e)) self.text_output.emit(str(e))
@ -153,7 +154,7 @@ class WorkerThread(QThread):
if profile is not None: if profile is not None:
try: try:
ProfileController.destroy(profile) ProfileController.destroy(profile, profile_observer, ticket_observer, connection_observer)
except Exception as e: except Exception as e:
error_name = type(e).__name__ error_name = type(e).__name__
error_text = str(e) or 'Unknown deletion error' error_text = str(e) or 'Unknown deletion error'
@ -244,7 +245,7 @@ class WorkerThread(QThread):
profile = ProfileController.get(int(self.profile_data['id'])) profile = ProfileController.get(int(self.profile_data['id']))
if profile: if profile:
ProfileController.disable( ProfileController.disable(
profile, profile_observer=profile_observer) profile, profile_observer=profile_observer, ticket_observer=ticket_observer, connection_observer=connection_observer, wipe_assassin=True)
else: else:
self.text_output.emit( self.text_output.emit(
f"No profile found with ID: {self.profile_data['id']}") f"No profile found with ID: {self.profile_data['id']}")