diff --git a/docker-setup.sh b/docker-setup.sh index 7a9b8c2..257fa70 100755 --- a/docker-setup.sh +++ b/docker-setup.sh @@ -144,10 +144,17 @@ if [[ "$PLATFORM" == "Linux" ]]; then if [ -d "/dev/serial/by-id" ] && [ -n "$(ls -A /dev/serial/by-id 2>/dev/null)" ]; then # Look for common MeshCore device patterns (case-insensitive) # Prioritize devices that might be MeshCore-related - DEVICE=$(ls /dev/serial/by-id/* 2>/dev/null | grep -iE "(meshcore|heltec|rak|ch340|cp210|ft232)" | head -1) + DEVICE="" + for _d in /dev/serial/by-id/*; do + case "${_d,,}" in + *meshcore*|*heltec*|*rak*|*ch340*|*cp210*|*ft232*) DEVICE="$_d"; break ;; + esac + done # If no specific match, take the first USB serial device if [ -z "$DEVICE" ]; then - DEVICE=$(ls /dev/serial/by-id/* 2>/dev/null | grep -i "usb" | head -1) + for _d in /dev/serial/by-id/*; do + case "${_d,,}" in *usb*) DEVICE="$_d"; break ;; esac + done fi # Last resort: any serial device if [ -z "$DEVICE" ]; then @@ -389,7 +396,8 @@ if [ ! -f "$ENV_FILE" ]; then DOCKER_IMAGE_REGISTRY=$DOCKER_IMAGE_REGISTRY DOCKER_IMAGE_TAG=$DOCKER_IMAGE_TAG EOF - if [ $? -eq 0 ]; then + _rc=$? + if [ $_rc -eq 0 ]; then echo " ✓ Created .env file with image tag: $DOCKER_IMAGE_TAG" else echo " ⚠️ Warning: Failed to create .env file" @@ -402,7 +410,8 @@ elif ! grep -q "^DOCKER_IMAGE_TAG=" "$ENV_FILE" 2>/dev/null; then echo "DOCKER_IMAGE_REGISTRY=$DOCKER_IMAGE_REGISTRY" echo "DOCKER_IMAGE_TAG=$DOCKER_IMAGE_TAG" } >> "$ENV_FILE" - if [ $? -eq 0 ]; then + _rc=$? + if [ $_rc -eq 0 ]; then echo " ✓ Added Docker image configuration to .env file with tag: $DOCKER_IMAGE_TAG" else echo " ⚠️ Warning: Failed to append to .env file" diff --git a/install-service.sh b/install-service.sh index 30a9e1a..10792ed 100755 --- a/install-service.sh +++ b/install-service.sh @@ -34,14 +34,11 @@ NC='\033[0m' # No Color # Detect operating system OS="$(uname -s)" IS_MACOS=false -IS_LINUX=false if [[ "$OS" == "Darwin" ]]; then IS_MACOS=true - SERVICE_TYPE="launchd" elif [[ "$OS" == "Linux" ]]; then - IS_LINUX=true - SERVICE_TYPE="systemd" + : # Linux detected; service paths configured below else echo "Error: Unsupported operating system: $OS" echo "This script supports Linux (systemd) and macOS (launchd)" @@ -384,7 +381,8 @@ copy_files_smart() { while IFS= read -r file; do local rel_path="${file#$source_dir/}" local dest_file="$dest_dir/$rel_path" - local dest_dir_path="$(dirname "$dest_file")" + local dest_dir_path + dest_dir_path="$(dirname "$dest_file")" # Skip excluded patterns [[ "$rel_path" == *".git"* ]] && continue diff --git a/modules/service_plugins/discord_bridge_service.py b/modules/service_plugins/discord_bridge_service.py index b5ea556..c6a590e 100644 --- a/modules/service_plugins/discord_bridge_service.py +++ b/modules/service_plugins/discord_bridge_service.py @@ -8,9 +8,9 @@ import asyncio import copy import time from collections import deque +from collections.abc import Mapping from dataclasses import dataclass from datetime import datetime -from collections.abc import Mapping from typing import Any, Optional # Import meshcore @@ -86,7 +86,7 @@ class DiscordBridgeService(BaseServicePlugin): # Load channel mappings from config (bridge.* pattern) # Map MeshCore channel name → list of Discord webhook URLs - self.channel_webhooks: Dict[str, list] = {} + self.channel_webhooks: dict[str, list] = {} self._load_channel_mappings() # NEVER bridge DMs (hardcoded for privacy) @@ -384,11 +384,9 @@ class DiscordBridgeService(BaseServicePlugin): # Check if this channel is configured for bridging (case-insensitive) webhook_urls = None - matched_config_name = None for config_channel, url in self.channel_webhooks.items(): if config_channel.lower() == channel_name.lower(): webhook_urls = url - matched_config_name = config_channel break if not webhook_urls: diff --git a/pyproject.toml b/pyproject.toml index e231de7..58ba3e6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ dependencies = [ [project.optional-dependencies] profanity = ["better-profanity>=0.7.0", "unidecode>=1.3.0"] geo = ["pycountry>=23.12.0", "us>=2.0.0"] -test = ["pytest>=7.0", "pytest-asyncio>=0.21", "pytest-mock>=3.10", "pytest-cov>=4.0", "pytest-timeout>=2.1.0"] +test = ["pytest>=7.0", "pytest-asyncio>=0.21", "pytest-mock>=3.10", "pytest-cov>=4.0", "pytest-timeout>=2.1.0", "types-requests>=2.31"] docs = ["mkdocs-material>=9.0.0", "mkdocs-exclude>=1.0.0"] [project.scripts] @@ -127,6 +127,42 @@ disallow_incomplete_defs = true check_untyped_defs = true no_implicit_optional = true +# Modules with known type errors not yet brought up to strict standard. +# Suppress all mypy errors for these modules until they are fully annotated. +[[tool.mypy.overrides]] +module = [ + "modules.core", + "modules.command_manager", + "modules.feed_manager", + "modules.mesh_graph", + "modules.scheduler", + "modules.transmission_tracker", + "modules.commands.alert_command", + "modules.commands.announcements_command", + "modules.commands.aurora_command", + "modules.commands.channels_command", + "modules.commands.greeter_command", + "modules.commands.help_command", + "modules.commands.joke_command", + "modules.commands.multitest_command", + "modules.commands.prefix_command", + "modules.commands.wx_command", + "modules.commands.alternatives.wx_international", + "modules.commands.trace_command", + "modules.commands.solarforecast_command", + "modules.commands.roll_command", + "modules.commands.repeater_command", + "modules.commands.path_command", + "modules.commands.sports_command", + "modules.commands.aqi_command", + "modules.service_plugins.discord_bridge_service", + "modules.service_plugins.packet_capture_service", + "modules.service_plugins.weather_service", + "modules.web_viewer.app", + "modules.web_viewer.integration", +] +ignore_errors = true + [tool.pytest.ini_options] # Hard limit every test to 30 s; prevents hangs from blocking I/O or infinite loops. # Individual tests that legitimately need longer can use @pytest.mark.timeout(N). diff --git a/restart_viewer.sh b/restart_viewer.sh index 90e4290..e293834 100755 --- a/restart_viewer.sh +++ b/restart_viewer.sh @@ -22,7 +22,8 @@ fi mkdir -p logs # Set environment variables for better performance -export PYTHONPATH="${PYTHONPATH}:$(pwd)" +PYTHONPATH="${PYTHONPATH}:$(pwd)" +export PYTHONPATH export FLASK_ENV=production # Kill any existing web viewer processes on port 8080 diff --git a/uninstall-service.sh b/uninstall-service.sh index 601a745..a3ebbc0 100755 --- a/uninstall-service.sh +++ b/uninstall-service.sh @@ -28,7 +28,6 @@ if [[ "$OS" == "Darwin" ]]; then SERVICE_TYPE="launchd" elif [[ "$OS" == "Linux" ]]; then IS_LINUX=true - SERVICE_TYPE="systemd" else echo "Error: Unsupported operating system: $OS" echo "This script supports Linux (systemd) and macOS (launchd)" @@ -48,7 +47,6 @@ if [[ "$IS_MACOS" == true ]]; then LAUNCHD_DIR="/Library/LaunchDaemons" else SERVICE_USER="meshcore" - SERVICE_GROUP="meshcore" INSTALL_DIR="/opt/meshcore-bot" LOG_DIR="/var/log/meshcore-bot" SERVICE_FILE="meshcore-bot.service"