diff --git a/.gitignore b/.gitignore index 5bceb25..1d30efb 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ client.db client.log settings.log config.json -default_config.log \ No newline at end of file +default_config.log +dist/ \ No newline at end of file diff --git a/globals.py b/mtcontact/globals.py similarity index 100% rename from globals.py rename to mtcontact/globals.py diff --git a/localisations/en.ini b/mtcontact/localisations/en.ini similarity index 100% rename from localisations/en.ini rename to mtcontact/localisations/en.ini diff --git a/main.py b/mtcontact/main.py similarity index 81% rename from main.py rename to mtcontact/main.py index c0028c3..51f6fd2 100644 --- a/main.py +++ b/mtcontact/main.py @@ -18,18 +18,18 @@ import logging import traceback import threading -from utilities.db_handler import init_nodedb, load_messages_from_db -from message_handlers.rx_handler import on_receive -from settings import set_region -from ui.curses_ui import main_ui -from ui.colors import setup_colors -from ui.splash import draw_splash -import ui.default_config as config -from utilities.arg_parser import setup_parser -from utilities.interfaces import initialize_interface -from utilities.input_handlers import get_list_input -from utilities.utils import get_channels, get_node_list, get_nodeNum -import globals +from mtcontact.utilities.db_handler import init_nodedb, load_messages_from_db +from mtcontact.message_handlers.rx_handler import on_receive +from mtcontact.settings import set_region +from mtcontact.ui.curses_ui import main_ui +from mtcontact.ui.colors import setup_colors +from mtcontact.ui.splash import draw_splash +import mtcontact.ui.default_config as config +from mtcontact.utilities.arg_parser import setup_parser +from mtcontact.utilities.interfaces import initialize_interface +from mtcontact.utilities.input_handlers import get_list_input +from mtcontact.utilities.utils import get_channels, get_node_list, get_nodeNum +import mtcontact.globals as globals # Set ncurses compatibility settings os.environ["NCURSES_NO_UTF8_ACS"] = "1" @@ -87,7 +87,7 @@ def main(stdscr): logging.error("Console output before crash:\n%s", console_output) raise # Re-raise only unexpected errors -if __name__ == "__main__": +def start(): log_file = config.log_file_path log_f = open(log_file, "a", buffering=1) # Enable line-buffering for immediate log writes @@ -103,4 +103,7 @@ if __name__ == "__main__": except Exception as e: logging.error("Fatal error in curses wrapper: %s", e) logging.error("Traceback: %s", traceback.format_exc()) - sys.exit(1) # Exit with an error code \ No newline at end of file + sys.exit(1) # Exit with an error code + +if __name__ == "__main__": + start() diff --git a/message_handlers/rx_handler.py b/mtcontact/message_handlers/rx_handler.py similarity index 91% rename from message_handlers/rx_handler.py rename to mtcontact/message_handlers/rx_handler.py index c95f0c5..b260587 100644 --- a/message_handlers/rx_handler.py +++ b/mtcontact/message_handlers/rx_handler.py @@ -1,11 +1,11 @@ import logging import time -from utilities.utils import refresh_node_list +from mtcontact.utilities.utils import refresh_node_list from datetime import datetime -from ui.curses_ui import draw_packetlog_win, draw_node_list, draw_messages_window, draw_channel_list, add_notification -from utilities.db_handler import save_message_to_db, maybe_store_nodeinfo_in_db, get_name_from_database, update_node_info_in_db -import ui.default_config as config -import globals +from mtcontact.ui.curses_ui import draw_packetlog_win, draw_node_list, draw_messages_window, draw_channel_list, add_notification +from mtcontact.utilities.db_handler import save_message_to_db, maybe_store_nodeinfo_in_db, get_name_from_database, update_node_info_in_db +import mtcontact.ui.default_config as config +import mtcontact.globals as globals from datetime import datetime diff --git a/message_handlers/tx_handler.py b/mtcontact/message_handlers/tx_handler.py similarity index 97% rename from message_handlers/tx_handler.py rename to mtcontact/message_handlers/tx_handler.py index 0b72fc9..e0772c5 100644 --- a/message_handlers/tx_handler.py +++ b/mtcontact/message_handlers/tx_handler.py @@ -3,9 +3,9 @@ import google.protobuf.json_format from meshtastic import BROADCAST_NUM from meshtastic.protobuf import mesh_pb2, portnums_pb2 -from utilities.db_handler import save_message_to_db, update_ack_nak, get_name_from_database, is_chat_archived, update_node_info_in_db -import ui.default_config as config -import globals +from mtcontact.utilities.db_handler import save_message_to_db, update_ack_nak, get_name_from_database, is_chat_archived, update_node_info_in_db +import mtcontact.ui.default_config as config +import mtcontact.globals as globals ack_naks = {} diff --git a/settings.py b/mtcontact/settings.py similarity index 83% rename from settings.py rename to mtcontact/settings.py index 5be03b4..cf6593c 100644 --- a/settings.py +++ b/mtcontact/settings.py @@ -5,13 +5,13 @@ import logging import sys import traceback -import ui.default_config as config -from utilities.input_handlers import get_list_input -from ui.colors import setup_colors -from ui.splash import draw_splash -from ui.control_ui import set_region, settings_menu -from utilities.arg_parser import setup_parser -from utilities.interfaces import initialize_interface +import mtcontact.ui.default_config as config +from mtcontact.utilities.input_handlers import get_list_input +from mtcontact.ui.colors import setup_colors +from mtcontact.ui.splash import draw_splash +from mtcontact.ui.control_ui import set_region, settings_menu +from mtcontact.utilities.arg_parser import setup_parser +from mtcontact.utilities.interfaces import initialize_interface def main(stdscr): diff --git a/ui/colors.py b/mtcontact/ui/colors.py similarity index 95% rename from ui/colors.py rename to mtcontact/ui/colors.py index 8016542..3891073 100644 --- a/ui/colors.py +++ b/mtcontact/ui/colors.py @@ -1,5 +1,5 @@ import curses -import ui.default_config as config +import mtcontact.ui.default_config as config COLOR_MAP = { "black": curses.COLOR_BLACK, diff --git a/ui/control_ui.py b/mtcontact/ui/control_ui.py similarity index 97% rename from ui/control_ui.py rename to mtcontact/ui/control_ui.py index c89a1a6..00630cf 100644 --- a/ui/control_ui.py +++ b/mtcontact/ui/control_ui.py @@ -5,14 +5,16 @@ import os import re import sys -from utilities.save_to_radio import save_changes -from utilities.config_io import config_export, config_import -from utilities.input_handlers import get_repeated_input, get_text_input, get_fixed32_input, get_list_input, get_admin_key_input -from ui.menus import generate_menu_from_protobuf -from ui.colors import get_color -from ui.dialog import dialog -from utilities.control_utils import parse_ini_file, transform_menu_path -from ui.user_config import json_editor +from mtcontact.utilities.save_to_radio import save_changes +from mtcontact.utilities.config_io import config_export, config_import +from mtcontact.utilities.input_handlers import get_repeated_input, get_text_input, get_fixed32_input, get_list_input, get_admin_key_input +from mtcontact.ui.menus import generate_menu_from_protobuf +from mtcontact.ui.colors import get_color +from mtcontact.ui.dialog import dialog +from mtcontact.utilities.control_utils import parse_ini_file, transform_menu_path +from mtcontact.ui.user_config import json_editor + +import mtcontact.localisations # Constants width = 80 @@ -27,8 +29,9 @@ parent_dir = os.path.abspath(os.path.join(script_dir, os.pardir)) # Paths locals_dir = os.path.dirname(os.path.abspath(sys.argv[0])) # Current script directory -translation_file = os.path.join(locals_dir, "localisations", "en.ini") -config_folder = os.path.join(parent_dir, "node-configs") +translation_file = os.path.join(parent_dir, "localisations", "en.ini") + +config_folder = os.path.join(locals_dir, "node-configs") # Load translations field_mapping, help_text = parse_ini_file(translation_file) diff --git a/ui/curses_ui.py b/mtcontact/ui/curses_ui.py similarity index 97% rename from ui/curses_ui.py rename to mtcontact/ui/curses_ui.py index 7547cfd..ca2f559 100644 --- a/ui/curses_ui.py +++ b/mtcontact/ui/curses_ui.py @@ -2,14 +2,14 @@ import curses import textwrap import logging import traceback -from utilities.utils import get_channels, get_readable_duration, get_time_ago, refresh_node_list -from settings import settings_menu -from message_handlers.tx_handler import send_message, send_traceroute -from ui.colors import setup_colors, get_color -from utilities.db_handler import get_name_from_database, update_node_info_in_db, is_chat_archived -import ui.default_config as config -import ui.dialog -import globals +from mtcontact.utilities.utils import get_channels, get_readable_duration, get_time_ago, refresh_node_list +from mtcontact.settings import settings_menu +from mtcontact.message_handlers.tx_handler import send_message, send_traceroute +from mtcontact.ui.colors import setup_colors, get_color +from mtcontact.utilities.db_handler import get_name_from_database, update_node_info_in_db, is_chat_archived +import mtcontact.ui.default_config as config +import mtcontact.ui.dialog +import mtcontact.globals as globals def handle_resize(stdscr, firstrun): global messages_pad, messages_win, nodes_pad, nodes_win, channel_pad, channel_win, function_win, packetlog_win, entry_win @@ -212,7 +212,7 @@ def main_ui(stdscr): elif char == chr(20): send_traceroute() curses.curs_set(0) # Hide cursor - ui.dialog.dialog(stdscr, "Traceroute Sent", "Results will appear in messages window.\nNote: Traceroute is limited to once every 30 seconds.") + mtcontact.ui.dialog.dialog(stdscr, "Traceroute Sent", "Results will appear in messages window.\nNote: Traceroute is limited to once every 30 seconds.") curses.curs_set(1) # Show cursor again handle_resize(stdscr, False) diff --git a/ui/default_config.py b/mtcontact/ui/default_config.py similarity index 100% rename from ui/default_config.py rename to mtcontact/ui/default_config.py diff --git a/ui/dialog.py b/mtcontact/ui/dialog.py similarity index 96% rename from ui/dialog.py rename to mtcontact/ui/dialog.py index 2d9ed67..c5a4c7a 100644 --- a/ui/dialog.py +++ b/mtcontact/ui/dialog.py @@ -1,5 +1,5 @@ import curses -from ui.colors import get_color +from mtcontact.ui.colors import get_color def dialog(stdscr, title, message): height, width = stdscr.getmaxyx() diff --git a/ui/menus.py b/mtcontact/ui/menus.py similarity index 100% rename from ui/menus.py rename to mtcontact/ui/menus.py diff --git a/ui/splash.py b/mtcontact/ui/splash.py similarity index 92% rename from ui/splash.py rename to mtcontact/ui/splash.py index 08fe2e5..785b5da 100644 --- a/ui/splash.py +++ b/mtcontact/ui/splash.py @@ -1,5 +1,5 @@ import curses -from ui.colors import get_color +from mtcontact.ui.colors import get_color def draw_splash(stdscr): curses.curs_set(0) diff --git a/ui/user_config.py b/mtcontact/ui/user_config.py similarity index 98% rename from ui/user_config.py rename to mtcontact/ui/user_config.py index 32aae7f..dc10db8 100644 --- a/ui/user_config.py +++ b/mtcontact/ui/user_config.py @@ -1,9 +1,9 @@ import os import json import curses -from ui.colors import get_color, setup_colors, COLOR_MAP -from ui.default_config import format_json_single_line_arrays, loaded_config -from utilities.input_handlers import get_list_input +from mtcontact.ui.colors import get_color, setup_colors, COLOR_MAP +from mtcontact.ui.default_config import format_json_single_line_arrays, loaded_config +from mtcontact.utilities.input_handlers import get_list_input width = 60 save_option_text = "Save Changes" diff --git a/utilities/arg_parser.py b/mtcontact/utilities/arg_parser.py similarity index 100% rename from utilities/arg_parser.py rename to mtcontact/utilities/arg_parser.py diff --git a/utilities/config_io.py b/mtcontact/utilities/config_io.py similarity index 100% rename from utilities/config_io.py rename to mtcontact/utilities/config_io.py diff --git a/utilities/control_utils.py b/mtcontact/utilities/control_utils.py similarity index 100% rename from utilities/control_utils.py rename to mtcontact/utilities/control_utils.py diff --git a/utilities/db_handler.py b/mtcontact/utilities/db_handler.py similarity index 99% rename from utilities/db_handler.py rename to mtcontact/utilities/db_handler.py index c471fb7..5a483aa 100644 --- a/utilities/db_handler.py +++ b/mtcontact/utilities/db_handler.py @@ -3,9 +3,9 @@ import time import logging from datetime import datetime -from utilities.utils import decimal_to_hex -import ui.default_config as config -import globals +from mtcontact.utilities.utils import decimal_to_hex +import mtcontact.ui.default_config as config +import mtcontact.globals as globals def get_table_name(channel): # Construct the table name diff --git a/utilities/input_handlers.py b/mtcontact/utilities/input_handlers.py similarity index 99% rename from utilities/input_handlers.py rename to mtcontact/utilities/input_handlers.py index 34b41ae..2c0ed34 100644 --- a/utilities/input_handlers.py +++ b/mtcontact/utilities/input_handlers.py @@ -3,7 +3,7 @@ import binascii import curses import ipaddress import re -from ui.colors import get_color +from mtcontact.ui.colors import get_color def wrap_text(text, wrap_width): """Wraps text while preserving spaces and breaking long words.""" diff --git a/utilities/interfaces.py b/mtcontact/utilities/interfaces.py similarity index 96% rename from utilities/interfaces.py rename to mtcontact/utilities/interfaces.py index 66c6e7b..03aeace 100644 --- a/utilities/interfaces.py +++ b/mtcontact/utilities/interfaces.py @@ -1,6 +1,6 @@ import logging import meshtastic.serial_interface, meshtastic.tcp_interface, meshtastic.ble_interface -import globals +import mtcontact.globals as globals def initialize_interface(args): try: diff --git a/utilities/save_to_radio.py b/mtcontact/utilities/save_to_radio.py similarity index 100% rename from utilities/save_to_radio.py rename to mtcontact/utilities/save_to_radio.py diff --git a/utilities/utils.py b/mtcontact/utilities/utils.py similarity index 97% rename from utilities/utils.py rename to mtcontact/utilities/utils.py index ce8d567..1997c36 100644 --- a/utilities/utils.py +++ b/mtcontact/utilities/utils.py @@ -1,7 +1,7 @@ -import globals +import mtcontact.globals as globals import datetime from meshtastic.protobuf import config_pb2 -import ui.default_config as config +import mtcontact.ui.default_config as config def get_channels(): """Retrieve channels from the node and update globals.channel_list and globals.all_messages.""" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..0a20233 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,21 @@ +[project] +name = "mtcontact" +version = "1.2.3" +description = "This Python curses client for Meshtastic is a terminal-based client designed to manage device settings, enable mesh chat communication, and handle configuration backups and restores." +authors = [ + {name = "pdxlocations",email = "you@example.com"} +] +license = "GPL-3.0-only" +readme = "README.md" +requires-python = ">=3.9" +dependencies = [ + "meshtastic (>=2.6.0,<3.0.0)" +] + + +[build-system] +requires = ["poetry-core>=2.0.0,<3.0.0"] +build-backend = "poetry.core.masonry.api" + +[tool.poetry.scripts] +mtcontact = "mtcontact.main:start"