diff --git a/gui/__main__.py b/gui/__main__.py index e0ba2ce..a8a1285 100644 --- a/gui/__main__.py +++ b/gui/__main__.py @@ -48,7 +48,7 @@ profile_observer = ProfileObserver() class WorkerThread(QThread): text_output = pyqtSignal(str) sync_output = pyqtSignal(list, bool, bool, list, bool) - invoice_output = pyqtSignal(dict, str) + invoice_output = pyqtSignal(object, str) invoice_finished = pyqtSignal(bool) profiles_output = pyqtSignal(dict) special_output = pyqtSignal(str) @@ -95,6 +95,24 @@ class WorkerThread(QThread): 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...") @@ -106,6 +124,7 @@ class WorkerThread(QThread): 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...") @@ -214,7 +233,6 @@ class WorkerThread(QThread): ConfigurationController.set_connection('system') ClientController.sync(client_observer=client_observer, connection_observer=connection_observer) locations = LocationController.get_all() - print(f'locations: {locations}') all_location_codes = [location.country_name for location in locations] self.sync_output.emit(all_location_codes, True, False, locations, False) except Exception as e: @@ -275,29 +293,17 @@ class WorkerThread(QThread): self.text_output.emit('An unknown error occurred') self.invoice_finished.emit(False) - def _get_billing_details(self, invoice, currency_code): - for payment_method in invoice.payment_methods: - if payment_method.code == currency_code: - return { - 'billing_code': invoice.billing_code, - 'due_amount': payment_method.due, - 'address': payment_method.address - } - - return f"Payment method for currency '{currency_code}' not found." - def handle_connection_events(self, event): self.text_output.emit(f'Profile disabled') - def handle_event(self, event, currency): + def handle_event(self, event, currency=None): invoice = event.subject - billing_details = self._get_billing_details(invoice, currency) - if isinstance(billing_details, dict): - self.invoice_output.emit(billing_details, '') + if isinstance(invoice, object): + self.invoice_output.emit(invoice, '') self.text_output.emit("Invoice generated. Awaiting payment...") else: - self.text_output.emit("No payment method found for the selected currency.") + self.text_output.emit("Invalid invoice data received.") class CustomWindow(QMainWindow): @@ -507,7 +513,6 @@ class CustomWindow(QMainWindow): self.animation_timer = QTimer() self.animation_timer.timeout.connect(self.animate_toggle) - # Create background self.toggle_bg = QLabel(self.toggle_button) self.toggle_bg.setGeometry(0, 0, 50, 22) @@ -521,14 +526,12 @@ class CustomWindow(QMainWindow): } """) - # Create ON/OFF labels self.on_label = QLabel("ON", self.toggle_button) self.on_label.setGeometry(8, 4, 15, 14) self.off_label = QLabel("OFF", self.toggle_button) self.off_label.setGeometry(25, 4, 40, 14) - # Apply colors self._update_toggle_colors(colors) if is_tor_mode: self.set_tor_icon() @@ -1022,13 +1025,14 @@ class Worker(QObject): self.update_signal.emit("Application version file integrity could not be verified.", False, None, None, None) except ProfileModificationError: self.update_signal.emit("WireGuard configuration could not be attached.", False, None, None, None) - except OSError: - self.update_signal.emit("Connection could not be established.", False, None, None, None) + #except OSError: + # self.update_signal.emit("Connection could not be established.", False, None, None, None) except ProfileStateConflictError: self.update_signal.emit("The profile is already being enabled...", False, None, None, None) except CommandNotFoundError as e : self.update_signal.emit(str(e), False, -1, None, None) except Exception as e: + print(e) self.update_signal.emit("An unknown error occurred", False, None, None, None) else: @@ -4619,8 +4623,12 @@ class Settings(Page): if profile and hasattr(profile, 'subscription') and profile.subscription: try: self.subscription_info["billing_code"].setText(str(profile.subscription.billing_code)) - expires_at = profile.subscription.expires_at.strftime("%Y-%m-%d %H:%M:%S UTC") - self.subscription_info["expires_at"].setText(expires_at) + + if hasattr(profile.subscription, 'expires_at') and profile.subscription.expires_at: + expires_at = profile.subscription.expires_at.strftime("%Y-%m-%d %H:%M:%S UTC") + self.subscription_info["expires_at"].setText(expires_at) + else: + self.subscription_info["expires_at"].setText("Not available") except Exception as e: print(f"Error updating subscription info: {e}") else: @@ -5048,31 +5056,39 @@ class PaymentPage(Page): super().__init__("Payment", page_stack, main_window, parent) self.update_status = main_window self.text_fields = [] - + self.invoice_data = {} self.create_interface_elements() - - self.button_reverse.setVisible(True) - - def on_request_invoice(self): - selected_currency = self.get_selected_currency() + def fetch_invoice_duration(self): selected_time = self.get_selected_time_length() - if selected_currency: - self.currency = selected_currency - else: - self.update_status.update_status('No currency selected') - return duration_month_num = int(selected_time.split()[0]) if duration_month_num == 12: total_hours = 365 * 24 else: total_hours = duration_month_num * (30 * 24) + return total_hours + + + def check_invoice(self): + total_hours = self.fetch_invoice_duration() + if self.invoice_data and self.invoice_data['duration'] == total_hours: + self.update_status.update_status('Checking invoice status...') + self.check_invoice_status(self.invoice_data['billing_details'].billing_code) + else: + self.on_request_invoice() + + def on_request_invoice(self): + total_hours = self.fetch_invoice_duration() + selected_currency = self.get_selected_currency() + if selected_currency is None: + self.update_status.update_status('No currency selected') + return profile_data = { 'id': int(self.update_status.current_profile_id), 'duration': total_hours, - 'currency': 'xmr' if self.currency == 'monero' else 'btc' if self.currency == 'bitcoin' else 'btc-ln' if self.currency == 'lightning' else 'ltc' if self.currency == 'litecoin' else None + 'currency': 'xmr' if selected_currency == 'monero' else 'btc' if selected_currency == 'bitcoin' else 'btc-ln' if selected_currency == 'lightning' else 'ltc' if selected_currency == 'litecoin' else None } self.update_status.update_status('Generating Invoice...') self.worker_thread = WorkerThread('GET_SUBSCRIPTION', profile_data=profile_data) @@ -5083,13 +5099,57 @@ class PaymentPage(Page): def invoice_update_text_output(self, text): self.update_status.update_status(text) - if text == "No payment method found for the selected currency.": - for field in self.text_fields: - field.setText('') - else: - self.text_fields[3].setText(text) + self.text_fields[3].setText(text) - def on_invoice_generation_finished(self, billing_details: dict, text: str): + if 'No compatible' in text: + for line in self.text_fields: + line.setText('') + + + def store_invoice_data(self, billing_details: dict, duration: int): + self.invoice_data = { + 'billing_details': billing_details, + 'duration': duration + } + + def check_invoice_status(self, billing_code: str): + self.worker_thread = WorkerThread('CHECK_INVOICE_STATUS', profile_data={'billing_code': billing_code}) + self.worker_thread.invoice_finished.connect(self.on_invoice_status_finished) + self.worker_thread.start() + + def on_invoice_status_finished(self, result): + if result: + self.update_status.update_status('Invoice is still valid. Parsing invoice data...') + self.parse_invoice_data(self.invoice_data['billing_details']) + else: + self.update_status.update_status('Invoice has expired. Generating new invoice...') + self.on_request_invoice() + + def on_invoice_generation_finished(self, billing_details: object, text: str): + total_hours = self.fetch_invoice_duration() + self.store_invoice_data(billing_details, duration=total_hours) + self.parse_invoice_data(billing_details) + + + def parse_invoice_data(self, invoice_data: object): + currency = self.get_selected_currency() + billing_details = { + 'billing_code': invoice_data.billing_code + } + + if currency.lower() == 'lightning': + currency = 'Bitcoin Lightning' + preferred_method = next((pm for pm in invoice_data.payment_methods if pm.name.lower() == currency.lower()), None) + + + if preferred_method: + billing_details['due_amount'] = preferred_method.due + billing_details['address'] = preferred_method.address + else: + self.update_status.update_status('No payment method found for the selected currency.') + return + + billing_values = list(billing_details.values()) for i, dict_value in enumerate(billing_values): if i < 3: @@ -5103,11 +5163,10 @@ class PaymentPage(Page): else: self.text_fields[i].setProperty("fullText", str(dict_value)) self.text_fields[i].setText(str(dict_value)) - self.text_fields[3].setText(text) - def on_invoice_finished(self, result): if result: + self.invoice_data.clear() self.show_payment_confirmed(self.text_fields[0].text()) return self.update_status.update_status('An error occurred when generating invoice') @@ -5230,7 +5289,7 @@ class PaymentPage(Page): self.buttonGroup.addButton(boton, j) boton.setIcon(QIcon(os.path.join(self.btn_path, f"{icon_name}.png"))) #boton.clicked.connect(lambda _, func=function: func()) - boton.clicked.connect(self.on_request_invoice) + boton.clicked.connect(self.check_invoice) # Establecer la exclusividad de los botones