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