from PyQt6.QtWidgets import QLabel, QPushButton from PyQt6 import QtCore from gui.v2.infrastructure.setup_observers import ticket_observer from gui.v2.ui.pages.Page import Page from gui.v2.ui.widgets.terminal_widget import TerminalWidget from gui.v2.workers.ticketing_worker_thread import TicketingWorkerThread HOW_MANY_PROFILES_DEFAULT = 6 class TicketPrepPage(Page): def __init__(self, page_stack, main_window=None, parent=None): super().__init__("TicketPrep", page_stack, main_window, parent) self.update_status = main_window self.worker = None self._terminal_bound = False self._tickets_ready = False self.title.setText("Preparing Tickets") self.title.setGeometry(QtCore.QRect(280, 20, 240, 40)) self.title.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) self.terminal = TerminalWidget(self) self.terminal.setGeometry(20, 70, 760, 380) self.status_label = QLabel("", self) self.status_label.setGeometry(20, 460, 760, 30) self.status_label.setStyleSheet("color: #00ffff; font-size: 14px;") self.status_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) self.continue_button = QPushButton("Continue", self) self.continue_button.setGeometry(340, 490, 120, 35) self.continue_button.setStyleSheet(""" 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.clicked.connect(self.on_continue) def _bind_terminal_once(self): if self._terminal_bound: return self.terminal.bind_observer(ticket_observer, [ 'preparing', 'connecting', 'sync_done', 'waiting', 'paid', 'ticket_ready', 'used', 'failed_input', 'failed_output', 'connection_error', 'unknown_error', 'error', ]) self._terminal_bound = True def start_prep(self): self._bind_terminal_once() self.terminal.append("=== Starting ticket preparation ===") self._tickets_ready = False self.continue_button.setEnabled(True) self.status_label.setText("Preparing tickets...") self.update_status.update_status("Preparing tickets...") self.worker = TicketingWorkerThread('PREPARE_TICKETS', params={ 'how_many_profiles': HOW_MANY_PROFILES_DEFAULT, }) 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): 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 unkown 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...") menu_page.enabling_profile({'id': int(profile_id)})