diff --git a/poetry.lock b/poetry.lock index 0490fac..b870fe0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -200,35 +200,6 @@ ssh = ["bcrypt (>=3.1.5)"] test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] -[[package]] -name = "customtkinter" -version = "5.2.2" -description = "Create modern looking GUIs with Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "customtkinter-5.2.2-py3-none-any.whl", hash = "sha256:14ad3e7cd3cb3b9eb642b9d4e8711ae80d3f79fb82545ad11258eeffb2e6b37c"}, - {file = "customtkinter-5.2.2.tar.gz", hash = "sha256:fd8db3bafa961c982ee6030dba80b4c2e25858630756b513986db19113d8d207"}, -] - -[package.dependencies] -darkdetect = "*" -packaging = "*" - -[[package]] -name = "darkdetect" -version = "0.8.0" -description = "Detect OS Dark Mode from Python" -optional = false -python-versions = ">=3.6" -files = [ - {file = "darkdetect-0.8.0-py3-none-any.whl", hash = "sha256:a7509ccf517eaad92b31c214f593dbcf138ea8a43b2935406bbd565e15527a85"}, - {file = "darkdetect-0.8.0.tar.gz", hash = "sha256:b5428e1170263eb5dea44c25dc3895edd75e6f52300986353cd63533fe7df8b1"}, -] - -[package.extras] -macos-listener = ["pyobjc-framework-Cocoa"] - [[package]] name = "decorator" version = "5.1.1" @@ -288,17 +259,6 @@ files = [ {file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"}, ] -[[package]] -name = "packaging" -version = "24.0" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.7" -files = [ - {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, - {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, -] - [[package]] name = "paramiko" version = "3.4.0" @@ -439,4 +399,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "e01c9fdf03da702f9839b29039b9b141a079b40b4210d2a288b572d07481afa5" +content-hash = "a6742759986eaac35d72d38a27ed349f010bf21820948b1c837749dfeea68af8" diff --git a/pyproject.toml b/pyproject.toml index c43d761..2234a6f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,6 @@ readme = "README.md" python = "^3.11" fabric = "^3.2.2" attrs = "^23.2.0" -customtkinter = "^5.2.2" cattrs = "^23.2.3" diff --git a/woven-ui.py b/woven-ui.py deleted file mode 100755 index 81d060c..0000000 --- a/woven-ui.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python3 - -from sys import platform -from argparse import ArgumentParser -from contextlib import redirect_stdout -from os import devnull -from sys import stdout, stderr, exit -from pathlib import Path -from woven import WovenMesh -from json import JSONDecodeError -from cattrs.errors import ClassValidationError -from tkinter.filedialog import askopenfilename -from tkinter.messagebox import showerror -import customtkinter as ctk - -def load_config(config_path: str) -> WovenMesh | None: - try: - return WovenMesh.load_json_file(config_path) - except FileNotFoundError: - pass - except JSONDecodeError as e: - showerror("Invalid JSON Error", f"Invalid JSON encountered in configuration file: {e}") - except ClassValidationError as e: - details = "\n".join(f'{type(e).__name__}: {e}' for e in e.exceptions) - showerror("Validation Error", f"The following validation errors occurred when loading the configuration file:\n{details}") - return None - -def start(config_path: str): - ctk.set_appearance_mode("System") - ctk.set_default_color_theme("dark-blue") - - if platform != "darwin" and not platform.startswith("win"): - ctk.set_widget_scaling(1.25) - ctk.set_window_scaling(1.25) - - root = ctk.CTk() - root.geometry("1200x800") - root.title("Woven") - root.minsize(240, 240) - root.grid_columnconfigure(0, weight = 1) - root.grid_rowconfigure(1, weight = 1) - - def update_config_handler(): - fn = askopenfilename(filetypes = [("JSON Files", "*.json")]) - if fn: - update_config(load_config(fn)) - - load_config_button = ctk.CTkButton(master = root, text = "Load Config", width = 0, command = update_config_handler) - load_config_button.grid(row = 0, padx = 20, pady = (20, 10), sticky = "w") - save_config_button = ctk.CTkButton(master = root, text = "Save Config", width = 0, command = update_config_handler) - save_config_button.grid(row = 0, padx = 20, pady = (20, 10), sticky = "e") - - config_textbox = ctk.CTkTextbox(master = root) - config_textbox.grid(row = 1, column = 0, padx = 20, pady = (10, 20), sticky = "nsew") - - def update_config(config: WovenMesh | None): - config_textbox.delete("0.0", "end") - config_textbox.insert("0.0", "" if config is None else config.to_json_str()) - - update_config(load_config(config_path)) - - root.mainloop() - -def main(): - parser = ArgumentParser("woven-ui") - parser.add_argument("-q", "--quiet", action = "store_true", help = "decrease output verbosity") - parser.add_argument("-c", "--config", default = "config.json", help = "The path to the config file") - args = parser.parse_args() - - with redirect_stdout(open(devnull, "w") if args.quiet else stdout): - start(args.config) - -if __name__ == "__main__": - try: - main() - except KeyboardInterrupt: - exit(130) - \ No newline at end of file diff --git a/woven.py b/woven.py index 4b636be..bf7f350 100755 --- a/woven.py +++ b/woven.py @@ -51,7 +51,7 @@ def validator_range(min_value: T, max_value: T) -> Callable[[T], T]: return _validate @define -class WovenNode: +class WovenMeshNode: address: IPv4Address | IPv6Address = field(converter = ip_address) gateway: IPv4Address | IPv6Address = field(converter = ip_address) interface: str @@ -73,8 +73,8 @@ class WovenMesh: wireguard_config_ext: str = field(default = "conf", converter = lambda x: str(x).lstrip(".")) table: Literal["auto", "off"] = field(default = "off", validator = validator_in(["auto", "off"])) allowed_ips: list[str] = field(factory = lambda: ["0.0.0.0/0", "::/0"]) - persistent_keepalive: int = field(default = 20, validator = validator_range(0, 1 << 31 - 1)) - mesh_nodes: dict[str, WovenNode] = field(factory = dict) + keep_alive: int = field(default = 20, validator = validator_range(0, 1 << 31 - 1)) + mesh_nodes: dict[str, WovenMeshNode] = field(factory = dict) def _surround(self, val: str) -> str: prefix_str = f"{self.tunnel_prefix}{self.tunnel_separator}" if self.tunnel_prefix else "" @@ -200,7 +200,7 @@ class WovenMesh: allowed_ips = self.allowed_ips, endpoint_host = node_b.address, endpoint_port = port, - persistent_keepalive = self.persistent_keepalive + persistent_keepalive = self.keep_alive ) } ) @@ -227,7 +227,7 @@ class WovenMesh: allowed_ips = self.allowed_ips, endpoint_host = node_a.address, endpoint_port = port, - persistent_keepalive = self.persistent_keepalive + persistent_keepalive = self.keep_alive ) } )