04-06-2025_large_update #35
@@ -10,7 +10,7 @@ from subprocess import CompletedProcess, run
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
import tkinter as tk
 | 
			
		||||
from typing import Optional, Dict, Any, NoReturn, List
 | 
			
		||||
from typing import Optional, Dict, Any, NoReturn
 | 
			
		||||
import zipfile
 | 
			
		||||
from datetime import datetime
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
@@ -84,7 +84,7 @@ class CryptoUtil:
 | 
			
		||||
        Checks if the private key already exists in the system using an external script.
 | 
			
		||||
        Returns True only if the full key is found exactly (no partial match).
 | 
			
		||||
        """
 | 
			
		||||
        process: CompletedProcess[bool] = run(
 | 
			
		||||
        process: CompletedProcess[str] = run(
 | 
			
		||||
            ["pkexec", "/usr/local/bin/match_found.py", key],
 | 
			
		||||
            capture_output=True,
 | 
			
		||||
            text=True,
 | 
			
		||||
@@ -120,7 +120,8 @@ class CryptoUtil:
 | 
			
		||||
            decoded = base64.b64decode(key)
 | 
			
		||||
            if len(decoded) != 32:  # 32 bytes = 256 bits
 | 
			
		||||
                return False
 | 
			
		||||
        except Exception:
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            logging.error(f"Error on decode Base64: {e}", exc_info=True)
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        return True
 | 
			
		||||
@@ -158,7 +159,7 @@ class LxTools:
 | 
			
		||||
            geometry = monitor.get_geometry()
 | 
			
		||||
            scale_factor = monitor.get_scale_factor()
 | 
			
		||||
 | 
			
		||||
            # Calculate center position on primary monitor
 | 
			
		||||
            # Calculate center position on the primary monitor
 | 
			
		||||
            x = geometry.x + (geometry.width - width // scale_factor) // 2
 | 
			
		||||
            y = geometry.y + (geometry.height - height // scale_factor) // 2
 | 
			
		||||
 | 
			
		||||
@@ -196,14 +197,14 @@ class LxTools:
 | 
			
		||||
                primary_x = int(geometry[1])
 | 
			
		||||
                primary_y = int(geometry[2])
 | 
			
		||||
 | 
			
		||||
                # Calculate center position on primary monitor
 | 
			
		||||
                # Calculate center position on the primary monitor
 | 
			
		||||
                x = primary_x + (primary_width - width) // 2
 | 
			
		||||
                y = primary_y + (primary_height - height) // 2
 | 
			
		||||
 | 
			
		||||
                # Set window geometry
 | 
			
		||||
                window.geometry(f"{width}x{height}+{x}+{y}")
 | 
			
		||||
                return
 | 
			
		||||
        except (subprocess.SubprocessError, ImportError, IndexError, ValueError):
 | 
			
		||||
        except (ImportError, IndexError, ValueError):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
        # Final fallback: Use standard Tkinter method
 | 
			
		||||
@@ -215,7 +216,7 @@ class LxTools:
 | 
			
		||||
        if (
 | 
			
		||||
            screen_width > screen_height * 1.8
 | 
			
		||||
        ):  # Heuristic for detecting multiple monitors
 | 
			
		||||
            # Assume primary monitor is on the left half
 | 
			
		||||
            # Assume the primary monitor is on the left half
 | 
			
		||||
            screen_width = screen_width // 2
 | 
			
		||||
 | 
			
		||||
        x = (screen_width - width) // 2
 | 
			
		||||
@@ -223,7 +224,7 @@ class LxTools:
 | 
			
		||||
        window.geometry(f"{width}x{height}+{x}+{y}")
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def clean_files(TEMP_DIR: Path = None, file: Path = None) -> None:
 | 
			
		||||
    def clean_files(tmp_dir: Path = AppConfig.TEMP_DIR, file: Path = None) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Deletes temporary files and directories for cleanup when exiting the application.
 | 
			
		||||
 | 
			
		||||
@@ -231,34 +232,13 @@ class LxTools:
 | 
			
		||||
        and a single file to free up resources at the end of the program's execution.
 | 
			
		||||
        All operations are performed securely, and errors such as `FileNotFoundError`
 | 
			
		||||
        are ignored if the target files or directories do not exist.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            TEMP_DIR (Path, optional): Path to the temporary directory that should be deleted.
 | 
			
		||||
        :param tmp_dir: (Path, optional): Path to the temporary directory that should be deleted.
 | 
			
		||||
                If `None`, the value of `AppConfig.TEMP_DIR` is used.
 | 
			
		||||
            file (Path, optional): Path to the file that should be deleted.
 | 
			
		||||
        :param file: (Path, optional): Path to the file that should be deleted.
 | 
			
		||||
                If `None`, no additional file will be deleted.
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            None: The method does not return any value.
 | 
			
		||||
 | 
			
		||||
        Examples:
 | 
			
		||||
            - Without parameters:
 | 
			
		||||
            ```python
 | 
			
		||||
            Tooltip.clean_files()
 | 
			
		||||
            ```
 | 
			
		||||
            Deletes the temporary directory defined in the configuration (`AppConfig.TEMP_DIR`).
 | 
			
		||||
 | 
			
		||||
            - With an explicit file path:
 | 
			
		||||
            ```python
 | 
			
		||||
            Tooltip.clean_files(file=Path("temp/file.txt"))
 | 
			
		||||
            ```
 | 
			
		||||
            Deletes the file `file.txt`, if it exists, and ignores errors.
 | 
			
		||||
 | 
			
		||||
            - Both parameters:
 | 
			
		||||
            ```python
 | 
			
		||||
            Tooltip.clean(TEMP_DIR=Path("/tmp/data"), file=Path("log.txt"))
 | 
			
		||||
            ```
 | 
			
		||||
            Deletes the directory `/tmp/data` and the file `log.txt`, if they exist.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        if AppConfig.TEMP_DIR is not None:
 | 
			
		||||
@@ -282,8 +262,10 @@ class LxTools:
 | 
			
		||||
        """
 | 
			
		||||
        Creates message windows
 | 
			
		||||
 | 
			
		||||
        :argument AppConfig.IMAGE_PATHS["icon_info"] = Image for TK window which is displayed to the left of the text
 | 
			
		||||
        :argument AppConfig.IMAGE_PATHS["icon_vpn"] = Image for Task Icon
 | 
			
		||||
        :param image_path2:
 | 
			
		||||
        :param image_path:
 | 
			
		||||
         AppConfig.IMAGE_PATHS["icon_info"] = Image for TK window which is displayed to the left of the text
 | 
			
		||||
         AppConfig.IMAGE_PATHS["icon_vpn"] = Image for Task Icon
 | 
			
		||||
        :argument w_title = Windows Title
 | 
			
		||||
        :argument w_txt = Text for Tk Window
 | 
			
		||||
        :argument txt2 = Text for Button two
 | 
			
		||||
@@ -294,7 +276,7 @@ class LxTools:
 | 
			
		||||
        msg.title(w_title)
 | 
			
		||||
        msg.configure(pady=15, padx=15)
 | 
			
		||||
 | 
			
		||||
        # load first image for window
 | 
			
		||||
        # load first image for a window
 | 
			
		||||
        try:
 | 
			
		||||
            msg.img = tk.PhotoImage(file=image_path)
 | 
			
		||||
            msg.i_window = tk.Label(msg, image=msg.img)
 | 
			
		||||
@@ -394,7 +376,7 @@ class Tunnel:
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def parse_files_to_dictionary(
 | 
			
		||||
        directory: Path = None, filepath: str = None, content: str = None
 | 
			
		||||
    ) -> dict | str | None:
 | 
			
		||||
    ) -> tuple[dict, str] | dict | None:
 | 
			
		||||
        data = {}
 | 
			
		||||
 | 
			
		||||
        if filepath is not None:
 | 
			
		||||
@@ -530,7 +512,7 @@ class Tunnel:
 | 
			
		||||
        return active if active is not None else ""
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def export() -> bool:
 | 
			
		||||
    def export() -> bool | None:
 | 
			
		||||
        """
 | 
			
		||||
        This will export the tunnels.
 | 
			
		||||
        A zipfile with the current date and time is created
 | 
			
		||||
@@ -582,6 +564,11 @@ class Tunnel:
 | 
			
		||||
                    )
 | 
			
		||||
                    return False
 | 
			
		||||
 | 
			
		||||
        except zipfile.BadZipFile as e:
 | 
			
		||||
            logging.error(f"Invalid ZIP file: {e}")
 | 
			
		||||
            return False
 | 
			
		||||
        except TypeError:
 | 
			
		||||
            pass
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            logging.error(f"Export failed: {str(e)}")
 | 
			
		||||
            LxTools.msg_window(
 | 
			
		||||
@@ -591,12 +578,6 @@ class Tunnel:
 | 
			
		||||
                Msg.STR["exp_try"],
 | 
			
		||||
            )
 | 
			
		||||
            return False
 | 
			
		||||
        except zipfile.BadZipFile as e:
 | 
			
		||||
            logging.error(f"Invalid ZIP file: {e}")
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        except TypeError:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
        finally:
 | 
			
		||||
            LxTools.clean_files(AppConfig.TEMP_DIR)
 | 
			
		||||
@@ -714,7 +695,7 @@ class GiteaUpdate:
 | 
			
		||||
    """
 | 
			
		||||
    Calling download requests the download URL of the running script,
 | 
			
		||||
    the taskbar image for the “Download OK” window, the taskbar image for the
 | 
			
		||||
    “Download error” window and the variable res
 | 
			
		||||
    “Download error” window, and the variable res
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
@@ -771,13 +752,12 @@ class GiteaUpdate:
 | 
			
		||||
        """
 | 
			
		||||
        Downloads new version of wirepy
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            urld: Download URL
 | 
			
		||||
            res: Result filename
 | 
			
		||||
            AppConfig.IMAGE_PATHS["icon_info"]: Image for TK window which is displayed to the left of the text
 | 
			
		||||
            AppConfig.IMAGE_PATHS["icon_vpn"]: Image for Task Icon
 | 
			
		||||
            AppConfig.IMAGE_PATHS["icon_error"]: Image for TK window which is displayed to the left of the text
 | 
			
		||||
            AppConfig.IMAGE_PATHS["icon_msg"]: Image for Task Icon
 | 
			
		||||
        :param urld: Download URL
 | 
			
		||||
        :param res: Result filename
 | 
			
		||||
        :param image_path: AppConfig.IMAGE_PATHS["icon_info"]: Image for TK window which is displayed to the left of the text
 | 
			
		||||
        :param image_path2: AppConfig.IMAGE_PATHS["icon_vpn"]: Image for Task Icon
 | 
			
		||||
        :param image_path3: AppConfig.IMAGE_PATHS["icon_error"]: Image for TK window which is displayed to the left of the text
 | 
			
		||||
        :param image_path4: AppConfig.IMAGE_PATHS["icon_msg"]: Image for Task Icon
 | 
			
		||||
        """
 | 
			
		||||
        try:
 | 
			
		||||
            to_down: str = f"wget -qP {Path.home()} {" "} {urld}"
 | 
			
		||||
@@ -846,7 +826,7 @@ class Tooltip:
 | 
			
		||||
        self.x_offset = x_offset
 | 
			
		||||
        self.y_offset = y_offset
 | 
			
		||||
 | 
			
		||||
        # Initial binding based on current state
 | 
			
		||||
        # Initial binding based on the current state
 | 
			
		||||
        self.update_bindings()
 | 
			
		||||
 | 
			
		||||
        # Add trace to the state_var if provided
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								wirepy.py
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								wirepy.py
									
									
									
									
									
								
							@@ -400,7 +400,7 @@ class FrameWidgets(ttk.Frame):
 | 
			
		||||
 | 
			
		||||
    # Update the labels based on the result
 | 
			
		||||
    def update_ui_for_update(self, res):
 | 
			
		||||
        """Update UI elements based on update check result"""
 | 
			
		||||
        """Update UI elements based on an update check result"""
 | 
			
		||||
        # First, remove the update button if it exists to avoid conflicts
 | 
			
		||||
        if hasattr(self, "update_btn"):
 | 
			
		||||
            self.update_btn.grid_forget()
 | 
			
		||||
@@ -412,13 +412,13 @@ class FrameWidgets(ttk.Frame):
 | 
			
		||||
            self.update_tooltip.set(_("Updates you have disabled"))
 | 
			
		||||
            # Clear the foreground color as requested
 | 
			
		||||
            self.update_foreground.set("")
 | 
			
		||||
            # Set tooltip for the label
 | 
			
		||||
            # Set the tooltip for the label
 | 
			
		||||
            Tooltip(self.updates_lb, self.update_tooltip.get(), self.tooltip_state)
 | 
			
		||||
 | 
			
		||||
        elif res == "No Internet Connection!":
 | 
			
		||||
            self.update_label.set(_("No Server Connection!"))
 | 
			
		||||
            self.update_foreground.set("red")
 | 
			
		||||
            # Set tooltip for "No Server Connection"
 | 
			
		||||
            # Set the tooltip for "No Server Connection"
 | 
			
		||||
            Tooltip(
 | 
			
		||||
                self.updates_lb,
 | 
			
		||||
                _("Could not connect to update server"),
 | 
			
		||||
@@ -429,7 +429,7 @@ class FrameWidgets(ttk.Frame):
 | 
			
		||||
            self.update_label.set(_("No Updates"))
 | 
			
		||||
            self.update_tooltip.set(_("Congratulations! Wire-Py is up to date"))
 | 
			
		||||
            self.update_foreground.set("")
 | 
			
		||||
            # Set tooltip for the label
 | 
			
		||||
            # Set the tooltip for the label
 | 
			
		||||
            Tooltip(self.updates_lb, self.update_tooltip.get(), self.tooltip_state)
 | 
			
		||||
 | 
			
		||||
        else:
 | 
			
		||||
@@ -505,7 +505,7 @@ class FrameWidgets(ttk.Frame):
 | 
			
		||||
                    AppConfig.UPDATE_URL, AppConfig.VERSION, "on"
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                # Make sure UI is updated regardless of previous state
 | 
			
		||||
                # Make sure the UI is updated regardless of the previous state
 | 
			
		||||
                if hasattr(self, "update_btn"):
 | 
			
		||||
                    self.update_btn.grid_forget()
 | 
			
		||||
                if hasattr(self, "updates_lb"):
 | 
			
		||||
@@ -550,8 +550,8 @@ class FrameWidgets(ttk.Frame):
 | 
			
		||||
        # This assumes it's the third item (index 2) in your menu
 | 
			
		||||
        self.settings.entryconfigure(1, label=self.tooltip_label.get())
 | 
			
		||||
 | 
			
		||||
    def update_theme_label(self) -> str:
 | 
			
		||||
        """Update the theme label based on current theme"""
 | 
			
		||||
    def update_theme_label(self) -> None:
 | 
			
		||||
        """Update the theme label based on the current theme"""
 | 
			
		||||
        current_theme = ConfigManager.get("theme")
 | 
			
		||||
        if current_theme == "light":
 | 
			
		||||
            self.theme_label.set(_("Dark"))
 | 
			
		||||
@@ -751,14 +751,10 @@ class FrameWidgets(ttk.Frame):
 | 
			
		||||
                Msg.STR["imp_err"],
 | 
			
		||||
                Msg.STR["no_valid_file"],
 | 
			
		||||
            )
 | 
			
		||||
        except IsADirectoryError:
 | 
			
		||||
        except (IsADirectoryError, TypeError, FileNotFoundError):
 | 
			
		||||
            print("File import: abort by user...")
 | 
			
		||||
        except EOFError as e:
 | 
			
		||||
            print(e)
 | 
			
		||||
        except TypeError:
 | 
			
		||||
            print("File import: abort by user...")
 | 
			
		||||
        except FileNotFoundError:
 | 
			
		||||
            print("File import: abort by user...")
 | 
			
		||||
 | 
			
		||||
    def delete(self) -> None:
 | 
			
		||||
        """
 | 
			
		||||
 
 | 
			
		||||
@@ -76,7 +76,7 @@ class AppConfig:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # System-dependent paths
 | 
			
		||||
    SYSTEM_PATHS: Dict[str, str] = {
 | 
			
		||||
    SYSTEM_PATHS: Dict[str, Path] = {
 | 
			
		||||
        "ssl_decrypt": "/usr/local/bin/ssl_decrypt.py",
 | 
			
		||||
        "ssl_encrypt": "/usr/local/bin/ssl_encrypt.py",
 | 
			
		||||
        "tcl_path": "/usr/share/TK-Themes",
 | 
			
		||||
@@ -84,7 +84,7 @@ class AppConfig:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Images and icons paths
 | 
			
		||||
    IMAGE_PATHS: Dict[str, str] = {
 | 
			
		||||
    IMAGE_PATHS: Dict[str, Path] = {
 | 
			
		||||
        "icon_vpn": "/usr/share/icons/lx-icons/48/wg_vpn.png",
 | 
			
		||||
        "icon_msg": "/usr/share/icons/lx-icons/48/wg_msg.png",
 | 
			
		||||
        "icon_import": "/usr/share/icons/lx-icons/48/wg_import.png",
 | 
			
		||||
@@ -127,9 +127,9 @@ class AppConfig:
 | 
			
		||||
            cls.SETTINGS_FILE.write_text(content)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_autostart_content(cls) -> str:
 | 
			
		||||
        """Returns the content for the autostart service file"""
 | 
			
		||||
        SYSTEMD_FILE: list[str] = [
 | 
			
		||||
    def get_autostart_content(cls) -> None:
 | 
			
		||||
        """Returns the content for an autostart service file"""
 | 
			
		||||
        systemd_file: list[str] = [
 | 
			
		||||
            "[Unit]",
 | 
			
		||||
            "Description=Automatic Tunnel Start",
 | 
			
		||||
            "After=network-online.target",
 | 
			
		||||
@@ -147,7 +147,7 @@ class AppConfig:
 | 
			
		||||
 | 
			
		||||
        if not cls.AUTOSTART_SERVICE.is_file():
 | 
			
		||||
 | 
			
		||||
            content = "\n".join([line for line in SYSTEMD_FILE])
 | 
			
		||||
            content = "\n".join([line for line in systemd_file])
 | 
			
		||||
            cls.AUTOSTART_SERVICE.write_text(content)
 | 
			
		||||
 | 
			
		||||
        process: CompletedProcess[str] = run(
 | 
			
		||||
@@ -161,7 +161,7 @@ class AppConfig:
 | 
			
		||||
            logging.error(f"{process.stderr} Code: {process.returncode}", exc_info=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# here is inizialize the class for translate strrings
 | 
			
		||||
# here is initializing the class for translation strings
 | 
			
		||||
_ = AppConfig.setup_translations()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user