Compare commits

..

No commits in common. "21-04-2025-new-tooltip" and "main" have entirely different histories.

10 changed files with 1286 additions and 587 deletions

View File

@ -1,3 +0,0 @@
<component name="ProjectDictionaryState">
<dictionary name="project" />
</component>

2
.idea/misc.xml generated
View File

@ -3,5 +3,5 @@
<component name="Black"> <component name="Black">
<option name="sdkName" value="Python 3.12 (wire-py)" /> <option name="sdkName" value="Python 3.12 (wire-py)" />
</component> </component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12" project-jdk-type="Python SDK" /> <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (wire-py)" project-jdk-type="Python SDK" />
</project> </project>

2
.idea/wire-py.iml generated
View File

@ -4,7 +4,7 @@
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" /> <excludeFolder url="file://$MODULE_DIR$/.venv" />
</content> </content>
<orderEntry type="jdk" jdkName="Python 3.12" jdkType="Python SDK" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
</module> </module>

46
.idea/workspace.xml generated
View File

@ -5,8 +5,8 @@
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="940e1630-c825-4d4c-be80-bc11f543c122" name="Changes" comment=" - Update Translate Files"> <list default="true" id="940e1630-c825-4d4c-be80-bc11f543c122" name="Changes" comment=" - Update Translate Files">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/cls_mth_fc.py" beforeDir="false" afterPath="$PROJECT_DIR$/cls_mth_fc.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/cls_mth_fc.py" beforeDir="false" afterPath="$PROJECT_DIR$/cls_mth_fc.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/wirepy.py" beforeDir="false" afterPath="$PROJECT_DIR$/wirepy.py" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -30,13 +30,14 @@
<option name="UPDATE_TYPE" value="REBASE" /> <option name="UPDATE_TYPE" value="REBASE" />
</component> </component>
<component name="HighlightingSettingsPerFile"> <component name="HighlightingSettingsPerFile">
<setting file="file:///usr/local/bin/ssl_decrypt.py" root0="SKIP_INSPECTION" /> <setting file="file://$PROJECT_DIR$/wg_func.py" root0="SKIP_INSPECTION" />
<setting file="file://$PROJECT_DIR$/wg_main.py" root0="FORCE_HIGHLIGHTING" />
</component> </component>
<component name="ProjectColorInfo">{ <component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 3 &quot;associatedIndex&quot;: 3
}</component> }</component>
<component name="ProjectId" id="2kSbZdjOvr0wsVJSNcaMwSfVaxR" /> <component name="ProjectId" id="2kSbZdjOvr0wsVJSNcaMwSfVaxR" />
<component name="ProjectLevelVcsManager"> <component name="ProjectLevelVcsManager" settingsEditedManually="true">
<ConfirmationsSetting value="2" id="Add" /> <ConfirmationsSetting value="2" id="Add" />
</component> </component>
<component name="ProjectViewState"> <component name="ProjectViewState">
@ -47,7 +48,6 @@
&quot;keyToString&quot;: { &quot;keyToString&quot;: {
&quot;ASKED_ADD_EXTERNAL_FILES&quot;: &quot;true&quot;, &quot;ASKED_ADD_EXTERNAL_FILES&quot;: &quot;true&quot;,
&quot;Python.INSTALL.executor&quot;: &quot;Run&quot;, &quot;Python.INSTALL.executor&quot;: &quot;Run&quot;,
&quot;Python.cls_mth_fc.executor&quot;: &quot;Run&quot;,
&quot;Python.install.executor&quot;: &quot;Run&quot;, &quot;Python.install.executor&quot;: &quot;Run&quot;,
&quot;Python.main.executor&quot;: &quot;Run&quot;, &quot;Python.main.executor&quot;: &quot;Run&quot;,
&quot;Python.messagebox.executor&quot;: &quot;Run&quot;, &quot;Python.messagebox.executor&quot;: &quot;Run&quot;,
@ -55,14 +55,12 @@
&quot;Python.testtheme.executor&quot;: &quot;Run&quot;, &quot;Python.testtheme.executor&quot;: &quot;Run&quot;,
&quot;Python.wg_func.executor&quot;: &quot;Run&quot;, &quot;Python.wg_func.executor&quot;: &quot;Run&quot;,
&quot;Python.wg_main.executor&quot;: &quot;Run&quot;, &quot;Python.wg_main.executor&quot;: &quot;Run&quot;,
&quot;Python.wirepy.executor&quot;: &quot;Run&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;, &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
&quot;Shell Script.install.executor&quot;: &quot;Run&quot;, &quot;Shell Script.install.executor&quot;: &quot;Run&quot;,
&quot;Shell Script.run_as.executor&quot;: &quot;Run&quot;, &quot;Shell Script.run_as.executor&quot;: &quot;Run&quot;,
&quot;git-widget-placeholder&quot;: &quot;21-04-2025-new-tooltip&quot;, &quot;git-widget-placeholder&quot;: &quot;1.11.1024&quot;,
&quot;last_opened_file_path&quot;: &quot;/home/punix/Pyapps/wire-py&quot;, &quot;last_opened_file_path&quot;: &quot;/home/punix/Pyapps/wire-py&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;ml.llm.LLMConfigurable&quot; &quot;settings.editor.selected.configurable&quot;: &quot;reference.settingsdialog.IDE.editor.colors&quot;
} }
}</component> }</component>
<component name="RecentsManager"> <component name="RecentsManager">
@ -77,7 +75,7 @@
<recent name="$PROJECT_DIR$/wire-py" /> <recent name="$PROJECT_DIR$/wire-py" />
</key> </key>
</component> </component>
<component name="RunManager" selected="Python.wirepy"> <component name="RunManager" selected="Python.wg_main">
<configuration name="start_wg" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true"> <configuration name="start_wg" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="wire-py" /> <module name="wire-py" />
<option name="ENV_FILES" value="" /> <option name="ENV_FILES" value="" />
@ -122,31 +120,8 @@
<option name="INPUT_FILE" value="" /> <option name="INPUT_FILE" value="" />
<method v="2" /> <method v="2" />
</configuration> </configuration>
<configuration name="wirepy" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="wire-py" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/wirepy.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<recent_temporary> <recent_temporary>
<list> <list>
<item itemvalue="Python.wirepy" />
<item itemvalue="Python.start_wg" /> <item itemvalue="Python.start_wg" />
</list> </list>
</recent_temporary> </recent_temporary>
@ -154,7 +129,7 @@
<component name="SharedIndexes"> <component name="SharedIndexes">
<attachedChunks> <attachedChunks>
<set> <set>
<option value="bundled-python-sdk-348a24fa61fa-5312c7369657-com.jetbrains.pycharm.community.sharedIndexes.bundled-PC-251.23774.444" /> <option value="bundled-python-sdk-8336bb23522e-31b6be0877a2-com.jetbrains.pycharm.community.sharedIndexes.bundled-PC-241.19072.16" />
</set> </set>
</attachedChunks> </attachedChunks>
</component> </component>
@ -625,11 +600,6 @@
<line>1128</line> <line>1128</line>
<option name="timeStamp" value="3" /> <option name="timeStamp" value="3" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/ssl_decrypt.py</url>
<line>3</line>
<option name="timeStamp" value="4" />
</line-breakpoint>
</breakpoints> </breakpoints>
</breakpoint-manager> </breakpoint-manager>
</component> </component>

View File

@ -4,16 +4,13 @@ import gettext
import locale import locale
import os import os
import shutil import shutil
import signal
import subprocess import subprocess
import sys
import tkinter as tk import tkinter as tk
from typing import Optional, Dict, Any, NoReturn, TextIO, Tuple, List
import zipfile import zipfile
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
from subprocess import check_call, CompletedProcess from subprocess import check_call
from tkinter import ttk, Toplevel from tkinter import ttk
import requests import requests
@ -24,6 +21,8 @@ gettext.bindtextdomain(APP, LOCALE_DIR)
gettext.textdomain(APP) gettext.textdomain(APP)
_ = gettext.gettext _ = gettext.gettext
wg_set = Path(Path.home() / ".config/wire_py/settings")
class Create: class Create:
""" """
@ -33,22 +32,24 @@ class Create:
""" """
@staticmethod @staticmethod
def dir_and_files() -> None: def dir_and_files():
""" """
check and create folders and files if not present check and create folders and files if not present
""" """
pth: Path = Path.home() / ".config/wire_py" pth = Path.home() / ".config/wire_py"
pth.mkdir(parents=True, exist_ok=True) pth.mkdir(parents=True, exist_ok=True)
sett: Path = Path.home() / ".config/wire_py/settings" sett = Path.home() / ".config/wire_py/settings"
ks: Path = Path.home() / ".config/wire_py/keys" ks = Path.home() / ".config/wire_py/keys"
if sett.exists(): if sett.exists():
pass pass
else: else:
sett.touch() sett.touch()
sett.write_text("[UPDATES]\non\n[THEME]\nlight\n[TOOLTIP]\nTrue\n[AUTOSTART ON]\noff\n") sett.write_text(
"[UPDATES]\non\n[THEME]\nlight\n[TOOLTIP]\nTrue\n[AUTOSTART ON]\noff\n"
)
if ks.exists(): if ks.exists():
pass pass
@ -57,59 +58,65 @@ class Create:
ks.touch() ks.touch()
@staticmethod @staticmethod
def files_for_autostart() -> None: def files_for_autostart():
""" """
check and create a file for auto start if not present and enable the service check and create file for auto start if not present and enable the service
""" """
pth2: Path = Path.home() / ".config/systemd/user" pth2 = Path.home() / ".config/systemd/user"
pth2.mkdir(parents=True, exist_ok=True) pth2.mkdir(parents=True, exist_ok=True)
wg_ser: Path = Path.home() / ".config/systemd/user/wg_start.service" wg_ser = Path.home() / ".config/systemd/user/wg_start.service"
if wg_ser.exists(): if wg_ser.exists():
pass pass
else: else:
wg_ser.touch() wg_ser.touch()
wg_ser.write_text("[Unit]\nDescription=Automatic Tunnel Start\nAfter=network-online.target\n\n[Service]\n" wg_ser.write_text(
"Type=oneshot\nExecStartPre=/bin/sleep 5\nExecStart=/usr/local/bin/start_wg.py\n[Install]" "[Unit]\nDescription=Automatic Tunnel Start\nAfter=network-online.target"
"\nWantedBy=default.target") "\n\n[Service]\nType=oneshot\nExecStartPre=/bin/sleep 5\nExecStart=/usr/"
"local/bin/start_wg.py\n[Install]\nWantedBy=default.target"
)
check_call(["systemctl", "--user", "enable", "wg_start.service"]) check_call(["systemctl", "--user", "enable", "wg_start.service"])
@staticmethod @staticmethod
def make_dir() -> None: def make_dir():
"""Folder Name "tlecdewg" = Tunnel Encrypt Decrypt Wireguard""" """Dirname "tlecdewg" = Tunnel Encrypt Decrypt Wireguard"""
folder_path: Path = Path("/tmp/tlecdcwg/") dirname = Path("/tmp/tlecdcwg/")
if folder_path.exists(): if dirname.exists():
pass pass
else: else:
folder_path.mkdir() dirname.mkdir()
@staticmethod @staticmethod
def decrypt() -> None: def decrypt():
""" """
Starts SSL dencrypt This start ssl_decrypt file
""" """
process: CompletedProcess[str] = subprocess.run(["pkexec", "/usr/local/bin/ssl_decrypt.py"], process = subprocess.run(
stdout=subprocess.PIPE, text=True, check=True) ["pkexec", "/usr/local/bin/ssl_decrypt.py"],
path: Path = Path.home() / ".config/wire_py/" stdout=subprocess.PIPE,
file_in_path: list[Path] = list(path.rglob("*.dat")) text=True,
if file_in_path: check=True,
if process.returncode == 0: )
print("File successfully decrypted...") # print(process.stdout)
else: if process.returncode == 0:
print(f"Error with the following code... {process.returncode}") print("File successfully decrypted...")
else: else:
print(_("Ready for import")) print(f"Error with the following code... {process.returncode}")
@staticmethod @staticmethod
def encrypt() -> None: def encrypt():
""" """
Starts SSL encryption this start ssl_encrypt file
""" """
process: CompletedProcess[str] = subprocess.run(["pkexec", "/usr/local/bin/ssl_encrypt.py"], process = subprocess.run(
stdout=subprocess.PIPE, text=True, check=True) ["pkexec", "/usr/local/bin/ssl_encrypt.py"],
stdout=subprocess.PIPE,
text=True,
check=True,
)
print(process.stdout) print(process.stdout)
if process.returncode == 0: if process.returncode == 0:
print("All Files successfully encrypted...") print("All Files successfully encrypted...")
@ -117,139 +124,18 @@ class Create:
print(f"Error with the following code... {process.returncode}") print(f"Error with the following code... {process.returncode}")
class LxTools(tk.Tk): def uos():
"""
Class LinuxTools methods that can also be used for other apps
""" """
def __init__(self, *args: Any, **kwargs: Any) -> None: uos = LOGIN USERNAME
super().__init__(*args, **kwargs)
@staticmethod This method displays the user name of the logged-in user,
def uos() -> None: even if you are rooted in a shell
""" """
uos = LOGIN USERNAME logname = str(Path.home())[6:]
file = Path.home() / "/tmp/.loguser"
This method displays the username of the logged-in user, with open(file, "w", encoding="utf-8") as f:
even if you are rooted in a shell f.write(logname)
"""
log_name: str = f"{Path.home()}"[6:]
file: Path = Path.home() / "/tmp/.log_user"
with open(file, "w", encoding="utf-8") as f:
f.write(log_name)
@staticmethod
def clean_files(folder_path: Path = None, file: Path = None) -> None:
"""
method that can be added after need to delete a folder and a file when quitting.
Args:
:param file: default None
:param folder_path: default None
"""
if folder_path is not None:
shutil.rmtree(folder_path)
if file is not None:
Path.unlink(file)
@staticmethod
def if_tip(path: Path) -> bool:
"""
method that writes in file whether tooltip is displayed or not
"""
with open(path, "r", encoding="utf-8") as set_f2:
lines2 = set_f2.readlines()
if "False\n" in lines2:
tip = False
else:
tip = True
return tip
@staticmethod
def msg_window(img_w: str, img_i: str, w_title: str, w_txt: str, txt2: Optional[str] = None,
com: Optional[str] = None) -> None:
"""
Creates message windows
:argument img_w = Image for TK window which is displayed to the left of the text
:argument img_i = Image for Task Icon
:argument w_title = Windows Title
:argument w_txt = Text for Tk Window
:argument txt2 = Text for Button two
:argument com = function for Button command
"""
msg: tk.Toplevel = tk.Toplevel()
msg.resizable(width=False, height=False)
msg.title(w_title)
msg.configure(pady=15, padx=15)
msg.img = tk.PhotoImage(file=img_w)
msg.i_window = tk.Label(msg, image=msg.img)
label: tk.Label = tk.Label(msg, text=w_txt)
label.grid(column=1, row=0)
if txt2 is not None and com is not None:
label.config(font=("Ubuntu", 11), padx=15, justify="left")
msg.i_window.grid(column=0, row=0, sticky="nw")
button2: ttk.Button = ttk.Button(msg, text=f"{txt2}", command=com, padding=4)
button2.grid(column=0, row=1, sticky="e", columnspan=2)
button: ttk.Button = ttk.Button(msg, text="OK", command=msg.destroy, padding=4)
button.grid(column=0, row=1, sticky="w", columnspan=2)
else:
label.config(font=("Ubuntu", 11), padx=15)
msg.i_window.grid(column=0, row=0)
button: ttk.Button = ttk.Button(msg, text="OK", command=msg.destroy, padding=4)
button.grid(column=0, columnspan=2, row=1)
img_i: tk.PhotoImage = tk.PhotoImage(file=img_i)
msg.iconphoto(True, img_i)
msg.columnconfigure(0, weight=1)
msg.rowconfigure(0, weight=1)
msg.winfo_toplevel()
@staticmethod
def sigi(file_path: Optional[Path] = None, file: Optional[Path] = None) -> None:
"""
Function for cleanup after a program interruption
:param file: Optional - File to be deleted
:param file_path: Optional - Directory to be deleted
"""
def signal_handler(signum: int, frame: Any) -> NoReturn:
"""
Determines clear text names for signal numbers and handles signals
Args:
signum: The signal number
frame: The current stack frame
Returns:
NoReturn since the function either exits the program or continues execution
"""
signals_to_names_dict: Dict[int, str] = dict((getattr(signal, n), n) for n in dir(signal)
if n.startswith("SIG") and "_" not in n)
signal_name: str = signals_to_names_dict.get(signum, f"Unnamed signal: {signum}")
# End program for certain signals, report to others only reception
if signum in (signal.SIGINT, signal.SIGTERM):
exit_code: int = 1
print(f"\nSignal {signal_name} {signum} received. => Aborting with exit code {exit_code}.")
LxTools.clean_files(file_path, file)
print("Breakdown by user...")
sys.exit(exit_code)
else:
print(f"Signal {signum} received and ignored.")
LxTools.clean_files(file_path, file)
print("Process unexpectedly ended...")
# Register signal handlers for various signals
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
signal.signal(signal.SIGHUP, signal_handler)
class GiteaUpdate: class GiteaUpdate:
@ -260,70 +146,108 @@ class GiteaUpdate:
""" """
@staticmethod @staticmethod
def api_down(update_api_url: str, version: str, file: Optional[Path] = None) -> str: def api_down(update_api_url, version):
""" """
Checks for updates via API Calling api_down requests the URL and the version of the running script.
Example: version = 'v. 1.1.1.1' GiteaUpdate.api_down(http://example.de, version)
Args:
update_api_url: Update API URL
version: Current version
file: Optional - Configuration file
Returns:
New version or status message
""" """
try: try:
response: requests.Response = requests.get(update_api_url, timeout=10) response = requests.get(update_api_url, timeout=10)
response_dict: Any = response.json() response_dict = response.json()
response_dict: Dict[str, Any] = response_dict[0] response_dict = response_dict[0]
with open(file, "r", encoding="utf-8") as set_f: with open(wg_set, "r", encoding="utf-8") as set_file:
set_f = set_f.read() set_file = set_file.read()
if "on\n" in set_f: if "on\n" in set_file:
if version[3:] != response_dict["tag_name"]: if version[3:] != response_dict["tag_name"]:
req: str = response_dict["tag_name"] req = response_dict["tag_name"]
else: else:
req: str = "No Updates" req = "No Updates"
else: else:
req: str = "False" req = "False"
return req return req
except requests.exceptions.RequestException: except requests.exceptions.RequestException:
req: str = "No Internet Connection!" req = "No Internet Connection!"
return req return req
@staticmethod @staticmethod
def download(urld: str, res: str, img_w: str = None, img_i: str = None, img_w2: str = None, img_i2: str = None) -> None: def download(urld, down_ok_image, down_not_ok_image, res):
""" """
Downloads new version of wirepy this is for download new Version of wirepy
Args:
urld: Download URL
res: Result filename
img_w: Image for TK window which is displayed to the left of the text
img_i: Image for Task Icon
img_w2: Image for TK window which is displayed to the left of the text
img_i2: Image for Task Icon
""" """
try: try:
to_down: str = f"wget -qP {Path.home()} {" "} {urld}" to_down = "wget -qP " + str(Path.home()) + " " + urld
result: int = subprocess.call(to_down, shell=True) result = subprocess.call(to_down, shell=True)
if result == 0: if result == 0:
shutil.chown(f"{Path.home()}/{res}.zip", 1000, 1000) shutil.chown(str(Path.home()) + f"/{res}.zip", 1000, 1000)
wt: str = _("Download Successful") # img_w, img_i, w_title, w_txt hand over
msg_t: str = _("Your zip file is in home directory") iw = r"/usr/share/icons/lx-icons/64/info.png"
LxTools.msg_window(img_w, img_i, wt, msg_t) ii = down_ok_image
wt = _("Download Successful")
msg_t = _("Your zip file is in home directory")
msg_window(iw, ii, wt, msg_t)
else: else:
wt: str = _("Download error") # img_w, img_i, w_title, w_txt hand over
msg_t: str = _("Download failed! Please try again") iw = r"/usr/share/icons/lx-icons/64/error.png"
LxTools.msg_window(img_w2, img_i2, wt, msg_t) ii = down_not_ok_image
wt = _("Download error")
msg_t = _("Download failed! Please try again")
msg_window(iw, ii, wt, msg_t)
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
wt: str = _("Download error") # img_w, img_i, w_title, w_txt hand over
msg_t: str = _("Download failed! No internet connection!") iw = r"/usr/share/icons/lx-icons/64/error.png"
LxTools.msg_window(img_w2, img_i2, wt, msg_t) ii = down_not_ok_image
wt = _("Download error")
msg_t = _("Download failed! No internet connection!")
msg_window(iw, ii, wt, msg_t)
def msg_window(img_w, img_i, w_title, w_txt, txt2=None, com=None):
"""
Function for different message windows for the user. with 4 arguments to be passed.
To create messages with your own images, icons, and titles.
As an alternative to Python Messagebox.
Paths to images must be specified: r'/usr/share/icons/lx-icons/64/info.png'
img_w = Image for Tk Window
img_i = Image for Icon
w_title = Windows Title
w_txt = Text for Tk Window
txt2 = Text for Button two
com = function for Button command
"""
msg = tk.Toplevel()
msg.resizable(width=False, height=False)
msg.title(w_title)
msg.configure(pady=15, padx=15)
msg.img = tk.PhotoImage(file=img_w)
msg.i_window = tk.Label(msg, image=msg.img)
label = tk.Label(msg, text=w_txt)
label.grid(column=1, row=0)
if txt2 is not None and com is not None:
label.config(font=("Ubuntu", 11), padx=15, justify="left")
msg.i_window.grid(column=0, row=0, sticky="nw")
button2 = ttk.Button(msg, text=f"{txt2}", command=com, padding=4)
button2.grid(column=0, row=1, sticky="e", columnspan=2)
button = ttk.Button(msg, text="OK", command=msg.destroy, padding=4)
button.grid(column=0, row=1, sticky="w", columnspan=2)
else:
label.config(font=("Ubuntu", 11), padx=15)
msg.i_window.grid(column=0, row=0)
button = ttk.Button(msg, text="OK", command=msg.destroy, padding=4)
button.grid(column=0, columnspan=2, row=1)
img_i = tk.PhotoImage(file=img_i)
msg.iconphoto(True, img_i)
msg.columnconfigure(0, weight=1)
msg.rowconfigure(0, weight=1)
msg.winfo_toplevel()
class Tunnel: class Tunnel:
@ -332,14 +256,15 @@ class Tunnel:
""" """
@classmethod @classmethod
def con_to_dict(cls, file: TextIO) -> Tuple[str, str, str, Optional[str]]: def con_to_dict(cls, file):
""" """
Returns tuple of (address, dns, endpoint, pre_key) The config file is packed into a dictionary,
to display the values Address , DNS and Peer in the labels
""" """
dictlist: List[str] = [] dictlist = []
for lines in file.readlines(): for lines in file.readlines():
line_plit: List[str] = lines.split() line_plit = lines.split()
dictlist = dictlist + line_plit dictlist = dictlist + line_plit
dictlist.remove("[Interface]") dictlist.remove("[Interface]")
dictlist.remove("[Peer]") dictlist.remove("[Peer]")
@ -351,37 +276,41 @@ class Tunnel:
# Here is the beginning (Loop) of convert List to Dictionary # Here is the beginning (Loop) of convert List to Dictionary
for _ in dictlist: for _ in dictlist:
a: List[str] = [dictlist[0], dictlist[1]] a = [dictlist[0], dictlist[1]]
b: List[str] = [dictlist[2], dictlist[3]] b = [dictlist[2], dictlist[3]]
c: List[str] = [dictlist[4], dictlist[5]] c = [dictlist[4], dictlist[5]]
d: List[str] = [dictlist[6], dictlist[7]] d = [dictlist[6], dictlist[7]]
e: List[str] = [dictlist[8], dictlist[9]] e = [dictlist[8], dictlist[9]]
f: List[str] = [dictlist[10], dictlist[11]] f = [dictlist[10], dictlist[11]]
g: List[str] = [dictlist[12], dictlist[13]] g = [dictlist[12], dictlist[13]]
h: List[str] = [dictlist[14], dictlist[15]] h = [dictlist[14], dictlist[15]]
new_list: List[List[str]] = [a, b, c, d, e, f, g, h] new_list = [a, b, c, d, e, f, g, h]
final_dict: Dict[str, str] = {} final_dict = {}
for elements in new_list: for elements in new_list:
final_dict[elements[0]] = elements[1] final_dict[elements[0]] = elements[1]
# end... result a Dictionary # end... result a Dictionary
address: str = final_dict["Address"] address = final_dict["Address"]
dns: str = final_dict["DNS"] dns = final_dict["DNS"]
if "," in dns: if "," in dns:
dns = dns[:-1] dns = dns[:-1]
endpoint: str = final_dict["Endpoint"] endpoint = final_dict["Endpoint"]
pre_key: Optional[str] = final_dict.get("PresharedKey") pre_key = final_dict.get("PresharedKey")
if pre_key is None: if pre_key is None:
pre_key: Optional[str] = final_dict.get("PreSharedKey") pre_key = final_dict.get("PreSharedKey")
return address, dns, endpoint, pre_key return address, dns, endpoint, pre_key
@staticmethod @staticmethod
def active() -> str: def active():
""" """
Shows the Active Tunnel Shows the Active Tunnel
""" """
active = (os.popen('nmcli con show --active | grep -iPo "(.*)(wireguard)"').read().split()) active = (
os.popen('nmcli con show --active | grep -iPo "(.*)(wireguard)"')
.read()
.split()
)
if not active: if not active:
active = "" active = ""
else: else:
@ -390,107 +319,111 @@ class Tunnel:
return active return active
@staticmethod @staticmethod
def list() -> List[str]: def list():
""" """
Returns a list of Wireguard tunnel names Shows all existing Wireguard tunnels a login user
""" """
folder_path: Path = Path("/tmp/tlecdcwg/") dirname = Path("/tmp/tlecdcwg/")
wg_s: List[str] = os.listdir(folder_path) wg_s = os.listdir(dirname)
return wg_s return wg_s
@staticmethod @staticmethod
def export(img_w: str = None, img_i: str = None, img_w2: str = None, img_i2: str = None, sl: str = None, pfit:str = None) -> None: def export():
""" """
This will export the tunnels. This will export the tunnels.
A zipfile with the current date and time is created A zipfile with current date and time is created
in the user's home directory with the correct right in the user's home directory with correct right
Args:
img_w: Image for TK window which is displayed to the left of the text
img_i: Image for Task Icon
img_w2: Image for TK window which is displayed to the left of the text
img_i2: Image for Task Icon
""" """
now_time: datetime = datetime.now() now_time = datetime.now()
now_datetime: str = now_time.strftime("wg-exp-%m-%d-%Y-%H:%M") now_datetime = now_time.strftime("wg-exp-" + "%m-%d-%Y" + "-" + "%H:%M")
tl: List[str] = Tunnel.list() tl = Tunnel.list()
try: try:
if len(tl) != 0: if len(tl) != 0:
wg_tar: str = f"{Path.home()}/{now_datetime}" wg_tar = str(Path.home()) + "/" + now_datetime
shutil.copytree("/tmp/tlecdcwg/", "/tmp/wire_py", dirs_exist_ok=True) shutil.copytree("/tmp/tlecdcwg/", "/tmp/wire_py", dirs_exist_ok=True)
source: Path = Path("/tmp/wire_py") source = Path("/tmp/wire_py")
shutil.make_archive(wg_tar, "zip", source) shutil.make_archive(wg_tar, "zip", source)
shutil.rmtree(source) shutil.rmtree(source)
with zipfile.ZipFile(f"{wg_tar}.zip", "r") as zf: with zipfile.ZipFile((wg_tar + ".zip"), "r") as zf:
if len(zf.namelist()) != 0: if len(zf.namelist()) != 0:
msg_t: str = _("Your zip file is in home directory") # img_w, img_i, w_title, w_txt hand over
LxTools.msg_window(img_w, img_i, _("Export Successful"), msg_t) iw = r"/usr/share/icons/lx-icons/64/info.png"
ii = r"/usr/share/icons/lx-icons/48/wg_vpn.png"
wt = _("Export Successful")
msg_t = _("Your zip file is in home directory")
msg_window(iw, ii, wt, msg_t)
else: else:
msg_t: str = _("Export failed! Please try again") # img_w, img_i, w_title, w_txt hand over
LxTools.msg_window(img_w2, img_i2, _("Export error"), msg_t) iw = r"/usr/share/icons/lx-icons/64/error.png"
ii = r"/usr/share/icons/lx-icons/48/wg_msg.png"
wt = _("Export error")
msg_t = _("Export failed! Please try again")
msg_window(iw, ii, wt, msg_t)
else: else:
LxTools.msg_window(img_w, img_i2, sl, pfit) # img_w, img_i, w_title, w_txt hand over
iw = r"/usr/share/icons/lx-icons/64/info.png"
ii = r"/usr/share/icons/lx-icons/48/wg_msg.png"
wt = _("Select tunnel")
msg_t = _("Please first import tunnel")
msg_window(iw, ii, wt, msg_t)
except TypeError: except TypeError:
pass pass
def if_tip(path):
"""
method that writes in file whether tooltip is displayed or not
"""
with open(path, "r", encoding="utf-8") as set_file2:
lines2 = set_file2.readlines()
if "False\n" in lines2:
tip = False
else:
tip = True
return tip
class Tooltip: class Tooltip:
""" """
class for Tooltip class for Tooltip
import Tooltip imoprt Tooltip
example: Tooltip(label, "Show tooltip on label") example: Tooltip(label, "Show tooltip on label")
example: Tooltip(button, "Show tooltip on button") examble: Tooltip(button, "Show tooltip on button")
info: label and button are parent. info: label and button is parrent.
""" """
def __init__(self, widget, text):
self.widget = widget
self.text = text
self.tooltip_window = None
self.widget.bind("<Enter>", self.show_tooltip)
self.widget.bind("<Leave>", self.hide_tooltip)
def __init__(self, widget: Any, text: str, tips: Optional[bool] = None) -> None: def show_tooltip(self, event=None):
"""
Tooltip Class
"""
self.widget: Any = widget
self.text: str = text
self.tooltip_window: Optional[Toplevel] = None
if tips:
self.widget.bind("<Enter>", self.show_tooltip)
self.widget.bind("<Leave>", self.hide_tooltip)
def show_tooltip(self, event: Optional[Any] = None) -> None:
"""
Shows the tooltip
"""
if self.tooltip_window or not self.text: if self.tooltip_window or not self.text:
return return
x: int x, y, _, _ = self.widget.bbox("insert")
y: int x += self.widget.winfo_rootx() + 25
cx: int y += self.widget.winfo_rooty() + 20
cy: int
x, y, cx, cy = self.widget.bbox("insert")
x += self.widget.winfo_rootx() + 65
y += self.widget.winfo_rooty() + 40
self.tooltip_window = tw = tk.Toplevel(self.widget) self.tooltip_window = tw = tk.Toplevel(self.widget)
tw.wm_overrideredirect(True) tw.wm_overrideredirect(True)
tw.wm_geometry(f"+{x}+{y}") tw.wm_geometry(f"+{x}+{y}")
label: tk.Label = tk.Label(tw, text=self.text, background="lightgreen", foreground="black", relief="solid", label = tk.Label(tw, text=self.text, relief="solid", borderwidth=1, padx=5, pady=5)
borderwidth=1, padx=5, pady=5)
label.grid() label.grid()
def hide_tooltip(self, event: Optional[Any] = None) -> None: def hide_tooltip(self, event=None):
"""
Hides the tooltip
"""
if self.tooltip_window: if self.tooltip_window:
self.tooltip_window.destroy() self.tooltip_window.destroy()
self.tooltip_window = None self.tooltip_window = None

View File

@ -1,35 +1,59 @@
#!/usr/bin/python3 #!/usr/bin/python3
""" This Script decrypt Wireguard files for Wirepy users """ """ This Script decrypt Wireguardfiles for Wirepy users """
import os import os
import shutil import shutil
from pathlib import Path from pathlib import Path
from subprocess import check_call from subprocess import check_call
uname: Path = Path("/tmp/.log_user") uname = Path("/tmp/.loguser")
with open(uname, "r", encoding="utf-8") as f: with open(uname, "r", encoding="utf-8") as f:
log_name = f.readline() logname = f.readline()
# Folder Name "tlecdewg" = Tunnel Encrypt Decrypt Wireguard # Dirname "tlecdewg" = Tunnel Encrypt Decrypt Wireguard
folder_path: Path = Path("/tmp/tlecdcwg/") dirname = Path("/tmp/tlecdcwg/")
keyfile: Path = Path(f"/home/{log_name}/.config/wire_py/pbwgk.pem") keyfile = Path(f"/home/{logname}/.config/wire_py/pbwgk.pem")
PKEYFILE: Path = "/usr/local/etc/ssl/pwgk.pem" PKEYFILE = "/usr/local/etc/ssl/pwgk.pem"
if not keyfile.is_file(): if not keyfile.is_file():
check_call(["openssl", "rsa", "-in", PKEYFILE, "-out", keyfile, "-outform", "PEM", "-pubout"]) check_call(
[
"openssl",
"rsa",
"-in",
PKEYFILE,
"-out",
keyfile,
"-outform",
"PEM",
"-pubout",
]
)
shutil.chown(keyfile, 1000, 1000) shutil.chown(keyfile, 1000, 1000)
folder_path2 = f"/home/{log_name}/.config/wire_py/" dirname2 = "/home/" + logname + "/.config/wire_py/"
detl: list[str] = os.listdir(folder_path2) detl = os.listdir(dirname2)
os.chdir(folder_path2) os.chdir(dirname2)
detl.remove("keys") detl.remove("keys")
detl.remove("settings") detl.remove("settings")
if os.path.exists(f"{folder_path2}pbwgk.pem"): if os.path.exists(dirname2 + "pbwgk.pem"):
detl.remove("pbwgk.pem") detl.remove("pbwgk.pem")
for detunnels in detl: for detunnels in detl:
tlname2 = f"{detunnels[:-4]}.conf" tlname2 = detunnels[:-4] + ".conf"
extpath = f"{folder_path}/{tlname2}" extpath = str(dirname) + "/" + tlname2
check_call(["openssl", "pkeyutl", "-decrypt", "-inkey", PKEYFILE, "-in", detunnels, "-out", extpath]) check_call(
[
"openssl",
"pkeyutl",
"-decrypt",
"-inkey",
PKEYFILE,
"-in",
detunnels,
"-out",
extpath,
]
)
shutil.chown(extpath, 1000, 1000) shutil.chown(extpath, 1000, 1000)

View File

@ -6,42 +6,78 @@ import shutil
from pathlib import Path from pathlib import Path
from subprocess import check_call from subprocess import check_call
uname: Path = Path("/tmp/.log_user") uname = Path("/tmp/.loguser")
with open(uname, "r", encoding="utf-8") as f: with open(uname, "r", encoding="utf-8") as f:
log_name: str = f.readline() logname = f.readline()
keyfile: Path = Path(f"/home/{log_name}/.config/wire_py/pbwgk.pem") keyfile = Path(f"/home/{logname}/.config/wire_py/pbwgk.pem")
folder_path: Path = Path("/tmp/tlecdcwg/") dirname = Path("/tmp/tlecdcwg/")
PKEYFILE = "/usr/local/etc/ssl/pwgk.pem" PKEYFILE = "/usr/local/etc/ssl/pwgk.pem"
if not keyfile.is_file(): if not keyfile.is_file():
check_call(["openssl", "rsa", "-in", PKEYFILE, "-out", keyfile, "-outform", "PEM", "-pubout"]) check_call(
[
"openssl",
"rsa",
"-in",
PKEYFILE,
"-out",
keyfile,
"-outform",
"PEM",
"-pubout",
]
)
shutil.chown(keyfile, 1000, 1000) shutil.chown(keyfile, 1000, 1000)
if folder_path.exists(): if dirname.exists():
tl = os.listdir(f"{folder_path}") tl = os.listdir(str(dirname))
CPTH: str = f"{keyfile}" CPTH = str(keyfile)
CRYPTFILES: str = CPTH[:-9] CRYPTFILES = CPTH[:-9]
if keyfile.exists() and len(tl) != 0: if keyfile.exists() and len(tl) != 0:
for tunnels in tl: for tunnels in tl:
sourcetl: str = f"{folder_path}/{tunnels}" sourcetl = str(dirname) + "/" + tunnels
tlname: str = f"{CRYPTFILES}{tunnels[:-5]}.dat" tlname = CRYPTFILES + tunnels[:-5] + ".dat"
check_call(["openssl", "pkeyutl", "-encrypt", "-inkey", keyfile, "-pubin", "-in", sourcetl, "-out", check_call(
tlname,]) [
"openssl",
"pkeyutl",
"-encrypt",
"-inkey",
keyfile,
"-pubin",
"-in",
sourcetl,
"-out",
tlname,
]
)
else: else:
if folder_path.exists(): if dirname.exists():
tl: list[str] = os.listdir(f"{folder_path}") tl = os.listdir(str(dirname))
CPTH: str = f"{keyfile}" CPTH = str(keyfile)
CRYPTFILES: str = CPTH[:-9] CRYPTFILES = CPTH[:-9]
if keyfile.exists() and len(tl) != 0: if keyfile.exists() and len(tl) != 0:
for tunnels in tl: for tunnels in tl:
sourcetl: str = f"{folder_path}/{tunnels}" sourcetl = str(dirname) + "/" + tunnels
tlname: str = f"{CRYPTFILES}{tunnels[:-5]}.dat" tlname = CRYPTFILES + tunnels[:-5] + ".dat"
check_call(["openssl", "pkeyutl", "-encrypt", "-inkey", keyfile, "-pubin", "-in", sourcetl, "-out", check_call(
tlname]) [
"openssl",
"pkeyutl",
"-encrypt",
"-inkey",
keyfile,
"-pubin",
"-in",
sourcetl,
"-out",
tlname,
]
)

View File

@ -8,8 +8,8 @@ from subprocess import check_call
path_to_file = Path(Path.home() / ".config/wire_py/settings") path_to_file = Path(Path.home() / ".config/wire_py/settings")
with open(path_to_file, "r", encoding="utf-8") as a_con: with open(path_to_file, "r", encoding="utf-8") as a_con:
# This function is for the independent autostarted of the previously selected tunnel # This funtion is for the independent autostart of the previously selected tunnel
lines = a_con.readlines() lines = a_con.readlines()
a_con = lines[7].strip() a_con = lines[7].strip()
if a_con != "off": if a_con != "off":

1169
wirepy.py

File diff suppressed because it is too large Load Diff