Compare commits
33 Commits
main
...
28-04-2025
Author | SHA1 | Date | |
---|---|---|---|
0cdad100b6 | |||
2cdc40f414 | |||
2311661735 | |||
c10667ec21 | |||
08bef8fe6e | |||
2e94a324a6 | |||
18ed97bf20 | |||
5dcfc91621 | |||
5fb4e68867 | |||
19d413ea97 | |||
213f772f40 | |||
6f02724daa | |||
53f66ea76d | |||
3039dbecb0 | |||
eadc2a06bf | |||
4eb9d6acd4 | |||
97ea07d34b | |||
cd625d173d | |||
950e04a246 | |||
1a853d4ff1 | |||
f6204c9071 | |||
f9ecd54e0a | |||
67ff24f0b6 | |||
af702f297b | |||
d2a57b329b | |||
87943b2489 | |||
c43c12f961 | |||
3bab0710a4 | |||
aa66f4dc68 | |||
c220951781 | |||
6c0662c62c | |||
5753a35d6c | |||
47bdfbfb17 |
3
.idea/dictionaries/project.xml
generated
Normal file
3
.idea/dictionaries/project.xml
generated
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<component name="ProjectDictionaryState">
|
||||||
|
<dictionary name="project" />
|
||||||
|
</component>
|
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@ -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 (wire-py)" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12" project-jdk-type="Python SDK" />
|
||||||
</project>
|
</project>
|
2
.idea/wire-py.iml
generated
2
.idea/wire-py.iml
generated
@ -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="inheritedJdk" />
|
<orderEntry type="jdk" jdkName="Python 3.12" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
50
.idea/workspace.xml
generated
50
.idea/workspace.xml
generated
@ -5,8 +5,12 @@
|
|||||||
</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 afterPath="$PROJECT_DIR$/.vscode/settings.json" 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$/ssl_decrypt.py" beforeDir="false" afterPath="$PROJECT_DIR$/ssl_decrypt.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/ssl_encrypt.py" beforeDir="false" afterPath="$PROJECT_DIR$/ssl_encrypt.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/wirepy.py" beforeDir="false" afterPath="$PROJECT_DIR$/wirepy.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/wp_app_config.py" beforeDir="false" afterPath="$PROJECT_DIR$/wp_app_config.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,14 +34,13 @@
|
|||||||
<option name="UPDATE_TYPE" value="REBASE" />
|
<option name="UPDATE_TYPE" value="REBASE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="HighlightingSettingsPerFile">
|
<component name="HighlightingSettingsPerFile">
|
||||||
<setting file="file://$PROJECT_DIR$/wg_func.py" root0="SKIP_INSPECTION" />
|
<setting file="file:///usr/local/bin/ssl_decrypt.py" root0="SKIP_INSPECTION" />
|
||||||
<setting file="file://$PROJECT_DIR$/wg_main.py" root0="FORCE_HIGHLIGHTING" />
|
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectColorInfo">{
|
<component name="ProjectColorInfo">{
|
||||||
"associatedIndex": 3
|
"associatedIndex": 3
|
||||||
}</component>
|
}</component>
|
||||||
<component name="ProjectId" id="2kSbZdjOvr0wsVJSNcaMwSfVaxR" />
|
<component name="ProjectId" id="2kSbZdjOvr0wsVJSNcaMwSfVaxR" />
|
||||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true">
|
<component name="ProjectLevelVcsManager">
|
||||||
<ConfirmationsSetting value="2" id="Add" />
|
<ConfirmationsSetting value="2" id="Add" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectViewState">
|
<component name="ProjectViewState">
|
||||||
@ -48,6 +51,7 @@
|
|||||||
"keyToString": {
|
"keyToString": {
|
||||||
"ASKED_ADD_EXTERNAL_FILES": "true",
|
"ASKED_ADD_EXTERNAL_FILES": "true",
|
||||||
"Python.INSTALL.executor": "Run",
|
"Python.INSTALL.executor": "Run",
|
||||||
|
"Python.cls_mth_fc.executor": "Run",
|
||||||
"Python.install.executor": "Run",
|
"Python.install.executor": "Run",
|
||||||
"Python.main.executor": "Run",
|
"Python.main.executor": "Run",
|
||||||
"Python.messagebox.executor": "Run",
|
"Python.messagebox.executor": "Run",
|
||||||
@ -55,12 +59,14 @@
|
|||||||
"Python.testtheme.executor": "Run",
|
"Python.testtheme.executor": "Run",
|
||||||
"Python.wg_func.executor": "Run",
|
"Python.wg_func.executor": "Run",
|
||||||
"Python.wg_main.executor": "Run",
|
"Python.wg_main.executor": "Run",
|
||||||
|
"Python.wirepy.executor": "Run",
|
||||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
|
"RunOnceActivity.git.unshallow": "true",
|
||||||
"Shell Script.install.executor": "Run",
|
"Shell Script.install.executor": "Run",
|
||||||
"Shell Script.run_as.executor": "Run",
|
"Shell Script.run_as.executor": "Run",
|
||||||
"git-widget-placeholder": "1.11.1024",
|
"git-widget-placeholder": "28-04-2025-more-methods-and-optimize-methods",
|
||||||
"last_opened_file_path": "/home/punix/Pyapps/wire-py",
|
"last_opened_file_path": "/home/punix/Pyapps/wire-py",
|
||||||
"settings.editor.selected.configurable": "reference.settingsdialog.IDE.editor.colors"
|
"settings.editor.selected.configurable": "ml.llm.LLMConfigurable"
|
||||||
}
|
}
|
||||||
}</component>
|
}</component>
|
||||||
<component name="RecentsManager">
|
<component name="RecentsManager">
|
||||||
@ -75,7 +81,7 @@
|
|||||||
<recent name="$PROJECT_DIR$/wire-py" />
|
<recent name="$PROJECT_DIR$/wire-py" />
|
||||||
</key>
|
</key>
|
||||||
</component>
|
</component>
|
||||||
<component name="RunManager" selected="Python.wg_main">
|
<component name="RunManager" selected="Python.wirepy">
|
||||||
<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="" />
|
||||||
@ -120,8 +126,31 @@
|
|||||||
<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>
|
||||||
@ -129,7 +158,7 @@
|
|||||||
<component name="SharedIndexes">
|
<component name="SharedIndexes">
|
||||||
<attachedChunks>
|
<attachedChunks>
|
||||||
<set>
|
<set>
|
||||||
<option value="bundled-python-sdk-8336bb23522e-31b6be0877a2-com.jetbrains.pycharm.community.sharedIndexes.bundled-PC-241.19072.16" />
|
<option value="bundled-python-sdk-348a24fa61fa-5312c7369657-com.jetbrains.pycharm.community.sharedIndexes.bundled-PC-251.23774.444" />
|
||||||
</set>
|
</set>
|
||||||
</attachedChunks>
|
</attachedChunks>
|
||||||
</component>
|
</component>
|
||||||
@ -600,6 +629,11 @@
|
|||||||
<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>
|
||||||
|
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"workbench.settings.openDefaultSettings": true
|
||||||
|
}
|
@ -41,7 +41,7 @@ My standard System: Linux Mint 22 Cinnamon
|
|||||||
|
|
||||||
- Fix ipv6 in Config File on import
|
- Fix ipv6 in Config File on import
|
||||||
- Wirepy run now as user
|
- Wirepy run now as user
|
||||||
- settings, keys and Config Files now in ~/.config/wire_py
|
- settings, AppConfig.KEYS_FILE and Config Files now in ~/.config/wire_py
|
||||||
- For new users, the required files are created and autostart service is started.
|
- For new users, the required files are created and autostart service is started.
|
||||||
- Tunnels are now read from the directory to view them in the list.
|
- Tunnels are now read from the directory to view them in the list.
|
||||||
To display only own tunnels, and read errors are minimized.
|
To display only own tunnels, and read errors are minimized.
|
||||||
|
Binary file not shown.
BIN
__pycache__/manage_tunnel.cpython-312.pyc
Normal file
BIN
__pycache__/manage_tunnel.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/wp_app_config.cpython-312.pyc
Normal file
BIN
__pycache__/wp_app_config.cpython-312.pyc
Normal file
Binary file not shown.
516
cls_mth_fc.py
516
cls_mth_fc.py
@ -4,25 +4,21 @@ 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
|
from subprocess import check_call, CompletedProcess
|
||||||
from tkinter import ttk
|
from tkinter import ttk, Toplevel
|
||||||
|
from wp_app_config import AppConfig, Msg
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
APP = "wirepy"
|
# Translate
|
||||||
LOCALE_DIR = "/usr/share/locale/"
|
_ = AppConfig.setup_translations()
|
||||||
locale.bindtextdomain(APP, LOCALE_DIR)
|
|
||||||
gettext.bindtextdomain(APP, LOCALE_DIR)
|
|
||||||
gettext.textdomain(APP)
|
|
||||||
_ = gettext.gettext
|
|
||||||
|
|
||||||
wg_set = Path(Path.home() / ".config/wire_py/settings")
|
|
||||||
|
|
||||||
|
|
||||||
class Create:
|
class Create:
|
||||||
"""
|
"""
|
||||||
@ -32,91 +28,82 @@ class Create:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def dir_and_files():
|
def dir_and_files() -> None:
|
||||||
"""
|
"""
|
||||||
check and create folders and files if not present
|
check and create folders and files if not present
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pth = Path.home() / ".config/wire_py"
|
pth: Path = Path.home() / ".config/wire_py"
|
||||||
pth.mkdir(parents=True, exist_ok=True)
|
pth.mkdir(parents=True, exist_ok=True)
|
||||||
sett = Path.home() / ".config/wire_py/settings"
|
sett: Path = Path.home() / ".config/wire_py/settings"
|
||||||
ks = Path.home() / ".config/wire_py/keys"
|
AppConfig.KEYS_FILE
|
||||||
|
|
||||||
if sett.exists():
|
if sett.exists():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
else:
|
else:
|
||||||
sett.touch()
|
sett.touch()
|
||||||
sett.write_text(
|
sett.write_text("[UPDATES]\non\n[THEME]\nlight\n[TOOLTIP]\nTrue\n[AUTOSTART ON]\noff\n")
|
||||||
"[UPDATES]\non\n[THEME]\nlight\n[TOOLTIP]\nTrue\n[AUTOSTART ON]\noff\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
if ks.exists():
|
if AppConfig.KEYS_FILE.exists():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
else:
|
else:
|
||||||
ks.touch()
|
AppConfig.KEYS_FILE.touch()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def files_for_autostart():
|
def files_for_autostart() -> None:
|
||||||
"""
|
"""
|
||||||
check and create file for auto start if not present and enable the service
|
check and create a file for auto start if not present and enable the service
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pth2 = Path.home() / ".config/systemd/user"
|
pth2: Path = Path.home() / ".config/systemd/user"
|
||||||
pth2.mkdir(parents=True, exist_ok=True)
|
pth2.mkdir(parents=True, exist_ok=True)
|
||||||
wg_ser = Path.home() / ".config/systemd/user/wg_start.service"
|
wg_ser: Path = 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(
|
wg_ser.write_text("[Unit]\nDescription=Automatic Tunnel Start\nAfter=network-online.target\n\n[Service]\n"
|
||||||
"[Unit]\nDescription=Automatic Tunnel Start\nAfter=network-online.target"
|
"Type=oneshot\nExecStartPre=/bin/sleep 5\nExecStart=/usr/local/bin/start_wg.py\n[Install]"
|
||||||
"\n\n[Service]\nType=oneshot\nExecStartPre=/bin/sleep 5\nExecStart=/usr/"
|
"\nWantedBy=default.target")
|
||||||
"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():
|
def make_dir() -> None:
|
||||||
"""Dirname "tlecdewg" = Tunnel Encrypt Decrypt Wireguard"""
|
"""Folder Name "tlecdewg" = Tunnel Encrypt Decrypt Wireguard"""
|
||||||
|
|
||||||
dirname = Path("/tmp/tlecdcwg/")
|
if AppConfig.TEMP_DIR.exists():
|
||||||
if dirname.exists():
|
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
dirname.mkdir()
|
AppConfig.TEMP_DIR.mkdir()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def decrypt():
|
def decrypt() -> None:
|
||||||
"""
|
"""
|
||||||
This start ssl_decrypt file
|
Starts SSL dencrypt
|
||||||
"""
|
"""
|
||||||
process = subprocess.run(
|
process: CompletedProcess[str] = subprocess.run(["pkexec", "/usr/local/bin/ssl_decrypt.py"],
|
||||||
["pkexec", "/usr/local/bin/ssl_decrypt.py"],
|
stdout=subprocess.PIPE, text=True, check=True)
|
||||||
stdout=subprocess.PIPE,
|
path: Path = Path.home() / ".config/wire_py/"
|
||||||
text=True,
|
file_in_path: list[Path] = list(path.rglob("*.dat"))
|
||||||
check=True,
|
if file_in_path:
|
||||||
)
|
|
||||||
# print(process.stdout)
|
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
print("File successfully decrypted...")
|
print("File successfully decrypted...")
|
||||||
else:
|
else:
|
||||||
print(f"Error with the following code... {process.returncode}")
|
print(f"Error with the following code... {process.returncode}")
|
||||||
|
else:
|
||||||
|
print(_("Ready for import"))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def encrypt():
|
def encrypt() -> None:
|
||||||
"""
|
"""
|
||||||
this start ssl_encrypt file
|
Starts SSL encryption
|
||||||
"""
|
"""
|
||||||
process = subprocess.run(
|
process: CompletedProcess[str] = subprocess.run(["pkexec", "/usr/local/bin/ssl_encrypt.py"],
|
||||||
["pkexec", "/usr/local/bin/ssl_encrypt.py"],
|
stdout=subprocess.PIPE, text=True, check=True)
|
||||||
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...")
|
||||||
@ -124,147 +111,177 @@ class Create:
|
|||||||
print(f"Error with the following code... {process.returncode}")
|
print(f"Error with the following code... {process.returncode}")
|
||||||
|
|
||||||
|
|
||||||
def uos():
|
class LxTools(tk.Tk):
|
||||||
|
"""
|
||||||
|
Class LinuxTools methods that can also be used for other apps
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_file_name(path: Path, i: int = 5) -> List[str]:
|
||||||
|
"""
|
||||||
|
Recursively searches the specified path for files and returns a list of filenames,
|
||||||
|
with the last 'i' characters of each filename removed.
|
||||||
|
|
||||||
|
This method is useful for obtaining filenames without specific file extensions,
|
||||||
|
e.g., to remove '.conf' from Wireguard configuration files.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path (Path): The directory path to search
|
||||||
|
i (int, optional): Number of characters to remove from the end of each filename.
|
||||||
|
Default is 5, which typically corresponds to the length of '.conf'.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List[str]: A list of filenames without the last 'i' characters
|
||||||
|
|
||||||
|
Example:
|
||||||
|
If path contains files like 'tunnel1.conf', 'tunnel2.conf' and i=5,
|
||||||
|
the method returns ['tunnel1', 'tunnel2'].
|
||||||
|
"""
|
||||||
|
lists_file = list(path.rglob("*"))
|
||||||
|
lists_file = [conf_file.name[:-i] for conf_file in lists_file]
|
||||||
|
return lists_file
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def uos() -> None:
|
||||||
|
"""
|
||||||
uos = LOGIN USERNAME
|
uos = LOGIN USERNAME
|
||||||
|
|
||||||
This method displays the user name of the logged-in user,
|
This method displays the username of the logged-in user,
|
||||||
even if you are rooted in a shell
|
even if you are rooted in a shell
|
||||||
"""
|
"""
|
||||||
logname = str(Path.home())[6:]
|
log_name: str = f"{Path.home()}"[6:]
|
||||||
file = Path.home() / "/tmp/.loguser"
|
file: Path = Path.home() / "/tmp/.log_user"
|
||||||
with open(file, "w", encoding="utf-8") as f:
|
Path(file).write_text(log_name, encoding="utf-8")
|
||||||
f.write(logname)
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
"""
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def api_down(update_api_url, version):
|
def clean_files(TEMP_DIR: Path = None, file: Path = None) -> None:
|
||||||
"""
|
"""
|
||||||
Calling api_down requests the URL and the version of the running script.
|
method that can be added after need to delete a folder and a file when quitting.
|
||||||
Example: version = 'v. 1.1.1.1' GiteaUpdate.api_down(http://example.de, version)
|
Args:
|
||||||
|
:param file: default None
|
||||||
|
:param AppConfig.TEMP_DIR: default None
|
||||||
"""
|
"""
|
||||||
try:
|
if AppConfig.TEMP_DIR is not None:
|
||||||
response = requests.get(update_api_url, timeout=10)
|
shutil.rmtree(AppConfig.TEMP_DIR)
|
||||||
response_dict = response.json()
|
if file is not None:
|
||||||
response_dict = response_dict[0]
|
Path.unlink(file)
|
||||||
with open(wg_set, "r", encoding="utf-8") as set_file:
|
|
||||||
set_file = set_file.read()
|
|
||||||
if "on\n" in set_file:
|
|
||||||
if version[3:] != response_dict["tag_name"]:
|
|
||||||
req = response_dict["tag_name"]
|
|
||||||
else:
|
|
||||||
req = "No Updates"
|
|
||||||
else:
|
|
||||||
req = "False"
|
|
||||||
return req
|
|
||||||
except requests.exceptions.RequestException:
|
|
||||||
req = "No Internet Connection!"
|
|
||||||
return req
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def download(urld, down_ok_image, down_not_ok_image, res):
|
def if_tip(path: Path) -> bool:
|
||||||
"""
|
"""
|
||||||
this is for download new Version of wirepy
|
method that writes in file whether tooltip is displayed or not
|
||||||
"""
|
"""
|
||||||
try:
|
lines = Path(path).read_text(encoding="utf-8")
|
||||||
to_down = "wget -qP " + str(Path.home()) + " " + urld
|
if "False\n" in lines:
|
||||||
result = subprocess.call(to_down, shell=True)
|
tip = False
|
||||||
if result == 0:
|
|
||||||
shutil.chown(str(Path.home()) + f"/{res}.zip", 1000, 1000)
|
|
||||||
|
|
||||||
# img_w, img_i, w_title, w_txt hand over
|
|
||||||
iw = r"/usr/share/icons/lx-icons/64/info.png"
|
|
||||||
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:
|
||||||
|
tip = True
|
||||||
|
return tip
|
||||||
|
|
||||||
# img_w, img_i, w_title, w_txt hand over
|
@staticmethod
|
||||||
iw = r"/usr/share/icons/lx-icons/64/error.png"
|
def msg_window(image_path: Path, image_path2: Path, w_title: str, w_txt: str, txt2: Optional[str] = None,
|
||||||
ii = down_not_ok_image
|
com: Optional[str] = None) -> None:
|
||||||
wt = _("Download error")
|
|
||||||
msg_t = _("Download failed! Please try again")
|
|
||||||
msg_window(iw, ii, wt, msg_t)
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
|
|
||||||
# img_w, img_i, w_title, w_txt hand over
|
|
||||||
iw = r"/usr/share/icons/lx-icons/64/error.png"
|
|
||||||
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.
|
Creates message windows
|
||||||
To create messages with your own images, icons, and titles.
|
|
||||||
As an alternative to Python Messagebox.
|
:argument AppConfig.IMAGE_PATHS["icon_info"] = Image for TK window which is displayed to the left of the text
|
||||||
Paths to images must be specified: r'/usr/share/icons/lx-icons/64/info.png'
|
:argument AppConfig.IMAGE_PATHS["icon_vpn"] = Image for Task Icon
|
||||||
img_w = Image for Tk Window
|
:argument w_title = Windows Title
|
||||||
img_i = Image for Icon
|
:argument w_txt = Text for Tk Window
|
||||||
w_title = Windows Title
|
:argument txt2 = Text for Button two
|
||||||
w_txt = Text for Tk Window
|
:argument com = function for Button command
|
||||||
txt2 = Text for Button two
|
|
||||||
com = function for Button command
|
|
||||||
"""
|
"""
|
||||||
msg = tk.Toplevel()
|
msg: tk.Toplevel = tk.Toplevel()
|
||||||
msg.resizable(width=False, height=False)
|
msg.resizable(width=False, height=False)
|
||||||
msg.title(w_title)
|
msg.title(w_title)
|
||||||
msg.configure(pady=15, padx=15)
|
msg.configure(pady=15, padx=15)
|
||||||
msg.img = tk.PhotoImage(file=img_w)
|
msg.img = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_info"])
|
||||||
msg.i_window = tk.Label(msg, image=msg.img)
|
msg.i_window = tk.Label(msg, image=msg.img)
|
||||||
|
|
||||||
label = tk.Label(msg, text=w_txt)
|
label: tk.Label = tk.Label(msg, text=w_txt)
|
||||||
|
|
||||||
label.grid(column=1, row=0)
|
label.grid(column=1, row=0)
|
||||||
|
|
||||||
if txt2 is not None and com is not None:
|
if txt2 is not None and com is not None:
|
||||||
label.config(font=("Ubuntu", 11), padx=15, justify="left")
|
label.config(font=("Ubuntu", 11), padx=15, justify="left")
|
||||||
msg.i_window.grid(column=0, row=0, sticky="nw")
|
msg.i_window.grid(column=0, row=0, sticky="nw")
|
||||||
button2 = ttk.Button(msg, text=f"{txt2}", command=com, padding=4)
|
button2: ttk.Button = ttk.Button(msg, text=f"{txt2}", command=com, padding=4)
|
||||||
button2.grid(column=0, row=1, sticky="e", columnspan=2)
|
button2.grid(column=0, row=1, sticky="e", columnspan=2)
|
||||||
button = ttk.Button(msg, text="OK", command=msg.destroy, padding=4)
|
button: ttk.Button = ttk.Button(msg, text="OK", command=msg.destroy, padding=4)
|
||||||
button.grid(column=0, row=1, sticky="w", columnspan=2)
|
button.grid(column=0, row=1, sticky="w", columnspan=2)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
label.config(font=("Ubuntu", 11), padx=15)
|
label.config(font=("Ubuntu", 11), padx=15)
|
||||||
msg.i_window.grid(column=0, row=0)
|
msg.i_window.grid(column=0, row=0)
|
||||||
button = ttk.Button(msg, text="OK", command=msg.destroy, padding=4)
|
button: ttk.Button = ttk.Button(msg, text="OK", command=msg.destroy, padding=4)
|
||||||
button.grid(column=0, columnspan=2, row=1)
|
button.grid(column=0, columnspan=2, row=1)
|
||||||
|
|
||||||
img_i = tk.PhotoImage(file=img_i)
|
AppConfig.IMAGE_PATHS["icon_vpn"]: tk.PhotoImage = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_vpn"])
|
||||||
msg.iconphoto(True, img_i)
|
msg.iconphoto(True, AppConfig.IMAGE_PATHS["icon_vpn"])
|
||||||
msg.columnconfigure(0, weight=1)
|
msg.columnconfigure(0, weight=1)
|
||||||
msg.rowconfigure(0, weight=1)
|
msg.rowconfigure(0, weight=1)
|
||||||
msg.winfo_toplevel()
|
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 Tunnel:
|
class Tunnel:
|
||||||
"""
|
"""
|
||||||
Class of Methods for Wire-Py
|
Class of Methods for Wire-Py
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def con_to_dict(cls, file):
|
def con_to_dict(cls, file: TextIO) -> Tuple[str, str, str, Optional[str]]:
|
||||||
"""
|
"""
|
||||||
The config file is packed into a dictionary,
|
Returns tuple of (address, dns, endpoint, pre_key)
|
||||||
to display the values Address , DNS and Peer in the labels
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
dictlist = []
|
dictlist: List[str] = []
|
||||||
for lines in file.readlines():
|
for lines in file.readlines():
|
||||||
line_plit = lines.split()
|
line_plit: List[str] = lines.split()
|
||||||
dictlist = dictlist + line_plit
|
dictlist = dictlist + line_plit
|
||||||
dictlist.remove("[Interface]")
|
dictlist.remove("[Interface]")
|
||||||
dictlist.remove("[Peer]")
|
dictlist.remove("[Peer]")
|
||||||
@ -276,41 +293,37 @@ 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 = [dictlist[0], dictlist[1]]
|
a: List[str] = [dictlist[0], dictlist[1]]
|
||||||
b = [dictlist[2], dictlist[3]]
|
b: List[str] = [dictlist[2], dictlist[3]]
|
||||||
c = [dictlist[4], dictlist[5]]
|
c: List[str] = [dictlist[4], dictlist[5]]
|
||||||
d = [dictlist[6], dictlist[7]]
|
d: List[str] = [dictlist[6], dictlist[7]]
|
||||||
e = [dictlist[8], dictlist[9]]
|
e: List[str] = [dictlist[8], dictlist[9]]
|
||||||
f = [dictlist[10], dictlist[11]]
|
f: List[str] = [dictlist[10], dictlist[11]]
|
||||||
g = [dictlist[12], dictlist[13]]
|
g: List[str] = [dictlist[12], dictlist[13]]
|
||||||
h = [dictlist[14], dictlist[15]]
|
h: List[str] = [dictlist[14], dictlist[15]]
|
||||||
new_list = [a, b, c, d, e, f, g, h]
|
new_list: List[List[str]] = [a, b, c, d, e, f, g, h]
|
||||||
final_dict = {}
|
final_dict: Dict[str, str] = {}
|
||||||
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 = final_dict["Address"]
|
address: str = final_dict["Address"]
|
||||||
dns = final_dict["DNS"]
|
dns: str = final_dict["DNS"]
|
||||||
if "," in dns:
|
if "," in dns:
|
||||||
dns = dns[:-1]
|
dns = dns[:-1]
|
||||||
endpoint = final_dict["Endpoint"]
|
endpoint: str = final_dict["Endpoint"]
|
||||||
pre_key = final_dict.get("PresharedKey")
|
pre_key: Optional[str] = final_dict.get("PresharedKey")
|
||||||
if pre_key is None:
|
if pre_key is None:
|
||||||
pre_key = final_dict.get("PreSharedKey")
|
pre_key: Optional[str] = final_dict.get("PreSharedKey")
|
||||||
return address, dns, endpoint, pre_key
|
return address, dns, endpoint, pre_key
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def active():
|
def active() -> str:
|
||||||
"""
|
"""
|
||||||
Shows the Active Tunnel
|
Shows the Active Tunnel
|
||||||
"""
|
"""
|
||||||
active = (
|
active = (os.popen('nmcli con show --active | grep -iPo "(.*)(wireguard)"').read().split())
|
||||||
os.popen('nmcli con show --active | grep -iPo "(.*)(wireguard)"')
|
|
||||||
.read()
|
|
||||||
.split()
|
|
||||||
)
|
|
||||||
if not active:
|
if not active:
|
||||||
active = ""
|
active = ""
|
||||||
else:
|
else:
|
||||||
@ -319,111 +332,182 @@ class Tunnel:
|
|||||||
return active
|
return active
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def list():
|
def list() -> List[str]:
|
||||||
"""
|
"""
|
||||||
Shows all existing Wireguard tunnels a login user
|
Returns a list of Wireguard tunnel names
|
||||||
"""
|
"""
|
||||||
dirname = Path("/tmp/tlecdcwg/")
|
AppConfig.TEMP_DIR: Path = Path("/tmp/tlecdcwg/")
|
||||||
wg_s = os.listdir(dirname)
|
wg_s: List[str] = os.listdir(AppConfig.TEMP_DIR)
|
||||||
|
|
||||||
return wg_s
|
return wg_s
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def export():
|
def export(image_path: Path = None, image_path2: Path = None, image_path3: Path = None, image_path4: Path = None,
|
||||||
|
title: Dict = None, window_msg: Dict = None) -> None:
|
||||||
"""
|
"""
|
||||||
This will export the tunnels.
|
This will export the tunnels.
|
||||||
A zipfile with current date and time is created
|
A zipfile with the current date and time is created
|
||||||
in the user's home directory with correct right
|
in the user's home directory with the correct right
|
||||||
|
Args:
|
||||||
|
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
|
||||||
"""
|
"""
|
||||||
now_time = datetime.now()
|
now_time: datetime = datetime.now()
|
||||||
now_datetime = now_time.strftime("wg-exp-" + "%m-%d-%Y" + "-" + "%H:%M")
|
now_datetime: str = now_time.strftime("wg-exp-%m-%d-%Y-%H:%M")
|
||||||
tl = Tunnel.list()
|
tl: List[str] = Tunnel.list()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if len(tl) != 0:
|
if len(tl) != 0:
|
||||||
wg_tar = str(Path.home()) + "/" + now_datetime
|
wg_tar: str = f"{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("/tmp/wire_py")
|
source: Path = 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((wg_tar + ".zip"), "r") as zf:
|
with zipfile.ZipFile(f"{wg_tar}.zip", "r") as zf:
|
||||||
if len(zf.namelist()) != 0:
|
if len(zf.namelist()) != 0:
|
||||||
|
|
||||||
# img_w, img_i, w_title, w_txt hand over
|
LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_info"], AppConfig.IMAGE_PATHS["icon_vpn"], Msg.STR["exp_succ"], Msg.STR["exp_in_home"])
|
||||||
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:
|
||||||
|
|
||||||
# img_w, img_i, w_title, w_txt hand over
|
LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_error"], AppConfig.IMAGE_PATHS["icon_msg"], Msg.STR["exp_err"], Msg.STR["exp_try"])
|
||||||
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:
|
||||||
|
|
||||||
# img_w, img_i, w_title, w_txt hand over
|
LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_info"], AppConfig.IMAGE_PATHS["icon_msg"], Msg.STR["sel_tl"], Msg.STR["tl_first"])
|
||||||
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):
|
class GiteaUpdate:
|
||||||
"""
|
"""
|
||||||
method that writes in file whether tooltip is displayed or not
|
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
|
||||||
"""
|
"""
|
||||||
with open(path, "r", encoding="utf-8") as set_file2:
|
|
||||||
lines2 = set_file2.readlines()
|
@staticmethod
|
||||||
if "False\n" in lines2:
|
def api_down(update_api_url: str, version: str, file: Optional[Path] = None) -> str:
|
||||||
tip = False
|
"""
|
||||||
|
Checks for updates via API
|
||||||
|
|
||||||
|
Args:
|
||||||
|
update_api_url: Update API URL
|
||||||
|
version: Current version
|
||||||
|
file: Optional - Configuration file
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
New version or status message
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
response: requests.Response = requests.get(update_api_url, timeout=10)
|
||||||
|
response_dict: Any = response.json()
|
||||||
|
response_dict: Dict[str, Any] = response_dict[0]
|
||||||
|
with open(file, "r", encoding="utf-8") as set_f:
|
||||||
|
set_f = set_f.read()
|
||||||
|
if "on\n" in set_f:
|
||||||
|
if version[3:] != response_dict["tag_name"]:
|
||||||
|
req: str = response_dict["tag_name"]
|
||||||
else:
|
else:
|
||||||
tip = True
|
req: str = "No Updates"
|
||||||
return tip
|
else:
|
||||||
|
req: str = "False"
|
||||||
|
return req
|
||||||
|
except requests.exceptions.RequestException:
|
||||||
|
req: str = "No Internet Connection!"
|
||||||
|
return req
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def download(urld: str, res: str, image_path: Path = None, image_path2: Path = None, image_path3: Path = None,
|
||||||
|
image_path4: Path = None) -> None:
|
||||||
|
"""
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
to_down: str = f"wget -qP {Path.home()} {" "} {urld}"
|
||||||
|
result: int = subprocess.call(to_down, shell=True)
|
||||||
|
if result == 0:
|
||||||
|
shutil.chown(f"{Path.home()}/{res}.zip", 1000, 1000)
|
||||||
|
|
||||||
|
wt: str = _("Download Successful")
|
||||||
|
msg_t: str = _("Your zip file is in home directory")
|
||||||
|
LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_info"], AppConfig.IMAGE_PATHS["icon_vpn"], wt, msg_t)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
wt: str = _("Download error")
|
||||||
|
msg_t: str = _("Download failed! Please try again")
|
||||||
|
LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_error"], AppConfig.IMAGE_PATHS["icon_msg"], wt, msg_t)
|
||||||
|
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
|
||||||
|
wt: str = _("Download error")
|
||||||
|
msg_t: str = _("Download failed! No internet connection!")
|
||||||
|
LxTools.msg_window(AppConfig.IMAGE_PATHS["icon_error"], AppConfig.IMAGE_PATHS["icon_msg"], wt, msg_t)
|
||||||
|
|
||||||
|
|
||||||
class Tooltip:
|
class Tooltip:
|
||||||
"""
|
"""
|
||||||
class for Tooltip
|
class for Tooltip
|
||||||
|
|
||||||
imoprt Tooltip
|
import Tooltip
|
||||||
|
|
||||||
example: Tooltip(label, "Show tooltip on label")
|
example: Tooltip(label, "Show tooltip on label")
|
||||||
examble: Tooltip(button, "Show tooltip on button")
|
example: Tooltip(button, "Show tooltip on button")
|
||||||
info: label and button is parrent.
|
info: label and button are parent.
|
||||||
"""
|
"""
|
||||||
def __init__(self, widget, text):
|
|
||||||
self.widget = widget
|
def __init__(self, widget: Any, text: str, tips: Optional[bool] = None) -> None:
|
||||||
self.text = text
|
"""
|
||||||
self.tooltip_window = 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("<Enter>", self.show_tooltip)
|
||||||
self.widget.bind("<Leave>", self.hide_tooltip)
|
self.widget.bind("<Leave>", self.hide_tooltip)
|
||||||
|
|
||||||
def show_tooltip(self, event=None):
|
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, y, _, _ = self.widget.bbox("insert")
|
x: int
|
||||||
x += self.widget.winfo_rootx() + 25
|
y: int
|
||||||
y += self.widget.winfo_rooty() + 20
|
cx: int
|
||||||
|
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(tw, text=self.text, relief="solid", borderwidth=1, padx=5, pady=5)
|
label: tk.Label = tk.Label(tw, text=self.text, background="lightgreen", foreground="black", relief="solid",
|
||||||
|
borderwidth=1, padx=5, pady=5)
|
||||||
label.grid()
|
label.grid()
|
||||||
|
self.tooltip_window.after(2200, lambda: tw.destroy())
|
||||||
|
|
||||||
def hide_tooltip(self, event=None):
|
def hide_tooltip(self, event: Optional[Any] = None) -> 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
|
||||||
|
|
||||||
|
|
10
install
10
install
@ -17,7 +17,7 @@ install_file_with(){
|
|||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
sudo apt install python3-tk && \
|
sudo apt install python3-tk && \
|
||||||
sudo cp -fv wirepy.py start_wg.py cls_mth_fc.py ssl_encrypt.py ssl_decrypt.py /usr/local/bin/ && \
|
sudo cp -fv wirepy.py start_wg.py wp_app_config.py cls_mth_fc.py ssl_encrypt.py ssl_decrypt.py /usr/local/bin/ && \
|
||||||
sudo cp -uR lx-icons /usr/share/icons/ && sudo cp -uR TK-Themes /usr/share/ && \
|
sudo cp -uR lx-icons /usr/share/icons/ && sudo cp -uR TK-Themes /usr/share/ && \
|
||||||
sudo cp -u languages/de/*.mo /usr/share/locale/de/LC_MESSAGES/ && \
|
sudo cp -u languages/de/*.mo /usr/share/locale/de/LC_MESSAGES/ && \
|
||||||
sudo cp -fv Wire-Py.desktop /usr/share/applications/ && \
|
sudo cp -fv Wire-Py.desktop /usr/share/applications/ && \
|
||||||
@ -43,7 +43,7 @@ install_arch_d(){
|
|||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
sudo pacman -S --noconfirm tk python3 python-requests && \
|
sudo pacman -S --noconfirm tk python3 python-requests && \
|
||||||
sudo cp -fv wirepy.py start_wg.py cls_mth_fc.py ssl_encrypt.py ssl_decrypt.py /usr/local/bin/ && \
|
sudo cp -fv wirepy.py start_wg.py wp_app_config.py cls_mth_fc.py ssl_encrypt.py ssl_decrypt.py /usr/local/bin/ && \
|
||||||
sudo cp -uR lx-icons /usr/share/icons/ && sudo cp -uR TK-Themes /usr/share/ && \
|
sudo cp -uR lx-icons /usr/share/icons/ && sudo cp -uR TK-Themes /usr/share/ && \
|
||||||
sudo cp -u languages/de/*.mo /usr/share/locale/de/LC_MESSAGES/ && \
|
sudo cp -u languages/de/*.mo /usr/share/locale/de/LC_MESSAGES/ && \
|
||||||
sudo cp -fv Wire-Py.desktop /usr/share/applications/ && \
|
sudo cp -fv Wire-Py.desktop /usr/share/applications/ && \
|
||||||
@ -120,7 +120,7 @@ install(){
|
|||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
sudo dnf install python3-tkinter -y
|
sudo dnf install python3-tkinter -y
|
||||||
sudo cp -fv wirepy.py start_wg.py cls_mth_fc.py ssl_encrypt.py ssl_decrypt.py /usr/local/bin/ && \
|
sudo cp -fv wirepy.py start_wg.py wp_app_config.py cls_mth_fc.py ssl_encrypt.py ssl_decrypt.py /usr/local/bin/ && \
|
||||||
sudo cp -uR lx-icons /usr/share/icons/ && sudo cp -uR TK-Themes /usr/share/ && \
|
sudo cp -uR lx-icons /usr/share/icons/ && sudo cp -uR TK-Themes /usr/share/ && \
|
||||||
sudo cp -u languages/de/*.mo /usr/share/locale/de/LC_MESSAGES/ && \
|
sudo cp -u languages/de/*.mo /usr/share/locale/de/LC_MESSAGES/ && \
|
||||||
sudo cp -fv Wire-Py.desktop /usr/share/applications/ && \
|
sudo cp -fv Wire-Py.desktop /usr/share/applications/ && \
|
||||||
@ -145,7 +145,7 @@ install(){
|
|||||||
rm -r ~/.config/wire_py && rm -r ~/.config/systemd
|
rm -r ~/.config/wire_py && rm -r ~/.config/systemd
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
sudo cp -fv wirepy.py start_wg.py cls_mth_fc.py ssl_encrypt.py ssl_decrypt.py /usr/local/bin/ && \
|
sudo cp -fv wirepy.py start_wg.py wp_app_config.py cls_mth_fc.py ssl_encrypt.py ssl_decrypt.py /usr/local/bin/ && \
|
||||||
sudo cp -uR lx-icons /usr/share/icons/ && sudo cp -uR TK-Themes /usr/share/ && \
|
sudo cp -uR lx-icons /usr/share/icons/ && sudo cp -uR TK-Themes /usr/share/ && \
|
||||||
sudo cp -u languages/de/*.mo /usr/share/locale/de/LC_MESSAGES/ && \
|
sudo cp -u languages/de/*.mo /usr/share/locale/de/LC_MESSAGES/ && \
|
||||||
sudo cp -fv Wire-Py.desktop /usr/share/applications/ && \
|
sudo cp -fv Wire-Py.desktop /usr/share/applications/ && \
|
||||||
@ -181,7 +181,7 @@ install(){
|
|||||||
|
|
||||||
remove(){
|
remove(){
|
||||||
sudo rm -f /usr/local/bin/wirepy /usr/local/bin/wirepy.py /usr/local/bin/start_wg.py \
|
sudo rm -f /usr/local/bin/wirepy /usr/local/bin/wirepy.py /usr/local/bin/start_wg.py \
|
||||||
/usr/local/bin/cls_mth_fc.py /usr/local/bin/ssl_encrypt.py /usr/local/bin/ssl_decrypt.py
|
/usr/local/bin/wp_app_config.py cls_mth_fc.py /usr/local/bin/ssl_encrypt.py /usr/local/bin/ssl_decrypt.py
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
exit 0
|
exit 0
|
||||||
|
15
manage_tunnel.py
Normal file
15
manage_tunnel.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
from pathlib import Path
|
||||||
|
from subprocess import check_call
|
||||||
|
from tkinter import filedialog, ttk
|
||||||
|
from cls_mth_fc import Create, LxTools
|
||||||
|
from wp_app_config import AppConfig, Msg
|
||||||
|
import gettext
|
||||||
|
import locale
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
from typing import Optional, Dict, Any, NoReturn, TextIO, Tuple, List
|
||||||
|
# Translate
|
||||||
|
_ = AppConfig.setup_translations()
|
||||||
|
|
@ -1,59 +1,34 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
""" This Script decrypt Wireguardfiles for Wirepy users """
|
""" This Script decrypt Wireguard files 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
|
||||||
|
from wp_app_config import AppConfig
|
||||||
|
|
||||||
uname = Path("/tmp/.loguser")
|
uname: Path = Path("/tmp/.log_user")
|
||||||
|
|
||||||
with open(uname, "r", encoding="utf-8") as f:
|
log_name = Path(uname).read_text(encoding="utf-8")
|
||||||
logname = f.readline()
|
|
||||||
|
|
||||||
# Dirname "tlecdewg" = Tunnel Encrypt Decrypt Wireguard
|
keyfile: Path = Path(f"/home/{log_name}/.config/wire_py/pbwgk.pem")
|
||||||
dirname = Path("/tmp/tlecdcwg/")
|
#PKEYFILE: Path = "/usr/local/etc/ssl/pwgk.pem"
|
||||||
keyfile = Path(f"/home/{logname}/.config/wire_py/pbwgk.pem")
|
|
||||||
PKEYFILE = "/usr/local/etc/ssl/pwgk.pem"
|
|
||||||
|
|
||||||
if not keyfile.is_file():
|
if not keyfile.is_file():
|
||||||
|
|
||||||
check_call(
|
check_call(["openssl", "rsa", "-in", AppConfig.SYSTEM_PATHS["pkey_path"], "-out", keyfile, "-outform", "PEM", "-pubout"])
|
||||||
[
|
|
||||||
"openssl",
|
|
||||||
"rsa",
|
|
||||||
"-in",
|
|
||||||
PKEYFILE,
|
|
||||||
"-out",
|
|
||||||
keyfile,
|
|
||||||
"-outform",
|
|
||||||
"PEM",
|
|
||||||
"-pubout",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
shutil.chown(keyfile, 1000, 1000)
|
shutil.chown(keyfile, 1000, 1000)
|
||||||
|
|
||||||
dirname2 = "/home/" + logname + "/.config/wire_py/"
|
AppConfig.TEMP_DIR2 = f"/home/{log_name}/.config/wire_py/"
|
||||||
detl = os.listdir(dirname2)
|
detl: list[str] = os.listdir(AppConfig.TEMP_DIR2)
|
||||||
os.chdir(dirname2)
|
os.chdir(AppConfig.TEMP_DIR2)
|
||||||
detl.remove("keys")
|
detl.remove("keys")
|
||||||
detl.remove("settings")
|
detl.remove("settings")
|
||||||
if os.path.exists(dirname2 + "pbwgk.pem"):
|
if os.path.exists(f"{AppConfig.TEMP_DIR2}pbwgk.pem"):
|
||||||
detl.remove("pbwgk.pem")
|
detl.remove("pbwgk.pem")
|
||||||
for detunnels in detl:
|
for detunnels in detl:
|
||||||
tlname2 = detunnels[:-4] + ".conf"
|
tlname2 = f"{detunnels[:-4]}.conf"
|
||||||
extpath = str(dirname) + "/" + tlname2
|
extpath = f"{AppConfig.TEMP_DIR}/{tlname2}"
|
||||||
check_call(
|
check_call(["openssl", "pkeyutl", "-decrypt", "-inkey", AppConfig.SYSTEM_PATHS["pkey_path"], "-in", detunnels,
|
||||||
[
|
"-out", extpath])
|
||||||
"openssl",
|
|
||||||
"pkeyutl",
|
|
||||||
"-decrypt",
|
|
||||||
"-inkey",
|
|
||||||
PKEYFILE,
|
|
||||||
"-in",
|
|
||||||
detunnels,
|
|
||||||
"-out",
|
|
||||||
extpath,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
shutil.chown(extpath, 1000, 1000)
|
shutil.chown(extpath, 1000, 1000)
|
||||||
|
@ -5,79 +5,42 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from subprocess import check_call
|
from subprocess import check_call
|
||||||
|
from cls_mth_fc import LxTools
|
||||||
|
from wp_app_config import AppConfig
|
||||||
|
|
||||||
uname = Path("/tmp/.loguser")
|
#uname: Path = Path("/tmp/.log_user")
|
||||||
|
|
||||||
with open(uname, "r", encoding="utf-8") as f:
|
#log_name = AppConfig.USER_FILE.read_text(encoding="utf-8")
|
||||||
logname = f.readline()
|
|
||||||
|
|
||||||
keyfile = Path(f"/home/{logname}/.config/wire_py/pbwgk.pem")
|
keyfile: Path = Path(f"/home/{AppConfig.USER_FILE.read_text(encoding="utf-8")}/.config/wire_py/pbwgk.pem")
|
||||||
dirname = Path("/tmp/tlecdcwg/")
|
|
||||||
PKEYFILE = "/usr/local/etc/ssl/pwgk.pem"
|
|
||||||
|
|
||||||
if not keyfile.is_file():
|
if not keyfile.is_file():
|
||||||
|
|
||||||
check_call(
|
check_call(["openssl", "rsa", "-in", AppConfig.SYSTEM_PATHS["pkey_path"], "-out", keyfile, "-outform", "PEM", "-pubout"])
|
||||||
[
|
|
||||||
"openssl",
|
|
||||||
"rsa",
|
|
||||||
"-in",
|
|
||||||
PKEYFILE,
|
|
||||||
"-out",
|
|
||||||
keyfile,
|
|
||||||
"-outform",
|
|
||||||
"PEM",
|
|
||||||
"-pubout",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
shutil.chown(keyfile, 1000, 1000)
|
shutil.chown(keyfile, 1000, 1000)
|
||||||
|
|
||||||
if dirname.exists():
|
if AppConfig.TEMP_DIR.exists():
|
||||||
tl = os.listdir(str(dirname))
|
tl = LxTools.get_file_name(AppConfig.TEMP_DIR)
|
||||||
CPTH = str(keyfile)
|
CPTH: str = f"{keyfile}"
|
||||||
CRYPTFILES = CPTH[:-9]
|
CRYPTFILES: str = 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(dirname) + "/" + tunnels
|
sourcetl: str = f"{AppConfig.TEMP_DIR}/{tunnels}"
|
||||||
tlname = CRYPTFILES + tunnels[:-5] + ".dat"
|
tlname: str = f"{CRYPTFILES}{tunnels[:-5]}.dat"
|
||||||
check_call(
|
check_call(["openssl", "pkeyutl", "-encrypt", "-inkey", keyfile, "-pubin", "-in", sourcetl, "-out",
|
||||||
[
|
tlname,])
|
||||||
"openssl",
|
|
||||||
"pkeyutl",
|
|
||||||
"-encrypt",
|
|
||||||
"-inkey",
|
|
||||||
keyfile,
|
|
||||||
"-pubin",
|
|
||||||
"-in",
|
|
||||||
sourcetl,
|
|
||||||
"-out",
|
|
||||||
tlname,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
if dirname.exists():
|
if AppConfig.TEMP_DIR.exists():
|
||||||
tl = os.listdir(str(dirname))
|
tl: list[str] = os.listdir(f"{AppConfig.TEMP_DIR}")
|
||||||
CPTH = str(keyfile)
|
CPTH: str = f"{keyfile}"
|
||||||
CRYPTFILES = CPTH[:-9]
|
CRYPTFILES: str = 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(dirname) + "/" + tunnels
|
sourcetl: str = f"{AppConfig.TEMP_DIR}/{tunnels}"
|
||||||
tlname = CRYPTFILES + tunnels[:-5] + ".dat"
|
tlname: str = f"{CRYPTFILES}{tunnels[:-5]}.dat"
|
||||||
check_call(
|
check_call(["openssl", "pkeyutl", "-encrypt", "-inkey", keyfile, "-pubin", "-in", sourcetl, "-out",
|
||||||
[
|
tlname])
|
||||||
"openssl",
|
|
||||||
"pkeyutl",
|
|
||||||
"-encrypt",
|
|
||||||
"-inkey",
|
|
||||||
keyfile,
|
|
||||||
"-pubin",
|
|
||||||
"-in",
|
|
||||||
sourcetl,
|
|
||||||
"-out",
|
|
||||||
tlname,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
11
start_wg.py
11
start_wg.py
@ -7,12 +7,9 @@ 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:
|
a_con = Path(path_to_file).read_text(encoding="utf-8").splitlines(keepends=True)
|
||||||
|
a_con = a_con[7].strip()
|
||||||
# This funtion is for the independent autostart of the previously selected tunnel
|
if a_con != "off":
|
||||||
lines = a_con.readlines()
|
|
||||||
a_con = lines[7].strip()
|
|
||||||
if a_con != "off":
|
|
||||||
check_call(["nmcli", "connection", "up", a_con])
|
check_call(["nmcli", "connection", "up", a_con])
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
178
wp_app_config.py
Normal file
178
wp_app_config.py
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""App configuration for Wire-Py"""
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import locale
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict, Any
|
||||||
|
|
||||||
|
class AppConfig:
|
||||||
|
"""Central configuration class for Wire-Py application"""
|
||||||
|
|
||||||
|
# Localization
|
||||||
|
APP_NAME: str = "wirepy"
|
||||||
|
LOCALE_DIR: Path = Path("/usr/share/locale/")
|
||||||
|
|
||||||
|
# Base paths
|
||||||
|
BASE_DIR: Path = Path.home()
|
||||||
|
CONFIG_DIR: Path = BASE_DIR / ".config/wire_py"
|
||||||
|
TEMP_DIR: Path = Path("/tmp/tlecdcwg")
|
||||||
|
USER_FILE: Path = Path("/tmp/.log_user")
|
||||||
|
|
||||||
|
# Configuration files
|
||||||
|
SETTINGS_FILE: Path = CONFIG_DIR / "settings"
|
||||||
|
KEYS_FILE: Path = CONFIG_DIR / "keys"
|
||||||
|
AUTOSTART_SERVICE: Path = Path.home() / ".config/systemd/user/wg_start.service"
|
||||||
|
|
||||||
|
# Default settings
|
||||||
|
DEFAULT_SETTINGS: Dict[str, Any] = {
|
||||||
|
"updates": "on",
|
||||||
|
"theme": "light",
|
||||||
|
"tooltip": True,
|
||||||
|
"autostart": "off"
|
||||||
|
}
|
||||||
|
|
||||||
|
# UI configuration
|
||||||
|
UI_CONFIG: Dict[str, Any] = {
|
||||||
|
"window_title": "Wire-Py",
|
||||||
|
"window_size": (600, 383),
|
||||||
|
"font_family": "Ubuntu",
|
||||||
|
"font_size": 11,
|
||||||
|
"resizable_window": (False, False)
|
||||||
|
}
|
||||||
|
|
||||||
|
# System-dependent paths
|
||||||
|
SYSTEM_PATHS: Dict[str, str]= {
|
||||||
|
"ssl_decrypt": "/usr/local/bin/ssl_decrypt.py",
|
||||||
|
"ssl_encrypt": "/usr/local/bin/ssl_encrypt.py",
|
||||||
|
"tcl_path": "/usr/share/TK-Themes",
|
||||||
|
"pkey_path": "/usr/local/etc/ssl/pwgk.pem"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# Images and icons paths
|
||||||
|
IMAGE_PATHS: Dict[str, str] = {
|
||||||
|
"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",
|
||||||
|
"icon_export": "/usr/share/icons/lx-icons/48/wg_export.png",
|
||||||
|
"icon_trash": "/usr/share/icons/lx-icons/48/wg_trash.png",
|
||||||
|
"icon_start": "/usr/share/icons/lx-icons/48/wg_vpn-start.png",
|
||||||
|
"icon_stop": "/usr/share/icons/lx-icons/48/wg_vpn-stop.png",
|
||||||
|
"icon_info": "/usr/share/icons/lx-icons/64/info.png",
|
||||||
|
"icon_error": "/usr/share/icons/lx-icons/64/error.png"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def setup_translations() -> gettext.gettext:
|
||||||
|
"""
|
||||||
|
Initialize translations and set the translation function
|
||||||
|
Special method for translating strings in this file
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The gettext translation function
|
||||||
|
"""
|
||||||
|
locale.bindtextdomain(AppConfig.APP_NAME, AppConfig.LOCALE_DIR)
|
||||||
|
gettext.bindtextdomain(AppConfig.APP_NAME, AppConfig.LOCALE_DIR)
|
||||||
|
gettext.textdomain(AppConfig.APP_NAME)
|
||||||
|
return gettext.gettext
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def ensure_directories(cls) -> None:
|
||||||
|
"""Ensures that all required directories exist"""
|
||||||
|
cls.CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
cls.TEMP_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_default_settings(cls) -> None:
|
||||||
|
"""Creates default settings if they don't exist"""
|
||||||
|
if not cls.SETTINGS_FILE.exists():
|
||||||
|
content = "\n".join(f"[{k.upper()}]\n{v}" for k, v in cls.DEFAULT_SETTINGS.items())
|
||||||
|
cls.SETTINGS_FILE.write_text(content)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_image_paths(cls) -> Dict[str, Path]:
|
||||||
|
"""Returns paths to UI images"""
|
||||||
|
return {
|
||||||
|
"main_icon": cls.SYSTEM_PATHS["image_path"] / "48/wg_vpn.png",
|
||||||
|
"warning": cls.CONFIG_DIR / "images/warning.png",
|
||||||
|
"success": cls.CONFIG_DIR / "images/success.png",
|
||||||
|
"error": cls.CONFIG_DIR / "images/error.png"
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_autostart_content(cls) -> str:
|
||||||
|
"""Returns the content for the autostart service file"""
|
||||||
|
return """[Unit]
|
||||||
|
Description=Automatic Tunnel Start
|
||||||
|
After=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStartPre=/bin/sleep 5
|
||||||
|
ExecStart=/usr/local/bin/start_wg.py
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target"""
|
||||||
|
|
||||||
|
# here is inizialize the class for translate strrings
|
||||||
|
_ = AppConfig.setup_translations()
|
||||||
|
|
||||||
|
class Msg:
|
||||||
|
"""
|
||||||
|
A utility class that provides centralized access to translated message strings.
|
||||||
|
|
||||||
|
This class contains a dictionary of message strings used throughout the Wire-Py application.
|
||||||
|
All strings are prepared for translation using gettext. The short key names make the code
|
||||||
|
more concise while maintaining readability.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
STR (dict): A dictionary mapping short keys to translated message strings.
|
||||||
|
Keys are abbreviated for brevity but remain descriptive.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
Import this class and access messages using the dictionary:
|
||||||
|
`Msg.STR["sel_tl"]` returns the translated "Select tunnel" message.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
Ensure that gettext translation is properly initialized before
|
||||||
|
accessing these strings to ensure correct localization.
|
||||||
|
"""
|
||||||
|
STR: Dict[str, str] = {
|
||||||
|
# Strings for messages
|
||||||
|
"sel_tl": _("Select tunnel"),
|
||||||
|
"ren_err": _("Renaming not possible"),
|
||||||
|
"exp_succ": _("Export successful"),
|
||||||
|
"exp_in_home": _("Your zip file is in home directory"),
|
||||||
|
"imp_err": _("Import Error"),
|
||||||
|
"exp_err": _("Export Error"),
|
||||||
|
"exp_try": _("Export failed! Please try again"),
|
||||||
|
"tl_first": _("Please first import tunnel"),
|
||||||
|
"sel_list": _("Please select a tunnel from the list"),
|
||||||
|
"sign_len": _("The new name may contain only 12 characters"),
|
||||||
|
"zero_signs": _("At least one character must be entered"),
|
||||||
|
"false signs": _("No valid sign. These must not be used.\nBlank, Slash, Backslash and { }\n"),
|
||||||
|
"is_in_use": _("The tunnel is already in use"),
|
||||||
|
"no_valid_file": _("Oh... no valid Wireguard File!\nPlease select a valid Wireguard File"),
|
||||||
|
"tl_exist": _("Tunnel already available!\nPlease use another file for import")
|
||||||
|
|
||||||
|
}
|
||||||
|
TTIP: Dict[str, str] = {
|
||||||
|
#Strings for Tooltips
|
||||||
|
"start_tl": _("Click to start selected Wireguard Tunnel"),
|
||||||
|
"empty_list": _("No tunnels to start in the list"),
|
||||||
|
"stop_tl": _("Click to stop selected Wireguard Tunnel"),
|
||||||
|
"del_tl": _("Click to delete selected Wireguard Tunnel"),
|
||||||
|
"rename_tl": _("To rename a tunnel, you need to\nselect a tunnel from the list"),
|
||||||
|
"export_tl": _(" Click to export all\nWireguard Tunnel to Zipfile"),
|
||||||
|
"trash_tl": _("Click to delete a Wireguard Tunnel\nSelect from the list!"),
|
||||||
|
"autostart": _("To use the autostart, enable this Checkbox"),
|
||||||
|
"autostart_info": _("You must have at least one\ntunnel in the list,to use the autostart"),
|
||||||
|
"export_tl_info": _("No Tunnels in List for Export"),
|
||||||
|
"start_tl_info": _("Click to start selected Wireguard Tunnel"),
|
||||||
|
"rename_tl_info": _("To rename a tunnel, at least one must be in the list"),
|
||||||
|
"trash_tl_info": _("No tunnels to delete in the list"),
|
||||||
|
"list_auto_info": _("To use the autostart, a tunnel must be selected from the list")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user