mirror of
https://github.com/dw-0/kiauh.git
synced 2025-12-26 17:23:35 +05:00
Compare commits
2 Commits
v6.0.0-alp
...
ee46346cd2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee46346cd2 | ||
|
|
6a766f7882 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,10 +1,6 @@
|
|||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
.pytest_cache
|
.pytest_cache
|
||||||
.jupyter
|
|
||||||
*.ipynb
|
|
||||||
*.ipynb_checkpoints
|
|
||||||
*.tmp
|
|
||||||
__pycache__
|
__pycache__
|
||||||
.kiauh-env
|
.kiauh-env
|
||||||
*.code-workspace
|
*.code-workspace
|
||||||
|
|||||||
@@ -353,16 +353,10 @@ def read_ports_from_nginx_configs() -> List[int]:
|
|||||||
lines = cfg.readlines()
|
lines = cfg.readlines()
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
line = re.sub(
|
line = line.replace("default_server", "")
|
||||||
r"default_server|http://|https://|[;\[\]]",
|
line = re.sub(r"[;:\[\]]", "", line.strip())
|
||||||
"",
|
if line.startswith("listen") and line.split()[-1] not in port_list:
|
||||||
line.strip(),
|
port_list.append(line.split()[-1])
|
||||||
)
|
|
||||||
if line.startswith("listen"):
|
|
||||||
if ":" not in line:
|
|
||||||
port_list.append(line.split()[-1])
|
|
||||||
else:
|
|
||||||
port_list.append(line.split(":")[-1])
|
|
||||||
|
|
||||||
ports_to_ints_list = [int(port) for port in port_list]
|
ports_to_ints_list = [int(port) for port in port_list]
|
||||||
return sorted(ports_to_ints_list, key=lambda x: int(x))
|
return sorted(ports_to_ints_list, key=lambda x: int(x))
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ CURRENT_USER = pwd.getpwuid(os.getuid())[0]
|
|||||||
|
|
||||||
# dirs
|
# dirs
|
||||||
SYSTEMD = Path("/etc/systemd/system")
|
SYSTEMD = Path("/etc/systemd/system")
|
||||||
PRINTER_DATA_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("printer-data-backups")
|
PRINTER_CFG_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("printer-cfg-backups")
|
||||||
NGINX_SITES_AVAILABLE = Path("/etc/nginx/sites-available")
|
NGINX_SITES_AVAILABLE = Path("/etc/nginx/sites-available")
|
||||||
NGINX_SITES_ENABLED = Path("/etc/nginx/sites-enabled")
|
NGINX_SITES_ENABLED = Path("/etc/nginx/sites-enabled")
|
||||||
NGINX_CONFD = Path("/etc/nginx/conf.d")
|
NGINX_CONFD = Path("/etc/nginx/conf.d")
|
||||||
|
|||||||
@@ -58,16 +58,12 @@ class ExtensionsMenu(BaseMenu):
|
|||||||
module_path = f"kiauh.extensions.{ext.name}.{module_name}"
|
module_path = f"kiauh.extensions.{ext.name}.{module_name}"
|
||||||
|
|
||||||
# get the class name of the extension
|
# get the class name of the extension
|
||||||
module = importlib.import_module(module_path)
|
ext_class: Type[BaseExtension] = inspect.getmembers(
|
||||||
|
importlib.import_module(module_path),
|
||||||
def predicate(o):
|
predicate=lambda o: inspect.isclass(o)
|
||||||
return (
|
and issubclass(o, BaseExtension)
|
||||||
inspect.isclass(o)
|
and o != BaseExtension,
|
||||||
and issubclass(o, BaseExtension)
|
)[0][1]
|
||||||
and o != BaseExtension
|
|
||||||
)
|
|
||||||
|
|
||||||
ext_class: type = inspect.getmembers(module, predicate)[0][1]
|
|
||||||
|
|
||||||
# instantiate the extension with its metadata and add to dict
|
# instantiate the extension with its metadata and add to dict
|
||||||
ext_instance: BaseExtension = ext_class(metadata)
|
ext_instance: BaseExtension = ext_class(metadata)
|
||||||
@@ -76,7 +72,7 @@ class ExtensionsMenu(BaseMenu):
|
|||||||
except (IOError, json.JSONDecodeError, ImportError) as e:
|
except (IOError, json.JSONDecodeError, ImportError) as e:
|
||||||
print(f"Failed loading extension {ext}: {e}")
|
print(f"Failed loading extension {ext}: {e}")
|
||||||
|
|
||||||
return dict(sorted(ext_dict.items(), key=lambda x: int(x[0])))
|
return dict(sorted(ext_dict.items()))
|
||||||
|
|
||||||
def extension_submenu(self, **kwargs):
|
def extension_submenu(self, **kwargs):
|
||||||
ExtensionSubmenu(kwargs.get("opt_data"), self.__class__).run()
|
ExtensionSubmenu(kwargs.get("opt_data"), self.__class__).run()
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ OA_REPO = "https://github.com/crysxd/OctoApp-Plugin.git"
|
|||||||
# directories
|
# directories
|
||||||
OA_DIR = Path.home().joinpath("octoapp")
|
OA_DIR = Path.home().joinpath("octoapp")
|
||||||
OA_ENV_DIR = Path.home().joinpath("octoapp-env")
|
OA_ENV_DIR = Path.home().joinpath("octoapp-env")
|
||||||
|
OA_STORE_DIR = OA_DIR.joinpath("octoapp-store")
|
||||||
|
|
||||||
# files
|
# files
|
||||||
OA_REQ_FILE = OA_DIR.joinpath("requirements.txt")
|
OA_REQ_FILE = OA_DIR.joinpath("requirements.txt")
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import json
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from components.moonraker.moonraker import Moonraker
|
from components.moonraker.moonraker import Moonraker
|
||||||
from components.klipper.klipper import Klipper
|
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
from core.logger import DialogType, Logger
|
from core.logger import DialogType, Logger
|
||||||
from extensions.base_extension import BaseExtension
|
from extensions.base_extension import BaseExtension
|
||||||
@@ -132,7 +131,6 @@ class OctoappExtension(BaseExtension):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
self._remove_OA_instances(ob_instances)
|
self._remove_OA_instances(ob_instances)
|
||||||
self._remove_OA_store_dirs()
|
|
||||||
self._remove_OA_dir()
|
self._remove_OA_dir()
|
||||||
self._remove_OA_env()
|
self._remove_OA_env()
|
||||||
remove_config_section(f"include {OA_SYS_CFG_NAME}", mr_instances)
|
remove_config_section(f"include {OA_SYS_CFG_NAME}", mr_instances)
|
||||||
@@ -183,21 +181,6 @@ class OctoappExtension(BaseExtension):
|
|||||||
|
|
||||||
run_remove_routines(OA_DIR)
|
run_remove_routines(OA_DIR)
|
||||||
|
|
||||||
|
|
||||||
def _remove_OA_store_dirs(self) -> None:
|
|
||||||
Logger.print_status("Removing OctoApp for Klipper store directory ...")
|
|
||||||
|
|
||||||
klipper_instances: List[Moonraker] = get_instances(Klipper)
|
|
||||||
|
|
||||||
for instance in klipper_instances:
|
|
||||||
store_dir = instance.data_dir.joinpath("octoapp-store")
|
|
||||||
if not store_dir.exists():
|
|
||||||
Logger.print_info(f"'{store_dir}' does not exist. Skipped ...")
|
|
||||||
return
|
|
||||||
|
|
||||||
run_remove_routines(store_dir)
|
|
||||||
|
|
||||||
|
|
||||||
def _remove_OA_env(self) -> None:
|
def _remove_OA_env(self) -> None:
|
||||||
Logger.print_status("Removing OctoApp for Klipper environment ...")
|
Logger.print_status("Removing OctoApp for Klipper environment ...")
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"metadata": {
|
|
||||||
"index": 10,
|
|
||||||
"module": "simply_print_extension",
|
|
||||||
"maintained_by": "dw-0",
|
|
||||||
"display_name": "SimplyPrint",
|
|
||||||
"description": [
|
|
||||||
"3D Printer Cloud Management Software.",
|
|
||||||
"\n\n",
|
|
||||||
"3D printing doesn't have to be a complicated, analog, SD card-filled experience; step into the future of modern 3D printing"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
# ======================================================================= #
|
|
||||||
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
|
||||||
# #
|
|
||||||
# This file is part of KIAUH - Klipper Installation And Update Helper #
|
|
||||||
# https://github.com/dw-0/kiauh #
|
|
||||||
# #
|
|
||||||
# This file may be distributed under the terms of the GNU GPLv3 license #
|
|
||||||
# ======================================================================= #
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
from components.moonraker.moonraker import Moonraker
|
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
|
||||||
from core.logger import DialogType, Logger
|
|
||||||
from core.submodules.simple_config_parser.src.simple_config_parser.simple_config_parser import (
|
|
||||||
SimpleConfigParser,
|
|
||||||
)
|
|
||||||
from extensions.base_extension import BaseExtension
|
|
||||||
from utils.common import backup_printer_config_dir, moonraker_exists
|
|
||||||
from utils.input_utils import get_confirm
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyMethodMayBeStatic
|
|
||||||
class SimplyPrintExtension(BaseExtension):
|
|
||||||
def install_extension(self, **kwargs) -> None:
|
|
||||||
Logger.print_status("Installing SimplyPrint ...")
|
|
||||||
|
|
||||||
if not (mr_instances := moonraker_exists("SimplyPrint Installer")):
|
|
||||||
return
|
|
||||||
|
|
||||||
Logger.print_dialog(
|
|
||||||
DialogType.INFO,
|
|
||||||
self._construct_dialog(mr_instances, True),
|
|
||||||
)
|
|
||||||
|
|
||||||
if not get_confirm(
|
|
||||||
"Continue SimplyPrint installation?",
|
|
||||||
default_choice=True,
|
|
||||||
allow_go_back=True,
|
|
||||||
):
|
|
||||||
Logger.print_info("Exiting SimplyPrint installation ...")
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._patch_moonraker_confs(mr_instances, True)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
Logger.print_error(f"Error during SimplyPrint installation:\n{e}")
|
|
||||||
|
|
||||||
def remove_extension(self, **kwargs) -> None:
|
|
||||||
Logger.print_status("Removing SimplyPrint ...")
|
|
||||||
|
|
||||||
if not (mr_instances := moonraker_exists("SimplyPrint Uninstaller")):
|
|
||||||
return
|
|
||||||
|
|
||||||
Logger.print_dialog(
|
|
||||||
DialogType.INFO,
|
|
||||||
self._construct_dialog(mr_instances, False),
|
|
||||||
)
|
|
||||||
|
|
||||||
if not get_confirm(
|
|
||||||
"Do you really want to uninstall SimplyPrint?",
|
|
||||||
default_choice=True,
|
|
||||||
allow_go_back=True,
|
|
||||||
):
|
|
||||||
Logger.print_info("Exiting SimplyPrint uninstallation ...")
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._patch_moonraker_confs(mr_instances, False)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
Logger.print_error(f"Error during SimplyPrint installation:\n{e}")
|
|
||||||
|
|
||||||
def _construct_dialog(
|
|
||||||
self, mr_instances: List[Moonraker], is_install: bool
|
|
||||||
) -> List[str]:
|
|
||||||
mr_names = [f"● {m.service_file_path.name}" for m in mr_instances]
|
|
||||||
_type = "install" if is_install else "uninstall"
|
|
||||||
|
|
||||||
return [
|
|
||||||
"The following Moonraker instances were found:",
|
|
||||||
*mr_names,
|
|
||||||
"\n\n",
|
|
||||||
f"The setup will {_type} SimplyPrint for all Moonraker instances. "
|
|
||||||
f"After {_type}ation, all Moonraker services will be restarted!",
|
|
||||||
]
|
|
||||||
|
|
||||||
def _patch_moonraker_confs(
|
|
||||||
self, mr_instances: List[Moonraker], is_install: bool
|
|
||||||
) -> None:
|
|
||||||
section = "simplyprint"
|
|
||||||
_type, _ft = ("Adding", "to") if is_install else ("Removing", "from")
|
|
||||||
|
|
||||||
patched_files = []
|
|
||||||
for moonraker in mr_instances:
|
|
||||||
Logger.print_status(
|
|
||||||
f"{_type} section 'simplyprint' {_ft} {moonraker.cfg_file} ..."
|
|
||||||
)
|
|
||||||
scp = SimpleConfigParser()
|
|
||||||
scp.read_file(moonraker.cfg_file)
|
|
||||||
|
|
||||||
install_and_has_section = is_install and scp.has_section(section)
|
|
||||||
uninstall_and_has_no_section = not is_install and not scp.has_section(
|
|
||||||
section
|
|
||||||
)
|
|
||||||
|
|
||||||
if install_and_has_section or uninstall_and_has_no_section:
|
|
||||||
status = "already" if is_install else "does not"
|
|
||||||
Logger.print_info(
|
|
||||||
f"Section 'simplyprint' {status} exists! Skipping ..."
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if is_install and not scp.has_section("simplyprint"):
|
|
||||||
backup_printer_config_dir()
|
|
||||||
scp.add_section(section)
|
|
||||||
elif not is_install and scp.has_section("simplyprint"):
|
|
||||||
backup_printer_config_dir()
|
|
||||||
scp.remove_section(section)
|
|
||||||
scp.write_file(moonraker.cfg_file)
|
|
||||||
patched_files.append(moonraker.cfg_file)
|
|
||||||
|
|
||||||
if patched_files:
|
|
||||||
InstanceManager.restart_all(mr_instances)
|
|
||||||
|
|
||||||
install_state = "successfully" if patched_files else "was already"
|
|
||||||
Logger.print_dialog(
|
|
||||||
DialogType.SUCCESS,
|
|
||||||
[f"SimplyPrint {install_state} {'' if is_install else 'un'}installed!"],
|
|
||||||
center_content=True,
|
|
||||||
)
|
|
||||||
@@ -14,11 +14,10 @@ from pathlib import Path
|
|||||||
from typing import Dict, List, Literal, Optional, Set
|
from typing import Dict, List, Literal, Optional, Set
|
||||||
|
|
||||||
from components.klipper.klipper import Klipper
|
from components.klipper.klipper import Klipper
|
||||||
from components.moonraker.moonraker import Moonraker
|
|
||||||
from core.constants import (
|
from core.constants import (
|
||||||
COLOR_CYAN,
|
COLOR_CYAN,
|
||||||
GLOBAL_DEPS,
|
GLOBAL_DEPS,
|
||||||
PRINTER_DATA_BACKUP_DIR,
|
PRINTER_CFG_BACKUP_DIR,
|
||||||
RESET_FORMAT,
|
RESET_FORMAT,
|
||||||
)
|
)
|
||||||
from core.logger import DialogType, Logger
|
from core.logger import DialogType, Logger
|
||||||
@@ -143,25 +142,23 @@ def backup_printer_config_dir() -> None:
|
|||||||
instances: List[Klipper] = get_instances(Klipper)
|
instances: List[Klipper] = get_instances(Klipper)
|
||||||
bm = BackupManager()
|
bm = BackupManager()
|
||||||
|
|
||||||
if not instances:
|
|
||||||
Logger.print_info("Unable to find directory to backup!")
|
|
||||||
Logger.print_info("Are there no Klipper instances installed?")
|
|
||||||
return
|
|
||||||
|
|
||||||
for instance in instances:
|
for instance in instances:
|
||||||
|
name = f"config-{instance.data_dir.name}"
|
||||||
bm.backup_directory(
|
bm.backup_directory(
|
||||||
instance.data_dir.name,
|
name,
|
||||||
source=instance.base.cfg_dir,
|
source=instance.base.cfg_dir,
|
||||||
target=PRINTER_DATA_BACKUP_DIR,
|
target=PRINTER_CFG_BACKUP_DIR,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def moonraker_exists(name: str = "") -> List[Moonraker]:
|
def moonraker_exists(name: str = "") -> bool:
|
||||||
"""
|
"""
|
||||||
Helper method to check if a Moonraker instance exists
|
Helper method to check if a Moonraker instance exists
|
||||||
:param name: Optional name of an installer where the check is performed
|
:param name: Optional name of an installer where the check is performed
|
||||||
:return: True if at least one Moonraker instance exists, False otherwise
|
:return: True if at least one Moonraker instance exists, False otherwise
|
||||||
"""
|
"""
|
||||||
|
from components.moonraker.moonraker import Moonraker
|
||||||
|
|
||||||
mr_instances: List[Moonraker] = get_instances(Moonraker)
|
mr_instances: List[Moonraker] = get_instances(Moonraker)
|
||||||
|
|
||||||
info = (
|
info = (
|
||||||
@@ -178,8 +175,8 @@ def moonraker_exists(name: str = "") -> List[Moonraker]:
|
|||||||
f"{info}. Please install Moonraker first!",
|
f"{info}. Please install Moonraker first!",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
return []
|
return False
|
||||||
return mr_instances
|
return True
|
||||||
|
|
||||||
|
|
||||||
def trunc_string(input_str: str, length: int) -> str:
|
def trunc_string(input_str: str, length: int) -> str:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from http.client import HTTPResponse
|
|||||||
from json import JSONDecodeError
|
from json import JSONDecodeError
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from subprocess import DEVNULL, PIPE, CalledProcessError, check_output, run
|
from subprocess import DEVNULL, PIPE, CalledProcessError, check_output, run
|
||||||
from typing import List, Tuple, Type
|
from typing import List, Type
|
||||||
|
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
from core.logger import Logger
|
from core.logger import Logger
|
||||||
@@ -70,7 +70,7 @@ def git_pull_wrapper(repo: str, target_dir: Path) -> None:
|
|||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def get_repo_name(repo: Path) -> Tuple[str, str]:
|
def get_repo_name(repo: Path) -> tuple[str, str] | None:
|
||||||
"""
|
"""
|
||||||
Helper method to extract the organisation and name of a repository |
|
Helper method to extract the organisation and name of a repository |
|
||||||
:param repo: repository to extract the values from
|
:param repo: repository to extract the values from
|
||||||
@@ -83,14 +83,11 @@ def get_repo_name(repo: Path) -> Tuple[str, str]:
|
|||||||
cmd = ["git", "-C", repo.as_posix(), "config", "--get", "remote.origin.url"]
|
cmd = ["git", "-C", repo.as_posix(), "config", "--get", "remote.origin.url"]
|
||||||
result: str = check_output(cmd, stderr=DEVNULL).decode(encoding="utf-8")
|
result: str = check_output(cmd, stderr=DEVNULL).decode(encoding="utf-8")
|
||||||
substrings: List[str] = result.strip().split("/")[-2:]
|
substrings: List[str] = result.strip().split("/")[-2:]
|
||||||
|
return substrings[0], substrings[1]
|
||||||
|
|
||||||
orga: str = substrings[0] if substrings[0] else "-"
|
# return "/".join(substrings).replace(".git", "")
|
||||||
name: str = substrings[1] if substrings[1] else "-"
|
|
||||||
|
|
||||||
return orga, name
|
|
||||||
|
|
||||||
except CalledProcessError:
|
except CalledProcessError:
|
||||||
return "-", "-"
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_local_tags(repo_path: Path, _filter: str | None = None) -> List[str]:
|
def get_local_tags(repo_path: Path, _filter: str | None = None) -> List[str]:
|
||||||
@@ -187,7 +184,7 @@ def compare_semver_tags(tag1: str, tag2: str) -> bool:
|
|||||||
if tag1 == tag2:
|
if tag1 == tag2:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def parse_version(v) -> List[int]:
|
def parse_version(v):
|
||||||
return list(map(int, v[1:].split(".")))
|
return list(map(int, v[1:].split(".")))
|
||||||
|
|
||||||
tag1_parts = parse_version(tag1)
|
tag1_parts = parse_version(tag1)
|
||||||
|
|||||||
@@ -358,6 +358,7 @@ function get_usb_id() {
|
|||||||
unset mcu_list
|
unset mcu_list
|
||||||
sleep 1
|
sleep 1
|
||||||
mcus=$(find /dev/serial/by-id/* 2>/dev/null)
|
mcus=$(find /dev/serial/by-id/* 2>/dev/null)
|
||||||
|
mcus+=" $(find /dev/serial/by-path/* 2>/dev/null)"
|
||||||
|
|
||||||
for mcu in ${mcus}; do
|
for mcu in ${mcus}; do
|
||||||
mcu_list+=("${mcu}")
|
mcu_list+=("${mcu}")
|
||||||
|
|||||||
Reference in New Issue
Block a user