ConfigParser lowercases all config keys, so bridge.Public is stored as
bridge.public in channel_webhooks. The test assertions expected title-case
"Public" but the actual stored key is "public". Runtime channel matching
was already case-insensitive; only the test expectations needed updating.
Each command's aliases are now configured as an `aliases` key in its own
config section (e.g. [Wx_Command] aliases = !weather, !w) rather than a
separate [Aliases] section. BaseCommand._load_aliases_from_config() reads
and injects them into keywords at startup. CommandManager.load_aliases()
and _apply_aliases() are removed. No behaviour change for commands without
aliases configured.
Add live and offline packet-parsing tests using paho-mqtt:
- tests/test_mqtt_live.py: schema validation + live integration tests;
subscribes to meshcore/SEA/+/packets; validates JSON against schema
- tests/mqtt_test_config.ini: broker/topic/timeout config; primary LAN
broker (10.0.2.123:1883); letsmesh as documented alternative
- tests/fixtures/mqtt_packets.json: 8 real packets from SEA region for
offline fallback
Run live: pytest -m mqtt
Run offline: pytest -m "not mqtt"
Collect fixtures: python tests/test_mqtt_live.py --collect-fixtures
Auth (BUG-001):
- Optional password via web_viewer_password in [Web_Viewer]; /login and
/logout; Flask session guard on all routes and SocketIO handlers
Contact management and export:
- Star contacts of any type; purge-preview + purge inactive contacts
- GET /api/export/contacts and /api/export/paths: CSV/JSON with time-range
Config tab and maintenance:
- /config page: SMTP, log rotation, DB backup settings in bot_metadata
- Nightly email digest (uptime, contacts, DB size, log errors); SMTP
timeout=30s; pre-rotation log attachment hook
- GET /api/maintenance/status: Maintenance Status card
DB backup, restore, and purge:
- POST /api/maintenance/backup_now; GET /api/maintenance/list_backups;
POST /api/maintenance/restore (SQLite magic-byte validation)
- POST /api/maintenance/purge: remove rows older than threshold
- Scheduled backups: daily/weekly/manual with retention pruning
- Config save validates db_backup_dir exists; 400 on missing path
Live streaming and realtime monitoring:
- Live Activity panel: colour-coded SocketIO feed with pause/clear
- capture_channel_message() feeds packet_stream; message_data event
- /realtime page: three independent stream panels; [#channel] prefix
- /logs page: subscribe_logs/log_line; log-tail thread; level colouring
- History replay: last 50/50/200 items on connect
- Werkzeug 3.1 WebSocket fix: _apply_werkzeug_websocket_fix()
- BUG-029: db_path resolved via config_base = Path(config_path).parent;
stored as self._config_base; dead _get_db_path() removed
Scroll/filter controls and connected agents:
- Scroll-to-top/bottom on Live Activity and all realtime panels
- Type-filter checkboxes (Packets/Commands/Messages) with applyFilters()
- GET /api/connected_clients: agent count clickable; Bootstrap modal
Add geographic_scoring_enabled = true/false to [Path_Command] config.
When disabled, path scoring uses hop count only and ignores GPS
coordinates. Evaluated per-command invocation; no restart required.
Add ScheduleCommand (DM-only by default). Displays configured scheduled
message times, target channels, message previews, and the current
advertisement interval. Read-only; does not modify schedule state.
Add ChannelRateLimiter to rate_limiter.py. Configure per-channel
cooldowns via [Rate_Limits] channel.<name>_seconds. Integrated into
_check_rate_limits() and send_channel_message() in command_manager.py.
GET /api/stats/rate_limiters exposes live stats for all four limiter
types.
Add POST /webhook endpoint to the web viewer. Authenticated via
Authorization: Bearer <token> set in [Webhook] config section. Relays
JSON or text payload to a configured MeshCore channel or user DM.
Test modules:
- test_enums: enum values and flag combinations
- test_models: MeshMessage dataclass field and type validation
- test_transmission_tracker: full TransmissionTracker coverage
- test_message_handler: path parsing, RF correlation, message routing
- test_repeater_manager: role detection, ACL, device type classification
- test_core: config loading, radio settings, reload paths
Tracking files:
- BUGS.md: known bugs and fix history log
- TESTING.md: test strategy, coverage targets, and how-to guide
- TODO.md: feature and task backlog with completion status
- scripts/update_todos.py: scans source for # TODO/FIXME/HACK markers
and regenerates the Inline TODOs section in TODO.md
- Updated config.ini.example and discord-bridge.md to reflect the ability to fan out a single MeshCore channel to multiple Discord servers using a comma- or whitespace-separated list of webhook URLs.
- Modified DiscordBridgeService to handle multiple webhooks per channel, including validation and logging improvements for better monitoring of configured webhooks.
- Updated the _cleanup_web_viewer and _cleanup_mesh_graph methods to avoid logging errors during shutdown, as the logger's stream may be closed at that time.
- Modified the shutdown method in MeshGraph to prevent logging of flushing errors, enhancing stability during the atexit process.
- Adjusted test configurations to use Path objects for bot_root and local_root, improving path handling in tests.
- Modified the test file to include a conditional import for the CheckInService, allowing tests to be skipped if the plugin is not installed. This change improves test reliability and clarity regarding plugin dependencies.
- Updated the MeshGraph class to prevent promoting a 1-byte edge to a 3-byte edge when the existing 1-byte edge lacks public keys, ensuring accurate observation attribution.
- Added a new test case to verify the behavior of edge promotion under specific conditions.
- Modified the BotDataViewer API to return the prefix length dynamically based on the edges, improving data consistency and user experience in the web viewer.
- Enhanced the mesh.html template to support displaying prefix byte counts, providing clearer information on node connections.
- Added `send_channel_messages_chunked` method to `CommandManager` for sending multiple messages with appropriate rate-limit spacing.
- Introduced `send_response_chunked` method in `BaseCommand` to facilitate chunked responses in both channels and DMs.
- Updated `GreeterCommand` to utilize the new chunked response functionality, simplifying the greeting message sending process.
- Enhanced documentation in `local-plugins.md` with examples for using chunked message sending, improving clarity on handling long messages and rate limits.
- Updated MeshGraph to support multi-resolution storage and node identity, allowing for better handling of 1-byte, 2-byte, and 3-byte edges.
- Implemented logic for merging and promoting edges based on observation counts and specificity.
- Enhanced BotDataViewer API to dynamically adjust prefix length based on configuration, improving data representation.
- Updated mesh.html template to display prefix byte counts, enhancing user experience with clearer information on node connections.
- Updated `meshcore` dependency version to `2.2.14` in both `pyproject.toml` and `requirements.txt`.
- Added multi-byte path support in the `PathCommand`, allowing for 1-, 2-, and 3-byte-per-hop paths.
- Enhanced `MessageHandler` to utilize `routing_info` for accurate path extraction and validation.
- Improved path extraction methods in `MultitestCommand` and `TestCommand` to prefer `routing_info` for node IDs.
- Refactored path handling logic across various commands to ensure consistent multi-byte path processing.
- Updated `.gitignore` to include local configuration and plugin directories, allowing users to add custom commands and services without modifying core code.
- Enhanced `config.ini.example` with instructions for using local plugins and added sections for local service configurations.
- Refactored `PluginLoader` and `ServicePluginLoader` to support loading local commands and services from specified directories, improving extensibility.
- Updated `mkdocs.yml` to include documentation for local plugins and the check-in API.
- Added tests to verify the discovery and loading of local plugins, ensuring functionality and preventing name collisions with built-in plugins.
- Added configuration options to bridge the bot's own channel responses to Discord and Telegram, allowing command replies to be sent to respective channels.
- Updated `DiscordBridgeService` and `TelegramBridgeService` to register listeners for bot-sent messages, ensuring they are included in the bridging process.
- Enhanced `CommandManager` to invoke listeners with a synthetic event when a message is successfully sent, providing context about the message.
- Updated `config.ini.example` to reflect the new `bridge_bot_responses` option for both services.
- Added tests to verify the correct invocation of listeners upon successful message sending.
- Added support for channel-specific triggers in the CommandManager, allowing triggers to be restricted to designated channels via `channel.<key>` or `channels.<key>` configuration.
- Updated `config.ini.example` to include examples of channel restrictions for triggers.
- Enhanced tests to verify that triggers only match in specified channels, ensuring proper functionality of the new feature.
- Updated the profanity filter to check for hate symbols (e.g., swastika Unicode) in addition to word-based profanity, ensuring comprehensive message filtering.
- Modified the `censor` function to replace hate symbols with `***`, maintaining functionality even when the `better-profanity` package is unavailable.
- Updated documentation in `discord-bridge.md` and `telegram-bridge.md` to reflect the new hate symbol handling features.
- Added tests to verify detection and censorship of hate symbols, ensuring robustness of the profanity filter.
- Introduced `filter_profanity` configuration option in `config.ini.example` to handle profanity in bridged messages: options include `drop` (default), `censor`, or `off`.
- Updated `requirements.txt` to include `better-profanity` for profanity filtering functionality.
- Enhanced `DiscordBridgeService` and `TelegramBridgeService` to implement the profanity filter logic, allowing messages with profanity to be dropped or censored before bridging.
- Updated documentation in `discord-bridge.md` and `telegram-bridge.md` to reflect the new profanity handling feature.
- Updated `MeshGraph` to support multi-resolution storage of edges, allowing prefixes of 2, 4, or 6 hex chars without truncation.
- Implemented prefix matching logic to ensure distinct links are maintained and accurately retrieved based on prefix queries.
- Refactored methods in `MessageHandler` and `PathCommand` to accommodate variable prefix lengths during graph lookups.
- Enhanced tests to validate prefix match functionality and edge management in the mesh graph.
- Replaced direct SQLite connection calls with a context manager in various modules to ensure proper resource management and prevent file descriptor leaks.
- Introduced a new `connection` method in `DBManager` to standardize connection handling.
- Updated all relevant database interactions in modules such as `feed_manager`, `scheduler`, `commands`, and others to utilize the new connection method.
- Improved code readability and maintainability by consolidating connection logic.
- Introduced a new utility function `decode_path_len_byte` to decode RF packet path length bytes, supporting both legacy and multi-byte paths.
- Updated various modules to utilize the new decoding logic, ensuring compatibility with configured prefix lengths.
- Modified database schemas to include `bytes_per_hop` and `out_bytes_per_hop` columns for better path management.
- Enhanced path parsing and validation across commands and services to accommodate variable prefix lengths.
- Improved logging and error handling for path-related operations, ensuring robustness during transitions.
- Update prefix command to accept BOTH legacy 2-char prefixes and
configured prefix_hex_chars (e.g. 4-char) during firmware transition
- Replace strict length validation with dual-length validation (2 or N)
- Ensure prefix lookups work with either input length via LIKE matching
- Update related SQL prefix extraction to use configured prefix length
- Add fallback handling in path parsing for legacy 2-char route data
Notes:
- This is an interim compatibility change to support mixed networks
where RF path data is still 1-byte while bot config may be 2-byte.
- Needs additional testing across real multi-hop scenarios and mixed
bot configurations.
- Translation updates are incomplete: only English strings were updated;
other translation files still need review.
- Behavior and UX may need refinement after real-world testing.
- Updated `config.ini.example` to include new settings for edge loading and graph data capture, providing clearer guidance on usage.
- Modified `MeshGraph` class to respect the new `graph_capture_enabled` setting, controlling the collection of edge data from incoming packets.
- Adjusted message handling to ensure graph updates only occur when data capture is enabled, optimizing performance and resource usage.
- Added tests to validate the new configuration options, ensuring proper functionality in various scenarios.
- Introduced `strip_optional_quotes` function to handle monitor channel values with optional surrounding quotes.
- Updated `load_monitor_channels` method in `CommandManager` to utilize the new function, ensuring compatibility with quoted and unquoted channel configurations.
- Modified `generate_samples` function to apply the same logic for consistency.
- Added tests for `strip_optional_quotes` to validate behavior with various input cases.
- Added assertions to ensure call arguments are not None in multiple command tests.
- Introduced a new test for the CmdCommand class to verify that long command lists are truncated correctly with a '(N more)' suffix, improving command list readability.
- Standardized the configuration keys for various commands by replacing specific `*_enabled` keys with a unified `enabled` key across configuration files.
- Updated command classes to support fallback mechanisms for legacy configuration keys, ensuring backward compatibility.
- Enhanced the logic in the `BaseCommand` class to handle both standard and legacy keys for command enabling.
- Added tests to verify the correct behavior of the new configuration handling and legacy support for commands including Stats, Sports, Hacker, and Alert.
- Standardized the configuration keys for joke commands by replacing `joke_enabled` and `dadjoke_enabled` with a unified `enabled` key in the configuration files.
- Updated the validation logic to warn users when both legacy `[Jokes]` and new `[Joke_Command]`/`[DadJoke_Command]` sections are present, suggesting the removal of the legacy section.
- Enhanced the command classes to support fallback mechanisms for legacy configuration keys, ensuring backward compatibility.
- Added tests to verify the correct behavior of the new configuration handling and legacy support.
- Enhanced .gitignore to allow test files in the tests/ directory and committed pytest.ini for test discovery.
- Added checks for missing sections in configuration files, specifically for Admin_ACL and Banned_Users, to prevent errors during bot startup.
- Updated generate_website.py and command_manager.py to handle cases where required sections are absent, returning empty lists instead of raising exceptions.
- Introduced optional dependencies for testing in pyproject.toml, ensuring a smoother development experience.
- Improved localization handling in core.py to default to English when the Localization section is missing, enhancing user experience.
- Move entire tests/ directory to docs/local/tests/
- Remove all test files from git tracking (20 files removed)
- Add tests/ to .gitignore to prevent future commits of test files
- Tests are development/experimental code not needed for public repository
- Repository is now cleaner and more focused on production code