import requests import sys from core.Constants import Constants from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QComboBox, QPushButton, QSizePolicy, QListWidget, QHBoxLayout from PyQt6.QtGui import QColor, QPalette, QFont from PyQt6.QtCore import Qt, QTimer class MyWindow(QWidget): def __init__(self): super().__init__() # Create Constants instance self.constants = Constants() # Set window title self.setWindowTitle("Debug Helper") self.setFixedSize(800, 600) # Set fixed size # Set the background color to black palette = QPalette() palette.setColor(QPalette.ColorRole.Window, QColor(0, 0, 0)) self.setPalette(palette) label_style = "font-size: 20px; color: white;" # Create a label with white text self.label_for_debug_one = QLabel("Pick from the dropbown which SYSTEM-WIDE profile to debug", self) self.label_for_debug_one.setStyleSheet(label_style) self.label_for_debug_one.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) # Expanding vertical size policy self.combo_box = QComboBox() self.combo_box.addItems(["Profile 1", "Profile 2", "Profile 3"]) self.combo_box.currentIndexChanged.connect(self.on_combobox_changed) # Set a larger font for the QComboBox font = QFont() font.setPointSize(16) # Set the font size to 16 self.combo_box.setFont(font) # Create a label with white text self.label_for_debug_two = QLabel("Selected: Profile Slot 1", self) self.label_for_debug_two.setStyleSheet(label_style) self.label_for_debug_two.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) # Expanding vertical size policy # Create a button: self.button_for_debug = QPushButton("Ok") self.button_for_debug.setStyleSheet("font-size: 20px; padding: 15px; background-color: green; color: yellow;") # Set background and text color self.button.clicked.connect(self.show_selected) self.button_for_debug.clicked.connect(self.first_debug_button_clicked) # Set up the layout self.layout = QVBoxLayout() self.layout.addWidget(self.label_for_debug_one) self.layout.addWidget(self.combo_box) self.layout.addWidget(self.label_for_debug_two) self.layout.addWidget(self.button_for_debug) self.setLayout(self.layout) def on_combobox_changed(self, index): selected_option = self.combo_box.itemText(index) self.label_for_debug_two.setText(f"Selected: {selected_option}") def get_endpoint_ip(self, file_path): with open(file_path, 'r') as file: for line in file: if line.startswith("Endpoint"): # Split the line and get the IP address part return line.split('=')[1].strip().split(':')[0] # Get the IP before the colon return None # Return None if no match is found def first_debug_button_clicked(self): # clear the page: for i in reversed(range(self.layout.count())): item = self.layout.itemAt(i) if item is not None: widget = item.widget() if widget is not None: widget.deleteLater() # Which Profile: index = self.combo_box.currentIndex() # Get the current index selected_option = self.combo_box.itemText(index) # Get the selected item self.last_character = selected_option[-1] ip_address = self.get_endpoint_ip(f'{self.constants.HV_PROFILE_CONFIG_HOME}/{self.last_character}/wg.conf.bak') print(f"WG Node's IP address is: {ip_address}") # Create a label to display the IP: label_style = "font-size: 20px; color: white;" self.label_for_debug_three = QLabel(f"Step 1, Can you Ping it? Copy-paste the command below into your terminal. This VPN Node's IP address is {ip_address}") self.label_for_debug_three.setStyleSheet(label_style) self.label_for_debug_three.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) self.label_for_debug_three.setWordWrap(True) # Enable word wrapping self.label_for_debug_three.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop) self.layout.addWidget(self.label_for_debug_three) # Create copy-paste for ping button: self.button_for_copy_paste_ping = QPushButton("Copy-paste this ping command") self.button_for_copy_paste_ping.setStyleSheet("font-size: 20px; padding: 15px; background-color: green; color: yellow;") self.button_for_copy_paste_ping.clicked.connect(lambda: self.copy_paste_command(self.ping_command)) self.layout.addWidget(self.button_for_copy_paste_ping) # create a box to show the ping command: self.ping_command = f"ping {ip_address}" self.label_for_ping_debug = QLabel(self.ping_command) self.label_for_ping_debug.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) # Expanding vertical size policy self.label_for_ping_debug.setStyleSheet("background-color: white; color: black; font-size: 30px;") self.label_for_ping_debug.setFixedWidth(700) self.label_for_ping_debug.setMaximumHeight(100) self.layout.addWidget(self.label_for_ping_debug) self.horizontal_layout_of_bottom_menu = QHBoxLayout() # Create yes button: self.button_for_yes_that_worked = QPushButton("Yes, that worked") self.button_for_yes_that_worked.setStyleSheet("font-size: 20px; padding: 15px; background-color: green; color: yellow;") self.button_for_yes_that_worked.clicked.connect(self.run_CLI_version) self.horizontal_layout_of_bottom_menu.addWidget(self.button_for_yes_that_worked) # Create no button: self.button_for_no = QPushButton("Nope, didn't work") self.button_for_no.setStyleSheet("font-size: 20px; padding: 15px; background-color: red; color: black;") self.button_for_no.clicked.connect(self.see_if_its_down) self.horizontal_layout_of_bottom_menu.addWidget(self.button_for_no) # add the whole horizonal bottom menu layout to the main one: self.layout.addLayout(self.horizontal_layout_of_bottom_menu) def copy_paste_command(self, insert_data): clipboard = QApplication.clipboard() clipboard.setText(insert_data) def see_if_its_down(self): # first, clear the page: for i in reversed(range(self.horizontal_layout_of_bottom_menu.count())): item = self.horizontal_layout_of_bottom_menu.itemAt(i) if item is not None: widget = item.widget() if widget is not None: widget.deleteLater() for i in reversed(range(self.layout.count())): item = self.layout.itemAt(i) if item is not None: widget = item.widget() if widget is not None: widget.deleteLater() label_style = "font-size: 40px; color: white;" self.label_for_debug_three = QLabel(f"Check if the location is down,") self.label_for_debug_three.setStyleSheet(label_style) self.label_for_debug_three.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) self.label_for_debug_three.setWordWrap(True) # Enable word wrapping self.label_for_debug_three.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop) self.layout.addWidget(self.label_for_debug_three) # create a box to show the website: self.status_website_url = 'https://status.simplifiedprivacy.is' self.label_for_website_url = QLabel(f"Website: {self.status_website_url}") self.label_for_website_url.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) # Expanding vertical size policy self.label_for_website_url.setStyleSheet("background-color: white; color: black; font-size: 30px;") self.label_for_website_url.setFixedWidth(700) self.label_for_website_url.setMaximumHeight(100) self.layout.addWidget(self.label_for_website_url) # Create copy-paste for status website button: self.button_to_fetch_downtime_api = QPushButton("Fetch it for me here (click ONCE and wait 10~ seconds)") self.button_to_fetch_downtime_api.setStyleSheet("font-size: 20px; padding: 15px; background-color: green; color: yellow;") self.button_to_fetch_downtime_api.clicked.connect(self.fetch_downtime_data) self.layout.addWidget(self.button_to_fetch_downtime_api) # Create copy-paste for status website button: self.button_for_copy_paste_status_website = QPushButton("Or Copy the URL to your clipboard") self.button_for_copy_paste_status_website.setStyleSheet("font-size: 20px; padding: 15px; background-color: yellow; color: black;") self.button_for_copy_paste_status_website.clicked.connect(lambda: self.copy_paste_command(self.status_website_url)) self.layout.addWidget(self.button_for_copy_paste_status_website) def run_CLI_version(self): # first, clear the page: for i in reversed(range(self.horizontal_layout_of_bottom_menu.count())): item = self.horizontal_layout_of_bottom_menu.itemAt(i) if item is not None: widget = item.widget() if widget is not None: widget.deleteLater() for i in reversed(range(self.layout.count())): item = self.layout.itemAt(i) if item is not None: widget = item.widget() if widget is not None: widget.deleteLater() # Create a label to display the IP: label_style = "font-size: 20px; color: white;" self.label_for_debug_four = QLabel(f"Step 2, Try to run the CLI version in your terminal. You'd need to know the path to the AppImage, and make sure the profile number at the end is correct. First slot is 1, second 2, ect.") self.label_for_debug_four.setStyleSheet(label_style) self.label_for_debug_four.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) self.label_for_debug_four.setWordWrap(True) # Enable word wrapping self.label_for_debug_four.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop) self.layout.addWidget(self.label_for_debug_four) # Create copy-paste for CLIng button: self.cli_command = f"./hydra-veil-x86_64.AppImage --cli profile enable -i {self.last_character}" self.button_for_copy_paste_cli = QPushButton("Copy to clipboard this CLI command") self.button_for_copy_paste_cli.setStyleSheet("font-size: 20px; padding: 15px; background-color: green; color: yellow;") self.button_for_copy_paste_cli.clicked.connect(lambda: self.copy_paste_command(self.cli_command)) self.layout.addWidget(self.button_for_copy_paste_cli) # create a box to show the CLI command: self.label_for_cli_debug = QLabel(self.cli_command) self.label_for_cli_debug.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) # Expanding vertical size policy self.label_for_cli_debug.setStyleSheet("background-color: white; color: black; font-size: 20px;") #self.label_for_cli_debug.setFixedWidth(700) self.label_for_cli_debug.setWordWrap(True) # Enable word wrapping self.label_for_cli_debug.setMaximumHeight(100) self.layout.addWidget(self.label_for_cli_debug) self.horizontal_layout_of_bottom_menu_two = QHBoxLayout() # Create yes button: self.button_for_yes_that_worked_two = QPushButton("Yes, that worked") self.button_for_yes_that_worked_two.setStyleSheet("font-size: 20px; padding: 15px; background-color: green; color: yellow;") self.button_for_yes_that_worked_two.clicked.connect(self.run_CLI_version_worked) self.horizontal_layout_of_bottom_menu_two.addWidget(self.button_for_yes_that_worked_two) # Create no button: self.button_for_no_two = QPushButton("Nope, didn't work") self.button_for_no_two.setStyleSheet("font-size: 20px; padding: 15px; background-color: red; color: black;") self.button_for_no_two.clicked.connect(self.run_wg_quick_raw) self.horizontal_layout_of_bottom_menu_two.addWidget(self.button_for_no_two) # add the whole horizonal bottom menu layout to the main one: self.layout.addLayout(self.horizontal_layout_of_bottom_menu_two) def run_CLI_version_worked(self): # first, clear the page: for i in reversed(range(self.horizontal_layout_of_bottom_menu_two.count())): item = self.horizontal_layout_of_bottom_menu_two.itemAt(i) if item is not None: widget = item.widget() if widget is not None: widget.deleteLater() for i in reversed(range(self.layout.count())): item = self.layout.itemAt(i) if item is not None: widget = item.widget() if widget is not None: widget.deleteLater() label_style = "font-size: 20px; color: white;" self.label_for_debug_five = QLabel(f"If the CLI worked, then let's try to isolate the GUI problem by running the GUI with terminal output. Please run the AppImage with the ./ in front of it. Then try in the GUI to enable your profile and share any errors with customer support.") self.label_for_debug_five.setStyleSheet(label_style) self.label_for_debug_five.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) self.label_for_debug_five.setWordWrap(True) # Enable word wrapping self.label_for_debug_five.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop) self.layout.addWidget(self.label_for_debug_five) # Create copy-paste for GUI in CLI button: self.gui_cli_debug_command = f"./hydra-veil-x86_64.AppImage" self.button_for_copy_paste_cli = QPushButton("Copy to clipboard this CLI command") self.button_for_copy_paste_cli.setStyleSheet("font-size: 20px; padding: 15px; background-color: green; color: yellow;") self.button_for_copy_paste_cli.clicked.connect(lambda: self.copy_paste_command(self.gui_cli_debug_command)) self.layout.addWidget(self.button_for_copy_paste_cli) # create a box to show the GUI in CLI command: self.label_for_gui_cli_debug = QLabel(self.gui_cli_debug_command) self.label_for_gui_cli_debug.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) # Expanding vertical size policy self.label_for_gui_cli_debug.setStyleSheet("background-color: white; color: black; font-size: 20px;") #self.label_for_cli_debug.setFixedWidth(700) self.label_for_gui_cli_debug.setWordWrap(True) # Enable word wrapping self.label_for_gui_cli_debug.setMaximumHeight(100) self.layout.addWidget(self.label_for_gui_cli_debug) def run_wg_quick_raw(self): # first, clear the page: for i in reversed(range(self.horizontal_layout_of_bottom_menu_two.count())): item = self.horizontal_layout_of_bottom_menu_two.itemAt(i) if item is not None: widget = item.widget() if widget is not None: widget.deleteLater() for i in reversed(range(self.layout.count())): item = self.layout.itemAt(i) if item is not None: widget = item.widget() if widget is not None: widget.deleteLater() label_style = "font-size: 20px; color: white;" self.label_for_debug_six = QLabel("Let's try connecting directly using your system's native wireguard commands (Any Wireguard config file would work, but the path laid out in this command (with /etc) is only for systemwide profiles).") self.label_for_debug_six.setStyleSheet(label_style) self.label_for_debug_six.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) self.label_for_debug_six.setWordWrap(True) # Enable word wrapping self.label_for_debug_six.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop) self.layout.addWidget(self.label_for_debug_six) # Create copy-paste for wg-quick CLI button: self.wg_quick_command_up_command = f"sudo wg-quick up '/etc/hydra-veil/profiles/{self.last_character}/wg.conf'" self.wg_quick_command_up = QPushButton("Copy to clipboard this wg-quick command") self.wg_quick_command_up.setStyleSheet("font-size: 20px; padding: 15px; background-color: green; color: yellow;") self.wg_quick_command_up.clicked.connect(lambda: self.copy_paste_command(self.wg_quick_command_up_command)) self.layout.addWidget(self.wg_quick_command_up) self.label_for_gui_cli_debug = QLabel(self.wg_quick_command_up_command) self.label_for_gui_cli_debug.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) # Expanding vertical size policy self.label_for_gui_cli_debug.setStyleSheet("background-color: white; color: black; font-size: 20px;") self.label_for_gui_cli_debug.setWordWrap(True) # Enable word wrapping self.label_for_gui_cli_debug.setMaximumHeight(100) self.layout.addWidget(self.label_for_gui_cli_debug) label_style = "font-size: 20px; color: white;" self.label_for_debug_seven = QLabel("Make sure the profile number is right in the folder path. If in doubt, you can 'cd' into that folder and check.") self.label_for_debug_seven.setStyleSheet(label_style) self.label_for_debug_seven.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) self.label_for_debug_seven.setWordWrap(True) # Enable word wrapping self.label_for_debug_seven.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop) self.layout.addWidget(self.label_for_debug_seven) self.label_for_how_to_cd_debug = QLabel("cd /etc/hydra-veil/profiles") self.label_for_how_to_cd_debug.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) # Expanding vertical size policy self.label_for_how_to_cd_debug.setStyleSheet("background-color: white; color: black; font-size: 20px;") self.label_for_how_to_cd_debug.setWordWrap(True) # Enable word wrapping self.label_for_how_to_cd_debug.setMaximumHeight(100) self.layout.addWidget(self.label_for_how_to_cd_debug) self.wg_quick_command_down_command = f"sudo wg-quick down '/etc/hydra-veil/profiles/{self.last_character}/wg.conf'" self.wg_quick_command_down = QPushButton("Copy to clipboard the DOWN version AFTER to END it") self.wg_quick_command_down.setStyleSheet("font-size: 20px; padding: 15px; background-color: green; color: yellow;") self.wg_quick_command_down.clicked.connect(lambda: self.copy_paste_command(self.wg_quick_command_down_command)) self.layout.addWidget(self.wg_quick_command_down) self.horizontal_layout_of_bottom_menu_two = QHBoxLayout() # Create yes button: self.button_for_yes_that_worked_two = QPushButton("Yes, that worked") self.button_for_yes_that_worked_two.setStyleSheet("font-size: 20px; padding: 15px; background-color: green; color: yellow;") self.button_for_yes_that_worked_two.clicked.connect(self.wg_quick_worked_but_not_CLI) self.horizontal_layout_of_bottom_menu_two.addWidget(self.button_for_yes_that_worked_two) # Create no button: self.button_for_no_two = QPushButton("Nope, didn't work") self.button_for_no_two.setStyleSheet("font-size: 20px; padding: 15px; background-color: red; color: black;") self.button_for_no_two.clicked.connect(self.change_the_port) self.horizontal_layout_of_bottom_menu_two.addWidget(self.button_for_no_two) # add the whole horizonal bottom menu layout to the main one: self.layout.addLayout(self.horizontal_layout_of_bottom_menu_two) def wg_quick_worked_but_not_CLI(self): # first, clear the page: for i in reversed(range(self.horizontal_layout_of_bottom_menu_two.count())): item = self.horizontal_layout_of_bottom_menu_two.itemAt(i) if item is not None: widget = item.widget() if widget is not None: widget.deleteLater() for i in reversed(range(self.layout.count())): item = self.layout.itemAt(i) if item is not None: widget = item.widget() if widget is not None: widget.deleteLater() label_style = "font-size: 20px; color: white;" self.label_for_debug_six = QLabel("So using Wireguard directly worked, but there must have been some compatibility issue with our software. Please report any CLI errors to customer support so we can assist you. Also, browser-only should now work once you got system-wide") self.label_for_debug_six.setStyleSheet(label_style) self.label_for_debug_six.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) self.label_for_debug_six.setWordWrap(True) # Enable word wrapping self.label_for_debug_six.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop) self.layout.addWidget(self.label_for_debug_six) def change_the_port(self): # first, clear the page: for i in reversed(range(self.horizontal_layout_of_bottom_menu_two.count())): item = self.horizontal_layout_of_bottom_menu_two.itemAt(i) if item is not None: widget = item.widget() if widget is not None: widget.deleteLater() for i in reversed(range(self.layout.count())): item = self.layout.itemAt(i) if item is not None: widget = item.widget() if widget is not None: widget.deleteLater() label_style = "font-size: 20px; color: white;" self.label_for_change_port = QLabel("Try to change the Port on the Wireguard config file. First edit it:") self.label_for_change_port.setStyleSheet(label_style) self.label_for_change_port.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) self.label_for_change_port.setWordWrap(True) # Enable word wrapping self.label_for_change_port.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop) self.layout.addWidget(self.label_for_change_port) self.nano_wg_conf_command = f"sudo nano /etc/hydra-veil/profiles/{self.last_character}/wg.conf" self.label_for_how_to_nano_wg_conf = QLabel(self.nano_wg_conf_command) self.label_for_how_to_nano_wg_conf.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) # Expanding vertical size policy self.label_for_how_to_nano_wg_conf.setStyleSheet("background-color: white; color: black; font-size: 20px;") self.label_for_how_to_nano_wg_conf.setWordWrap(True) # Enable word wrapping self.label_for_how_to_nano_wg_conf.setMaximumHeight(100) self.layout.addWidget(self.label_for_how_to_nano_wg_conf) self.nano_edit_copy_paste = QPushButton("Copy to clipboard the nano edit command") self.nano_edit_copy_paste.setStyleSheet("font-size: 20px; padding: 15px; background-color: green; color: yellow;") self.nano_edit_copy_paste.clicked.connect(lambda: self.copy_paste_command(self.nano_wg_conf_command)) self.layout.addWidget(self.nano_edit_copy_paste) self.label_for_change_port = QLabel("The port is located on the line with Endpoint = ") self.label_for_change_port.setStyleSheet(label_style) self.label_for_change_port.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) self.label_for_change_port.setWordWrap(True) # Enable word wrapping self.label_for_change_port.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop) self.layout.addWidget(self.label_for_change_port) self.label_for_endpoint_port = QLabel(f"Endpoint = :") self.label_for_endpoint_port.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) # Expanding vertical size policy self.label_for_endpoint_port.setStyleSheet("background-color: grey; color: black; font-size: 20px;") self.label_for_endpoint_port.setWordWrap(True) # Enable word wrapping self.label_for_endpoint_port.setMaximumHeight(100) self.layout.addWidget(self.label_for_endpoint_port) self.label_for_change_port_to_what = QLabel("Change it to either 48271 or 52428") self.label_for_change_port_to_what.setStyleSheet(label_style) self.label_for_change_port_to_what.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) self.label_for_change_port_to_what.setWordWrap(True) # Enable word wrapping self.label_for_change_port_to_what.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop) self.layout.addWidget(self.label_for_change_port_to_what) self.label_for_endpoint_port_with_change = QLabel(f"Endpoint = :48271") self.label_for_endpoint_port_with_change.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) # Expanding vertical size policy self.label_for_endpoint_port_with_change.setStyleSheet("background-color: grey; color: black; font-size: 20px;") self.label_for_endpoint_port_with_change.setWordWrap(True) # Enable word wrapping self.label_for_endpoint_port_with_change.setMaximumHeight(100) self.layout.addWidget(self.label_for_endpoint_port_with_change) def fetch_downtime_data(self): for i in reversed(range(self.layout.count())): item = self.layout.itemAt(i) if item is not None: widget = item.widget() if widget is not None: widget.deleteLater() api_url = 'https://status.simplifiedprivacy.is/api/nodes' try: response = requests.get(api_url) # Check if the request was successful response.raise_for_status() # Parse the JSON response downtime_list_as_json = response.json() if isinstance(downtime_list_as_json, dict): # Create a QVBoxLayout layout_two = QVBoxLayout() # Create a QLabel to display the dictionary colored_label = QLabel() # Build the HTML formatted string for the dictionary html_text = "" for key, value in downtime_list_as_json.items(): color = "green" if value == "up" else "red" # Create a larger font size html_text += f"{key}: {value}
" # Set the formatted text to the label colored_label.setText(html_text) # Add the label to the layout layout_two.addWidget(colored_label) self.layout.addLayout(layout_two) else: print("Data is not in the expected format.") # Print the JSON data to the terminal #print(json_data) except requests.exceptions.RequestException as e: print(f"An error occurred: {e}") if __name__ == "__main__": app = QApplication(sys.argv) window = MyWindow() window.resize(800, 600) # Set the window size window.show() sys.exit(app.exec())