Compare commits

...

4 Commits

Author SHA1 Message Date
dw-0
ad56b51e70 feat(LogUpload): implement log upload feature
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-01-28 22:27:38 +01:00
dw-0
c6999f1990 refactor(kiauh): if self.options is an empty dict, return invalid input error message.
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-01-28 22:26:54 +01:00
dw-0
bc30cf418b refactor(kiauh): add option index parameter to method calls from menus
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-01-28 22:25:22 +01:00
dw-0
ee81ee4c0c fix(Mainsail): correctly handle invalid config value for default_port
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-01-28 15:35:00 +01:00
12 changed files with 211 additions and 80 deletions

View File

@@ -23,6 +23,7 @@ from kiauh.utils.constants import (
COLOR_CYAN, COLOR_CYAN,
RESET_FORMAT, RESET_FORMAT,
) )
from kiauh.utils.logger import Logger
def clear(): def clear():
@@ -92,6 +93,8 @@ def print_back_help_footer():
class BaseMenu(ABC): class BaseMenu(ABC):
NAVI_OPTIONS = {"quit": ["q"], "back": ["b"], "back_help": ["b", "h"]}
def __init__( def __init__(
self, self,
options: Dict[int, Any], options: Dict[int, Any],
@@ -130,29 +133,20 @@ class BaseMenu(ABC):
while True: while True:
choice = input(f"{COLOR_CYAN}###### Perform action: {RESET_FORMAT}") choice = input(f"{COLOR_CYAN}###### Perform action: {RESET_FORMAT}")
error_msg = (
f"{COLOR_RED}Invalid input.{RESET_FORMAT}"
if choice.isalpha()
else f"{COLOR_RED}Invalid input. Select a number between {min(self.options)} and {max(self.options)}.{RESET_FORMAT}"
)
if choice.isdigit() and 0 <= int(choice) < len(self.options): if choice.isdigit() and 0 <= int(choice) < len(self.options):
return choice return choice
elif choice.isalpha(): elif choice.isalpha() and (
allowed_input = { self.footer_type in self.NAVI_OPTIONS
"quit": ["q"], and choice.lower() in self.NAVI_OPTIONS[self.footer_type]
"back": ["b"], ):
"back_help": ["b", "h"], return choice
}
if (
self.footer_type in allowed_input
and choice.lower() in allowed_input[self.footer_type]
):
return choice
else:
print(error_msg)
else: else:
print(error_msg) error_msg = (
"Invalid input!"
if choice.isalpha() or (not self.options and len(self.options) < 1)
else f"Invalid input! Select a number between {min(self.options)} and {max(self.options)}."
)
Logger.print_error(error_msg, False)
def start(self): def start(self):
while True: while True:
@@ -160,7 +154,7 @@ class BaseMenu(ABC):
choice = self.handle_user_input() choice = self.handle_user_input()
if choice == "q": if choice == "q":
print(f"{COLOR_GREEN}###### Happy printing!{RESET_FORMAT}") Logger.print_ok("###### Happy printing!", False)
sys.exit(0) sys.exit(0)
elif choice == "b": elif choice == "b":
return return
@@ -175,7 +169,7 @@ class BaseMenu(ABC):
if isinstance(option, type) and issubclass(option, BaseMenu): if isinstance(option, type) and issubclass(option, BaseMenu):
self.navigate_to_submenu(option) self.navigate_to_submenu(option)
elif callable(option): elif callable(option):
option() option(opt_index=choice)
elif option is None: elif option is None:
raise NotImplementedError(f"No implementation for option {choice}") raise NotImplementedError(f"No implementation for option {choice}")
else: else:

View File

@@ -19,6 +19,7 @@ from kiauh.modules.moonraker import moonraker_setup
from kiauh.utils.constants import COLOR_GREEN, RESET_FORMAT from kiauh.utils.constants import COLOR_GREEN, RESET_FORMAT
# noinspection PyUnusedLocal
# noinspection PyMethodMayBeStatic # noinspection PyMethodMayBeStatic
class InstallMenu(BaseMenu): class InstallMenu(BaseMenu):
def __init__(self): def __init__(self):
@@ -63,35 +64,35 @@ class InstallMenu(BaseMenu):
)[1:] )[1:]
print(menu, end="") print(menu, end="")
def install_klipper(self): def install_klipper(self, **kwargs):
klipper_setup.install_klipper() klipper_setup.install_klipper()
def install_moonraker(self): def install_moonraker(self, **kwargs):
moonraker_setup.install_moonraker() moonraker_setup.install_moonraker()
def install_mainsail(self): def install_mainsail(self, **kwargs):
mainsail_setup.install_mainsail() mainsail_setup.install_mainsail()
def install_fluidd(self): def install_fluidd(self, **kwargs):
print("install_fluidd") print("install_fluidd")
def install_klipperscreen(self): def install_klipperscreen(self, **kwargs):
print("install_klipperscreen") print("install_klipperscreen")
def install_pretty_gcode(self): def install_pretty_gcode(self, **kwargs):
print("install_pretty_gcode") print("install_pretty_gcode")
def install_telegram_bot(self): def install_telegram_bot(self, **kwargs):
print("install_telegram_bot") print("install_telegram_bot")
def install_obico(self): def install_obico(self, **kwargs):
print("install_obico") print("install_obico")
def install_octoeverywhere(self): def install_octoeverywhere(self, **kwargs):
print("install_octoeverywhere") print("install_octoeverywhere")
def install_mobileraker(self): def install_mobileraker(self, **kwargs):
print("install_mobileraker") print("install_mobileraker")
def install_crowsnest(self): def install_crowsnest(self, **kwargs):
print("install_crowsnest") print("install_crowsnest")

View File

@@ -19,6 +19,7 @@ from kiauh.core.menus.remove_menu import RemoveMenu
from kiauh.core.menus.settings_menu import SettingsMenu from kiauh.core.menus.settings_menu import SettingsMenu
from kiauh.core.menus.update_menu import UpdateMenu from kiauh.core.menus.update_menu import UpdateMenu
from kiauh.modules.klipper.klipper_utils import get_klipper_status from kiauh.modules.klipper.klipper_utils import get_klipper_status
from kiauh.modules.log_uploads.menus.log_upload_menu import LogUploadMenu
from kiauh.modules.mainsail.mainsail_utils import get_mainsail_status from kiauh.modules.mainsail.mainsail_utils import get_mainsail_status
from kiauh.modules.moonraker.moonraker_utils import get_moonraker_status from kiauh.modules.moonraker.moonraker_utils import get_moonraker_status
from kiauh.utils.constants import ( from kiauh.utils.constants import (
@@ -36,7 +37,7 @@ class MainMenu(BaseMenu):
super().__init__( super().__init__(
header=True, header=True,
options={ options={
0: None, 0: LogUploadMenu,
1: InstallMenu, 1: InstallMenu,
2: UpdateMenu, 2: UpdateMenu,
3: RemoveMenu, 3: RemoveMenu,

View File

@@ -19,6 +19,7 @@ from kiauh.modules.moonraker.menus.moonraker_remove_menu import MoonrakerRemoveM
from kiauh.utils.constants import COLOR_RED, RESET_FORMAT from kiauh.utils.constants import COLOR_RED, RESET_FORMAT
# noinspection PyUnusedLocal
# noinspection PyMethodMayBeStatic # noinspection PyMethodMayBeStatic
class RemoveMenu(BaseMenu): class RemoveMenu(BaseMenu):
def __init__(self): def __init__(self):
@@ -69,35 +70,35 @@ class RemoveMenu(BaseMenu):
)[1:] )[1:]
print(menu, end="") print(menu, end="")
def remove_fluidd(self): def remove_fluidd(self, **kwargs):
print("remove_fluidd") print("remove_fluidd")
def remove_fluidd_config(self): def remove_fluidd_config(self, **kwargs):
print("remove_fluidd_config") print("remove_fluidd_config")
def remove_klipperscreen(self): def remove_klipperscreen(self, **kwargs):
print("remove_klipperscreen") print("remove_klipperscreen")
def remove_crowsnest(self): def remove_crowsnest(self, **kwargs):
print("remove_crowsnest") print("remove_crowsnest")
def remove_mjpgstreamer(self): def remove_mjpgstreamer(self, **kwargs):
print("remove_mjpgstreamer") print("remove_mjpgstreamer")
def remove_pretty_gcode(self): def remove_pretty_gcode(self, **kwargs):
print("remove_pretty_gcode") print("remove_pretty_gcode")
def remove_telegram_bot(self): def remove_telegram_bot(self, **kwargs):
print("remove_telegram_bot") print("remove_telegram_bot")
def remove_obico(self): def remove_obico(self, **kwargs):
print("remove_obico") print("remove_obico")
def remove_octoeverywhere(self): def remove_octoeverywhere(self, **kwargs):
print("remove_octoeverywhere") print("remove_octoeverywhere")
def remove_mobileraker(self): def remove_mobileraker(self, **kwargs):
print("remove_mobileraker") print("remove_mobileraker")
def remove_nginx(self): def remove_nginx(self, **kwargs):
print("remove_nginx") print("remove_nginx")

View File

@@ -27,6 +27,7 @@ from kiauh.modules.moonraker.moonraker_utils import get_moonraker_status
from kiauh.utils.constants import COLOR_GREEN, RESET_FORMAT, COLOR_YELLOW, COLOR_WHITE from kiauh.utils.constants import COLOR_GREEN, RESET_FORMAT, COLOR_YELLOW, COLOR_WHITE
# noinspection PyUnusedLocal
# noinspection PyMethodMayBeStatic # noinspection PyMethodMayBeStatic
class UpdateMenu(BaseMenu): class UpdateMenu(BaseMenu):
def __init__(self): def __init__(self):
@@ -93,43 +94,43 @@ class UpdateMenu(BaseMenu):
)[1:] )[1:]
print(menu, end="") print(menu, end="")
def update_all(self): def update_all(self, **kwargs):
print("update_all") print("update_all")
def update_klipper(self): def update_klipper(self, **kwargs):
update_klipper() update_klipper()
def update_moonraker(self): def update_moonraker(self, **kwargs):
update_moonraker() update_moonraker()
def update_mainsail(self): def update_mainsail(self, **kwargs):
update_mainsail() update_mainsail()
def update_fluidd(self): def update_fluidd(self, **kwargs):
print("update_fluidd") print("update_fluidd")
def update_klipperscreen(self): def update_klipperscreen(self, **kwargs):
print("update_klipperscreen") print("update_klipperscreen")
def update_pgc_for_klipper(self): def update_pgc_for_klipper(self, **kwargs):
print("update_pgc_for_klipper") print("update_pgc_for_klipper")
def update_telegram_bot(self): def update_telegram_bot(self, **kwargs):
print("update_telegram_bot") print("update_telegram_bot")
def update_moonraker_obico(self): def update_moonraker_obico(self, **kwargs):
print("update_moonraker_obico") print("update_moonraker_obico")
def update_octoeverywhere(self): def update_octoeverywhere(self, **kwargs):
print("update_octoeverywhere") print("update_octoeverywhere")
def update_mobileraker(self): def update_mobileraker(self, **kwargs):
print("update_mobileraker") print("update_mobileraker")
def update_crowsnest(self): def update_crowsnest(self, **kwargs):
print("update_crowsnest") print("update_crowsnest")
def upgrade_system_packages(self): def upgrade_system_packages(self, **kwargs):
print("upgrade_system_packages") print("upgrade_system_packages")
def fetch_update_status(self): def fetch_update_status(self):

View File

@@ -18,6 +18,7 @@ from kiauh.modules.moonraker import moonraker_remove
from kiauh.utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN from kiauh.utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN
# noinspection PyUnusedLocal
class KlipperRemoveMenu(BaseMenu): class KlipperRemoveMenu(BaseMenu):
def __init__(self): def __init__(self):
super().__init__( super().__init__(
@@ -67,25 +68,25 @@ class KlipperRemoveMenu(BaseMenu):
)[1:] )[1:]
print(menu, end="") print(menu, end="")
def toggle_all(self) -> None: def toggle_all(self, **kwargs) -> None:
self.remove_klipper_service = True self.remove_klipper_service = True
self.remove_klipper_dir = True self.remove_klipper_dir = True
self.remove_klipper_env = True self.remove_klipper_env = True
self.delete_klipper_logs = True self.delete_klipper_logs = True
def toggle_remove_klipper_service(self) -> None: def toggle_remove_klipper_service(self, **kwargs) -> None:
self.remove_klipper_service = not self.remove_klipper_service self.remove_klipper_service = not self.remove_klipper_service
def toggle_remove_klipper_dir(self) -> None: def toggle_remove_klipper_dir(self, **kwargs) -> None:
self.remove_klipper_dir = not self.remove_klipper_dir self.remove_klipper_dir = not self.remove_klipper_dir
def toggle_remove_klipper_env(self) -> None: def toggle_remove_klipper_env(self, **kwargs) -> None:
self.remove_klipper_env = not self.remove_klipper_env self.remove_klipper_env = not self.remove_klipper_env
def toggle_delete_klipper_logs(self) -> None: def toggle_delete_klipper_logs(self, **kwargs) -> None:
self.delete_klipper_logs = not self.delete_klipper_logs self.delete_klipper_logs = not self.delete_klipper_logs
def run_removal_process(self) -> None: def run_removal_process(self, **kwargs) -> None:
if ( if (
not self.remove_klipper_service not self.remove_klipper_service
and not self.remove_klipper_dir and not self.remove_klipper_dir

View File

@@ -0,0 +1,16 @@
#!/usr/bin/env python3
# ======================================================================= #
# 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 pathlib import Path
from typing import Dict, Union, Literal
FileKey = Literal["filepath", "display_name"]
LogFile = Dict[FileKey, Union[str, Path]]

View File

@@ -0,0 +1,57 @@
#!/usr/bin/env python3
# ======================================================================= #
# 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 pathlib import Path
import urllib.request
from kiauh.core.instance_manager.instance_manager import InstanceManager
from kiauh.modules.klipper.klipper import Klipper
from kiauh.modules.log_uploads import LogFile
from kiauh.utils.logger import Logger
def get_logfile_list() -> List[LogFile]:
cm = InstanceManager(Klipper)
log_dirs: List[Path] = [instance.log_dir for instance in cm.instances]
logfiles: List[LogFile] = []
for _dir in log_dirs:
for f in _dir.iterdir():
logfiles.append({"filepath": f, "display_name": get_display_name(f)})
return logfiles
def get_display_name(filepath: Path) -> str:
printer = " ".join(filepath.parts[-3].split("_")[:-1])
name = filepath.name
return f"{printer}: {name}"
def upload_logfile(logfile: LogFile) -> None:
file = logfile.get("filepath")
name = logfile.get("display_name")
Logger.print_status(f"Uploading the following logfile from {name} ...")
with open(file, "rb") as f:
headers = {"x-random": ""}
req = urllib.request.Request("http://paste.c-net.org/", headers=headers, data=f)
try:
response = urllib.request.urlopen(req)
link = response.read().decode("utf-8")
Logger.print_ok("Upload successfull! Access it via the following link:")
Logger.print_ok(f">>>> {link}", False)
except Exception as e:
Logger.print_error(f"Uploading logfile failed!")
Logger.print_error(str(e))

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env python3
# ======================================================================= #
# 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 #
# ======================================================================= #
import textwrap
from kiauh.core.menus import BACK_FOOTER
from kiauh.core.menus.base_menu import BaseMenu
from kiauh.modules.log_uploads.log_upload_utils import upload_logfile
from kiauh.modules.log_uploads.log_upload_utils import get_logfile_list
from kiauh.utils.constants import RESET_FORMAT, COLOR_YELLOW
# noinspection PyMethodMayBeStatic
class LogUploadMenu(BaseMenu):
def __init__(self):
self.logfile_list = get_logfile_list()
options = {index: self.upload for index in range(len(self.logfile_list))}
super().__init__(
header=True,
options=options,
footer_type=BACK_FOOTER,
)
def print_menu(self):
header = " [ Log Upload ] "
color = COLOR_YELLOW
count = 62 - len(color) - len(RESET_FORMAT)
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| You can select the following logfiles for uploading: |
| |
"""
)[1:]
logfile_list = get_logfile_list()
for logfile in enumerate(logfile_list):
line = f"{logfile[0]}) {logfile[1].get('display_name')}"
menu += f"| {line:<54}|\n"
print(menu, end="")
def upload(self, **kwargs):
upload_logfile(self.logfile_list[kwargs.get("opt_index")])

View File

@@ -90,10 +90,13 @@ def install_mainsail() -> None:
question = "Download the recommended macros?" question = "Download the recommended macros?"
install_ms_config = get_confirm(question, allow_go_back=False) install_ms_config = get_confirm(question, allow_go_back=False)
# if a default port is configured in the kiauh.cfg, we use that for the port
# otherwise we default to port 80, but show the user a dialog to confirm/change that port
cm = ConfigManager(cfg_file=KIAUH_CFG) cm = ConfigManager(cfg_file=KIAUH_CFG)
default_port = cm.get_value("mainsail", "default_port") default_port = cm.get_value("mainsail", "default_port")
mainsail_port = default_port if default_port else "80" is_valid_port = default_port and default_port.isdigit()
if not default_port: mainsail_port = default_port if is_valid_port else "80"
if not is_valid_port:
print_mainsail_port_select_dialog(mainsail_port) print_mainsail_port_select_dialog(mainsail_port)
mainsail_port = get_number_input( mainsail_port = get_number_input(
"Configure Mainsail for port", "Configure Mainsail for port",

View File

@@ -17,6 +17,7 @@ from kiauh.modules.mainsail import mainsail_remove
from kiauh.utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN from kiauh.utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN
# noinspection PyUnusedLocal
class MainsailRemoveMenu(BaseMenu): class MainsailRemoveMenu(BaseMenu):
def __init__(self): def __init__(self):
super().__init__( super().__init__(
@@ -72,29 +73,29 @@ class MainsailRemoveMenu(BaseMenu):
)[1:] )[1:]
print(menu, end="") print(menu, end="")
def toggle_all(self) -> None: def toggle_all(self, **kwargs) -> None:
self.remove_mainsail = True self.remove_mainsail = True
self.remove_ms_config = True self.remove_ms_config = True
self.backup_config_json = True self.backup_config_json = True
self.remove_updater_section = True self.remove_updater_section = True
self.remove_printer_cfg_include = True self.remove_printer_cfg_include = True
def toggle_remove_mainsail(self) -> None: def toggle_remove_mainsail(self, **kwargs) -> None:
self.remove_mainsail = not self.remove_mainsail self.remove_mainsail = not self.remove_mainsail
def toggle_remove_ms_config(self) -> None: def toggle_remove_ms_config(self, **kwargs) -> None:
self.remove_ms_config = not self.remove_ms_config self.remove_ms_config = not self.remove_ms_config
def toggle_backup_config_json(self) -> None: def toggle_backup_config_json(self, **kwargs) -> None:
self.backup_config_json = not self.backup_config_json self.backup_config_json = not self.backup_config_json
def toggle_remove_updater_section(self) -> None: def toggle_remove_updater_section(self, **kwargs) -> None:
self.remove_updater_section = not self.remove_updater_section self.remove_updater_section = not self.remove_updater_section
def toggle_remove_printer_cfg_include(self) -> None: def toggle_remove_printer_cfg_include(self, **kwargs) -> None:
self.remove_printer_cfg_include = not self.remove_printer_cfg_include self.remove_printer_cfg_include = not self.remove_printer_cfg_include
def run_removal_process(self) -> None: def run_removal_process(self, **kwargs) -> None:
if ( if (
not self.remove_mainsail not self.remove_mainsail
and not self.remove_ms_config and not self.remove_ms_config

View File

@@ -17,6 +17,7 @@ from kiauh.modules.moonraker import moonraker_remove
from kiauh.utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN from kiauh.utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN
# noinspection PyUnusedLocal
class MoonrakerRemoveMenu(BaseMenu): class MoonrakerRemoveMenu(BaseMenu):
def __init__(self): def __init__(self):
super().__init__( super().__init__(
@@ -70,29 +71,29 @@ class MoonrakerRemoveMenu(BaseMenu):
)[1:] )[1:]
print(menu, end="") print(menu, end="")
def toggle_all(self) -> None: def toggle_all(self, **kwargs) -> None:
self.remove_moonraker_service = True self.remove_moonraker_service = True
self.remove_moonraker_dir = True self.remove_moonraker_dir = True
self.remove_moonraker_env = True self.remove_moonraker_env = True
self.remove_moonraker_polkit = True self.remove_moonraker_polkit = True
self.delete_moonraker_logs = True self.delete_moonraker_logs = True
def toggle_remove_moonraker_service(self) -> None: def toggle_remove_moonraker_service(self, **kwargs) -> None:
self.remove_moonraker_service = not self.remove_moonraker_service self.remove_moonraker_service = not self.remove_moonraker_service
def toggle_remove_moonraker_dir(self) -> None: def toggle_remove_moonraker_dir(self, **kwargs) -> None:
self.remove_moonraker_dir = not self.remove_moonraker_dir self.remove_moonraker_dir = not self.remove_moonraker_dir
def toggle_remove_moonraker_env(self) -> None: def toggle_remove_moonraker_env(self, **kwargs) -> None:
self.remove_moonraker_env = not self.remove_moonraker_env self.remove_moonraker_env = not self.remove_moonraker_env
def toggle_remove_moonraker_polkit(self) -> None: def toggle_remove_moonraker_polkit(self, **kwargs) -> None:
self.remove_moonraker_polkit = not self.remove_moonraker_polkit self.remove_moonraker_polkit = not self.remove_moonraker_polkit
def toggle_delete_moonraker_logs(self) -> None: def toggle_delete_moonraker_logs(self, **kwargs) -> None:
self.delete_moonraker_logs = not self.delete_moonraker_logs self.delete_moonraker_logs = not self.delete_moonraker_logs
def run_removal_process(self) -> None: def run_removal_process(self, **kwargs) -> None:
if ( if (
not self.remove_moonraker_service not self.remove_moonraker_service
and not self.remove_moonraker_dir and not self.remove_moonraker_dir