Commit Graph

433 Commits

Author SHA1 Message Date
Stacy Olivas
54aeb28bf0 security: SSRF hardening, log injection sanitization, and allow_local_smtp
Add SSRF host validation to maintenance.py send_nightly_email and
scheduler.py send_zombie_alert_email using validate_external_url().
New allow_local_smtp config key permits private-IP SMTP for local
relay setups.

Add sanitize_name() to security_utils and apply it to all log calls
in message_handler, repeater_manager, path_command, solarforecast_command,
command_manager, and discord_bridge_service to prevent log injection.

Move nightly email logic from duplicate scheduler._send_nightly_email()
into the canonical maintenance.py implementation, removing the duplicate.
Update tests to call maintenance.send_nightly_email() directly.

Add validate_external_url allow_private parameter with support for
loopback, RFC1918, CGN, and link-local address ranges.
2026-04-14 10:02:36 -07:00
Stacy Olivas
c7fa0ba3d2 fix: resolve ruff F401 violations in command_manager and upstream test files
- Add noqa: F401 to PUBLIC_CHANNEL_KEY_HEX import (re-exported for core.py)
- Remove unused `call` import from test_flood_scope_reply.py
- Remove unused `asyncio` import from test_log_data_scope_fields.py
- Remove unused `patch` and `validate_config` imports from
  test_public_channel_guard.py; fix import sort order
2026-04-14 10:01:51 -07:00
Stacy Olivas
640568bcc9 fix: add X-Requested-With header to zombie-recover and radio-offline-clear fetch calls
Both banner action buttons were posting without the required
X-Requested-With header, causing the CSRF guard to return 403.
2026-04-14 10:01:51 -07:00
Stacy Olivas
ae71179940 fix: ruff compliance for upstream version_info.py and packet_capture_service.py 2026-04-14 10:01:51 -07:00
Stacy Olivas
fd0875611d fix: restore MaintenanceRunner arch and correct zombie-detection tests 2026-04-14 10:01:51 -07:00
Stacy Olivas
c543cac5bf fix: import validate_external_url in scheduler.py for SMTP SSRF guard 2026-04-14 10:01:51 -07:00
Stacy Olivas
cac999bcde fix: remove trailing whitespace in core.py (W293) 2026-04-14 10:01:51 -07:00
Stacy Olivas
f09b214a73 fix: prevent packetcapture restart storm during radio reconnect 2026-04-14 10:01:51 -07:00
Stacy Olivas
9ce69702c2 feat: radio debug logging mode with web UI toggle 2026-04-14 10:01:51 -07:00
Stacy Olivas
51ab5d312c feat: radio-offline fail state — suppress sends, auto-restart, banner, and docs 2026-04-14 10:01:51 -07:00
Stacy Olivas
8b14c40958 feat: zombie radio banner on all pages + zombie alert config screen options
- base.html: persistent danger banner appears on every web page when
  is_radio_zombie is true; shows datetime zombie was detected; includes
  "Restart Bot Processing" button (POST /api/admin/zombie-recover) that
  clears _radio_zombie_detected and _radio_fail_count on the live bot
  object and removes the persisted DB flag; banner turns green on success

- config.html: new "Zombie Radio Alert" card with enable/disable toggle
  and alert-email field; "Save" writes to bot_metadata (immediate,
  survives restarts); "Save to config.ini" also persists values to
  config.ini and keeps the in-memory config in sync; card shows
  current config.ini values as baseline defaults

- app.py: inject_template_vars context processor now provides
  radio_zombie and radio_zombie_since to all templates; added
  GET/POST /api/config/zombie-alert endpoints (GET returns both
  bot_metadata and config.ini values; POST supports write_to_config
  flag); added POST /api/admin/zombie-recover endpoint; stored
  config_path on self for write-back use

- scheduler.py: send_zombie_alert_email now prefers bot_metadata
  (zombie.alert_enabled, zombie.alert_email) over config.ini so web
  UI changes take effect without a restart; uses isinstance(..., str)
  guard so mock/None values safely fall through to config.ini defaults
2026-04-14 10:01:51 -07:00
Stacy Olivas
22e1b2b53c fix: guard send_advert() with asyncio.wait_for(timeout=30) to prevent event loop lockup
When the radio firmware is unresponsive but not yet flagged as zombie,
send_advert() would hang indefinitely on the main event loop, blocking
all packet processing (no data in/out) for 60+ seconds until the
scheduler thread's future.result() timed out — but that only timed
out the waiting thread, not the coroutine itself.

Fix: wrap every send_advert() call that runs on the event loop with
asyncio.wait_for(timeout=30.0).  On timeout in the interval-advert
path, _radio_fail_count is incremented so repeated timeouts feed into
the existing zombie-detection threshold.
2026-04-14 10:01:51 -07:00
Stacy Olivas
d0ae737066 feat: zombie radio detection — health probe, timeout guards, and alert system 2026-04-14 10:01:51 -07:00
agessaman
13e3e040b2 Refactor project root path handling in web viewer
- Updated `app.py` to ensure the project root is correctly added to `sys.path` when the script is executed directly, allowing for proper module imports.
- Removed redundant code that previously handled project root path insertion, streamlining the import process.
2026-04-12 15:53:37 -07:00
Adam Gessaman
d9e32c86f2 Merge branch 'dev' into main 2026-04-11 19:00:06 -07:00
agessaman
8bea10cdc3 Enhance mention handling in message processing
- Updated `config.ini.example` to introduce the `respond_to_mentions` setting, allowing configuration of how the bot responds to mentions in channel messages.
- Refactored `MessageHandler` to implement logic for handling mentions based on the new configuration, including stripping mentions when appropriate.
- Added `cleanup_message_for_matching` method in `BaseCommand` to streamline message processing and mention validation.
- Enhanced various command classes to utilize the new cleanup method for consistent mention handling.
- Introduced tests to validate the behavior of the new mention handling logic across different configurations.
2026-04-11 18:45:34 -07:00
Chris Wiegand
9d4b142071 log from user, and if in channel or DM 2026-04-11 15:49:49 -06:00
Chris Wiegand
56be1e7784 actually fix the message's copy of content since some implementations pull further arguments from it 2026-04-11 15:49:41 -06:00
Chris Wiegand
277491f535 create common base function to match replies of bot name even when command class is inherited, patch all overriding implementations to use this 2026-04-11 15:34:00 -06:00
agessaman
4ee20794df fix: reduce channel message budget by 10 bytes for regional flood scope
Match firmware TC_FLOOD scope overhead in get_max_message_length via
MeshMessage.effective_outgoing_flood_scope; keep CommandManager and
BaseCommand in sync with tests.

Made-with: Cursor
2026-04-10 20:11:57 -07:00
agessaman
2ac1722014 Refactor flood scope configuration and enhance message handling
- Updated `config.ini.example` to clarify the usage of `outgoing_flood_scope_override` and `flood_scopes`, providing examples for better understanding.
- Modified `configuration.md` to reflect changes in flood scope handling, emphasizing the distinction between `outgoing_flood_scope_override` and `flood_scopes`.
- Refactored `CommandManager` to utilize the new `outgoing_flood_scope_override` for sending messages, ensuring consistent scope handling.
- Enhanced `MessageHandler` to prioritize library-provided scope fields for improved accuracy in flood scope matching.
- Added tests to validate the handling of flood scope fields from library payloads, ensuring robustness in message processing.
2026-04-10 16:29:52 -07:00
agessaman
8b6ccc9dd3 Modify web viewer password handling to emphasize but not require a password; improve error logging
- Updated `config.ini.example` to clarify password requirements for web viewer authentication, emphasizing the need for a password when binding to non-loopback interfaces.
- Introduced a new function `normalized_web_viewer_password` in `integration.py` to standardize password retrieval and validation, handling various empty and null placeholder cases.
- Enhanced error logging in `core.py` to use `logger.error` for web viewer integration failures, improving visibility of issues.
- Modified `app.py` to utilize the new password normalization function, ensuring consistent password handling across the application.
- Added tests in `test_web_viewer_integration.py` to validate password normalization and error logging behavior when the web viewer is configured without a password.
2026-04-10 15:28:33 -07:00
Adam Gessaman
4bf09291f5 Implement public channel guard and enhance configuration validation
- Updated `config.ini.example` to include a warning about running the bot on the Public channel and added an override key for intentional usage.
- Enhanced `config_validation.py` to implement a public channel guard that prevents the bot from starting if the Public channel is included in monitored channels without the override.
- Refactored `CommandManager` and `Core` to check for the Public channel key during channel loading and connection setup, ensuring compliance with the new guard.
- Improved documentation in `configuration.md` and `config-validation.md` to clarify the implications of using the Public channel and the necessary configuration changes.
2026-04-09 20:44:48 -07:00
Adam Gessaman
4f820ffbd4 Enhance flood scope handling and channel fetching logic
- Updated `config.ini.example` to clarify flood scope configuration, introducing the auto-hashtag format for region names and adding support for multi-scope replies.
- Refactored `ChannelManager` to improve handling of empty channels, adjusting timeout logic and increasing request delay to prevent overwhelming devices.
- Enhanced `CommandManager` to load flood scope keys for HMAC matching and normalize scope names for consistency.
- Implemented scope matching in `MessageHandler` to ensure replies respect configured flood scopes, improving message routing accuracy.
- Updated `MeshMessage` model to include a `reply_scope` attribute for tracking matched flood scopes.
2026-04-08 21:14:04 -07:00
agessaman
883b67daf9 Update per-user rate limit and implement version command support
- Increased the per-user rate limit from 5 to 30 seconds across multiple configuration files to reduce response frequency.
- Added the version command to the configuration examples and updated help text to include the new command.
- Refactored version information retrieval in the bot and web viewer to utilize a shared runtime resolver for consistency.
- Improved documentation in README.md to reflect changes in commands and configuration options.
2026-04-05 20:00:01 -07:00
agessaman
fbf39958f1 Enhance multibyte path chart rendering in web viewer
- Refactored the logic for displaying multibyte path statistics in the doughnut chart, improving clarity and responsiveness.
- Introduced a function to disable animations for smoother updates when data changes.
- Updated chart options to dynamically reflect multibyte and other path data, enhancing user experience and visual representation.

These changes improve the accuracy and usability of the multibyte path statistics in the dashboard.
2026-04-05 16:36:58 -07:00
agessaman
ba52c3ba07 Fix path length calculation and hash mode handling in MessageHandler
- Improved error handling for `out_path_hash_mode` and `out_path_len` to ensure proper type conversion and validation.
- Added logic to derive `out_path_len` from `out_path` when it is missing, enhancing robustness against incomplete data.
- Updated tests to verify correct behavior when `out_path_hash_mode` is provided as a string and `out_path_len` is absent.
2026-04-05 11:07:52 -07:00
agessaman
3670f5db41 Enhance path condensing functionality in MultitestCommand
- Introduced a new `CondensePathsMode` type to support multiple condensing styles: "off", "flat", and "nested".
- Updated `_condense_path_lines` to handle different condensing modes, improving path representation.
- Enhanced test coverage for path condensing scenarios, ensuring accurate output for various path configurations.

These changes improve the flexibility and usability of path handling in the MultitestCommand, allowing for better visualization of path structures.
2026-04-05 10:47:13 -07:00
Adam Gessaman
615dbb008a Merge pull request #134 from lincomatic/reconnect
add reconnect logic
2026-04-05 10:40:51 -07:00
agessaman
12e677a9cf Update default value for condense_paths in MultitestCommand
- Changed the fallback value for condense_paths from False to True in the MultitestCommand class, ensuring that paths are condensed by default. This adjustment improves the command's usability and aligns with expected behavior.
2026-04-04 09:52:22 -07:00
agessaman
c6a7355b3c Enhance multibyte path statistics and UI in web viewer
- Added calculations for contacts and incoming packets with multibyte path evidence over the last 7 days in `app.py`, improving data accuracy.
- Introduced new methods for handling multibyte path chunks and counting packets from JSON data, enhancing backend functionality.
- Updated `contacts.html` and `index.html` templates to display multibyte path encoding badges and tooltips, improving user interface clarity.
- Enhanced CSS for path encoding badges to differentiate between multibyte and one-byte paths, ensuring better visual representation.

These changes improve the overall user experience and data representation in the Bot Data Viewer.
2026-04-03 20:27:00 -07:00
agessaman
48fd46287e Refactor MQTT weather configuration and payload handling
- Updated `config.ini.example` to include detailed MQTT weather configuration options, enhancing clarity and usability.
- Expanded JSON template placeholders in `mqtt_weather.py` to support additional weather data fields, improving data representation.
- Introduced new utility functions for better handling of numeric and non-negative integer values in payload formatting.
- Enhanced test coverage for MQTT weather functionality, ensuring robust handling of extended placeholders and configuration loading.

These changes improve the flexibility and reliability of the MQTT weather integration, allowing for more comprehensive weather data management.
2026-04-03 17:05:18 -07:00
agessaman
f829c9e30b Update JSON placeholders in feeds.html and mesh.html for improved readability
- Changed single quotes to HTML entities in JSON placeholders within the feeds.html file to ensure proper rendering.
- Updated the assignment of PREFIX_HEX_CHARS in mesh.html to parse the value as an integer, enhancing type safety and clarity.

These changes enhance the user interface and code maintainability in the web viewer templates.
2026-04-03 11:36:33 -07:00
agessaman
531e87bcd9 refactor(weather): use APScheduler for daily forecast cron
Remove the schedule package; align fixed alarm times with bot timezone
via get_config_timezone like MessageScheduler.
2026-04-03 11:26:54 -07:00
agessaman
6ff876ab15 Refactor type hints and imports across multiple modules
- Updated type hints to use `|` for union types instead of `Optional` where applicable, enhancing readability and consistency.
- Cleaned up import statements by removing unnecessary imports and organizing them for better clarity.
- Adjusted function signatures in various modules to reflect the new type hinting style, improving type safety and code maintainability.

These changes contribute to a more modern and consistent codebase, aligning with current Python typing practices.
2026-04-03 11:15:47 -07:00
Adam Gessaman
7f16fc0862 Merge branch 'dev' into reconnect 2026-04-03 11:03:49 -07:00
agessaman
b3d5054074 Merge branch 'integration/massive-pr' into dev
Resolve conflicts by combining v0.9 integration work with dev-only behavior:
- Keep channel_responses_enabled, greeter pause checks, and max_response_hops gating
- Retain TRACE/repeat handling, MQTT weather, temperature format helpers, and feed tooling
- Unify package-data globs, ruff/mypy/pytest config, Rate_Limits/Webhook in config example
- Web viewer: config panels + X-Requested-With on channel API; drop redundant DBManager import

Made-with: Cursor
2026-04-03 10:51:50 -07:00
lincomatic
6a9e0eccbe add reconnect logic 2026-04-02 22:17:53 -07:00
agessaman
60cbf79a3d Implement concurrency controls for auto-purge and per-key removal in RepeaterManager
- Introduced locking mechanisms to prevent overlapping auto-purge runs and duplicate purge attempts for specific keys.
- Added methods to manage in-flight purge attempts, ensuring that concurrent calls do not interfere with each other.
- Updated the `check_and_auto_purge` method to utilize the new locking logic, enhancing the reliability of the auto-purge process.
- Expanded test coverage to validate the new concurrency controls, ensuring correct behavior under concurrent execution scenarios.

These changes improve the stability and efficiency of the repeater management system during purge operations.
2026-04-02 10:35:47 -07:00
agessaman
9d768a3cf7 Implement MQTT weather support in weather commands and configuration
- Added new configuration options in `config.ini.example` for enabling and configuring MQTT weather sources.
- Updated `WxCommand` and `GlobalWxCommand` classes to retrieve weather data from custom MQTT topics, enhancing flexibility in weather data sources.
- Introduced error handling for MQTT data retrieval, ensuring robust responses for various error scenarios.
- Expanded translation strings in `en.json` to support MQTT-related messages, improving user feedback.

These changes enhance the application's capability to utilize MQTT for weather data, providing users with more options for weather information retrieval.
2026-04-02 10:24:49 -07:00
agessaman
81866487ab Fix UnboundLocalError in decode_meshcore_packet for invalid hex input
- Ensured `byte_data` and `hex_data` are always defined for error logging, preventing UnboundLocalError when handling invalid hex strings.
- Updated test case to confirm that invalid hex input returns None without raising exceptions, improving error handling in the message decoding process.

These changes enhance the robustness of the message handling system by addressing potential error scenarios.
2026-03-30 19:49:39 -07:00
agessaman
f3e667e64f Enhance TRACE payload handling and path extraction in message processing
- Updated `update_mesh_graph_from_trace_data` to clarify the format of `path_hashes` as per-hop hash strings from the trace payload.
- Modified `MessageHandler` to differentiate between TRACE packets and regular transmissions, preventing incorrect extraction of repeater prefixes from RF path bytes.
- Introduced `parse_trace_payload_route_hashes` utility to extract TRACE route hash segments from payloads, ensuring accurate handling of path data.
- Enhanced `PacketCaptureService` to correctly populate packet information for TRACE packets, including SNR path and route hashes.
- Expanded test coverage for TRACE payload decoding and path extraction to validate functionality and correctness.

These changes improve the accuracy and reliability of TRACE data processing in the application.
2026-03-30 17:36:52 -07:00
Chris Barker
8966be89a6 Adds max_response_hops
Before this there was no way to prevent the bot to reply to random
channel noise from a temprorary strong link to another distant mesh.

This provides the ability for users in larger meshes to cap the bot
to reply to only messages sent likely from nearby repeaters. This works
well in conjunction with region scoping.

Default value is still 64, to not change behavior on existing installs,
but the example config.ini's all include a suggested start valu of 10.
2026-03-30 15:11:05 +01:00
agessaman
6a7a79af3c Refactor path node ID extraction and distance calculation in utils
- Introduced `extract_path_node_ids_from_message` to streamline extraction of node IDs from mesh messages, prioritizing `routing_info.path_nodes` and supporting multi-byte comma parsing.
- Updated `calculate_path_distances` to accept an optional message parameter, enhancing its functionality by allowing it to derive node IDs from messages.
- Added `node_ids_from_path_string` to handle parsing of path strings into node IDs, improving the handling of both legacy and multi-byte formats.
- Refactored `TestCommand` to utilize the new extraction function, ensuring consistent behavior across commands.
- Expanded test coverage for new utility functions to validate their correctness and robustness.

These changes improve the clarity and maintainability of path-related utilities, enhancing overall functionality in message processing.
2026-03-29 22:05:36 -07:00
agessaman
5b1bcac2a0 Implement temperature formatting in weather commands and services
- Added new configuration options in `config.ini.example` for customizing the display of daily high/low temperatures.
- Introduced `format_temperature_high_low` function in `utils.py` to format temperature strings based on user-defined templates.
- Updated `WxCommand`, `GlobalWxCommand`, and `WeatherService` classes to utilize the new formatting function, enhancing the presentation of temperature data in weather forecasts.
- Refactored existing high/low temperature handling to improve code clarity and maintainability.

These changes enhance the flexibility and readability of temperature displays in weather-related outputs.
2026-03-29 21:22:00 -07:00
agessaman
5f6eced45d Add Open-Meteo model selection support in weather configuration
- Introduced a new configuration option for selecting Open-Meteo models in `config.ini.example`, allowing users to specify a model or default to "best_match".
- Implemented `_load_weather_model` method in `GlobalWxCommand` and `WeatherService` classes to handle model selection logic, including validation and fallback mechanisms.
- Updated API request parameters to include the selected weather model when available, enhancing the flexibility of weather data retrieval.

These changes improve the customization of weather data requests and ensure robust handling of model selection in the application.
2026-03-29 20:58:26 -07:00
agessaman
aa2677bc4b Add Unix signal handling for graceful shutdown and config reload
- Introduced a new function to configure Unix signal handlers for SIGTERM, SIGINT, and SIGHUP, allowing for graceful shutdown and in-process configuration reload.
- Updated the main function to utilize the new signal handling setup, improving the bot's responsiveness to system signals.
- Enhanced documentation in the service installation guide to clarify the use of the reload command for configuration changes without restarting the service.

These changes improve the bot's operational flexibility and user experience during configuration updates.
2026-03-29 20:32:54 -07:00
agessaman
43f450e702 Update path formatting and message handling in commands
- Modified path formatting in `multitest_command.py` to use ideographic space for nested branches, enhancing visual clarity.
- Updated the `schedule_command.py` to strip control characters from messages, ensuring safe and clean previews.
- Adjusted test cases in `test_multitest_command.py` to reflect changes in path formatting, improving consistency across tests.

These changes enhance the readability of path outputs and improve message handling in scheduled commands.
2026-03-29 20:27:18 -07:00
agessaman
507c7ad31e Enhance database migration safety and improve repeater management
- Added a regex pattern to validate SQLite column definitions, preventing SQL injection in the _add_column() function.
- Introduced a new validation function to ensure safe column definitions are used.
- Updated repeater_manager.py to use list() for iterating over contacts, ensuring compatibility with potential changes in the underlying data structure.
- Enhanced error handling in the MessageScheduler for better debugging during scheduler shutdown and message sending.

These changes improve the security and reliability of database operations and enhance the robustness of the repeater management system.
2026-03-29 20:00:44 -07:00
agessaman
4685ea734c Enhance contacts UI with mobile-friendly toolbar and search functionality
- Introduced a responsive toolbar for filtering and searching contacts, improving usability on mobile devices.
- Added a dropdown for timespan selection, allowing users to filter contacts based on different timeframes.
- Updated styles to ensure consistent alignment and height for toolbar elements, enhancing the overall appearance and functionality.

These changes improve the user experience for managing contacts in the web viewer.
2026-03-29 17:29:49 -07:00