forked from Support/sp-hydra-veil-gui
Ticket pages isolated to PyQt only, with calls to action functions that thread core
This commit is contained in:
parent
d1dfa788db
commit
38535aee1c
4 changed files with 161 additions and 158 deletions
|
|
@ -1,13 +1,11 @@
|
||||||
# core
|
# core
|
||||||
|
from core.services.using_tickets.use_ticket_orchestrator import use_ticket_orchestrator
|
||||||
|
from core.controllers.tickets.TicketPrepController import prepare_tickets
|
||||||
from core.controllers.ConfigurationController import ConfigurationController
|
from core.controllers.ConfigurationController import ConfigurationController
|
||||||
from core.controllers.tickets.UseTicketController import use_ticket
|
|
||||||
from core.services.prepare_tickets.ticket_tracker import get_a_random_ticket
|
from core.services.prepare_tickets.ticket_tracker import get_a_random_ticket
|
||||||
from core.models.BaseProfile import BaseProfile as Profile
|
from core.services.subscriptions.subscriptions_by_protocol import start_new_payment_cycle, get_ticket_invoice
|
||||||
from core.controllers.ProfileController import ProfileController
|
|
||||||
# from core.controllers.tickets.TicketPayController import initiate_payment
|
|
||||||
from core.services.subscriptions.subscriptions_by_protocol import start_new_payment_cycle, save_subscription, get_ticket_invoice
|
|
||||||
from core.services.payment_phase.ticket_cycle import wipe_ticket_cycle
|
from core.services.payment_phase.ticket_cycle import wipe_ticket_cycle
|
||||||
# from core.services.payment_phase.payment_state import OverallPaymentCycle
|
from core.services.payment_phase.payment_state import TicketPaymentData
|
||||||
from core.models.enum_models import PaymentCategory
|
from core.models.enum_models import PaymentCategory
|
||||||
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.utils.type_checker import type_checker
|
from core.utils.type_checker import type_checker
|
||||||
|
|
@ -24,9 +22,24 @@ from gui.v2.actions.error_handlers import navigate_to_new_sub_page
|
||||||
# generic:
|
# generic:
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
|
||||||
|
# from core.controllers.tickets.UseTicketController import use_ticket
|
||||||
|
# from core.models.BaseProfile import BaseProfile as Profile
|
||||||
|
# from core.controllers.ProfileController import ProfileController
|
||||||
|
# from core.controllers.tickets.TicketPayController import initiate_payment
|
||||||
|
|
||||||
|
|
||||||
|
@register_action(ResultError.TICKET_EXPIRED)
|
||||||
|
def wipe_ticket_billing() -> Result:
|
||||||
|
"""Wipe existing data and start over."""
|
||||||
|
wiped = wipe_ticket_cycle()
|
||||||
|
if wiped.valid:
|
||||||
|
return Result(valid=True, error_type=ResultError.NAVIGATE_TO, navigate_to="plan_picker")
|
||||||
|
else:
|
||||||
|
return Result(valid=False, error_type=ResultError.NAVIGATE_TO, navigate_to="plan_picker")
|
||||||
|
|
||||||
|
|
||||||
@register_action(ResultError.NO_TICKET)
|
@register_action(ResultError.NO_TICKET)
|
||||||
def start_and_navigate_to_ticketing():
|
def start_and_navigate_to_ticketing() -> Result:
|
||||||
"""Starts a new ticketing cycle. (assumes the user opted in)."""
|
"""Starts a new ticketing cycle. (assumes the user opted in)."""
|
||||||
start_result = start_new_payment_cycle(category=PaymentCategory.TICKET)
|
start_result = start_new_payment_cycle(category=PaymentCategory.TICKET)
|
||||||
if start_result.valid:
|
if start_result.valid:
|
||||||
|
|
@ -43,7 +56,6 @@ def random_ticket_dispatch(profile_id: int, passed_ui_caller: Callable) -> Resul
|
||||||
User explicitly wants a random ticket.
|
User explicitly wants a random ticket.
|
||||||
The reason this is in GUI repo, is because use_a_ticket is.
|
The reason this is in GUI repo, is because use_a_ticket is.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
random_ticket_result = get_a_random_ticket()
|
random_ticket_result = get_a_random_ticket()
|
||||||
|
|
||||||
if not random_ticket_result.valid:
|
if not random_ticket_result.valid:
|
||||||
|
|
@ -55,8 +67,16 @@ def random_ticket_dispatch(profile_id: int, passed_ui_caller: Callable) -> Resul
|
||||||
if not which_ticket:
|
if not which_ticket:
|
||||||
Result(valid=False, error_type=ResultError.NO_TICKET, message="No tickets left. Would you like to get some?")
|
Result(valid=False, error_type=ResultError.NO_TICKET, message="No tickets left. Would you like to get some?")
|
||||||
|
|
||||||
# calls GUI repo function:
|
# thread work that calls the caller, not return:
|
||||||
return use_a_ticket(profile_id=profile_id, which_ticket=which_ticket, ui_caller=passed_ui_caller)
|
take_action(
|
||||||
|
action=use_ticket_orchestrator,
|
||||||
|
ui_caller=passed_ui_caller,
|
||||||
|
profile_id=profile_id,
|
||||||
|
which_ticket=which_ticket,
|
||||||
|
connection_observer=connection_observer,
|
||||||
|
ticket_observer=ticket_observer
|
||||||
|
)
|
||||||
|
return Result(valid=True)
|
||||||
|
|
||||||
|
|
||||||
@type_checker
|
@type_checker
|
||||||
|
|
@ -79,25 +99,44 @@ def dispatch_ticketing(profile_id: int, passed_ui_caller: Callable) -> Result:
|
||||||
return navigate_to_new_sub_page()
|
return navigate_to_new_sub_page()
|
||||||
|
|
||||||
|
|
||||||
def start_ticket(ui_caller: Callable) -> Result:
|
def start_ticket(ui_caller: Callable):
|
||||||
|
"""Start the entire billing cycle for tickets"""
|
||||||
logger.info("started ticketing billing state")
|
logger.info("started ticketing billing state")
|
||||||
notification = "Started Ticket Billing"
|
notification = "Started Ticket Billing"
|
||||||
Notifications.emit(EventType.STATUS_UPDATE, notification)
|
Notifications.emit(EventType.STATUS_UPDATE, notification)
|
||||||
return take_action(
|
take_action(
|
||||||
action=start_new_payment_cycle,
|
action=start_new_payment_cycle,
|
||||||
category=PaymentCategory.TICKET,
|
category=PaymentCategory.TICKET,
|
||||||
ui_caller=ui_caller
|
ui_caller=ui_caller
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def fetch_ticket_invoice(ui_caller: Callable) -> str | None:
|
def fetch_ticket_invoice(ui_caller: Callable):
|
||||||
return take_action(
|
"""Fetch the invoice for tickets"""
|
||||||
|
take_action(
|
||||||
action=get_ticket_invoice,
|
action=get_ticket_invoice,
|
||||||
ui_caller=ui_caller,
|
ui_caller=ui_caller,
|
||||||
connection_observer=connection_observer
|
connection_observer=connection_observer
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def start_bulk_ticket_prep(ui_caller: Callable) -> Result:
|
||||||
|
"""After paid for, start the actual math"""
|
||||||
|
ticket_cycle = TicketPaymentData()
|
||||||
|
how_many_profiles = ticket_cycle.how_many_profiles
|
||||||
|
|
||||||
|
return take_action(
|
||||||
|
action=prepare_tickets,
|
||||||
|
ui_caller=ui_caller,
|
||||||
|
how_many_profiles=how_many_profiles,
|
||||||
|
connection_observer=connection_observer,
|
||||||
|
ticket_observer=ticket_observer,
|
||||||
|
which_ticket=None,
|
||||||
|
billing_code=None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_ticket_data() -> Result:
|
def get_ticket_data() -> Result:
|
||||||
"""This is running in the background ALREADY. Get & format a list of unused tickets from core"""
|
"""This is running in the background ALREADY. Get & format a list of unused tickets from core"""
|
||||||
|
|
||||||
|
|
@ -120,78 +159,14 @@ def get_ticket_data() -> Result:
|
||||||
return Result(valid=True, data=formatted_data)
|
return Result(valid=True, data=formatted_data)
|
||||||
|
|
||||||
|
|
||||||
def use_a_ticket(profile_id: int, which_ticket: int, ui_caller: Callable) -> str | None:
|
|
||||||
"""Coordinate the use of a given ticket. Returns a string on error, or None on success"""
|
|
||||||
|
|
||||||
try:
|
def use_a_ticket(profile_id: int, which_ticket: int, ui_caller: Callable):
|
||||||
profile = ProfileController.get(int(profile_id))
|
"""Use of a given ticket."""
|
||||||
except Exception as e:
|
take_action(
|
||||||
return f"The selected profile of {str(profile_id)} is either malformed or missing. {str(e)}"
|
action=use_ticket_orchestrator,
|
||||||
|
ui_caller=ui_caller,
|
||||||
which_location = profile.location.id
|
profile_id=profile_id,
|
||||||
protocol_choice = profile.connection.code
|
|
||||||
|
|
||||||
PRE_REQS = [profile, which_ticket, which_location, protocol_choice, ui_caller]
|
|
||||||
if None in PRE_REQS:
|
|
||||||
return "You are missing one of the pre-reqs to use a ticket."
|
|
||||||
|
|
||||||
ticket_user = TicketUser(
|
|
||||||
actual_profile=profile,
|
|
||||||
which_ticket=which_ticket,
|
which_ticket=which_ticket,
|
||||||
ui_caller=ui_caller
|
ticket_observer=ticket_observer,
|
||||||
|
connection_observer=connection_observer
|
||||||
)
|
)
|
||||||
ticket_user.begin_thread()
|
|
||||||
return None # no error
|
|
||||||
|
|
||||||
|
|
||||||
class TicketUser():
|
|
||||||
actual_profile: Profile
|
|
||||||
which_ticket: int
|
|
||||||
ui_caller: Callable
|
|
||||||
|
|
||||||
def begin_thread(self):
|
|
||||||
"""Step 1, begin a background thread with use"""
|
|
||||||
notification = "Using Ticket.."
|
|
||||||
Notifications.emit(EventType.STATUS_UPDATE, notification)
|
|
||||||
take_action(
|
|
||||||
action=use_ticket,
|
|
||||||
ui_caller=self.apply_code,
|
|
||||||
which_location=self.which_location,
|
|
||||||
protocol_choice=self.protocol_choice,
|
|
||||||
ticket_observer=ticket_observer,
|
|
||||||
connection_observer=connection_observer,
|
|
||||||
)
|
|
||||||
|
|
||||||
def apply_code(self, result: Result):
|
|
||||||
"""Step 2. Check if it worked. If so, apply it"""
|
|
||||||
|
|
||||||
if not result.valid:
|
|
||||||
logger.error("Use failed, returning to UI layer..")
|
|
||||||
self.ui_caller(result)
|
|
||||||
|
|
||||||
subscription = result.data
|
|
||||||
if not subscription:
|
|
||||||
logger.error("Use of ticket gave a blank subscription, returning to UI layer..")
|
|
||||||
self.ui_caller(result)
|
|
||||||
|
|
||||||
# core saves it:
|
|
||||||
logger.info("saving subscription..")
|
|
||||||
saved = save_subscription(profile=self.actual_profile, subscription=subscription)
|
|
||||||
if not saved:
|
|
||||||
error_msg = "Could not save the subscription"
|
|
||||||
logger.error(error_msg)
|
|
||||||
new_result = Result(valid=False, error_type=ResultError.FILE_SYSTEM, message=error_msg)
|
|
||||||
self.ui_caller(new_result)
|
|
||||||
|
|
||||||
logger.info("Saved sub, returning to UI layer..")
|
|
||||||
self.ui_caller(result)
|
|
||||||
|
|
||||||
|
|
||||||
@register_action(ResultError.TICKET_EXPIRED)
|
|
||||||
def wipe_ticket_billing() -> Result:
|
|
||||||
"""Wipe existing data and start over."""
|
|
||||||
wiped = wipe_ticket_cycle()
|
|
||||||
if wiped.valid:
|
|
||||||
return Result(valid=True, error_type=ResultError.NAVIGATE_TO, navigate_to="plan_picker")
|
|
||||||
else:
|
|
||||||
return Result(valid=False, error_type=ResultError.NAVIGATE_TO, navigate_to="plan_picker")
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ from gui.v2.actions.menu_tasks import enable_profile
|
||||||
from gui.v2.infrastructure.setup_observers import ticket_observer
|
from gui.v2.infrastructure.setup_observers import ticket_observer
|
||||||
from gui.v2.ui.pages.Page import Page
|
from gui.v2.ui.pages.Page import Page
|
||||||
from gui.v2.infrastructure.take_plumbing_action import take_action
|
from gui.v2.infrastructure.take_plumbing_action import take_action
|
||||||
from gui.v2.actions.ticket_actions import get_ticket_data
|
from gui.v2.actions.ticket_actions import get_ticket_data, use_a_ticket
|
||||||
|
|
||||||
# Bring background threads to the main thread UI:
|
# Bring background threads to the main thread UI:
|
||||||
from gui.v2.infrastructure.ThreadSafetyTool import ThreadSafetyTool
|
from gui.v2.infrastructure.ThreadSafetyTool import ThreadSafetyTool
|
||||||
|
|
@ -125,17 +125,14 @@ class TicketOrBillingChoicePage(Page):
|
||||||
self.update_status.update_status("Can not find the correct profile id")
|
self.update_status.update_status("Can not find the correct profile id")
|
||||||
return
|
return
|
||||||
|
|
||||||
error_msg = use_a_ticket(profile_id=profile_id, which_ticket=which_ticket, ui_caller=self.recieve_use_result)
|
use_a_ticket(profile_id=profile_id, which_ticket=which_ticket, ui_caller=self.recieve_use_result)
|
||||||
if error_msg:
|
self.update_status.update_status(f"Using ticket #{which_ticket}...")
|
||||||
self.show_a_popup(str(error_msg))
|
|
||||||
else:
|
|
||||||
self.update_status.update_status(f"Using ticket #{which_ticket}...")
|
|
||||||
|
|
||||||
|
|
||||||
def recieve_use_result(self, result: Result):
|
def recieve_use_result(self, result: Result):
|
||||||
"""Recieves the callback from gui_uses_ticket"""
|
"""Recieves the callback from gui_uses_ticket"""
|
||||||
|
|
||||||
if not result:
|
if not result or not isinstance(result, Result):
|
||||||
self.show_a_popup("This is a developer error, the use of the ticket failed to produce a result object")
|
self.show_a_popup("This is a developer error, the use of the ticket failed to produce a result object")
|
||||||
|
|
||||||
if not result.valid:
|
if not result.valid:
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
from PyQt6.QtWidgets import QLabel, QPushButton
|
from core.models.Result import Result, ResultError
|
||||||
from PyQt6 import QtCore
|
|
||||||
|
|
||||||
|
from gui.v2.actions.ticket_actions import start_bulk_ticket_prep
|
||||||
|
from gui.v2.ui.styles.css.ticket_billing_styles import TICKET_TERMINAL_STYLE, TICKET_TERMINAL_STYLE_SHEET
|
||||||
from gui.v2.infrastructure.setup_observers import ticket_observer
|
from gui.v2.infrastructure.setup_observers import ticket_observer
|
||||||
from gui.v2.actions.menu_tasks import enable_profile
|
from gui.v2.actions.menu_tasks import enable_profile
|
||||||
from gui.v2.ui.pages.Page import Page
|
from gui.v2.ui.pages.Page import Page
|
||||||
from gui.v2.ui.widgets.terminal_widget import TerminalWidget
|
from gui.v2.ui.widgets.terminal_widget import TerminalWidget
|
||||||
from gui.v2.workers.ticketing_worker_thread import TicketingWorkerThread
|
# from gui.v2.workers.ticketing_worker_thread import TicketingWorkerThread
|
||||||
|
|
||||||
|
from PyQt6.QtWidgets import QLabel, QPushButton
|
||||||
|
from PyQt6 import QtCore
|
||||||
|
|
||||||
|
|
||||||
HOW_MANY_PROFILES_DEFAULT = 6
|
HOW_MANY_PROFILES_DEFAULT = 6
|
||||||
|
|
@ -18,7 +22,10 @@ class TicketPrepPage(Page):
|
||||||
self.worker = None
|
self.worker = None
|
||||||
self._terminal_bound = False
|
self._terminal_bound = False
|
||||||
self._tickets_ready = False
|
self._tickets_ready = False
|
||||||
|
self.setup_initial_layout()
|
||||||
|
self.start_prep()
|
||||||
|
|
||||||
|
def setup_initial_layout(self):
|
||||||
self.title.setText("Preparing Tickets")
|
self.title.setText("Preparing Tickets")
|
||||||
self.title.setGeometry(QtCore.QRect(280, 20, 240, 40))
|
self.title.setGeometry(QtCore.QRect(280, 20, 240, 40))
|
||||||
self.title.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
self.title.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||||
|
|
@ -28,18 +35,12 @@ class TicketPrepPage(Page):
|
||||||
|
|
||||||
self.status_label = QLabel("", self)
|
self.status_label = QLabel("", self)
|
||||||
self.status_label.setGeometry(20, 460, 760, 30)
|
self.status_label.setGeometry(20, 460, 760, 30)
|
||||||
self.status_label.setStyleSheet("color: #00ffff; font-size: 14px;")
|
self.status_label.setStyleSheet(TICKET_TERMINAL_STYLE_SHEET)
|
||||||
self.status_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
self.status_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||||
|
|
||||||
self.continue_button = QPushButton("Continue", self)
|
self.continue_button = QPushButton("Continue", self)
|
||||||
self.continue_button.setGeometry(340, 490, 120, 35)
|
self.continue_button.setGeometry(340, 490, 120, 35)
|
||||||
self.continue_button.setStyleSheet("""
|
self.continue_button.setStyleSheet(TICKET_TERMINAL_STYLE)
|
||||||
QPushButton {
|
|
||||||
background-color: #2ecc71; color: white; border: none;
|
|
||||||
border-radius: 5px; font-size: 14px; font-weight: bold;
|
|
||||||
}
|
|
||||||
QPushButton:disabled { background-color: #555555; }
|
|
||||||
""")
|
|
||||||
self.continue_button.setEnabled(True)
|
self.continue_button.setEnabled(True)
|
||||||
self.continue_button.clicked.connect(self.on_continue)
|
self.continue_button.clicked.connect(self.on_continue)
|
||||||
|
|
||||||
|
|
@ -61,60 +62,79 @@ class TicketPrepPage(Page):
|
||||||
self.status_label.setText("Preparing tickets...")
|
self.status_label.setText("Preparing tickets...")
|
||||||
self.update_status.update_status("Preparing tickets...")
|
self.update_status.update_status("Preparing tickets...")
|
||||||
|
|
||||||
self.worker = TicketingWorkerThread('PREPARE_TICKETS', params={
|
# Actually Start it:
|
||||||
'how_many_profiles': HOW_MANY_PROFILES_DEFAULT,
|
start_bulk_ticket_prep(ui_caller=self.on_prep_done)
|
||||||
})
|
|
||||||
self.worker.prep_done.connect(self.on_prep_done)
|
|
||||||
self.worker.error.connect(self.on_error)
|
|
||||||
self.worker.start()
|
|
||||||
|
|
||||||
def on_prep_done(self, result):
|
def on_prep_done(self, result: Result):
|
||||||
if not isinstance(result, dict):
|
|
||||||
self.terminal.append("ERROR: invalid result format.")
|
|
||||||
self.status_label.setText("Preparation failed.")
|
|
||||||
return
|
|
||||||
if result.get('valid') is True:
|
|
||||||
self._tickets_ready = True
|
|
||||||
self.update_status.clear_ticket_verification_failure()
|
|
||||||
self.terminal.append("=== Ticket preparation complete ===")
|
|
||||||
self.status_label.setText("Tickets ready. Click Continue to apply one to your profile.")
|
|
||||||
self.update_status.update_status("Tickets ready.")
|
|
||||||
self.continue_button.setEnabled(True)
|
|
||||||
else:
|
|
||||||
msg = result.get('message', 'failed')
|
|
||||||
self.terminal.append(f"ERROR: {msg}")
|
|
||||||
if msg == 'verification_failed':
|
|
||||||
how_many_failed = result.get('how_many_failed', '?')
|
|
||||||
failed_validations = result.get('failed_validations', [])
|
|
||||||
self.terminal.append(f" failed count: {how_many_failed}")
|
|
||||||
self.terminal.append(f" failed indices: {failed_validations}")
|
|
||||||
if self.update_status.save_ticket_verification_failure(result):
|
|
||||||
self.terminal.append("Recovery data saved. Open Settings > Tickets to evaluate or resume.")
|
|
||||||
self.status_label.setText("Verification failed. Open Settings > Tickets for recovery.")
|
|
||||||
self.update_status.update_status("Ticket verification failed")
|
|
||||||
self.continue_button.setEnabled(True)
|
|
||||||
return
|
|
||||||
self.status_label.setText(f"Preparation failed: {msg}")
|
|
||||||
self.update_status.update_status(f"An error occurred")
|
|
||||||
self.continue_button.setEnabled(True)
|
|
||||||
|
|
||||||
def on_error(self, msg):
|
|
||||||
self.terminal.append(f"EXCEPTION: {msg}")
|
|
||||||
self.status_label.setText(f"An unknown error occured")
|
|
||||||
self.continue_button.setEnabled(True)
|
self.continue_button.setEnabled(True)
|
||||||
|
|
||||||
|
if not result or not isinstance(result, Result):
|
||||||
|
self.terminal.append("Results returned to the graphical display in an invalid format.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if result.valid:
|
||||||
|
self.terminal.append("=== Ticket preparation complete ===")
|
||||||
|
self.status_label.setText("Tickets ready. Click Continue to continue to the main page.")
|
||||||
|
self.update_status.update_status("Tickets ready.")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.terminal.append("Recovery data saved. Open Settings > Tickets to evaluate or resume.")
|
||||||
|
self.status_label.setText("Verification failed. Open Settings > Tickets for recovery.")
|
||||||
|
self.update_status.update_status("Ticket verification failed")
|
||||||
|
|
||||||
def on_continue(self):
|
def on_continue(self):
|
||||||
menu_page = self.custom_window.navigator.get_cached("menu")
|
self.custom_window.navigator.navigate("menu")
|
||||||
profile_id = getattr(self.update_status, 'current_profile_id', None)
|
|
||||||
if menu_page:
|
|
||||||
self.custom_window.navigator.navigate("menu")
|
|
||||||
if not self._tickets_ready:
|
|
||||||
self.update_status.update_status("Ticket preparation was not completed.")
|
|
||||||
return
|
|
||||||
if profile_id is None or menu_page is None:
|
|
||||||
self.update_status.update_status("Tickets ready. Random ticket use is ON.")
|
# self.status_label.setText("Preparation failed.")
|
||||||
return
|
# if not isinstance(result, dict):
|
||||||
self.update_status.update_status("Applying random ticket to profile...")
|
# self.terminal.append("ERROR: invalid result format.")
|
||||||
self.profile_enable_worker = enable_profile(
|
# return
|
||||||
{'id': int(profile_id)}, menu_page.handle_task_result, allow_uninstalled_tor=True,
|
|
||||||
)
|
# if result.get('valid') is True:
|
||||||
|
# self._tickets_ready = True
|
||||||
|
# self.update_status.clear_ticket_verification_failure()
|
||||||
|
# else:
|
||||||
|
# msg = result.get('message', 'failed')
|
||||||
|
# self.terminal.append(f"ERROR: {msg}")
|
||||||
|
# if msg == 'verification_failed':
|
||||||
|
# how_many_failed = result.get('how_many_failed', '?')
|
||||||
|
# failed_validations = result.get('failed_validations', [])
|
||||||
|
# self.terminal.append(f" failed count: {how_many_failed}")
|
||||||
|
# self.terminal.append(f" failed indices: {failed_validations}")
|
||||||
|
# if self.update_status.save_ticket_verification_failure(result):
|
||||||
|
|
||||||
|
# self.terminal.append("Recovery data saved. Open Settings > Tickets to evaluate or resume.")
|
||||||
|
# self.status_label.setText("Verification failed. Open Settings > Tickets for recovery.")
|
||||||
|
# self.update_status.update_status("Ticket verification failed")
|
||||||
|
# self.continue_button.setEnabled(True)
|
||||||
|
# return
|
||||||
|
# self.status_label.setText(f"Preparation failed: {msg}")
|
||||||
|
# self.update_status.update_status(f"An error occurred")
|
||||||
|
# self.continue_button.setEnabled(True)
|
||||||
|
|
||||||
|
# def on_error(self, msg):
|
||||||
|
# self.terminal.append(f"EXCEPTION: {msg}")
|
||||||
|
# self.status_label.setText(f"An unknown error occured")
|
||||||
|
# self.continue_button.setEnabled(True)
|
||||||
|
|
||||||
|
# def on_continue(self):
|
||||||
|
# menu_page = self.custom_window.navigator.get_cached("menu")
|
||||||
|
# profile_id = getattr(self.update_status, 'current_profile_id', None)
|
||||||
|
# if menu_page:
|
||||||
|
# self.custom_window.navigator.navigate("menu")
|
||||||
|
# if not self._tickets_ready:
|
||||||
|
# self.update_status.update_status("Ticket preparation was not completed.")
|
||||||
|
# return
|
||||||
|
# if profile_id is None or menu_page is None:
|
||||||
|
# self.update_status.update_status("Tickets ready. Random ticket use is ON.")
|
||||||
|
# return
|
||||||
|
# self.update_status.update_status("Applying random ticket to profile...")
|
||||||
|
# self.profile_enable_worker = enable_profile(
|
||||||
|
# {'id': int(profile_id)}, menu_page.handle_task_result, allow_uninstalled_tor=True,
|
||||||
|
# )
|
||||||
|
|
|
||||||
|
|
@ -27,4 +27,15 @@ USE_BILLING_BUTTON_STYLE = """
|
||||||
font-size: 14px; font-weight: bold;
|
font-size: 14px; font-weight: bold;
|
||||||
}
|
}
|
||||||
QPushButton:hover { background-color: #003333; }
|
QPushButton:hover { background-color: #003333; }
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
TICKET_TERMINAL_STYLE = """
|
||||||
|
QPushButton {
|
||||||
|
background-color: #2ecc71; color: white; border: none;
|
||||||
|
border-radius: 5px; font-size: 14px; font-weight: bold;
|
||||||
|
}
|
||||||
|
QPushButton:disabled { background-color: #555555; }
|
||||||
|
"""
|
||||||
|
|
||||||
|
TICKET_TERMINAL_STYLE_SHEET = "color: #00ffff; font-size: 14px;"
|
||||||
Loading…
Reference in a new issue